From f15f9d7d78056e15a028bc0d824d19b92878a870 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 14 Dec 2023 00:16:42 -0700 Subject: [PATCH 001/157] Shadow JGraphT --- dependencies.gradle | 3 +++ gradle.properties | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 82ef07ce6a8..2089f28dcd1 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -27,6 +27,9 @@ dependencies { implementation rfg.deobf("curse.maven:codechicken-lib-1-8-242818:2779848") // CCL 3.2.3.358 implementation("com.cleanroommc:modularui:2.4.1") { transitive = false } + // Shadowed Dependencies + shadowCompile 'org.jgrapht:jgrapht-core:1.5.1' + // Soft Dependencies // Can change any of these from compileOnlyApi -> implementation to test them in-game. diff --git a/gradle.properties b/gradle.properties index 8cc69185de4..1e3c0eb3e6d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -80,7 +80,7 @@ includeCommonDevEnvMods = true # If enabled, you may use 'shadowCompile' for dependencies. They will be integrated in your jar. It is your # responsibility check the licence and request permission for distribution, if required. -usesShadowedDependencies = false +usesShadowedDependencies = true # If disabled, won't remove unused classes from shaded dependencies. Some libraries use reflection to access # their own classes, making the minimization unreliable. minimizeShadowedDependencies = true From 2e1fee9bcd5748204cf74990c6a04f8aa219b3ad Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 14 Dec 2023 00:16:50 -0700 Subject: [PATCH 002/157] First batch of work --- src/main/java/gregtech/api/pipenet/NodeG.java | 99 +++++++ .../gregtech/api/pipenet/WorldPipeNetG.java | 263 ++++++++++++++++++ .../api/pipenet/tile/TileEntityPipeBase.java | 7 +- 3 files changed, 366 insertions(+), 3 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/NodeG.java create mode 100644 src/main/java/gregtech/api/pipenet/WorldPipeNetG.java diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java new file mode 100644 index 00000000000..4d6e1a06f56 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -0,0 +1,99 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.tile.IPipeTile; + +import gregtech.api.pipenet.tile.TileEntityPipeBase; + +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.common.util.INBTSerializable; + +import java.util.Objects; + +public class NodeG & IPipeType, NodeDataType> implements INBTSerializable { + + public static final int DEFAULT_MARK = 0; + + public NodeDataType data; + /** + * Specifies bitmask of blocked connections + * Node will not connect in blocked direction in any case, + * even if neighbour node mark matches + */ + public int openConnections; + /** + * Specifies mark of this node + * Nodes can connect only if their marks are equal, or if + * one of marks is default one + */ + public int mark; + public boolean isActive; + + public IPipeTile heldMTE; + private BlockPos nodePos; + + public NodeG(NodeDataType data, int openConnections, int mark, boolean isActive, IPipeTile heldMTE) { + this.data = data; + this.openConnections = openConnections; + this.mark = mark; + this.isActive = isActive; + this.heldMTE = heldMTE; + this.nodePos = heldMTE.getPipePos(); + } + + /** + * For construction during NBT reading only + */ + public NodeG(NBTTagCompound tag) { + deserializeNBT(tag); + } + + /** + * For internal usage only + */ + NodeG(BlockPos pos) { + this.nodePos = pos; + } + + public boolean isBlocked(EnumFacing facing) { + return (openConnections & 1 << facing.getIndex()) == 0; + } + + public BlockPos getNodePos() { + return nodePos; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setLong("Pos", this.nodePos.toLong()); + tag.setInteger("Mark", this.mark); + tag.setInteger("OpenConnections", this.openConnections); + tag.setBoolean("IsActive", this.isActive); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + this.nodePos = BlockPos.fromLong(nbt.getLong("Pos")); + this.mark = nbt.getInteger("Mark"); + this.openConnections = nbt.getInteger("OpenConnections"); + this.isActive = nbt.getBoolean("IsActive"); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + NodeG nodeG = (NodeG) o; + return Objects.equals(nodePos, nodeG.nodePos); + } + + @Override + public int hashCode() { + return Objects.hash(nodePos); + } +} diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java new file mode 100644 index 00000000000..0c93ab4e459 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -0,0 +1,263 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.block.IPipeType; + +import gregtech.api.pipenet.tile.IPipeTile; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.storage.WorldSavedData; + +import net.minecraftforge.common.util.Constants; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; +import org.jgrapht.GraphPath; +import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; +import org.jgrapht.graph.DefaultWeightedEdge; +import org.jgrapht.graph.SimpleWeightedGraph; +import org.jgrapht.util.ConcurrencyUtil; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ThreadPoolExecutor; + +public abstract class WorldPipeNetG & IPipeType> extends WorldSavedData { + + // note - should this be shut down at some point during server shutdown? + public static ThreadPoolExecutor EXECUTOR = + ConcurrencyUtil.createThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2); + + private WeakReference worldRef = new WeakReference<>(null); + private final Graph, DefaultWeightedEdge> pipeGraph; + private final Map> pipeMap = new Object2ObjectOpenHashMap<>(); + + private ShortestPathsAlgorithm, DefaultWeightedEdge> shortestPaths; + // this is a monstrosity + private final Map, Map, GraphPath, DefaultWeightedEdge>>> shortestPathsCache = new Object2ObjectOpenHashMap<>(); + private boolean validPathsCache = true; + + public WorldPipeNetG(String name) { + super(name); + this.pipeGraph = new SimpleWeightedGraph<>(DefaultWeightedEdge.class); + } + + public World getWorld() { + return this.worldRef.get(); + } + + protected void setWorldAndInit(World world) { + if (world != this.worldRef.get()) { + this.worldRef = new WeakReference<>(world); + onWorldSet(world); + } + } + + public static String getDataID(final String baseID, final World world) { + if (world == null || world.isRemote) + throw new RuntimeException("WorldPipeNetG should only be created on the server!"); + int dimension = world.provider.getDimension(); + return dimension == 0 ? baseID : baseID + '.' + dimension; + } + + protected void onWorldSet(World world) { + for (NodeG node : pipeGraph.vertexSet()) { + // do initial edge additions & fully initialize nodes + IPipeTile pipe = castTE(world.getTileEntity(node.getNodePos())); + if (pipe != null) { + node.heldMTE = pipe; + node.data = pipe.getNodeData(); + addNodeSilent(node); + addEdges(node); + } + + } + rebuildShortestPaths(); + } + + /** + * Preferred override + * @param tile The {@link IPipeTile} that paths are being requested for + * @return the collection of paths associated with the {@link IPipeTile} + */ + public Map, GraphPath, DefaultWeightedEdge>> getPaths(IPipeTile tile) { + return getPaths(new NodeG<>(tile.getPipePos()), tile); + } + + /** + * Special-case override + * @param pos The {@link BlockPos} that paths are being requested for + * @return the collection of paths associated with the {@link BlockPos} + */ + public Map, GraphPath, DefaultWeightedEdge>> getPaths(BlockPos pos) { + return getPaths(new NodeG<>(pos), null); + } + + public Map, GraphPath, DefaultWeightedEdge>> getPaths( + NodeG node, @Nullable IPipeTile tile) { + World world = this.worldRef.get(); + if (world == null) + throw new RuntimeException("The world of a PipeNet should be set before getting paths from it!"); + + if (!this.validPathsCache) { + this.rebuildShortestPaths(); + this.shortestPathsCache.clear(); + } + + if (!node.heldMTE.isValidTile()) { + if (tile != null) { + node.heldMTE = tile; + } else { + IPipeTile pipe = castTE(world.getTileEntity(node.getNodePos())); + if (pipe != null) + node.heldMTE = pipe; + } + } + + Map, GraphPath, DefaultWeightedEdge>> cache = + this.shortestPathsCache.get(node); + if (cache != null) return cache; + + return this.shortestPaths.getPathsMap(node); + } + + protected IPipeTile castTE(TileEntity te) { + if (te instanceof IPipeTile pipe) { + if (!getBasePipeClass().isAssignableFrom(pipe.getClass())) { + return null; + } + return (IPipeTile) pipe; + } + return null; + } + + protected abstract Class> getBasePipeClass(); + + public void addNode(BlockPos nodePos, NodeDataType nodeData, int mark, int openConnections, boolean isActive, IPipeTile heldMTE) { + NodeG node = new NodeG<>(nodeData, openConnections, mark, isActive, heldMTE); + if (!canAttachNode(nodeData)) return; + + this.addNode(node); + addEdges(node); + + } + + private void addEdges(NodeG node) { + for (EnumFacing facing : EnumFacing.VALUES) { + BlockPos offsetPos = node.getNodePos().offset(facing); + NodeG nodeOffset = this.pipeMap.get(offsetPos); + if (nodeOffset != null && this.canNodesConnect(node, facing, nodeOffset)) { + this.addEdge(node, nodeOffset); + } + } + } + + protected final boolean canNodesConnect(NodeG node1, EnumFacing nodeFacing, NodeG node2) { + return areNodeBlockedConnectionsCompatible(node1, nodeFacing, node2) && + areMarksCompatible(node1.mark, node2.mark) && areNodesCustomContactable(node1.data, node2.data); + } + + private static boolean areMarksCompatible(int mark1, int mark2) { + return mark1 == mark2 || mark1 == Node.DEFAULT_MARK || mark2 == Node.DEFAULT_MARK; + } + + private boolean areNodeBlockedConnectionsCompatible(NodeG node1, EnumFacing nodeFacing, NodeG node2) { + return !node1.isBlocked(nodeFacing) && !node2.isBlocked(nodeFacing.getOpposite()); + } + + protected boolean areNodesCustomContactable(NodeDataType node1, NodeDataType node2) { + return true; + } + + protected boolean canAttachNode(NodeDataType nodeData) { + return true; + } + + public void addNodeSilent(NodeG node) { + pipeGraph.addVertex(node); + this.pipeMap.put(node.getNodePos(), node); + this.validPathsCache = false; + } + + public void addNode(NodeG node) { + addNodeSilent(node); + this.markDirty(); + } + + public void addEdge(NodeG node1, NodeG node2) { + addEdge(node1, node2, 1); + this.validPathsCache = false; + } + + public void addEdge(NodeG node1, NodeG node2, int weight) { + pipeGraph.addEdge(node1, node2); + pipeGraph.setEdgeWeight(node1, node2, weight); + this.validPathsCache = false; + } + + public void removeEdge(NodeG node1, NodeG node2) { + if (pipeGraph.removeEdge(node1, node2) != null) + this.validPathsCache = false; + } + + public void removeNode(NodeG node) { + if (pipeGraph.removeVertex(node)) { + this.validPathsCache = false; + this.markDirty(); + } + } + + protected void rebuildShortestPaths() { + this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph, EXECUTOR); + this.validPathsCache = true; + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + NBTTagList allPipeNodes = nbt.getTagList("PipeNodes", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < allPipeNodes.tagCount(); i++) { + NBTTagCompound pNodeTag = allPipeNodes.getCompoundTagAt(i); + this.addNodeSilent(new NodeG<>(pNodeTag)); + } + } + + @NotNull + @Override + public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { + NBTTagList allPipeNodes = new NBTTagList(); + for (NodeG node : pipeGraph.vertexSet()) { + NBTTagCompound nodeTag = node.serializeNBT(); + allPipeNodes.appendTag(nodeTag); + } + compound.setTag("PipeNodes", allPipeNodes); + return compound; + } + + // CHManyToManyShortestPaths is a very good algorithm because our graph will be extremely sparse. + protected static class ShortestPathsAlgorithm extends CHManyToManyShortestPaths { + + public ShortestPathsAlgorithm(Graph graph, ThreadPoolExecutor executor) { + super(graph, executor); + } + + public Map> getPathsMap(V source) { + if (!graph.containsVertex(source)) { + throw new IllegalArgumentException("graph must contain the source vertex"); + } + + Map> paths = new HashMap<>(); + for (V v : graph.vertexSet()) { + paths.put(v, getPath(source, v)); + } + return paths; + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 84897a022e8..87e67dea4f8 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -535,9 +535,10 @@ public boolean isValidTile() { } @Override - public boolean shouldRefresh(@NotNull World world, @NotNull BlockPos pos, IBlockState oldState, - IBlockState newSate) { - return oldState.getBlock() != newSate.getBlock(); + public boolean shouldRefresh(@NotNull World world, @NotNull BlockPos pos, @NotNull IBlockState oldState, + @NotNull IBlockState newSate) { + // always return true to ensure that the Chunk marks the old MTE as invalid + return true; } @MustBeInvokedByOverriders From 610ed17cef92b046c336916c2f676b7f88658c08 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 15 Dec 2023 00:59:22 -0700 Subject: [PATCH 003/157] Second batch of work, API backbone complete? --- .../java/gregtech/api/pipenet/NetEdge.java | 61 +++++ src/main/java/gregtech/api/pipenet/NodeG.java | 37 ++- .../gregtech/api/pipenet/WorldPipeNetG.java | 226 +++++++++++++----- 3 files changed, 256 insertions(+), 68 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/NetEdge.java diff --git a/src/main/java/gregtech/api/pipenet/NetEdge.java b/src/main/java/gregtech/api/pipenet/NetEdge.java new file mode 100644 index 00000000000..254accda423 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/NetEdge.java @@ -0,0 +1,61 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.util.function.TriConsumer; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.util.INBTSerializable; + +import org.jgrapht.graph.DefaultWeightedEdge; + +import java.util.Map; + +class NetEdge extends DefaultWeightedEdge implements INBTSerializable { + + @Override + protected NodeG getSource() { + return (NodeG) super.getSource(); + } + + @Override + protected NodeG getTarget() { + return (NodeG) super.getTarget(); + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setLong("SourceLongPos", getSource().getLongPos()); + tag.setLong("TargetLongPos", getTarget().getLongPos()); + tag.setDouble("Weight", getWeight()); + return null; + } + + /** + * Use {@link Builder} instead, this does nothing. + */ + @Override + public void deserializeNBT(NBTTagCompound nbt) {} + + static final class Builder & IPipeType, NodeDataType> { + private final NodeG node1; + private final NodeG node2; + private final double weight; + private final boolean buildable; + + private final TriConsumer, NodeG, Double> edgeProducer; + Builder(Map> longPosMap, NBTTagCompound tag, TriConsumer, NodeG, Double> edgeProducer) { + this.node1 = longPosMap.get(tag.getLong("SourceLongPos")); + this.node2 = longPosMap.get(tag.getLong("TargetLongPos")); + this.weight = tag.getDouble("Weight"); + this.edgeProducer = edgeProducer; + this.buildable = node1 != null && node2 != null; + } + + void addIfBuildable() { + if (buildable) { + edgeProducer.accept(node1, node2, weight); + } + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 4d6e1a06f56..6f225cdd3d2 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -5,7 +5,6 @@ import gregtech.api.pipenet.tile.TileEntityPipeBase; -import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -32,10 +31,14 @@ public class NodeG & IPipeType, No public int mark; public boolean isActive; - public IPipeTile heldMTE; + public TileEntityPipeBase heldMTE; + + /** + * CANNOT BE CHANGED DURING THE LIFETIME OF A NODE OR THE GRAPH WILL BREAK (or so I've been told) + */ private BlockPos nodePos; - public NodeG(NodeDataType data, int openConnections, int mark, boolean isActive, IPipeTile heldMTE) { + public NodeG(NodeDataType data, int openConnections, int mark, boolean isActive, TileEntityPipeBase heldMTE) { this.data = data; this.openConnections = openConnections; this.mark = mark; @@ -47,8 +50,9 @@ public NodeG(NodeDataType data, int openConnections, int mark, boolean isActive, /** * For construction during NBT reading only */ - public NodeG(NBTTagCompound tag) { + public NodeG(NBTTagCompound tag, WorldPipeNetG net) { deserializeNBT(tag); + this.data = net.readNodeData(tag.getCompoundTag("Data")); } /** @@ -62,10 +66,35 @@ public boolean isBlocked(EnumFacing facing) { return (openConnections & 1 << facing.getIndex()) == 0; } + void setBlocked(EnumFacing facing, boolean isBlocked) { + if (!isBlocked) { + this.openConnections |= 1 << facing.getIndex(); + } else { + this.openConnections &= ~(1 << facing.getIndex()); + } + } + public BlockPos getNodePos() { return nodePos; } + public long getLongPos() { + return nodePos.toLong(); + } + + void sync(NodeG node) { + this.data = node.data; + this.mark = node.mark; + this.isActive = node.isActive; + this.openConnections = node.openConnections; + // if heldMTE is not null, then it is more up to date than the graph's version. + if (this.heldMTE == null) { + this.heldMTE = node.heldMTE; + } else { + node.heldMTE = this.heldMTE; + } + } + @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 0c93ab4e459..84ee0dd6ee8 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -4,8 +4,13 @@ import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.pipenet.tile.TileEntityPipeBase; + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; @@ -20,34 +25,47 @@ import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; import org.jgrapht.GraphPath; +import org.jgrapht.ListenableGraph; +import org.jgrapht.alg.connectivity.ConnectivityInspector; import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; -import org.jgrapht.graph.DefaultWeightedEdge; +import org.jgrapht.graph.DefaultListenableGraph; import org.jgrapht.graph.SimpleWeightedGraph; -import org.jgrapht.util.ConcurrencyUtil; import java.lang.ref.WeakReference; -import java.util.HashMap; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; public abstract class WorldPipeNetG & IPipeType> extends WorldSavedData { + // create an executor for graph algorithm. Allows 2 threads per JVM processor, and keeps them alive for 5 seconds. // note - should this be shut down at some point during server shutdown? - public static ThreadPoolExecutor EXECUTOR = - ConcurrencyUtil.createThreadPoolExecutor(Runtime.getRuntime().availableProcessors() * 2); + public static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(0, Runtime.getRuntime().availableProcessors() * 2, 5, TimeUnit.SECONDS, new SynchronousQueue<>()); private WeakReference worldRef = new WeakReference<>(null); - private final Graph, DefaultWeightedEdge> pipeGraph; + private final Graph, NetEdge> backingGraph; + private final ListenableGraph, NetEdge> pipeGraph; + private final ConnectivityInspector, NetEdge> graphInspector; private final Map> pipeMap = new Object2ObjectOpenHashMap<>(); - private ShortestPathsAlgorithm, DefaultWeightedEdge> shortestPaths; + private ShortestPathsAlgorithm shortestPaths; // this is a monstrosity - private final Map, Map, GraphPath, DefaultWeightedEdge>>> shortestPathsCache = new Object2ObjectOpenHashMap<>(); - private boolean validPathsCache = true; + private final Map, List, NetEdge>>> shortestPathsCache = new Object2ObjectOpenHashMap<>(); + private boolean validPathsCache = false; public WorldPipeNetG(String name) { super(name); - this.pipeGraph = new SimpleWeightedGraph<>(DefaultWeightedEdge.class); + this.backingGraph = new SimpleWeightedGraph<>(NetEdge.class); + // multithreading? in this economy? + this.pipeGraph = new DefaultListenableGraph<>(this.backingGraph, true); + this.graphInspector = new ConnectivityInspector<>(this.pipeGraph); + this.pipeGraph.addGraphListener(this.graphInspector); } public World getWorld() { @@ -69,79 +87,72 @@ public static String getDataID(final String baseID, final World world) { } protected void onWorldSet(World world) { - for (NodeG node : pipeGraph.vertexSet()) { - // do initial edge additions & fully initialize nodes - IPipeTile pipe = castTE(world.getTileEntity(node.getNodePos())); - if (pipe != null) { - node.heldMTE = pipe; - node.data = pipe.getNodeData(); - addNodeSilent(node); - addEdges(node); - } - - } - rebuildShortestPaths(); + this.rebuildShortestPaths(); } /** - * Preferred override - * @param tile The {@link IPipeTile} that paths are being requested for - * @return the collection of paths associated with the {@link IPipeTile} + * Preferred override, reduces operational cost + * @param tile The {@link TileEntityPipeBase} that paths are being requested for + * @return the ordered list of paths associated with the {@link TileEntityPipeBase} */ - public Map, GraphPath, DefaultWeightedEdge>> getPaths(IPipeTile tile) { + public List, NetEdge>> getPaths(TileEntityPipeBase tile) { return getPaths(new NodeG<>(tile.getPipePos()), tile); } /** * Special-case override * @param pos The {@link BlockPos} that paths are being requested for - * @return the collection of paths associated with the {@link BlockPos} + * @return the ordered list of paths associated with the {@link BlockPos} */ - public Map, GraphPath, DefaultWeightedEdge>> getPaths(BlockPos pos) { + public List, NetEdge>> getPaths(BlockPos pos) { return getPaths(new NodeG<>(pos), null); } - public Map, GraphPath, DefaultWeightedEdge>> getPaths( - NodeG node, @Nullable IPipeTile tile) { - World world = this.worldRef.get(); - if (world == null) - throw new RuntimeException("The world of a PipeNet should be set before getting paths from it!"); + public List, NetEdge>> getPaths( + NodeG node, @Nullable TileEntityPipeBase tile) { + node.heldMTE = tile; if (!this.validPathsCache) { this.rebuildShortestPaths(); this.shortestPathsCache.clear(); } - if (!node.heldMTE.isValidTile()) { - if (tile != null) { - node.heldMTE = tile; - } else { - IPipeTile pipe = castTE(world.getTileEntity(node.getNodePos())); - if (pipe != null) - node.heldMTE = pipe; - } - } - - Map, GraphPath, DefaultWeightedEdge>> cache = + List, NetEdge>> cache = this.shortestPathsCache.get(node); - if (cache != null) return cache; + if (cache != null) return verifyList(cache, node); + + List, NetEdge>> list = this.shortestPaths.getPathsList(node); + this.shortestPathsCache.put(node, list); + return verifyList(list, node); + } - return this.shortestPaths.getPathsMap(node); + protected List, NetEdge>> verifyList(List, NetEdge>> list, NodeG source) { + if (!verifyNode(source)) return new ObjectArrayList<>(); + return list.stream().filter(a -> verifyNode(a.getEndVertex())).collect(Collectors.toList()); } - protected IPipeTile castTE(TileEntity te) { - if (te instanceof IPipeTile pipe) { + protected boolean verifyNode(NodeG node) { + if (!getWorld().loadedTileEntityList.contains(node.heldMTE)) { + TileEntityPipeBase pipe = castTE(getWorld().getTileEntity(node.getNodePos())); + if (pipe == null) return false; + node.heldMTE = pipe; + } + return true; + } + + protected TileEntityPipeBase castTE(TileEntity te) { + if (te instanceof TileEntityPipeBase pipe) { if (!getBasePipeClass().isAssignableFrom(pipe.getClass())) { return null; } - return (IPipeTile) pipe; + return (TileEntityPipeBase) pipe; } return null; } protected abstract Class> getBasePipeClass(); - public void addNode(BlockPos nodePos, NodeDataType nodeData, int mark, int openConnections, boolean isActive, IPipeTile heldMTE) { + public void addNode(BlockPos nodePos, NodeDataType nodeData, int mark, int openConnections, boolean isActive, TileEntityPipeBase heldMTE) { NodeG node = new NodeG<>(nodeData, openConnections, mark, isActive, heldMTE); if (!canAttachNode(nodeData)) return; @@ -181,6 +192,47 @@ protected boolean canAttachNode(NodeDataType nodeData) { return true; } + public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean isBlocked) { + NodeG node = pipeMap.get(nodePos); + if (node == null || node.isBlocked(side) == isBlocked) return; + + node.setBlocked(side, isBlocked); + NodeG nodeOffset = pipeMap.get(nodePos.offset(side)); + if (nodeOffset == null) return; + + if (!node.isBlocked(side) && !nodeOffset.isBlocked(side.getOpposite())) { + addEdge(node, nodeOffset); + } else { + removeEdge(node, nodeOffset); + } + } + + public void updateMark(BlockPos nodePos, int newMark) { + NodeG node = pipeMap.get(nodePos); + if (node == null) return; + + int oldMark = node.mark; + node.mark = newMark; + + for (EnumFacing side : EnumFacing.VALUES) { + NodeG nodeOffset = pipeMap.get(nodePos.offset(side)); + if (nodeOffset == null) continue; + if (!areNodeBlockedConnectionsCompatible(node, side, nodeOffset) || + !areNodesCustomContactable(node.data, nodeOffset.data)) continue; + if (areMarksCompatible(oldMark, nodeOffset.mark) == areMarksCompatible(newMark, nodeOffset.mark)) continue; + + if (areMarksCompatible(newMark, nodeOffset.mark)) { + addEdge(node, nodeOffset); + } else { + removeEdge(node, nodeOffset); + } + } + } + + public boolean hasNode(BlockPos pos) { + return pipeMap.containsKey(pos); + } + public void addNodeSilent(NodeG node) { pipeGraph.addVertex(node); this.pipeMap.put(node.getNodePos(), node); @@ -197,15 +249,19 @@ public void addEdge(NodeG node1, NodeG node1, NodeG node2, int weight) { - pipeGraph.addEdge(node1, node2); - pipeGraph.setEdgeWeight(node1, node2, weight); - this.validPathsCache = false; + public void addEdge(NodeG node1, NodeG node2, double weight) { + if (pipeGraph.addEdge(node1, node2) != null) { + pipeGraph.setEdgeWeight(node1, node2, weight); + this.validPathsCache = false; + this.markDirty(); + } } public void removeEdge(NodeG node1, NodeG node2) { - if (pipeGraph.removeEdge(node1, node2) != null) + if (pipeGraph.removeEdge(node1, node2) != null) { this.validPathsCache = false; + this.markDirty(); + } } public void removeNode(NodeG node) { @@ -216,16 +272,24 @@ public void removeNode(NodeG node) { } protected void rebuildShortestPaths() { - this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph, EXECUTOR); + this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph, EXECUTOR, graphInspector); this.validPathsCache = true; } @Override public void readFromNBT(NBTTagCompound nbt) { NBTTagList allPipeNodes = nbt.getTagList("PipeNodes", Constants.NBT.TAG_COMPOUND); + NBTTagList allNetEdges = nbt.getTagList("NetEdges", Constants.NBT.TAG_COMPOUND); + Map> longPosMap = new Long2ObjectOpenHashMap<>(); for (int i = 0; i < allPipeNodes.tagCount(); i++) { NBTTagCompound pNodeTag = allPipeNodes.getCompoundTagAt(i); - this.addNodeSilent(new NodeG<>(pNodeTag)); + NodeG node = new NodeG<>(pNodeTag, this); + longPosMap.put(node.getLongPos(), node); + this.addNodeSilent(node); + } + for (int i = 0; i < allNetEdges.tagCount(); i++) { + NBTTagCompound gEdgeTag = allNetEdges.getCompoundTagAt(i); + new NetEdge.Builder<>(longPosMap, gEdgeTag, this::addEdge).addIfBuildable(); } } @@ -235,28 +299,62 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { NBTTagList allPipeNodes = new NBTTagList(); for (NodeG node : pipeGraph.vertexSet()) { NBTTagCompound nodeTag = node.serializeNBT(); + NBTTagCompound dataTag = new NBTTagCompound(); + writeNodeData(node.data, dataTag); + nodeTag.setTag("Data", dataTag); allPipeNodes.appendTag(nodeTag); } compound.setTag("PipeNodes", allPipeNodes); + + NBTTagList allNetEdges = new NBTTagList(); + for (NetEdge edge : pipeGraph.edgeSet()) { + allNetEdges.appendTag(edge.serializeNBT()); + } + compound.setTag("NetEdges", allNetEdges); return compound; } + /** + * Serializes node data into specified tag compound + * Used for writing persistent node data + */ + protected abstract void writeNodeData(NodeDataType nodeData, NBTTagCompound tagCompound); + + /** + * Deserializes node data from specified tag compound + * Used for reading persistent node data + */ + protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); + // CHManyToManyShortestPaths is a very good algorithm because our graph will be extremely sparse. - protected static class ShortestPathsAlgorithm extends CHManyToManyShortestPaths { + protected static final class ShortestPathsAlgorithm & IPipeType, NDT> extends CHManyToManyShortestPaths, NetEdge> { - public ShortestPathsAlgorithm(Graph graph, ThreadPoolExecutor executor) { + private final ConnectivityInspector, NetEdge> inspector; + + public ShortestPathsAlgorithm(Graph, NetEdge> graph, ThreadPoolExecutor executor, ConnectivityInspector, NetEdge> inspector) { super(graph, executor); + this.inspector = inspector; } - public Map> getPathsMap(V source) { + public List, NetEdge>> getPathsList(NodeG source) { if (!graph.containsVertex(source)) { throw new IllegalArgumentException("graph must contain the source vertex"); } - - Map> paths = new HashMap<>(); - for (V v : graph.vertexSet()) { - paths.put(v, getPath(source, v)); + ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths(Collections.singleton(source), inspector.connectedSetOf(source)); + List, NetEdge>> paths = new ObjectArrayList<>(); + for (NodeG v : inspector.connectedSetOf(source)) { + // update mutably so that the returned paths are also updated + if (v.equals(source)) { + source.sync(v); + continue; + } + + GraphPath, NetEdge> path = manyToManyPaths.getPath(source, v); + if (path != null) { + paths.add(path); + } } + paths.sort(Comparator.comparingDouble(GraphPath::getWeight)); return paths; } } From c14719ebb38ee3432868f0eba5526d779cd2cc1c Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 15 Dec 2023 10:49:33 -0700 Subject: [PATCH 004/157] Add NetGroups to reduce algorithm overhead --- .../java/gregtech/api/pipenet/NetGroup.java | 152 ++++++++++++++++++ src/main/java/gregtech/api/pipenet/NodeG.java | 17 ++ .../gregtech/api/pipenet/WorldPipeNetG.java | 67 ++++---- 3 files changed, 203 insertions(+), 33 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/NetGroup.java diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java new file mode 100644 index 00000000000..474732921be --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -0,0 +1,152 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.block.IPipeType; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jgrapht.Graph; +import org.jgrapht.traverse.BreadthFirstIterator; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class NetGroup & IPipeType, NodeDataType> { + + private final Graph, NetEdge> graph; + + private final Set> nodes; + + public NetGroup(Graph, NetEdge> graph) { + this.graph = graph; + this.nodes = new ObjectOpenHashSet<>(); + } + + public NetGroup(Graph, NetEdge> graph, Set> nodes) { + this.graph = graph; + this.nodes = nodes; + this.nodes.forEach(b -> b.setGroup(this)); + } + + /** + * Removes all nodes from a group + */ + private void clear() { + this.nodes.clear(); + } + + public void addNode(NodeG node) { + this.nodes.add(node); + node.setGroup(this); + } + + protected void addNodes(Set> nodes) { + this.nodes.addAll(nodes); + this.nodes.forEach(b -> b.setGroup(this)); + } + + /** + * Merges the groups of an edge if necessary. + * @param source the source node of the edge + * @param target the target node of the edge + * @return True if both nodes belonged to no group, and no merge could be conducted. + */ + public static boolean mergeEdge(NodeG source, NodeG target) { + NetGroup sourceGroup = source.getGroup(); + NetGroup targetGroup = target.getGroup(); + if (sourceGroup == targetGroup) return sourceGroup == null; + if (sourceGroup != null) { + sourceGroup.mergeNode(target); + } else { + targetGroup.mergeNode(source); + } + return false; + } + + /** + * Adds a node to this group, merging its group if it has one. + * @param node the node to merge + */ + void mergeNode(NodeG node) { + NodeG cast = (NodeG) node; + if (cast.getGroup() != null) { + this.addNodes(cast.getGroup().getNodes()); + cast.getGroup().clear(); + } else addNode(cast); + } + + /** + * Split this group by removing a node. Automatically removes the node from the graph. + * @param source node to remove + * @return Whether the node existed in the graph + */ + public boolean splitNode(NodeG source) { + if (graph.containsVertex(source)) { + List> targets = graph.edgesOf(source).stream().map(NetEdge::getTarget) + .collect(Collectors.toList()); + graph.removeVertex(source); + while (!targets.isEmpty()) { + // get the lastmost target; if this throws a cast exception, something is very wrong with the graph. + NodeG target = + (NodeG) targets.remove(targets.size() - 1); + + Set> targetGroup = new ObjectOpenHashSet<>(); + BreadthFirstIterator, NetEdge> i = new BreadthFirstIterator<>(graph, + target); + NodeG temp; + while (i.hasNext()) { + temp = i.next(); + targetGroup.add(temp); + // if we find a target node in our search, remove it from the list + targets.remove(temp); + } + this.nodes.removeAll(targetGroup); + // if 1 or fewer nodes are in the new group, no need to create it. + if (targetGroup.size() > 1) { + // No need to do more than create it, the involved nodes are automatically updated in constructor + new NetGroup<>(this.graph, targetGroup); + } else { + targetGroup.forEach(NodeG::clearGroup); + } + } + return true; + } + return false; + } + + /** + * Split this group by removing an edge. Automatically removes the edge from the graph. + * @param source source of the edge + * @param target target of the edge + * @return Whether the edge existed in the graph + */ + public boolean splitEdge(NodeG source, NodeG target) { + if (graph.removeEdge(source, target) != null) { + Set> targetGroup = new ObjectOpenHashSet<>(); + BreadthFirstIterator, NetEdge> i = new BreadthFirstIterator<>(graph, target); + NodeG temp; + while (i.hasNext()) { + temp = i.next(); + // if there's a another complete path to the source node from the target node, there's no need to split + if (source == temp) return true; + targetGroup.add(temp); + } + this.nodes.removeAll(targetGroup); + // if 1 or fewer nodes are in the new group, no need to create it. + if (targetGroup.size() > 1) { + // No need to do more than create it, the involved nodes are automatically updated in constructor + new NetGroup<>(this.graph, targetGroup); + } else { + targetGroup.forEach(NodeG::clearGroup); + } + return true; + } + return false; + } + + /** + * For memory considerations, returns the uncloned set. Do not modify this directly. + */ + Set> getNodes() { + return nodes; + } +} diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 6f225cdd3d2..f8ff57f89e5 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -10,6 +10,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraftforge.common.util.INBTSerializable; +import org.jetbrains.annotations.Nullable; + import java.util.Objects; public class NodeG & IPipeType, NodeDataType> implements INBTSerializable { @@ -38,6 +40,8 @@ public class NodeG & IPipeType, No */ private BlockPos nodePos; + private NetGroup group = null; + public NodeG(NodeDataType data, int openConnections, int mark, boolean isActive, TileEntityPipeBase heldMTE) { this.data = data; this.openConnections = openConnections; @@ -62,6 +66,19 @@ public NodeG(NBTTagCompound tag, WorldPipeNetG net) { this.nodePos = pos; } + @Nullable + NetGroup getGroup() { + return group; + } + + void setGroup(NetGroup group) { + this.group = group; + } + + void clearGroup() { + this.group = null; + } + public boolean isBlocked(EnumFacing facing) { return (openConnections & 1 << facing.getIndex()) == 0; } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 84ee0dd6ee8..021fe029e34 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -6,6 +6,7 @@ import gregtech.api.pipenet.tile.TileEntityPipeBase; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -30,6 +31,7 @@ import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; import org.jgrapht.graph.DefaultListenableGraph; import org.jgrapht.graph.SimpleWeightedGraph; +import org.jgrapht.traverse.BreadthFirstIterator; import java.lang.ref.WeakReference; import java.util.Collections; @@ -49,9 +51,7 @@ public abstract class WorldPipeNetG()); private WeakReference worldRef = new WeakReference<>(null); - private final Graph, NetEdge> backingGraph; - private final ListenableGraph, NetEdge> pipeGraph; - private final ConnectivityInspector, NetEdge> graphInspector; + private final Graph, NetEdge> pipeGraph; private final Map> pipeMap = new Object2ObjectOpenHashMap<>(); private ShortestPathsAlgorithm shortestPaths; @@ -61,11 +61,7 @@ public abstract class WorldPipeNetG(NetEdge.class); - // multithreading? in this economy? - this.pipeGraph = new DefaultListenableGraph<>(this.backingGraph, true); - this.graphInspector = new ConnectivityInspector<>(this.pipeGraph); - this.pipeGraph.addGraphListener(this.graphInspector); + this.pipeGraph = new SimpleWeightedGraph<>(NetEdge.class); } public World getWorld() { @@ -75,7 +71,7 @@ public World getWorld() { protected void setWorldAndInit(World world) { if (world != this.worldRef.get()) { this.worldRef = new WeakReference<>(world); - onWorldSet(world); + onWorldSet(); } } @@ -86,7 +82,7 @@ public static String getDataID(final String baseID, final World world) { return dimension == 0 ? baseID : baseID + '.' + dimension; } - protected void onWorldSet(World world) { + protected void onWorldSet() { this.rebuildShortestPaths(); } @@ -171,20 +167,20 @@ private void addEdges(NodeG node) { } } - protected final boolean canNodesConnect(NodeG node1, EnumFacing nodeFacing, NodeG node2) { - return areNodeBlockedConnectionsCompatible(node1, nodeFacing, node2) && - areMarksCompatible(node1.mark, node2.mark) && areNodesCustomContactable(node1.data, node2.data); + protected final boolean canNodesConnect(NodeG source, EnumFacing nodeFacing, NodeG target) { + return areNodeBlockedConnectionsCompatible(source, nodeFacing, target) && + areMarksCompatible(source.mark, target.mark) && areNodesCustomContactable(source.data, target.data); } private static boolean areMarksCompatible(int mark1, int mark2) { return mark1 == mark2 || mark1 == Node.DEFAULT_MARK || mark2 == Node.DEFAULT_MARK; } - private boolean areNodeBlockedConnectionsCompatible(NodeG node1, EnumFacing nodeFacing, NodeG node2) { - return !node1.isBlocked(nodeFacing) && !node2.isBlocked(nodeFacing.getOpposite()); + private boolean areNodeBlockedConnectionsCompatible(NodeG source, EnumFacing nodeFacing, NodeG target) { + return !source.isBlocked(nodeFacing) && !target.isBlocked(nodeFacing.getOpposite()); } - protected boolean areNodesCustomContactable(NodeDataType node1, NodeDataType node2) { + protected boolean areNodesCustomContactable(NodeDataType source, NodeDataType target) { return true; } @@ -236,7 +232,7 @@ public boolean hasNode(BlockPos pos) { public void addNodeSilent(NodeG node) { pipeGraph.addVertex(node); this.pipeMap.put(node.getNodePos(), node); - this.validPathsCache = false; + // we do not need to invalidate the cache, because just adding a node means it's not connected to anything. } public void addNode(NodeG node) { @@ -244,35 +240,41 @@ public void addNode(NodeG node) { this.markDirty(); } - public void addEdge(NodeG node1, NodeG node2) { - addEdge(node1, node2, 1); + public void addEdge(NodeG source, NodeG target) { + addEdge(source, target, 1); this.validPathsCache = false; } - public void addEdge(NodeG node1, NodeG node2, double weight) { - if (pipeGraph.addEdge(node1, node2) != null) { - pipeGraph.setEdgeWeight(node1, node2, weight); + public void addEdge(NodeG source, NodeG target, double weight) { + if (pipeGraph.addEdge(source, target) != null) { + if (NetGroup.mergeEdge(source, target)) { + new NetGroup<>(this.pipeGraph).addNodes(Set.of(source, target)); + } + pipeGraph.setEdgeWeight(source, target, weight); this.validPathsCache = false; this.markDirty(); } } - public void removeEdge(NodeG node1, NodeG node2) { - if (pipeGraph.removeEdge(node1, node2) != null) { + public void removeEdge(NodeG source, NodeG target) { + if (source.getGroup() != null && source.getGroup().splitEdge(source, target)) { this.validPathsCache = false; this.markDirty(); } } public void removeNode(NodeG node) { - if (pipeGraph.removeVertex(node)) { + if (node.getGroup() != null && node.getGroup().splitNode(node)) { + // if the node has no group, then it isn't connected to anything, and thus the cache is still valid this.validPathsCache = false; - this.markDirty(); + } else { + this.pipeGraph.removeVertex(node); } + this.markDirty(); } protected void rebuildShortestPaths() { - this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph, EXECUTOR, graphInspector); + this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph, EXECUTOR); this.validPathsCache = true; } @@ -329,20 +331,19 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { // CHManyToManyShortestPaths is a very good algorithm because our graph will be extremely sparse. protected static final class ShortestPathsAlgorithm & IPipeType, NDT> extends CHManyToManyShortestPaths, NetEdge> { - private final ConnectivityInspector, NetEdge> inspector; - - public ShortestPathsAlgorithm(Graph, NetEdge> graph, ThreadPoolExecutor executor, ConnectivityInspector, NetEdge> inspector) { + public ShortestPathsAlgorithm(Graph, NetEdge> graph, ThreadPoolExecutor executor) { super(graph, executor); - this.inspector = inspector; } public List, NetEdge>> getPathsList(NodeG source) { if (!graph.containsVertex(source)) { throw new IllegalArgumentException("graph must contain the source vertex"); } - ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths(Collections.singleton(source), inspector.connectedSetOf(source)); List, NetEdge>> paths = new ObjectArrayList<>(); - for (NodeG v : inspector.connectedSetOf(source)) { + // if the source has no group, it has no paths. + if (source.getGroup() == null) return paths; + ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths(Collections.singleton(source), source.getGroup().getNodes()); + for (NodeG v : source.getGroup().getNodes()) { // update mutably so that the returned paths are also updated if (v.equals(source)) { source.sync(v); From 4310e10b8e8ab7dad28b03dc316050f078a8a9ba Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 15 Dec 2023 11:23:11 -0700 Subject: [PATCH 005/157] INodeData to allow for calculating edge weights --- src/main/java/gregtech/api/pipenet/INodeData.java | 8 ++++++++ src/main/java/gregtech/api/pipenet/NetEdge.java | 2 +- src/main/java/gregtech/api/pipenet/NetGroup.java | 2 +- src/main/java/gregtech/api/pipenet/NodeG.java | 2 +- src/main/java/gregtech/api/pipenet/WorldPipeNetG.java | 8 ++++---- 5 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/INodeData.java diff --git a/src/main/java/gregtech/api/pipenet/INodeData.java b/src/main/java/gregtech/api/pipenet/INodeData.java new file mode 100644 index 00000000000..6217bae28c7 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/INodeData.java @@ -0,0 +1,8 @@ +package gregtech.api.pipenet; + +public interface INodeData { + + default double getWeightFactor() { + return 0.5; + } +} diff --git a/src/main/java/gregtech/api/pipenet/NetEdge.java b/src/main/java/gregtech/api/pipenet/NetEdge.java index 254accda423..75ce268ed19 100644 --- a/src/main/java/gregtech/api/pipenet/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/NetEdge.java @@ -37,7 +37,7 @@ public NBTTagCompound serializeNBT() { @Override public void deserializeNBT(NBTTagCompound nbt) {} - static final class Builder & IPipeType, NodeDataType> { + static final class Builder & IPipeType, NodeDataType extends INodeData> { private final NodeG node1; private final NodeG node2; private final double weight; diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 474732921be..ea4e6911a87 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -10,7 +10,7 @@ import java.util.Set; import java.util.stream.Collectors; -public class NetGroup & IPipeType, NodeDataType> { +public class NetGroup & IPipeType, NodeDataType extends INodeData> { private final Graph, NetEdge> graph; diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index f8ff57f89e5..200cfdd99de 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -14,7 +14,7 @@ import java.util.Objects; -public class NodeG & IPipeType, NodeDataType> implements INBTSerializable { +public class NodeG & IPipeType, NodeDataType extends INodeData> implements INBTSerializable { public static final int DEFAULT_MARK = 0; diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 021fe029e34..e021f32e687 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -44,10 +44,10 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -public abstract class WorldPipeNetG & IPipeType> extends WorldSavedData { +public abstract class WorldPipeNetG & IPipeType> extends WorldSavedData { // create an executor for graph algorithm. Allows 2 threads per JVM processor, and keeps them alive for 5 seconds. - // note - should this be shut down at some point during server shutdown? + // note - should this be explicitly shut down at some point during server shutdown? public static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(0, Runtime.getRuntime().availableProcessors() * 2, 5, TimeUnit.SECONDS, new SynchronousQueue<>()); private WeakReference worldRef = new WeakReference<>(null); @@ -241,7 +241,7 @@ public void addNode(NodeG node) { } public void addEdge(NodeG source, NodeG target) { - addEdge(source, target, 1); + addEdge(source, target, source.data.getWeightFactor() + target.data.getWeightFactor()); this.validPathsCache = false; } @@ -329,7 +329,7 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); // CHManyToManyShortestPaths is a very good algorithm because our graph will be extremely sparse. - protected static final class ShortestPathsAlgorithm & IPipeType, NDT> extends CHManyToManyShortestPaths, NetEdge> { + protected static final class ShortestPathsAlgorithm & IPipeType, NDT extends INodeData> extends CHManyToManyShortestPaths, NetEdge> { public ShortestPathsAlgorithm(Graph, NetEdge> graph, ThreadPoolExecutor executor) { super(graph, executor); From 65ccf2425cfbd595b927f2be5b003ddc428abdb3 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 15 Dec 2023 16:21:47 -0700 Subject: [PATCH 006/157] Downgrade JGraphT to 1.4 for Java 8 compatibility, and a minor fix --- dependencies.gradle | 2 +- src/main/java/gregtech/api/pipenet/NetGroup.java | 11 +++++++++-- .../java/gregtech/api/pipenet/WorldPipeNetG.java | 12 ++++-------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 2089f28dcd1..0423f956b8d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -28,7 +28,7 @@ dependencies { implementation("com.cleanroommc:modularui:2.4.1") { transitive = false } // Shadowed Dependencies - shadowCompile 'org.jgrapht:jgrapht-core:1.5.1' + shadowCompile 'org.jgrapht:jgrapht-core:1.4.0' // Soft Dependencies // Can change any of these from compileOnlyApi -> implementation to test them in-game. diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index ea4e6911a87..ad036260788 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -39,9 +39,16 @@ public void addNode(NodeG node) { node.setGroup(this); } - protected void addNodes(Set> nodes) { + public void addNodes(Set> nodes) { this.nodes.addAll(nodes); - this.nodes.forEach(b -> b.setGroup(this)); + nodes.forEach(a -> a.setGroup(this)); + } + + @SafeVarargs + public final void addNodes(NodeG... nodes) { + for (NodeG node : nodes) { + this.addNode(node); + } } /** diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index e021f32e687..652ba334c75 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -46,10 +46,6 @@ public abstract class WorldPipeNetG & IPipeType> extends WorldSavedData { - // create an executor for graph algorithm. Allows 2 threads per JVM processor, and keeps them alive for 5 seconds. - // note - should this be explicitly shut down at some point during server shutdown? - public static ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(0, Runtime.getRuntime().availableProcessors() * 2, 5, TimeUnit.SECONDS, new SynchronousQueue<>()); - private WeakReference worldRef = new WeakReference<>(null); private final Graph, NetEdge> pipeGraph; private final Map> pipeMap = new Object2ObjectOpenHashMap<>(); @@ -248,7 +244,7 @@ public void addEdge(NodeG source, NodeG source, NodeG target, double weight) { if (pipeGraph.addEdge(source, target) != null) { if (NetGroup.mergeEdge(source, target)) { - new NetGroup<>(this.pipeGraph).addNodes(Set.of(source, target)); + new NetGroup<>(this.pipeGraph).addNodes(source, target); } pipeGraph.setEdgeWeight(source, target, weight); this.validPathsCache = false; @@ -274,7 +270,7 @@ public void removeNode(NodeG node) { } protected void rebuildShortestPaths() { - this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph, EXECUTOR); + this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph); this.validPathsCache = true; } @@ -331,8 +327,8 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { // CHManyToManyShortestPaths is a very good algorithm because our graph will be extremely sparse. protected static final class ShortestPathsAlgorithm & IPipeType, NDT extends INodeData> extends CHManyToManyShortestPaths, NetEdge> { - public ShortestPathsAlgorithm(Graph, NetEdge> graph, ThreadPoolExecutor executor) { - super(graph, executor); + public ShortestPathsAlgorithm(Graph, NetEdge> graph) { + super(graph); } public List, NetEdge>> getPathsList(NodeG source) { From 3318506c3869c21e7cdc3674d80afff09de300f5 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 16 Dec 2023 20:29:20 -0700 Subject: [PATCH 007/157] Improve path caching & fetching --- .../java/gregtech/api/pipenet/NetGroup.java | 27 +++++----- src/main/java/gregtech/api/pipenet/NodeG.java | 23 +++++++++ .../gregtech/api/pipenet/WorldPipeNetG.java | 49 ++++++++----------- 3 files changed, 59 insertions(+), 40 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index ad036260788..4bea2dd4836 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -2,11 +2,14 @@ import gregtech.api.pipenet.block.IPipeType; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jgrapht.Graph; +import org.jgrapht.GraphPath; import org.jgrapht.traverse.BreadthFirstIterator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -27,25 +30,22 @@ public NetGroup(Graph, NetEdge> graph, Set b.setGroup(this)); } - /** - * Removes all nodes from a group - */ private void clear() { this.nodes.clear(); } - public void addNode(NodeG node) { + protected void addNode(NodeG node) { this.nodes.add(node); node.setGroup(this); } - public void addNodes(Set> nodes) { + protected void addNodes(Set> nodes) { this.nodes.addAll(nodes); nodes.forEach(a -> a.setGroup(this)); } @SafeVarargs - public final void addNodes(NodeG... nodes) { + protected final void addNodes(NodeG... nodes) { for (NodeG node : nodes) { this.addNode(node); } @@ -63,17 +63,15 @@ public static boolean mergeEdge(NodeG source, NodeG target) { if (sourceGroup == targetGroup) return sourceGroup == null; if (sourceGroup != null) { sourceGroup.mergeNode(target); + sourceGroup.clearPathCaches(); } else { targetGroup.mergeNode(source); + targetGroup.clearPathCaches(); } return false; } - /** - * Adds a node to this group, merging its group if it has one. - * @param node the node to merge - */ - void mergeNode(NodeG node) { + protected void mergeNode(NodeG node) { NodeG cast = (NodeG) node; if (cast.getGroup() != null) { this.addNodes(cast.getGroup().getNodes()); @@ -88,6 +86,7 @@ void mergeNode(NodeG node) { */ public boolean splitNode(NodeG source) { if (graph.containsVertex(source)) { + this.clearPathCaches(); List> targets = graph.edgesOf(source).stream().map(NetEdge::getTarget) .collect(Collectors.toList()); graph.removeVertex(source); @@ -128,7 +127,9 @@ public boolean splitNode(NodeG source) { */ public boolean splitEdge(NodeG source, NodeG target) { if (graph.removeEdge(source, target) != null) { + this.clearPathCaches(); Set> targetGroup = new ObjectOpenHashSet<>(); + this.graph.removeEdge(source, target); BreadthFirstIterator, NetEdge> i = new BreadthFirstIterator<>(graph, target); NodeG temp; while (i.hasNext()) { @@ -156,4 +157,8 @@ public boolean splitEdge(NodeG source, NodeG> getNodes() { return nodes; } + + protected void clearPathCaches() { + this.nodes.forEach(NodeG::clearPathCache); + } } diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 200cfdd99de..b4e69b7b160 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -11,7 +11,9 @@ import net.minecraftforge.common.util.INBTSerializable; import org.jetbrains.annotations.Nullable; +import org.jgrapht.GraphPath; +import java.util.List; import java.util.Objects; public class NodeG & IPipeType, NodeDataType extends INodeData> implements INBTSerializable { @@ -42,6 +44,8 @@ public class NodeG & IPipeType, No private NetGroup group = null; + private List, NetEdge>> pathCache = null; + public NodeG(NodeDataType data, int openConnections, int mark, boolean isActive, TileEntityPipeBase heldMTE) { this.data = data; this.openConnections = openConnections; @@ -112,6 +116,25 @@ void sync(NodeG node) { } } + @Nullable + public List, NetEdge>> getPathCache() { + return pathCache; + } + + /** + * Sets the path cache to the provided cache. Returns the provided cache for convenience. + * @param pathCache The new cache. + * @return The new cache. + */ + public List, NetEdge>> setPathCache(List, NetEdge>> pathCache) { + this.pathCache = pathCache; + return pathCache; + } + + public void clearPathCache() { + this.pathCache = null; + } + @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 652ba334c75..e2e83f44fdf 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -6,7 +6,6 @@ import gregtech.api.pipenet.tile.TileEntityPipeBase; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -26,22 +25,14 @@ import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; import org.jgrapht.GraphPath; -import org.jgrapht.ListenableGraph; -import org.jgrapht.alg.connectivity.ConnectivityInspector; import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; -import org.jgrapht.graph.DefaultListenableGraph; import org.jgrapht.graph.SimpleWeightedGraph; -import org.jgrapht.traverse.BreadthFirstIterator; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; public abstract class WorldPipeNetG & IPipeType> extends WorldSavedData { @@ -52,8 +43,7 @@ public abstract class WorldPipeNetG shortestPaths; // this is a monstrosity - private final Map, List, NetEdge>>> shortestPathsCache = new Object2ObjectOpenHashMap<>(); - private boolean validPathsCache = false; + private boolean validAlgorithmInstance = false; public WorldPipeNetG(String name) { super(name); @@ -83,41 +73,42 @@ protected void onWorldSet() { } /** - * Preferred override, reduces operational cost + * Preferred override. Only collects a fresh TE from the server if the provided TE is not loaded. * @param tile The {@link TileEntityPipeBase} that paths are being requested for * @return the ordered list of paths associated with the {@link TileEntityPipeBase} */ public List, NetEdge>> getPaths(TileEntityPipeBase tile) { - return getPaths(new NodeG<>(tile.getPipePos()), tile); + return getPaths(this.pipeMap.get(tile.getPipePos()), tile); } /** - * Special-case override + * Special-case override. Forces the collection of a fresh TE from the server. * @param pos The {@link BlockPos} that paths are being requested for * @return the ordered list of paths associated with the {@link BlockPos} */ public List, NetEdge>> getPaths(BlockPos pos) { - return getPaths(new NodeG<>(pos), null); + return getPaths(this.pipeMap.get(pos), null); } public List, NetEdge>> getPaths( - NodeG node, @Nullable TileEntityPipeBase tile) { + @Nullable NodeG node, @Nullable TileEntityPipeBase tile) { + if (node == null) return new ObjectArrayList<>(); + node.heldMTE = tile; - if (!this.validPathsCache) { - this.rebuildShortestPaths(); - this.shortestPathsCache.clear(); - } + if (!this.validAlgorithmInstance) this.rebuildShortestPaths(); List, NetEdge>> cache = - this.shortestPathsCache.get(node); - if (cache != null) return verifyList(cache, node); + node.getPathCache(); + if (cache != null) { + return node.setPathCache(verifyList(cache, node)); + } List, NetEdge>> list = this.shortestPaths.getPathsList(node); - this.shortestPathsCache.put(node, list); - return verifyList(list, node); + return node.setPathCache(verifyList(list, node)); } + // Verification removes paths ending in unloaded TEs, or removes all paths if the source TE is unloaded. protected List, NetEdge>> verifyList(List, NetEdge>> list, NodeG source) { if (!verifyNode(source)) return new ObjectArrayList<>(); return list.stream().filter(a -> verifyNode(a.getEndVertex())).collect(Collectors.toList()); @@ -238,7 +229,7 @@ public void addNode(NodeG node) { public void addEdge(NodeG source, NodeG target) { addEdge(source, target, source.data.getWeightFactor() + target.data.getWeightFactor()); - this.validPathsCache = false; + this.validAlgorithmInstance = false; } public void addEdge(NodeG source, NodeG target, double weight) { @@ -247,14 +238,14 @@ public void addEdge(NodeG source, NodeG(this.pipeGraph).addNodes(source, target); } pipeGraph.setEdgeWeight(source, target, weight); - this.validPathsCache = false; + this.validAlgorithmInstance = false; this.markDirty(); } } public void removeEdge(NodeG source, NodeG target) { if (source.getGroup() != null && source.getGroup().splitEdge(source, target)) { - this.validPathsCache = false; + this.validAlgorithmInstance = false; this.markDirty(); } } @@ -262,7 +253,7 @@ public void removeEdge(NodeG source, NodeG node) { if (node.getGroup() != null && node.getGroup().splitNode(node)) { // if the node has no group, then it isn't connected to anything, and thus the cache is still valid - this.validPathsCache = false; + this.validAlgorithmInstance = false; } else { this.pipeGraph.removeVertex(node); } @@ -271,7 +262,7 @@ public void removeNode(NodeG node) { protected void rebuildShortestPaths() { this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph); - this.validPathsCache = true; + this.validAlgorithmInstance = true; } @Override From de9f555a369a02b58c4726936c50e88149700fd8 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 16 Dec 2023 22:18:23 -0700 Subject: [PATCH 008/157] Added INodeData math --- src/main/java/gregtech/api/pipenet/INodeData.java | 2 +- .../material/properties/FluidPipeProperties.java | 10 +++++++++- .../material/properties/ItemPipeProperties.java | 10 +++++++++- .../material/properties/WireProperties.java | 9 ++++++++- .../common/pipelike/laser/LaserPipeProperties.java | 4 +++- .../common/pipelike/optical/OpticalPipeProperties.java | 4 +++- 6 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/INodeData.java b/src/main/java/gregtech/api/pipenet/INodeData.java index 6217bae28c7..9e4639ff833 100644 --- a/src/main/java/gregtech/api/pipenet/INodeData.java +++ b/src/main/java/gregtech/api/pipenet/INodeData.java @@ -3,6 +3,6 @@ public interface INodeData { default double getWeightFactor() { - return 0.5; + return 1; } } diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 5bd1ce7e1ec..b3e7b37d825 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -5,6 +5,8 @@ import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.fluids.attribute.FluidAttributes; +import gregtech.api.pipenet.INodeData; + import it.unimi.dsi.fastutil.objects.Object2BooleanMap; import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; import org.jetbrains.annotations.NotNull; @@ -13,7 +15,7 @@ import java.util.Collection; import java.util.Objects; -public class FluidPipeProperties implements IMaterialProperty, IPropertyFluidFilter { +public class FluidPipeProperties implements IMaterialProperty, IPropertyFluidFilter, INodeData { private final Object2BooleanMap containmentPredicate = new Object2BooleanOpenHashMap<>(); @@ -138,6 +140,12 @@ public void setPlasmaProof(boolean plasmaProof) { this.plasmaProof = plasmaProof; } + @Override + public double getWeightFactor() { + // behold 170, the magic number + return Math.pow(2, (int) (Double.MAX_EXPONENT / (Math.log(this.getThroughput()) * 170))); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java index 8314d4a7c07..f558b0e76d9 100644 --- a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java @@ -1,8 +1,10 @@ package gregtech.api.unification.material.properties; +import gregtech.api.pipenet.INodeData; + import java.util.Objects; -public class ItemPipeProperties implements IMaterialProperty { +public class ItemPipeProperties implements IMaterialProperty, INodeData { /** * Items will try to take the path with the lowest priority @@ -73,6 +75,12 @@ public void verifyProperty(MaterialProperties properties) { } } + @Override + public double getWeightFactor() { + // behold 200, the magic number + return Math.pow(2, (int) (Double.MAX_EXPONENT / (Math.log(this.getTransferRate() * 64) * 200))); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java index 7335be2e0c7..68f56e94546 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java @@ -1,13 +1,14 @@ package gregtech.api.unification.material.properties; import gregtech.api.GTValues; +import gregtech.api.pipenet.INodeData; import gregtech.api.unification.material.Material; import java.util.Objects; import static gregtech.api.unification.material.info.MaterialFlags.GENERATE_FOIL; -public class WireProperties implements IMaterialProperty { +public class WireProperties implements IMaterialProperty, INodeData { private int voltage; private int amperage; @@ -142,6 +143,12 @@ public void verifyProperty(MaterialProperties properties) { } } + @Override + public double getWeightFactor() { + // aren't weighted graphs great? + return 1d / this.getLossPerBlock(); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java b/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java index e2872f43b85..1cdd995c64b 100644 --- a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java +++ b/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java @@ -1,6 +1,8 @@ package gregtech.common.pipelike.laser; -public class LaserPipeProperties { +import gregtech.api.pipenet.INodeData; + +public class LaserPipeProperties implements INodeData { public static final LaserPipeProperties INSTANCE = new LaserPipeProperties(); } diff --git a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java index f4a47a3a0d7..9c9601b83a0 100644 --- a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java +++ b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java @@ -1,6 +1,8 @@ package gregtech.common.pipelike.optical; -public class OpticalPipeProperties { +import gregtech.api.pipenet.INodeData; + +public class OpticalPipeProperties implements INodeData { public static final OpticalPipeProperties INSTANCE = new OpticalPipeProperties(); } From 72a3955173484b9935801cbaeb71cee8c7154887 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 16 Dec 2023 22:25:27 -0700 Subject: [PATCH 009/157] Inefficient syntax begone --- .../gregtech/api/pipenet/block/BlockPipe.java | 32 +++++-------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java index 5468aae38dd..dccba8d7289 100644 --- a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java @@ -81,30 +81,14 @@ public static Cuboid6 getSideBox(EnumFacing side, float thickness) { if (side == null) return new Cuboid6(min, min, min, max, max, max); - Cuboid6 cuboid; - switch (side) { - case WEST: - cuboid = new Cuboid6(faceMin, min, min, min, max, max); - break; - case EAST: - cuboid = new Cuboid6(max, min, min, faceMax, max, max); - break; - case NORTH: - cuboid = new Cuboid6(min, min, faceMin, max, max, min); - break; - case SOUTH: - cuboid = new Cuboid6(min, min, max, max, max, faceMax); - break; - case UP: - cuboid = new Cuboid6(min, max, min, max, faceMax, max); - break; - case DOWN: - cuboid = new Cuboid6(min, faceMin, min, max, min, max); - break; - default: - cuboid = new Cuboid6(min, min, min, max, max, max); - } - return cuboid; + return switch (side) { + case WEST -> new Cuboid6(faceMin, min, min, min, max, max); + case EAST -> new Cuboid6(max, min, min, faceMax, max, max); + case NORTH -> new Cuboid6(min, min, faceMin, max, max, min); + case SOUTH -> new Cuboid6(min, min, max, max, max, faceMax); + case UP -> new Cuboid6(min, max, min, max, faceMax, max); + case DOWN -> new Cuboid6(min, faceMin, min, max, min, max); + }; } /** From e54c467c53e6c5e3abfc8ecee8aef74f8bae0aba Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 16 Dec 2023 23:02:10 -0700 Subject: [PATCH 010/157] Running around putting out fires & applying spotless --- .../java/gregtech/api/pipenet/NetEdge.java | 32 ++++---- .../java/gregtech/api/pipenet/NetGroup.java | 20 +++-- src/main/java/gregtech/api/pipenet/NodeG.java | 11 +-- .../gregtech/api/pipenet/WorldPipeNetG.java | 75 ++++++++++++------- .../gregtech/api/pipenet/block/BlockPipe.java | 24 ++---- .../gregtech/api/pipenet/block/IPipeType.java | 4 +- .../api/pipenet/block/ItemBlockPipe.java | 4 +- .../block/material/BlockMaterialPipe.java | 9 ++- .../block/material/IMaterialPipeTile.java | 4 +- .../block/material/IMaterialPipeType.java | 3 +- .../block/material/ItemBlockMaterialPipe.java | 4 +- .../material/TileEntityMaterialPipeBase.java | 3 +- .../pipenet/block/simple/BlockSimplePipe.java | 9 ++- .../gregtech/api/pipenet/tile/IPipeTile.java | 3 +- .../api/pipenet/tile/TileEntityPipeBase.java | 26 +++---- .../properties/FluidPipeProperties.java | 1 - 16 files changed, 136 insertions(+), 96 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/NetEdge.java b/src/main/java/gregtech/api/pipenet/NetEdge.java index 75ce268ed19..9c931e5ec7c 100644 --- a/src/main/java/gregtech/api/pipenet/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/NetEdge.java @@ -37,25 +37,29 @@ public NBTTagCompound serializeNBT() { @Override public void deserializeNBT(NBTTagCompound nbt) {} - static final class Builder & IPipeType, NodeDataType extends INodeData> { + static final class Builder & IPipeType, + NodeDataType extends INodeData> { + private final NodeG node1; private final NodeG node2; private final double weight; private final boolean buildable; private final TriConsumer, NodeG, Double> edgeProducer; - Builder(Map> longPosMap, NBTTagCompound tag, TriConsumer, NodeG, Double> edgeProducer) { - this.node1 = longPosMap.get(tag.getLong("SourceLongPos")); - this.node2 = longPosMap.get(tag.getLong("TargetLongPos")); - this.weight = tag.getDouble("Weight"); - this.edgeProducer = edgeProducer; - this.buildable = node1 != null && node2 != null; - } - - void addIfBuildable() { - if (buildable) { - edgeProducer.accept(node1, node2, weight); - } - } + + Builder(Map> longPosMap, NBTTagCompound tag, + TriConsumer, NodeG, Double> edgeProducer) { + this.node1 = longPosMap.get(tag.getLong("SourceLongPos")); + this.node2 = longPosMap.get(tag.getLong("TargetLongPos")); + this.weight = tag.getDouble("Weight"); + this.edgeProducer = edgeProducer; + this.buildable = node1 != null && node2 != null; + } + + void addIfBuildable() { + if (buildable) { + edgeProducer.accept(node1, node2, weight); + } + } } } diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 4bea2dd4836..7ec71fa0c9f 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -2,14 +2,11 @@ import gregtech.api.pipenet.block.IPipeType; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jgrapht.Graph; -import org.jgrapht.GraphPath; import org.jgrapht.traverse.BreadthFirstIterator; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -19,6 +16,8 @@ public class NetGroup & IPipeType, private final Set> nodes; + private long lastUpdate; + public NetGroup(Graph, NetEdge> graph) { this.graph = graph; this.nodes = new ObjectOpenHashSet<>(); @@ -30,6 +29,14 @@ public NetGroup(Graph, NetEdge> graph, Set b.setGroup(this)); } + protected void onNodeConnectionsUpdate() { + this.lastUpdate = System.currentTimeMillis(); + } + + public long getLastUpdate() { + return lastUpdate; + } + private void clear() { this.nodes.clear(); } @@ -53,6 +60,7 @@ protected final void addNodes(NodeG... nodes) { /** * Merges the groups of an edge if necessary. + * * @param source the source node of the edge * @param target the target node of the edge * @return True if both nodes belonged to no group, and no merge could be conducted. @@ -81,6 +89,7 @@ protected void mergeNode(NodeG node) { /** * Split this group by removing a node. Automatically removes the node from the graph. + * * @param source node to remove * @return Whether the node existed in the graph */ @@ -92,8 +101,8 @@ public boolean splitNode(NodeG source) { graph.removeVertex(source); while (!targets.isEmpty()) { // get the lastmost target; if this throws a cast exception, something is very wrong with the graph. - NodeG target = - (NodeG) targets.remove(targets.size() - 1); + NodeG target = (NodeG) targets + .remove(targets.size() - 1); Set> targetGroup = new ObjectOpenHashSet<>(); BreadthFirstIterator, NetEdge> i = new BreadthFirstIterator<>(graph, @@ -121,6 +130,7 @@ public boolean splitNode(NodeG source) { /** * Split this group by removing an edge. Automatically removes the edge from the graph. + * * @param source source of the edge * @param target target of the edge * @return Whether the edge existed in the graph diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index b4e69b7b160..3a4dddc695f 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -3,8 +3,6 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -16,7 +14,8 @@ import java.util.List; import java.util.Objects; -public class NodeG & IPipeType, NodeDataType extends INodeData> implements INBTSerializable { +public class NodeG & IPipeType, NodeDataType extends INodeData> + implements INBTSerializable { public static final int DEFAULT_MARK = 0; @@ -35,7 +34,7 @@ public class NodeG & IPipeType, No public int mark; public boolean isActive; - public TileEntityPipeBase heldMTE; + public IPipeTile heldMTE; /** * CANNOT BE CHANGED DURING THE LIFETIME OF A NODE OR THE GRAPH WILL BREAK (or so I've been told) @@ -46,7 +45,8 @@ public class NodeG & IPipeType, No private List, NetEdge>> pathCache = null; - public NodeG(NodeDataType data, int openConnections, int mark, boolean isActive, TileEntityPipeBase heldMTE) { + public NodeG(NodeDataType data, int openConnections, int mark, boolean isActive, + IPipeTile heldMTE) { this.data = data; this.openConnections = openConnections; this.mark = mark; @@ -123,6 +123,7 @@ public List, NetEdge>> getPathCache() { /** * Sets the path cache to the provided cache. Returns the provided cache for convenience. + * * @param pathCache The new cache. * @return The new cache. */ diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index e2e83f44fdf..3425de6d22d 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -1,16 +1,9 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; - import gregtech.api.pipenet.tile.IPipeTile; - import gregtech.api.pipenet.tile.TileEntityPipeBase; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; @@ -18,9 +11,11 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.storage.WorldSavedData; - import net.minecraftforge.common.util.Constants; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; @@ -35,14 +30,15 @@ import java.util.Map; import java.util.stream.Collectors; -public abstract class WorldPipeNetG & IPipeType> extends WorldSavedData { +public abstract class WorldPipeNetG & IPipeType> extends WorldSavedData { private WeakReference worldRef = new WeakReference<>(null); private final Graph, NetEdge> pipeGraph; private final Map> pipeMap = new Object2ObjectOpenHashMap<>(); private ShortestPathsAlgorithm shortestPaths; - // this is a monstrosity + private boolean validAlgorithmInstance = false; public WorldPipeNetG(String name) { @@ -74,6 +70,7 @@ protected void onWorldSet() { /** * Preferred override. Only collects a fresh TE from the server if the provided TE is not loaded. + * * @param tile The {@link TileEntityPipeBase} that paths are being requested for * @return the ordered list of paths associated with the {@link TileEntityPipeBase} */ @@ -83,6 +80,7 @@ public List, NetEdge>> getPaths(TileEnti /** * Special-case override. Forces the collection of a fresh TE from the server. + * * @param pos The {@link BlockPos} that paths are being requested for * @return the ordered list of paths associated with the {@link BlockPos} */ @@ -91,15 +89,15 @@ public List, NetEdge>> getPaths(BlockPos } public List, NetEdge>> getPaths( - @Nullable NodeG node, @Nullable TileEntityPipeBase tile) { + @Nullable NodeG node, + @Nullable TileEntityPipeBase tile) { if (node == null) return new ObjectArrayList<>(); - + node.heldMTE = tile; if (!this.validAlgorithmInstance) this.rebuildShortestPaths(); - List, NetEdge>> cache = - node.getPathCache(); + List, NetEdge>> cache = node.getPathCache(); if (cache != null) { return node.setPathCache(verifyList(cache, node)); } @@ -109,39 +107,43 @@ public List, NetEdge>> getPaths( } // Verification removes paths ending in unloaded TEs, or removes all paths if the source TE is unloaded. - protected List, NetEdge>> verifyList(List, NetEdge>> list, NodeG source) { + protected List, NetEdge>> verifyList(List, NetEdge>> list, + NodeG source) { if (!verifyNode(source)) return new ObjectArrayList<>(); return list.stream().filter(a -> verifyNode(a.getEndVertex())).collect(Collectors.toList()); } protected boolean verifyNode(NodeG node) { if (!getWorld().loadedTileEntityList.contains(node.heldMTE)) { - TileEntityPipeBase pipe = castTE(getWorld().getTileEntity(node.getNodePos())); + IPipeTile pipe = castTE(getWorld().getTileEntity(node.getNodePos())); if (pipe == null) return false; node.heldMTE = pipe; } return true; } - protected TileEntityPipeBase castTE(TileEntity te) { - if (te instanceof TileEntityPipeBase pipe) { + protected IPipeTile castTE(TileEntity te) { + if (te instanceof IPipeTilepipe) { if (!getBasePipeClass().isAssignableFrom(pipe.getClass())) { return null; } - return (TileEntityPipeBase) pipe; + return (IPipeTile) pipe; } return null; } protected abstract Class> getBasePipeClass(); - public void addNode(BlockPos nodePos, NodeDataType nodeData, int mark, int openConnections, boolean isActive, TileEntityPipeBase heldMTE) { + public void addNode(BlockPos nodePos, NodeDataType nodeData, int mark, int openConnections, boolean isActive, + @Nullable IPipeTile heldMTE) { + if (heldMTE == null) { + heldMTE = castTE(this.getWorld().getTileEntity(nodePos)); + } NodeG node = new NodeG<>(nodeData, openConnections, mark, isActive, heldMTE); if (!canAttachNode(nodeData)) return; this.addNode(node); addEdges(node); - } private void addEdges(NodeG node) { @@ -154,7 +156,8 @@ private void addEdges(NodeG node) { } } - protected final boolean canNodesConnect(NodeG source, EnumFacing nodeFacing, NodeG target) { + protected final boolean canNodesConnect(NodeG source, EnumFacing nodeFacing, + NodeG target) { return areNodeBlockedConnectionsCompatible(source, nodeFacing, target) && areMarksCompatible(source.mark, target.mark) && areNodesCustomContactable(source.data, target.data); } @@ -163,7 +166,8 @@ private static boolean areMarksCompatible(int mark1, int mark2) { return mark1 == mark2 || mark1 == Node.DEFAULT_MARK || mark2 == Node.DEFAULT_MARK; } - private boolean areNodeBlockedConnectionsCompatible(NodeG source, EnumFacing nodeFacing, NodeG target) { + private boolean areNodeBlockedConnectionsCompatible(NodeG source, EnumFacing nodeFacing, + NodeG target) { return !source.isBlocked(nodeFacing) && !target.isBlocked(nodeFacing.getOpposite()); } @@ -201,7 +205,8 @@ public void updateMark(BlockPos nodePos, int newMark) { NodeG nodeOffset = pipeMap.get(nodePos.offset(side)); if (nodeOffset == null) continue; if (!areNodeBlockedConnectionsCompatible(node, side, nodeOffset) || - !areNodesCustomContactable(node.data, nodeOffset.data)) continue; + !areNodesCustomContactable(node.data, nodeOffset.data)) + continue; if (areMarksCompatible(oldMark, nodeOffset.mark) == areMarksCompatible(newMark, nodeOffset.mark)) continue; if (areMarksCompatible(newMark, nodeOffset.mark)) { @@ -250,6 +255,10 @@ public void removeEdge(NodeG source, NodeG node) { if (node.getGroup() != null && node.getGroup().splitNode(node)) { // if the node has no group, then it isn't connected to anything, and thus the cache is still valid @@ -260,6 +269,16 @@ public void removeNode(NodeG node) { this.markDirty(); } + public boolean markNodeAsActive(BlockPos nodePos, boolean isActive) { + NodeG node = this.pipeMap.get(nodePos); + if (node != null && node.isActive != isActive) { + node.isActive = isActive; + this.markDirty(); + return true; + } + return false; + } + protected void rebuildShortestPaths() { this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph); this.validAlgorithmInstance = true; @@ -294,7 +313,7 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { allPipeNodes.appendTag(nodeTag); } compound.setTag("PipeNodes", allPipeNodes); - + NBTTagList allNetEdges = new NBTTagList(); for (NetEdge edge : pipeGraph.edgeSet()) { allNetEdges.appendTag(edge.serializeNBT()); @@ -316,7 +335,8 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); // CHManyToManyShortestPaths is a very good algorithm because our graph will be extremely sparse. - protected static final class ShortestPathsAlgorithm & IPipeType, NDT extends INodeData> extends CHManyToManyShortestPaths, NetEdge> { + protected static final class ShortestPathsAlgorithm & IPipeType, NDT extends INodeData> + extends CHManyToManyShortestPaths, NetEdge> { public ShortestPathsAlgorithm(Graph, NetEdge> graph) { super(graph); @@ -329,7 +349,8 @@ public List, NetEdge>> getPathsList(NodeG sour List, NetEdge>> paths = new ObjectArrayList<>(); // if the source has no group, it has no paths. if (source.getGroup() == null) return paths; - ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths(Collections.singleton(source), source.getGroup().getNodes()); + ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths( + Collections.singleton(source), source.getGroup().getNodes()); for (NodeG v : source.getGroup().getNodes()) { // update mutably so that the returned paths are also updated if (v.equals(source)) { diff --git a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java index dccba8d7289..f4c428139fc 100644 --- a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java @@ -8,8 +8,8 @@ import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.pipenet.IBlockAppearance; -import gregtech.api.pipenet.PipeNet; -import gregtech.api.pipenet.WorldPipeNet; +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.PipeCoverableImplementation; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -59,8 +59,9 @@ import static gregtech.api.metatileentity.MetaTileEntity.FULL_CUBE_COLLISION; @SuppressWarnings("deprecation") -public abstract class BlockPipe & IPipeType, NodeDataType, - WorldPipeNetType extends WorldPipeNet>> extends BuiltInRenderBlock +public abstract class BlockPipe & IPipeType, + NodeDataType extends INodeData, + WorldPipeNetType extends WorldPipeNetG> extends BuiltInRenderBlock implements ITileEntityProvider, IFacadeWrapper, IBlockAppearance { protected final ThreadLocal> tileEntities = new ThreadLocal<>(); @@ -146,7 +147,8 @@ public void updateTick(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull I if (pipeTile != null) { int activeConnections = pipeTile.getConnections(); boolean isActiveNode = activeConnections != 0; - getWorldPipeNet(worldIn).addNode(pos, createProperties(pipeTile), 0, activeConnections, isActiveNode); + getWorldPipeNet(worldIn).addNode(pos, createProperties(pipeTile), 0, activeConnections, isActiveNode, + pipeTile); onActiveModeChange(worldIn, pos, isActiveNode, true); } } @@ -206,16 +208,6 @@ public void onNeighborChange(@NotNull IBlockAccess world, @NotNull BlockPos pos, } } - @Override - public void observedNeighborChange(@NotNull IBlockState observerState, @NotNull World world, - @NotNull BlockPos observerPos, @NotNull Block changedBlock, - @NotNull BlockPos changedBlockPos) { - PipeNet net = getWorldPipeNet(world).getNetFromPos(observerPos); - if (net != null) { - net.onNeighbourUpdate(changedBlockPos); - } - } - @Override public boolean canConnectRedstone(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, @Nullable EnumFacing side) { @@ -242,7 +234,7 @@ public void updateActiveNodeStatus(@NotNull World worldIn, BlockPos pos, IPipeTile pipeTile) { if (worldIn.isRemote) return; - PipeNet pipeNet = getWorldPipeNet(worldIn).getNetFromPos(pos); + WorldPipeNetG pipeNet = getWorldPipeNet(worldIn); if (pipeNet != null && pipeTile != null) { int activeConnections = pipeTile.getConnections(); // remove blocked connections boolean isActiveNodeNow = activeConnections != 0; diff --git a/src/main/java/gregtech/api/pipenet/block/IPipeType.java b/src/main/java/gregtech/api/pipenet/block/IPipeType.java index c0b4caf8121..89442a6da24 100644 --- a/src/main/java/gregtech/api/pipenet/block/IPipeType.java +++ b/src/main/java/gregtech/api/pipenet/block/IPipeType.java @@ -1,8 +1,10 @@ package gregtech.api.pipenet.block; +import gregtech.api.pipenet.INodeData; + import net.minecraft.util.IStringSerializable; -public interface IPipeType extends IStringSerializable { +public interface IPipeType extends IStringSerializable { float getThickness(); diff --git a/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java b/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java index 30b283a9b3f..7b6f56a3877 100644 --- a/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java @@ -1,5 +1,6 @@ package gregtech.api.pipenet.block; +import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.common.ConfigHolder; @@ -14,7 +15,8 @@ import org.jetbrains.annotations.NotNull; -public class ItemBlockPipe & IPipeType, NodeDataType> extends ItemBlock { +public class ItemBlockPipe & IPipeType, NodeDataType extends INodeData> + extends ItemBlock { protected final BlockPipe blockPipe; diff --git a/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java b/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java index 003fda2a5de..fda19359089 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java @@ -1,8 +1,8 @@ package gregtech.api.pipenet.block.material; import gregtech.api.GTValues; -import gregtech.api.pipenet.PipeNet; -import gregtech.api.pipenet.WorldPipeNet; +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; @@ -27,8 +27,9 @@ import java.util.Objects; public abstract class BlockMaterialPipe< - PipeType extends Enum & IPipeType & IMaterialPipeType, NodeDataType, - WorldPipeNetType extends WorldPipeNet>> + PipeType extends Enum & IPipeType & IMaterialPipeType, + NodeDataType extends INodeData, + WorldPipeNetType extends WorldPipeNetG> extends BlockPipe { protected final PipeType pipeType; diff --git a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java b/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java index bada7d3c132..4638029e581 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java +++ b/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java @@ -1,10 +1,12 @@ package gregtech.api.pipenet.block.material; +import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.Material; -public interface IMaterialPipeTile & IPipeType, NodeDataType> +public interface IMaterialPipeTile & IPipeType, + NodeDataType extends INodeData> extends IPipeTile { Material getPipeMaterial(); diff --git a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeType.java b/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeType.java index e6be75677e2..2657dd88799 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeType.java +++ b/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeType.java @@ -1,9 +1,10 @@ package gregtech.api.pipenet.block.material; +import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.unification.ore.OrePrefix; -public interface IMaterialPipeType extends IPipeType { +public interface IMaterialPipeType extends IPipeType { /** * Determines ore prefix used for this pipe type, which gives pipe ore dictionary key diff --git a/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java b/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java index 70467ecf809..b186ab5cd7b 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java @@ -1,5 +1,6 @@ package gregtech.api.pipenet.block.material; +import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.block.ItemBlockPipe; import gregtech.api.unification.material.Material; @@ -7,7 +8,8 @@ import org.jetbrains.annotations.NotNull; -public class ItemBlockMaterialPipe & IMaterialPipeType, NodeDataType> +public class ItemBlockMaterialPipe & IMaterialPipeType, + NodeDataType extends INodeData> extends ItemBlockPipe { public ItemBlockMaterialPipe(BlockMaterialPipe block) { diff --git a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java index d5164c30d11..dec816518d6 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java @@ -1,5 +1,6 @@ package gregtech.api.pipenet.block.material; +import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -15,7 +16,7 @@ import static gregtech.api.capability.GregtechDataCodes.UPDATE_PIPE_MATERIAL; public abstract class TileEntityMaterialPipeBase & IMaterialPipeType, - NodeDataType> extends TileEntityPipeBase + NodeDataType extends INodeData> extends TileEntityPipeBase implements IMaterialPipeTile { private Material pipeMaterial = Materials.Aluminium; diff --git a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java index 52e344243c8..22fd9885cf4 100644 --- a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java +++ b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java @@ -1,7 +1,7 @@ package gregtech.api.pipenet.block.simple; -import gregtech.api.pipenet.PipeNet; -import gregtech.api.pipenet.WorldPipeNet; +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; @@ -9,8 +9,9 @@ import net.minecraft.item.ItemStack; -public abstract class BlockSimplePipe & IPipeType, NodeDataType, - WorldPipeNetType extends WorldPipeNet>> +public abstract class BlockSimplePipe & IPipeType, + NodeDataType extends INodeData, + WorldPipeNetType extends WorldPipeNetG> extends BlockPipe { @Override diff --git a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java index 486ddfa6d8b..199ac7f2696 100644 --- a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java +++ b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java @@ -1,6 +1,7 @@ package gregtech.api.pipenet.tile; import gregtech.api.metatileentity.interfaces.INeighborCache; +import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.unification.material.Material; @@ -15,7 +16,7 @@ import java.util.function.Consumer; -public interface IPipeTile & IPipeType, NodeDataType> +public interface IPipeTile & IPipeType, NodeDataType extends INodeData> extends INeighborCache { World getPipeWorld(); diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 87e67dea4f8..6ad464f6f74 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -5,8 +5,8 @@ import gregtech.api.cover.Cover; import gregtech.api.metatileentity.NeighborCacheTileEntityBase; import gregtech.api.metatileentity.SyncedTileEntityBase; -import gregtech.api.pipenet.PipeNet; -import gregtech.api.pipenet.WorldPipeNet; +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.unification.material.Material; @@ -35,7 +35,8 @@ import static gregtech.api.capability.GregtechDataCodes.*; public abstract class TileEntityPipeBase & IPipeType, - NodeDataType> extends NeighborCacheTileEntityBase implements IPipeTile { + NodeDataType extends INodeData> extends NeighborCacheTileEntityBase + implements IPipeTile { protected final PipeCoverableImplementation coverableImplementation = new PipeCoverableImplementation(this); protected int paintingColor = -1; @@ -146,7 +147,8 @@ public IPipeTile setSupportsTicking() { if (pipeBlock == null) { Block block = getBlockState().getBlock(); // noinspection unchecked - this.pipeBlock = block instanceof BlockPipe blockPipe ? blockPipe : null; + this.pipeBlock = block instanceof BlockPipeblockPipe ? + (BlockPipe) blockPipe : null; } return pipeBlock; } @@ -217,7 +219,7 @@ public void setConnection(EnumFacing side, boolean connected, boolean fromNeighb TileEntity tile = getNeighbor(side); // block connections if Pipe Types do not match if (connected && - tile instanceof IPipeTile pipeTile && + tile instanceof IPipeTilepipeTile && pipeTile.getPipeType().getClass() != this.getPipeType().getClass()) { return; } @@ -229,7 +231,7 @@ public void setConnection(EnumFacing side, boolean connected, boolean fromNeighb }); markDirty(); - if (!fromNeighbor && tile instanceof IPipeTile pipeTile) { + if (!fromNeighbor && tile instanceof IPipeTilepipeTile) { syncPipeConnections(side, pipeTile); } } @@ -247,7 +249,7 @@ private void syncPipeConnections(EnumFacing side, IPipeTile pipe) { } private void updateNetworkConnection(EnumFacing side, boolean connected) { - WorldPipeNet worldPipeNet = getPipeBlock().getWorldPipeNet(getWorld()); + WorldPipeNetG worldPipeNet = getPipeBlock().getWorldPipeNet(getWorld()); worldPipeNet.updateBlockedConnections(getPos(), side, !connected); } @@ -268,11 +270,8 @@ public void setFaceBlocked(EnumFacing side, boolean blocked) { buf.writeVarInt(blockedConnections); }); markDirty(); - WorldPipeNet worldPipeNet = getPipeBlock().getWorldPipeNet(getWorld()); - PipeNet net = worldPipeNet.getNetFromPos(pos); - if (net != null) { - net.onPipeConnectionsUpdate(); - } + WorldPipeNetG worldPipeNet = getPipeBlock().getWorldPipeNet(getWorld()); + worldPipeNet.updateBlockedConnections(this.getPipePos(), side, blocked); } } @@ -390,7 +389,8 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { if (compound.hasKey("PipeBlock", NBT.TAG_STRING)) { Block block = Block.REGISTRY.getObject(new ResourceLocation(compound.getString("PipeBlock"))); // noinspection unchecked - this.pipeBlock = block instanceof BlockPipe blockPipe ? blockPipe : null; + this.pipeBlock = block instanceof BlockPipeblockPipe ? + (BlockPipe) blockPipe : null; } this.pipeType = getPipeTypeClass().getEnumConstants()[compound.getInteger("PipeType")]; diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index b3e7b37d825..4db060a5697 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -4,7 +4,6 @@ import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.fluids.attribute.FluidAttributes; - import gregtech.api.pipenet.INodeData; import it.unimi.dsi.fastutil.objects.Object2BooleanMap; From f487042ee2ec8dd772c0e069606dd17c00de5ea8 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 17 Dec 2023 15:55:12 -0700 Subject: [PATCH 011/157] Pain and suffering (also fixed item pipe nets?) --- .../java/gregtech/api/pipenet/INodeData.java | 6 +- .../java/gregtech/api/pipenet/NetEdge.java | 13 +- .../java/gregtech/api/pipenet/NetGroup.java | 2 +- .../java/gregtech/api/pipenet/NetPath.java | 139 +++++++++++++++ src/main/java/gregtech/api/pipenet/NodeG.java | 50 ++++-- .../gregtech/api/pipenet/WorldPipeNetG.java | 88 +++++++--- .../properties/FluidPipeProperties.java | 22 ++- .../properties/ItemPipeProperties.java | 21 ++- .../material/properties/WireProperties.java | 17 +- .../pipelike/itempipe/net/ItemNetHandler.java | 165 ++++++++++-------- .../itempipe/net/WorldItemPipeNet.java | 48 ++++- .../itempipe/tile/TileEntityItemPipe.java | 34 +--- .../pipelike/laser/LaserPipeProperties.java | 9 +- .../optical/OpticalPipeProperties.java | 9 +- 14 files changed, 460 insertions(+), 163 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/NetPath.java diff --git a/src/main/java/gregtech/api/pipenet/INodeData.java b/src/main/java/gregtech/api/pipenet/INodeData.java index 9e4639ff833..2062cdd6970 100644 --- a/src/main/java/gregtech/api/pipenet/INodeData.java +++ b/src/main/java/gregtech/api/pipenet/INodeData.java @@ -1,8 +1,12 @@ package gregtech.api.pipenet; -public interface INodeData { +import java.util.Set; + +public interface INodeData> { default double getWeightFactor() { return 1; } + + T getMinData(Set datas); } diff --git a/src/main/java/gregtech/api/pipenet/NetEdge.java b/src/main/java/gregtech/api/pipenet/NetEdge.java index 9c931e5ec7c..3d0a1881105 100644 --- a/src/main/java/gregtech/api/pipenet/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/NetEdge.java @@ -8,10 +8,21 @@ import org.jgrapht.graph.DefaultWeightedEdge; +import java.util.List; import java.util.Map; +import java.util.function.Predicate; class NetEdge extends DefaultWeightedEdge implements INBTSerializable { + private List> predicates; + + public void setPredicates(List> predicates) { + this.predicates = predicates; + } + public List> getPredicates() { + return predicates; + } + @Override protected NodeG getSource() { return (NodeG) super.getSource(); @@ -38,7 +49,7 @@ public NBTTagCompound serializeNBT() { public void deserializeNBT(NBTTagCompound nbt) {} static final class Builder & IPipeType, - NodeDataType extends INodeData> { + NodeDataType extends INodeData> { private final NodeG node1; private final NodeG node2; diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 7ec71fa0c9f..3e814acda69 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -10,7 +10,7 @@ import java.util.Set; import java.util.stream.Collectors; -public class NetGroup & IPipeType, NodeDataType extends INodeData> { +public class NetGroup & IPipeType, NodeDataType extends INodeData> { private final Graph, NetEdge> graph; diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java new file mode 100644 index 00000000000..07e29a68493 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -0,0 +1,139 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.block.IPipeType; + +import gregtech.api.util.FacingPos; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; + +import org.jgrapht.GraphPath; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class NetPath & IPipeType, NodeDataType extends INodeData> { + + protected final List> nodeList; + private final List edgeList; + + protected final NodeG sourceNode; + + protected final NodeG targetNode; + + protected final double weight; + + private NodeDataType data = null; + + private Iterator facingIterator; + + public NetPath(GraphPath, NetEdge> path) { + this.sourceNode = path.getStartVertex(); + this.targetNode = path.getEndVertex(); + this.nodeList = path.getVertexList(); + // convert weight to the true value of the involved nodes + this.weight = (path.getWeight() + sourceNode.data.getWeightFactor() + targetNode.data.getWeightFactor()) / 2; + this.edgeList = path.getEdgeList(); + resetFacingIterator(); + } + + public List> getNodeList() { + return nodeList; + } + + public NodeG getSourceNode() { + return sourceNode; + } + + public NodeG getTargetNode() { + return targetNode; + } + + public FacedNetPath withFacing(EnumFacing facing) { + return new FacedNetPath<>(this, facing); + } + + public void resetFacingIterator() { + this.facingIterator = this.getTargetTEs().keySet().iterator(); + } + + public FacedNetPath nextFacing() { + return new FacedNetPath<>(this, this.facingIterator.next()); + } + + public boolean hasNextFacing() { + return this.facingIterator.hasNext(); + } + + public Map getTargetTEs() { + return targetNode.getConnecteds(); + } + + public double getWeight() { + return weight; + } + + public NodeDataType getData() { + // generate min data on-demand and cache it, rather than generating for every path always + if (this.data == null) { + this.data = sourceNode.data.getMinData(this.nodeList.stream().map(NodeG::getData).collect(Collectors.toSet())); + } + return data; + } + + public boolean checkPredicate(Object o) { + for (NetEdge edge : this.edgeList) + for (Predicate predicate : edge.getPredicates()) + predicate.test(o); + return true; + } + + public static class FacedNetPath & IPipeType, NDT extends INodeData> { + + public NetPath path; + + public EnumFacing facing; + + public FacedNetPath(NetPath path, EnumFacing facing) { + new FacedNetPath<>(path, facing); + } + + public TileEntity getTargetTE() { + return path.getTargetTEs().get(facing); + } + public List> getNodeList() { + return path.getNodeList(); + } + + public NodeG getSourceNode() { + return path.getSourceNode(); + } + + public NodeG getTargetNode() { + return path.getTargetNode(); + } + + public Map getTargetTEs() { + return path.getTargetTEs(); + } + + public double getWeight() { + return path.getWeight(); + } + + public NDT getData() { + return path.getData(); + } + + public boolean checkPredicate(Object o) { + return path.checkPredicate(o); + } + + public FacingPos toFacingPos() { + return new FacingPos(path.getTargetNode().getNodePos(), this.facing); + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 3a4dddc695f..e6c8a857fe1 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -3,7 +3,12 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraftforge.common.util.INBTSerializable; @@ -11,10 +16,16 @@ import org.jetbrains.annotations.Nullable; import org.jgrapht.GraphPath; +import java.lang.ref.WeakReference; +import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; -public class NodeG & IPipeType, NodeDataType extends INodeData> +public class NodeG & IPipeType, NodeDataType extends INodeData> implements INBTSerializable { public static final int DEFAULT_MARK = 0; @@ -34,7 +45,12 @@ public class NodeG & IPipeType, No public int mark; public boolean isActive; + // TODO make weak reference public IPipeTile heldMTE; + /** + * Connected tile entities + */ + private Map> connecteds = new Object2ObjectOpenHashMap<>(6); /** * CANNOT BE CHANGED DURING THE LIFETIME OF A NODE OR THE GRAPH WILL BREAK (or so I've been told) @@ -43,7 +59,7 @@ public class NodeG & IPipeType, No private NetGroup group = null; - private List, NetEdge>> pathCache = null; + private List> pathCache = null; public NodeG(NodeDataType data, int openConnections, int mark, boolean isActive, IPipeTile heldMTE) { @@ -63,13 +79,6 @@ public NodeG(NBTTagCompound tag, WorldPipeNetG net) { this.data = net.readNodeData(tag.getCompoundTag("Data")); } - /** - * For internal usage only - */ - NodeG(BlockPos pos) { - this.nodePos = pos; - } - @Nullable NetGroup getGroup() { return group; @@ -83,6 +92,21 @@ void clearGroup() { this.group = null; } + public boolean hasConnecteds() { + Optional o = this.connecteds.values().stream().map(a -> a.get() != null).reduce((a, b) -> a || b); + return o.isPresent() && o.get(); + } + + public Map getConnecteds() { + //noinspection DataFlowIssue + return this.connecteds.entrySet().stream().filter(a -> a.getValue().get() != null) + .collect(Collectors.toMap(Map.Entry::getKey, a -> a.getValue().get())); + } + + public TileEntity getConnnected(EnumFacing facing) { + return this.connecteds.get(facing).get(); + } + public boolean isBlocked(EnumFacing facing) { return (openConnections & 1 << facing.getIndex()) == 0; } @@ -116,8 +140,12 @@ void sync(NodeG node) { } } + public NodeDataType getData() { + return data; + } + @Nullable - public List, NetEdge>> getPathCache() { + public List> getPathCache() { return pathCache; } @@ -127,7 +155,7 @@ public List, NetEdge>> getPathCache() { * @param pathCache The new cache. * @return The new cache. */ - public List, NetEdge>> setPathCache(List, NetEdge>> pathCache) { + public List> setPathCache(List> pathCache) { this.pathCache = pathCache; return pathCache; } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 3425de6d22d..edb4c2e3d7d 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -1,9 +1,12 @@ package gregtech.api.pipenet; +import gregtech.api.cover.Cover; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.common.covers.CoverShutter; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; @@ -24,13 +27,15 @@ import org.jgrapht.graph.SimpleWeightedGraph; import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.function.Predicate; import java.util.stream.Collectors; -public abstract class WorldPipeNetG, PipeType extends Enum & IPipeType> extends WorldSavedData { private WeakReference worldRef = new WeakReference<>(null); @@ -74,7 +79,7 @@ protected void onWorldSet() { * @param tile The {@link TileEntityPipeBase} that paths are being requested for * @return the ordered list of paths associated with the {@link TileEntityPipeBase} */ - public List, NetEdge>> getPaths(TileEntityPipeBase tile) { + public List> getPaths(TileEntityPipeBase tile) { return getPaths(this.pipeMap.get(tile.getPipePos()), tile); } @@ -84,11 +89,11 @@ public List, NetEdge>> getPaths(TileEnti * @param pos The {@link BlockPos} that paths are being requested for * @return the ordered list of paths associated with the {@link BlockPos} */ - public List, NetEdge>> getPaths(BlockPos pos) { + public List> getPaths(BlockPos pos) { return getPaths(this.pipeMap.get(pos), null); } - public List, NetEdge>> getPaths( + public List> getPaths( @Nullable NodeG node, @Nullable TileEntityPipeBase tile) { if (node == null) return new ObjectArrayList<>(); @@ -97,42 +102,52 @@ public List, NetEdge>> getPaths( if (!this.validAlgorithmInstance) this.rebuildShortestPaths(); - List, NetEdge>> cache = node.getPathCache(); + List> cache = node.getPathCache(); if (cache != null) { - return node.setPathCache(verifyList(cache, node)); + return verifyList(cache, node); } - List, NetEdge>> list = this.shortestPaths.getPathsList(node); - return node.setPathCache(verifyList(list, node)); + List> list = this.shortestPaths.getPathsList(node); + return verifyList(node.setPathCache(list), node); } - // Verification removes paths ending in unloaded TEs, or removes all paths if the source TE is unloaded. - protected List, NetEdge>> verifyList(List, NetEdge>> list, + /** + * Verification removes paths ending in unloaded TEs, + * paths that don't connect to anything, + * and all paths if the source TE is unloaded. + */ + protected List> verifyList(List> list, NodeG source) { if (!verifyNode(source)) return new ObjectArrayList<>(); - return list.stream().filter(a -> verifyNode(a.getEndVertex())).collect(Collectors.toList()); + return list.stream().filter(a -> verifyNode(a.getTargetNode())).collect(Collectors.toList()); } protected boolean verifyNode(NodeG node) { - if (!getWorld().loadedTileEntityList.contains(node.heldMTE)) { - IPipeTile pipe = castTE(getWorld().getTileEntity(node.getNodePos())); - if (pipe == null) return false; - node.heldMTE = pipe; + if (!node.hasConnecteds()) return false; + node.heldMTE = verifyTE(node.getNodePos(), (TileEntity) node.heldMTE); + return node.heldMTE != null; + } + + @Nullable + protected TileEntityPipeBase verifyTE(BlockPos pos, @Nullable TileEntity te) { + if (!getWorld().loadedTileEntityList.contains(te)) { + return castTE(getWorld().getTileEntity(pos)); } - return true; + return castTE(te); } - protected IPipeTile castTE(TileEntity te) { - if (te instanceof IPipeTilepipe) { + @Nullable + protected TileEntityPipeBase castTE(TileEntity te) { + if (te instanceof TileEntityPipeBase pipe) { if (!getBasePipeClass().isAssignableFrom(pipe.getClass())) { return null; } - return (IPipeTile) pipe; + return (TileEntityPipeBase) pipe; } return null; } - protected abstract Class> getBasePipeClass(); + protected abstract Class> getBasePipeClass(); public void addNode(BlockPos nodePos, NodeDataType nodeData, int mark, int openConnections, boolean isActive, @Nullable IPipeTile heldMTE) { @@ -237,6 +252,10 @@ public void addEdge(NodeG source, NodeG getNode(BlockPos pos) { + return this.pipeMap.get(pos); + } + public void addEdge(NodeG source, NodeG target, double weight) { if (pipeGraph.addEdge(source, target) != null) { if (NetGroup.mergeEdge(source, target)) { @@ -248,6 +267,25 @@ public void addEdge(NodeG source, NodeG source = this.pipeMap.get(pos); + NodeG target = this.pipeMap.get(pos.offset(faceToNeighbour)); + Cover thisCover = source.heldMTE.getCoverableImplementation().getCoverAtSide(faceToNeighbour); + Cover neighbourCover = target.heldMTE.getCoverableImplementation().getCoverAtSide(faceToNeighbour.getOpposite()); + List> filters = new ArrayList<>(); + if (thisCover instanceof CoverShutter) { + filters.add(o -> !((CoverShutter) thisCover).isWorkingEnabled()); + } + if (neighbourCover instanceof CoverShutter) { + filters.add(o -> !((CoverShutter) neighbourCover).isWorkingEnabled()); + } + filters.add(getPredicate(thisCover, neighbourCover)); + NetEdge edge = this.pipeGraph.getEdge(source, target); + edge.setPredicates(filters); + } + + protected abstract Predicate getPredicate(Cover thisCover, Cover neighbourCover); + public void removeEdge(NodeG source, NodeG target) { if (source.getGroup() != null && source.getGroup().splitEdge(source, target)) { this.validAlgorithmInstance = false; @@ -335,18 +373,18 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); // CHManyToManyShortestPaths is a very good algorithm because our graph will be extremely sparse. - protected static final class ShortestPathsAlgorithm & IPipeType, NDT extends INodeData> + protected static final class ShortestPathsAlgorithm & IPipeType, NDT extends INodeData> extends CHManyToManyShortestPaths, NetEdge> { public ShortestPathsAlgorithm(Graph, NetEdge> graph) { super(graph); } - public List, NetEdge>> getPathsList(NodeG source) { + public List> getPathsList(NodeG source) { if (!graph.containsVertex(source)) { throw new IllegalArgumentException("graph must contain the source vertex"); } - List, NetEdge>> paths = new ObjectArrayList<>(); + List> paths = new ObjectArrayList<>(); // if the source has no group, it has no paths. if (source.getGroup() == null) return paths; ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths( @@ -360,10 +398,10 @@ public List, NetEdge>> getPathsList(NodeG sour GraphPath, NetEdge> path = manyToManyPaths.getPath(source, v); if (path != null) { - paths.add(path); + paths.add(new NetPath<>(path)); } } - paths.sort(Comparator.comparingDouble(GraphPath::getWeight)); + paths.sort(Comparator.comparingDouble(NetPath::getWeight)); return paths; } } diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 4db060a5697..3f68a1e3603 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -13,8 +13,9 @@ import java.util.Collection; import java.util.Objects; +import java.util.Set; -public class FluidPipeProperties implements IMaterialProperty, IPropertyFluidFilter, INodeData { +public class FluidPipeProperties implements IMaterialProperty, IPropertyFluidFilter, INodeData { private final Object2BooleanMap containmentPredicate = new Object2BooleanOpenHashMap<>(); @@ -145,6 +146,25 @@ public double getWeightFactor() { return Math.pow(2, (int) (Double.MAX_EXPONENT / (Math.log(this.getThroughput()) * 170))); } + @Override + public FluidPipeProperties getMinData(Set datas) { + int maxFluidTemperature = Integer.MAX_VALUE; + int throughput = Integer.MAX_VALUE; + boolean gasProof = true; + boolean acidProof = true; + boolean cryoProof = true; + boolean plasmaProof = true; + for (FluidPipeProperties data : datas) { + maxFluidTemperature = Math.min(maxFluidTemperature, data.getMaxFluidTemperature()); + throughput = Math.min(throughput, data.getThroughput()); + gasProof &= data.isGasProof(); + acidProof &= data.isAcidProof(); + cryoProof &= data.isCryoProof(); + plasmaProof &= data.isPlasmaProof(); + } + return new FluidPipeProperties(); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java index f558b0e76d9..35294ec56a6 100644 --- a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java @@ -3,8 +3,9 @@ import gregtech.api.pipenet.INodeData; import java.util.Objects; +import java.util.Set; -public class ItemPipeProperties implements IMaterialProperty, INodeData { +public class ItemPipeProperties implements IMaterialProperty, INodeData { /** * Items will try to take the path with the lowest priority @@ -77,15 +78,25 @@ public void verifyProperty(MaterialProperties properties) { @Override public double getWeightFactor() { - // behold 200, the magic number - return Math.pow(2, (int) (Double.MAX_EXPONENT / (Math.log(this.getTransferRate() * 64) * 200))); + // 200 the magic number is dead ;-; + return priority; + } + + @Override + public ItemPipeProperties getMinData(Set datas) { + float transferRate = Integer.MAX_VALUE; + int priority = 0; + for (ItemPipeProperties data : datas) { + transferRate = Math.min(transferRate, data.getTransferRate()); + priority += data.getPriority(); + } + return new ItemPipeProperties(priority, transferRate); } @Override public boolean equals(Object o) { if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - ItemPipeProperties that = (ItemPipeProperties) o; + if (!(o instanceof ItemPipeProperties that)) return false; return priority == that.priority && Float.compare(that.transferRate, transferRate) == 0; } diff --git a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java index 68f56e94546..2d9d236158a 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java @@ -5,10 +5,11 @@ import gregtech.api.unification.material.Material; import java.util.Objects; +import java.util.Set; import static gregtech.api.unification.material.info.MaterialFlags.GENERATE_FOIL; -public class WireProperties implements IMaterialProperty, INodeData { +public class WireProperties implements IMaterialProperty, INodeData { private int voltage; private int amperage; @@ -149,11 +150,21 @@ public double getWeightFactor() { return 1d / this.getLossPerBlock(); } + @Override + public WireProperties getMinData(Set datas) { + int amperage = Integer.MAX_VALUE; + int lossPerBlock = 0; + for (WireProperties data : datas) { + amperage = Math.min(amperage, data.getAmperage()); + lossPerBlock += data.getLossPerBlock(); + } + return new WireProperties(-1, amperage, lossPerBlock); + } + @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof WireProperties)) return false; - WireProperties that = (WireProperties) o; + if (!(o instanceof WireProperties that)) return false; return voltage == that.voltage && amperage == that.amperage && lossPerBlock == that.lossPerBlock && diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index a2313f82398..c73f8df6461 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -3,15 +3,19 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; import gregtech.api.cover.CoverHolder; +import gregtech.api.pipenet.NetPath; +import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.util.FacingPos; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.ItemStackHashStrategy; import gregtech.common.covers.*; +import gregtech.common.pipelike.itempipe.ItemPipeType; import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemStackHandler; @@ -29,28 +33,24 @@ public class ItemNetHandler implements IItemHandler { - private ItemPipeNet net; + private final WorldItemPipeNet net; private TileEntityItemPipe pipe; private final EnumFacing facing; private final Object2IntMap simulatedTransfersGlobalRoundRobin = new Object2IntOpenHashMap<>(); private int simulatedTransfers = 0; private final ItemStackHandler testHandler = new ItemStackHandler(1); - public ItemNetHandler(ItemPipeNet net, TileEntityItemPipe pipe, EnumFacing facing) { + public ItemNetHandler(WorldItemPipeNet net, TileEntityItemPipe pipe, EnumFacing facing) { this.net = net; this.pipe = pipe; this.facing = facing; } - public void updateNetwork(ItemPipeNet net) { - this.net = net; - } - public void updatePipe(TileEntityItemPipe pipe) { this.pipe = pipe; } - public ItemPipeNet getNet() { + public WorldItemPipeNet getNet() { return net; } @@ -75,7 +75,7 @@ public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate copyTransferred(); Cover pipeCover = this.pipe.getCoverableImplementation().getCoverAtSide(facing); - Cover tileCover = getCoverOnNeighbour(this.pipe, facing); + Cover tileCover = getCoverOnNeighbour(this.pipe.getPipePos(), facing); boolean pipeConveyor = pipeCover instanceof CoverConveyor, tileConveyor = tileCover instanceof CoverConveyor; // abort if there are two conveyors @@ -109,8 +109,8 @@ public static boolean checkImportCover(Cover cover, boolean onPipe, ItemStack st } public ItemStack insertFirst(ItemStack stack, boolean simulate) { - for (ItemRoutePath inv : net.getNetData(pipe.getPipePos(), facing)) { - stack = insert(inv, stack, simulate); + for (NetPath inv : net.getPaths(pipe)) { + stack = insert(inv.nextFacing(), stack, simulate); if (stack.isEmpty()) return ItemStack.EMPTY; } @@ -118,12 +118,13 @@ public ItemStack insertFirst(ItemStack stack, boolean simulate) { } public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean global) { - List routePaths = net.getNetData(pipe.getPipePos(), facing); + List> routePaths = net.getPaths(pipe); if (routePaths.isEmpty()) return stack; - if (routePaths.size() == 1) - return insert(routePaths.get(0), stack, simulate); - List routePathsCopy = new ArrayList<>(routePaths); + if (routePaths.size() == 1 && routePaths.get(0).getTargetTEs().size() == 1) { + return insert(routePaths.get(0).nextFacing(), stack, simulate); + } + List> routePathsCopy = new ArrayList<>(routePaths); if (global) { stack = insertToHandlersEnhanced(routePathsCopy, stack, routePaths.size(), simulate); @@ -145,34 +146,36 @@ public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean glo * @param simulate simulate * @return remainder */ - private ItemStack insertToHandlers(List copy, ItemStack stack, boolean simulate) { - Iterator routePathIterator = copy.listIterator(); + private ItemStack insertToHandlers(List> copy, ItemStack stack, boolean simulate) { + Iterator> routePathIterator = copy.listIterator(); int inserted = 0; int count = stack.getCount(); int c = count / copy.size(); int m = c == 0 ? count % copy.size() : 0; while (routePathIterator.hasNext()) { - ItemRoutePath routePath = routePathIterator.next(); + NetPath routePath = routePathIterator.next(); + while (routePath.hasNextFacing()) { + NetPath.FacedNetPath facedNetPath = routePath.nextFacing(); + int amount = c; + if (m > 0) { + amount++; + m--; + } + amount = Math.min(amount, stack.getCount() - inserted); + if (amount == 0) break; + ItemStack toInsert = stack.copy(); + toInsert.setCount(amount); + int r = insert(facedNetPath, toInsert, simulate).getCount(); + if (r < amount) { + inserted += (amount - r); + } + if (r == 1 && c == 0 && amount == 1) { + m++; + } - int amount = c; - if (m > 0) { - amount++; - m--; - } - amount = Math.min(amount, stack.getCount() - inserted); - if (amount == 0) break; - ItemStack toInsert = stack.copy(); - toInsert.setCount(amount); - int r = insert(routePath, toInsert, simulate).getCount(); - if (r < amount) { - inserted += (amount - r); + if (r > 0) + routePathIterator.remove(); } - if (r == 1 && c == 0 && amount == 1) { - m++; - } - - if (r > 0) - routePathIterator.remove(); } ItemStack remainder = stack.copy(); @@ -180,26 +183,29 @@ private ItemStack insertToHandlers(List copy, ItemStack stack, bo return remainder; } - private ItemStack insertToHandlersEnhanced(List copy, ItemStack stack, int dest, boolean simulate) { + private ItemStack insertToHandlersEnhanced(List> copy, ItemStack stack, int dest, boolean simulate) { List transferred = new ArrayList<>(); IntList steps = new IntArrayList(); int min = Integer.MAX_VALUE; ItemStack simStack; // find inventories that are not full and get the amount that was inserted in total - for (ItemRoutePath inv : copy) { - simStack = stack.copy(); - int ins = stack.getCount() - insert(inv, simStack, true, true).getCount(); - if (ins <= 0) - continue; - int didTransfer = didTransferTo(inv, simulate); - EnhancedRoundRobinData data = new EnhancedRoundRobinData(inv, ins, didTransfer); - transferred.add(data); - - min = Math.min(min, didTransfer); - - if (!steps.contains(didTransfer)) { - steps.add(didTransfer); + for (NetPath inv : copy) { + while (inv.hasNextFacing()) { + NetPath.FacedNetPath faceInv = inv.nextFacing(); + simStack = stack.copy(); + int ins = stack.getCount() - insert(faceInv, simStack, true, true).getCount(); + if (ins <= 0) + continue; + int didTransfer = didTransferTo(faceInv, simulate); + EnhancedRoundRobinData data = new EnhancedRoundRobinData(faceInv, ins, didTransfer); + transferred.add(data); + + min = Math.min(min, didTransfer); + + if (!steps.contains(didTransfer)) { + steps.add(didTransfer); + } } } @@ -293,19 +299,19 @@ private ItemStack insertToHandlersEnhanced(List copy, ItemStack s return remainder; } - public ItemStack insert(ItemRoutePath routePath, ItemStack stack, boolean simulate) { + public ItemStack insert(NetPath.FacedNetPath routePath, ItemStack stack, boolean simulate) { return insert(routePath, stack, simulate, false); } - public ItemStack insert(ItemRoutePath routePath, ItemStack stack, boolean simulate, boolean ignoreLimit) { + public ItemStack insert(NetPath.FacedNetPath routePath, ItemStack stack, boolean simulate, boolean ignoreLimit) { int allowed = ignoreLimit ? stack.getCount() : - checkTransferable(routePath.getProperties().getTransferRate(), stack.getCount(), simulate); - if (allowed == 0 || !routePath.matchesFilters(stack)) { + checkTransferable(routePath.getData().getTransferRate(), stack.getCount(), simulate); + if (allowed == 0 || !routePath.checkPredicate(stack)) { return stack; } - Cover pipeCover = routePath.getTargetPipe().getCoverableImplementation() - .getCoverAtSide(routePath.getTargetFacing()); - Cover tileCover = getCoverOnNeighbour(routePath.getTargetPipe(), routePath.getTargetFacing()); + Cover pipeCover = routePath.getTargetNode().heldMTE.getCoverableImplementation() + .getCoverAtSide(routePath.facing); + Cover tileCover = getCoverOnNeighbour(routePath.getTargetTE().getPos(), routePath.facing.getOpposite()); if (pipeCover != null) { testHandler.setStackInSlot(0, stack.copy()); @@ -318,19 +324,21 @@ public ItemStack insert(ItemRoutePath routePath, ItemStack stack, boolean simula } testHandler.setStackInSlot(0, ItemStack.EMPTY); } - IItemHandler neighbourHandler = routePath.getHandler(); - if (pipeCover instanceof CoverRoboticArm && - ((CoverRoboticArm) pipeCover).getConveyorMode() == CoverConveyor.ConveyorMode.EXPORT) { - return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) pipeCover, stack, simulate, allowed, - ignoreLimit); - } - if (tileCover instanceof CoverRoboticArm && - ((CoverRoboticArm) tileCover).getConveyorMode() == CoverConveyor.ConveyorMode.IMPORT) { - return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) tileCover, stack, simulate, allowed, - ignoreLimit); - } + if (routePath.getTargetTE() instanceof IItemHandler neighbourHandler) { + if (pipeCover instanceof CoverRoboticArm && + ((CoverRoboticArm) pipeCover).getConveyorMode() == CoverConveyor.ConveyorMode.EXPORT) { + return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) pipeCover, stack, simulate, allowed, + ignoreLimit); + } + if (tileCover instanceof CoverRoboticArm && + ((CoverRoboticArm) tileCover).getConveyorMode() == CoverConveyor.ConveyorMode.IMPORT) { + return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) tileCover, stack, simulate, allowed, + ignoreLimit); + } - return insert(neighbourHandler, stack, simulate, allowed, ignoreLimit); + return insert(neighbourHandler, stack, simulate, allowed, ignoreLimit); + } + return stack; } private ItemStack insert(IItemHandler handler, ItemStack stack, boolean simulate, int allowed, @@ -351,8 +359,8 @@ private ItemStack insert(IItemHandler handler, ItemStack stack, boolean simulate return remainder; } - public Cover getCoverOnNeighbour(TileEntityItemPipe itemPipe, EnumFacing facing) { - TileEntity tile = itemPipe.getNeighbor(facing); + public Cover getCoverOnNeighbour(BlockPos pos, EnumFacing facing) { + TileEntity tile = net.getNode(pos).getConnnected(facing); if (tile != null) { CoverHolder coverHolder = tile.getCapability(GregtechTileCapabilities.CAPABILITY_COVER_HOLDER, facing.getOpposite()); @@ -374,14 +382,16 @@ public ItemStack insertOverRobotArm(IItemHandler handler, CoverRoboticArm arm, I rate = arm.getItemFilterContainer().getTransferStackSize(); int count; switch (arm.getTransferMode()) { - case TRANSFER_ANY: + case TRANSFER_ANY -> { return insert(handler, stack, simulate, allowed, ignoreLimit); - case KEEP_EXACT: + } + case KEEP_EXACT -> { count = rate - countStack(handler, stack, arm, isStackSpecific); if (count <= 0) return stack; count = Math.min(allowed, Math.min(stack.getCount(), count)); return insert(handler, stack, simulate, count, ignoreLimit); - case TRANSFER_EXACT: + } + case TRANSFER_EXACT -> { int max = allowed + arm.getBuffer(); count = Math.min(max, Math.min(rate, stack.getCount())); if (count < rate) { @@ -394,6 +404,7 @@ public ItemStack insertOverRobotArm(IItemHandler handler, CoverRoboticArm arm, I return stack; } return insert(handler, stack, simulate, count, ignoreLimit); + } } return stack; } @@ -449,7 +460,7 @@ public int getSlotLimit(int i) { return 64; } - private void transferTo(ItemRoutePath routePath, boolean simulate, int amount) { + private void transferTo(NetPath.FacedNetPath routePath, boolean simulate, int amount) { if (simulate) simulatedTransfersGlobalRoundRobin.merge(routePath.toFacingPos(), amount, Integer::sum); else @@ -461,7 +472,7 @@ private boolean contains(ItemRoutePath routePath, boolean simulate) { pipe.getTransferred().containsKey(routePath.toFacingPos()); } - private int didTransferTo(ItemRoutePath routePath, boolean simulate) { + private int didTransferTo(NetPath.FacedNetPath routePath, boolean simulate) { if (simulate) return simulatedTransfersGlobalRoundRobin.getInt(routePath.toFacingPos()); return pipe.getTransferred().getInt(routePath.toFacingPos()); @@ -482,12 +493,12 @@ private void decrementBy(int amount) { private static class EnhancedRoundRobinData { - private final ItemRoutePath routePath; + private final NetPath.FacedNetPath routePath; private final int maxInsertable; private int transferred; private int toTransfer = 0; - private EnhancedRoundRobinData(ItemRoutePath routePath, int maxInsertable, int transferred) { + private EnhancedRoundRobinData(NetPath.FacedNetPath routePath, int maxInsertable, int transferred) { this.maxInsertable = maxInsertable; this.transferred = transferred; this.routePath = routePath; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index 62cac8b52af..0a29cba6d23 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -1,11 +1,25 @@ package gregtech.common.pipelike.itempipe.net; +import gregtech.api.cover.Cover; import gregtech.api.pipenet.WorldPipeNet; +import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.ItemPipeProperties; +import gregtech.common.covers.CoverItemFilter; +import gregtech.common.covers.CoverShutter; +import gregtech.common.covers.ItemFilterMode; +import gregtech.common.pipelike.itempipe.ItemPipeType; + +import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; -public class WorldItemPipeNet extends WorldPipeNet { +import java.util.function.Predicate; + +public class WorldItemPipeNet extends WorldPipeNetG { private static final String DATA_ID = "gregtech.item_pipe_net"; @@ -24,7 +38,35 @@ public WorldItemPipeNet(String name) { } @Override - protected ItemPipeNet createNetInstance() { - return new ItemPipeNet(this); + protected Class> getBasePipeClass() { + return TileEntityItemPipe.class; + } + + @Override + protected Predicate getPredicate(Cover thisCover, Cover neighbourCover) { + return o -> { + if (!(o instanceof ItemStack s)) return false; + boolean b = true; + if (thisCover instanceof CoverItemFilter filter && + filter.getFilterMode() != ItemFilterMode.FILTER_INSERT) { + b = filter.testItemStack(s); + } + if (b && neighbourCover instanceof CoverItemFilter filter && + filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT) { + b = filter.testItemStack(s); + } + return b; + }; + } + + @Override + protected void writeNodeData(ItemPipeProperties nodeData, NBTTagCompound tagCompound) { + tagCompound.setInteger("Resistance", nodeData.getPriority()); + tagCompound.setFloat("Rate", nodeData.getTransferRate()); + } + + @Override + protected ItemPipeProperties readNodeData(NBTTagCompound tagCompound) { + return new ItemPipeProperties(tagCompound.getInteger("Range"), tagCompound.getFloat("Rate")); } } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java index 80b5e233b92..9cc4977b4a5 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java @@ -29,7 +29,6 @@ public class TileEntityItemPipe extends TileEntityMaterialPipeBase currentPipeNet = new WeakReference<>(null); private int transferredItems = 0; private long timer = 0; @@ -49,10 +48,7 @@ public boolean supportsTicking() { } private void initHandlers() { - ItemPipeNet net = getItemPipeNet(); - if (net == null) { - return; - } + WorldItemPipeNet net = WorldItemPipeNet.getWorldPipeNet(getPipeWorld()); for (EnumFacing facing : EnumFacing.values()) { handlers.put(facing, new ItemNetHandler(net, this, facing)); } @@ -69,39 +65,11 @@ public T getCapabilityInternal(Capability capability, @Nullable EnumFacin if (handlers.size() == 0) initHandlers(); - checkNetwork(); return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(handlers.getOrDefault(facing, defaultHandler)); } return super.getCapabilityInternal(capability, facing); } - public void checkNetwork() { - if (defaultHandler != null) { - ItemPipeNet current = getItemPipeNet(); - if (defaultHandler.getNet() != current) { - defaultHandler.updateNetwork(current); - for (ItemNetHandler handler : handlers.values()) { - handler.updateNetwork(current); - } - } - } - } - - public ItemPipeNet getItemPipeNet() { - if (world == null || world.isRemote) - return null; - ItemPipeNet currentPipeNet = this.currentPipeNet.get(); - if (currentPipeNet != null && currentPipeNet.isValid() && - currentPipeNet.containsNode(getPipePos())) - return currentPipeNet; // if current net is valid and does contain position, return it - WorldItemPipeNet worldFluidPipeNet = (WorldItemPipeNet) getPipeBlock().getWorldPipeNet(getPipeWorld()); - currentPipeNet = worldFluidPipeNet.getNetFromPos(getPipePos()); - if (currentPipeNet != null) { - this.currentPipeNet = new WeakReference<>(currentPipeNet); - } - return currentPipeNet; - } - public void resetTransferred() { transferred.clear(); } diff --git a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java b/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java index 1cdd995c64b..8e4d2bec8b9 100644 --- a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java +++ b/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java @@ -2,7 +2,14 @@ import gregtech.api.pipenet.INodeData; -public class LaserPipeProperties implements INodeData { +import java.util.Set; + +public class LaserPipeProperties implements INodeData { public static final LaserPipeProperties INSTANCE = new LaserPipeProperties(); + + @Override + public LaserPipeProperties getMinData(Set datas) { + return this; + } } diff --git a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java index 9c9601b83a0..b064f7eb83a 100644 --- a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java +++ b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java @@ -2,7 +2,14 @@ import gregtech.api.pipenet.INodeData; -public class OpticalPipeProperties implements INodeData { +import java.util.Set; + +public class OpticalPipeProperties implements INodeData { public static final OpticalPipeProperties INSTANCE = new OpticalPipeProperties(); + + @Override + public OpticalPipeProperties getMinData(Set datas) { + return this; + } } From 7b3982c71c562a4b670935f77c3c737080be9c55 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 18 Dec 2023 12:33:35 -0700 Subject: [PATCH 012/157] Directed graphing, cover predicates (if you squint), and more! --- .../api/pipenet/AbstractEdgePredicate.java | 57 ++++++++++ .../gregtech/api/pipenet/BasicPredicate.java | 52 +++++++++ .../java/gregtech/api/pipenet/NetEdge.java | 34 ++++-- .../java/gregtech/api/pipenet/NetPath.java | 4 +- src/main/java/gregtech/api/pipenet/NodeG.java | 8 +- .../gregtech/api/pipenet/WorldPipeNetG.java | 104 +++++++++++++----- .../gregtech/api/pipenet/block/BlockPipe.java | 2 +- .../gregtech/api/pipenet/tile/IPipeTile.java | 2 +- .../api/pipenet/tile/TileEntityPipeBase.java | 6 +- .../api/util/function/QuadConsumer.java | 7 ++ .../pipelike/itempipe/net/ItemPredicate.java | 84 ++++++++++++++ .../itempipe/net/WorldItemPipeNet.java | 26 ++--- 12 files changed, 329 insertions(+), 57 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java create mode 100644 src/main/java/gregtech/api/pipenet/BasicPredicate.java create mode 100644 src/main/java/gregtech/api/util/function/QuadConsumer.java create mode 100644 src/main/java/gregtech/common/pipelike/itempipe/net/ItemPredicate.java diff --git a/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java b/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java new file mode 100644 index 00000000000..28fb1d93481 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java @@ -0,0 +1,57 @@ +package gregtech.api.pipenet; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.common.util.INBTSerializable; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.Predicate; + +public abstract class AbstractEdgePredicate> implements Predicate, INBTSerializable { + + protected static final Map> PREDICATES = new Object2ObjectOpenHashMap<>(); + + protected BlockPos sourcePos; + protected BlockPos targetPos; + + public void setPosInfo(BlockPos sourcePos, BlockPos targetPos) { + this.sourcePos = sourcePos; + this.targetPos = targetPos; + } + + @NotNull + protected abstract T createPredicate(); + + protected abstract String predicateType(); + + public static AbstractEdgePredicate newPredicate(String identifier) { + AbstractEdgePredicate predicate = PREDICATES.get(identifier); + if (predicate != null) { + return predicate.createPredicate(); + } + return null; + } + + @Nullable + public static AbstractEdgePredicate nbtPredicate(NBTTagCompound nbt) { + AbstractEdgePredicate predicate = PREDICATES.get(nbt.getString("Type")); + if (predicate != null) { + predicate = predicate.createPredicate(); + predicate.deserializeNBT(nbt.getCompoundTag("Data")); + return predicate; + } + return null; + } + + public static NBTTagCompound toNBT(AbstractEdgePredicate predicate) { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString("Type", predicate.predicateType()); + tag.setTag("Data", predicate.serializeNBT()); + return tag; + } +} diff --git a/src/main/java/gregtech/api/pipenet/BasicPredicate.java b/src/main/java/gregtech/api/pipenet/BasicPredicate.java new file mode 100644 index 00000000000..9d84f42f02c --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/BasicPredicate.java @@ -0,0 +1,52 @@ +package gregtech.api.pipenet; + +import net.minecraft.nbt.NBTTagCompound; + +import org.jetbrains.annotations.NotNull; + +public class BasicPredicate extends AbstractEdgePredicate { + + static { + PREDICATES.put("Basic", new BasicPredicate()); + } + + protected boolean shutteredSource; + protected boolean shutteredTarget; + + public void setShutteredSource(boolean shutteredSource) { + this.shutteredSource = shutteredSource; + } + + public void setShutteredTarget(boolean shutteredTarget) { + this.shutteredTarget = shutteredTarget; + } + + @Override + public boolean test(Object o) { + return !(shutteredSource || shutteredTarget); + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + if (shutteredSource) tag.setBoolean("ShutteredSource", true); + if (shutteredTarget) tag.setBoolean("ShutteredTarget", true); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + shutteredSource = nbt.getBoolean("ShutteredSource"); + shutteredTarget = nbt.getBoolean("ShutteredTarget"); + } + + @Override + public @NotNull BasicPredicate createPredicate() { + return new BasicPredicate(); + } + + @Override + protected String predicateType() { + return "Basic"; + } +} diff --git a/src/main/java/gregtech/api/pipenet/NetEdge.java b/src/main/java/gregtech/api/pipenet/NetEdge.java index 3d0a1881105..59be6bfcc76 100644 --- a/src/main/java/gregtech/api/pipenet/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/NetEdge.java @@ -1,6 +1,7 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.util.function.QuadConsumer; import gregtech.api.util.function.TriConsumer; import net.minecraft.nbt.NBTTagCompound; @@ -10,17 +11,23 @@ import java.util.List; import java.util.Map; -import java.util.function.Predicate; class NetEdge extends DefaultWeightedEdge implements INBTSerializable { - private List> predicates; + private AbstractEdgePredicate predicate; + private boolean invertedPredicate; - public void setPredicates(List> predicates) { - this.predicates = predicates; + public void setPredicate(AbstractEdgePredicate predicate) { + this.predicate = predicate; + this.invertedPredicate = predicate.sourcePos != this.getSource().getNodePos(); } - public List> getPredicates() { - return predicates; + + public AbstractEdgePredicate getPredicate() { + return predicate; + } + + public boolean isPredicateInverted() { + return invertedPredicate; } @Override @@ -39,6 +46,8 @@ public NBTTagCompound serializeNBT() { tag.setLong("SourceLongPos", getSource().getLongPos()); tag.setLong("TargetLongPos", getTarget().getLongPos()); tag.setDouble("Weight", getWeight()); + tag.setTag("Predicate", AbstractEdgePredicate.toNBT(predicate)); + tag.setBoolean("InvertedPredicate", isPredicateInverted()); return null; } @@ -53,23 +62,30 @@ static final class Builder & IPipeType node1; private final NodeG node2; + private final AbstractEdgePredicate predicate; private final double weight; private final boolean buildable; - private final TriConsumer, NodeG, Double> edgeProducer; + private final QuadConsumer, NodeG, Double, AbstractEdgePredicate> edgeProducer; Builder(Map> longPosMap, NBTTagCompound tag, - TriConsumer, NodeG, Double> edgeProducer) { + QuadConsumer, NodeG, Double, AbstractEdgePredicate> edgeProducer) { this.node1 = longPosMap.get(tag.getLong("SourceLongPos")); this.node2 = longPosMap.get(tag.getLong("TargetLongPos")); this.weight = tag.getDouble("Weight"); + this.predicate = AbstractEdgePredicate.nbtPredicate(tag.getCompoundTag("Predicate")); + if (predicate != null) { + if (tag.getBoolean("InvertedPredicate")) + this.predicate.setPosInfo(this.node2.getNodePos(), this.node1.getNodePos()); + else this.predicate.setPosInfo(this.node1.getNodePos(), this.node2.getNodePos()); + } this.edgeProducer = edgeProducer; this.buildable = node1 != null && node2 != null; } void addIfBuildable() { if (buildable) { - edgeProducer.accept(node1, node2, weight); + edgeProducer.accept(node1, node2, weight, predicate); } } } diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index 07e29a68493..cdbd33767f2 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -12,7 +12,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.function.Predicate; import java.util.stream.Collectors; public class NetPath & IPipeType, NodeDataType extends INodeData> { @@ -86,8 +85,7 @@ public NodeDataType getData() { public boolean checkPredicate(Object o) { for (NetEdge edge : this.edgeList) - for (Predicate predicate : edge.getPredicates()) - predicate.test(o); + if (!edge.getPredicate().test(o)) return false; return true; } diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index e6c8a857fe1..b397ac1ada9 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -62,13 +62,13 @@ public class NodeG & IPipeType, No private List> pathCache = null; public NodeG(NodeDataType data, int openConnections, int mark, boolean isActive, - IPipeTile heldMTE) { + IPipeTile heldMTE, BlockPos pos) { this.data = data; this.openConnections = openConnections; this.mark = mark; this.isActive = isActive; this.heldMTE = heldMTE; - this.nodePos = heldMTE.getPipePos(); + this.nodePos = pos; } /** @@ -92,6 +92,10 @@ void clearGroup() { this.group = null; } + public void addConnected(EnumFacing facing, TileEntity te) { + this.connecteds.put(facing, new WeakReference<>(te)); + } + public boolean hasConnecteds() { Optional o = this.connecteds.values().stream().map(a -> a.get() != null).reduce((a, b) -> a || b); return o.isPresent() && o.get(); diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index edb4c2e3d7d..d26a12ec105 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -24,15 +24,13 @@ import org.jgrapht.Graph; import org.jgrapht.GraphPath; import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; -import org.jgrapht.graph.SimpleWeightedGraph; +import org.jgrapht.graph.DirectedWeightedMultigraph; import java.lang.ref.WeakReference; -import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; -import java.util.function.Predicate; import java.util.stream.Collectors; public abstract class WorldPipeNetG, @@ -48,7 +46,7 @@ public abstract class WorldPipeNetG public WorldPipeNetG(String name) { super(name); - this.pipeGraph = new SimpleWeightedGraph<>(NetEdge.class); + this.pipeGraph = new DirectedWeightedMultigraph<>(NetEdge.class); } public World getWorld() { @@ -130,7 +128,7 @@ protected boolean verifyNode(NodeG node) { @Nullable protected TileEntityPipeBase verifyTE(BlockPos pos, @Nullable TileEntity te) { - if (!getWorld().loadedTileEntityList.contains(te)) { + if (te == null || te.isInvalid()) { return castTE(getWorld().getTileEntity(pos)); } return castTE(te); @@ -149,12 +147,28 @@ protected TileEntityPipeBase castTE(TileEntity te) { protected abstract Class> getBasePipeClass(); + public void syncNode(IPipeTile pipe) { + NodeG node = this.pipeMap.get(pipe.getPipePos()); + if (node != null) { + node.heldMTE = pipe; + for (EnumFacing facing : EnumFacing.VALUES) { + if (pipeMap.containsKey(node.getNodePos().offset(facing))) continue; + if (node.heldMTE.isConnected(facing)) { + node.addConnected(facing, node.heldMTE.getNeighbor(facing)); + } + } + } + } + public void addNode(BlockPos nodePos, NodeDataType nodeData, int mark, int openConnections, boolean isActive, @Nullable IPipeTile heldMTE) { - if (heldMTE == null) { + if (heldMTE != null && this.pipeMap.containsKey(nodePos)) { + this.syncNode(heldMTE); + return; + } else if (heldMTE == null) { heldMTE = castTE(this.getWorld().getTileEntity(nodePos)); } - NodeG node = new NodeG<>(nodeData, openConnections, mark, isActive, heldMTE); + NodeG node = new NodeG<>(nodeData, openConnections, mark, isActive, heldMTE, nodePos); if (!canAttachNode(nodeData)) return; this.addNode(node); @@ -166,7 +180,8 @@ private void addEdges(NodeG node) { BlockPos offsetPos = node.getNodePos().offset(facing); NodeG nodeOffset = this.pipeMap.get(offsetPos); if (nodeOffset != null && this.canNodesConnect(node, facing, nodeOffset)) { - this.addEdge(node, nodeOffset); + this.addUndirectedEdge(node, nodeOffset); + this.predicateUndirectedEdge(node, nodeOffset, facing); } } } @@ -203,7 +218,7 @@ public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean if (nodeOffset == null) return; if (!node.isBlocked(side) && !nodeOffset.isBlocked(side.getOpposite())) { - addEdge(node, nodeOffset); + addEdge(node, nodeOffset, null); } else { removeEdge(node, nodeOffset); } @@ -225,7 +240,7 @@ public void updateMark(BlockPos nodePos, int newMark) { if (areMarksCompatible(oldMark, nodeOffset.mark) == areMarksCompatible(newMark, nodeOffset.mark)) continue; if (areMarksCompatible(newMark, nodeOffset.mark)) { - addEdge(node, nodeOffset); + addEdge(node, nodeOffset, null); } else { removeEdge(node, nodeOffset); } @@ -247,44 +262,83 @@ public void addNode(NodeG node) { this.markDirty(); } - public void addEdge(NodeG source, NodeG target) { - addEdge(source, target, source.data.getWeightFactor() + target.data.getWeightFactor()); + public NodeG getNode(BlockPos pos) { + return this.pipeMap.get(pos); + } + + public void addUndirectedEdge(NodeG source, NodeG target) { + this.addEdge(source, target, null); + this.addEdge(target, source, null); + } + + public void addEdge(NodeG source, NodeG target, @Nullable AbstractEdgePredicate predicate) { + addEdge(source, target, source.data.getWeightFactor() + target.data.getWeightFactor(), predicate); this.validAlgorithmInstance = false; } - public NodeG getNode(BlockPos pos) { - return this.pipeMap.get(pos); + public void addUndirectedEdge(NodeG source, NodeG target, double weight) { + this.addEdge(source, target, weight, null); + this.addEdge(target, source, weight, null); } - public void addEdge(NodeG source, NodeG target, double weight) { + public void addEdge(NodeG source, NodeG target, double weight, @Nullable AbstractEdgePredicate predicate) { if (pipeGraph.addEdge(source, target) != null) { if (NetGroup.mergeEdge(source, target)) { new NetGroup<>(this.pipeGraph).addNodes(source, target); } pipeGraph.setEdgeWeight(source, target, weight); + if (predicate != null) { + pipeGraph.getEdge(source, target).setPredicate(predicate); + } this.validAlgorithmInstance = false; this.markDirty(); } } + public void predicateUndirectedEdge(BlockPos pos, EnumFacing faceToNeighbour) { + NodeG source = this.pipeMap.get(pos); + NodeG target = this.pipeMap.get(pos.offset(faceToNeighbour)); + if (source != null && target != null) { + this.predicateUndirectedEdge(source, target, faceToNeighbour); + } + } + public void predicateEdge(BlockPos pos, EnumFacing faceToNeighbour) { NodeG source = this.pipeMap.get(pos); NodeG target = this.pipeMap.get(pos.offset(faceToNeighbour)); + if (source != null && target != null) + this.predicateEdge(source, target, faceToNeighbour); + } + + public void predicateUndirectedEdge(NodeG source, NodeG target, EnumFacing faceToNeighbour) { + this.predicateEdge(source, target, faceToNeighbour); + this.predicateEdge(target, source, faceToNeighbour.getOpposite()); + } + + public void predicateEdge(NodeG source, NodeG target, EnumFacing faceToNeighbour) { Cover thisCover = source.heldMTE.getCoverableImplementation().getCoverAtSide(faceToNeighbour); Cover neighbourCover = target.heldMTE.getCoverableImplementation().getCoverAtSide(faceToNeighbour.getOpposite()); - List> filters = new ArrayList<>(); - if (thisCover instanceof CoverShutter) { - filters.add(o -> !((CoverShutter) thisCover).isWorkingEnabled()); - } - if (neighbourCover instanceof CoverShutter) { - filters.add(o -> !((CoverShutter) neighbourCover).isWorkingEnabled()); - } - filters.add(getPredicate(thisCover, neighbourCover)); + AbstractEdgePredicate predicate = getPredicate(thisCover, neighbourCover); + predicate.setPosInfo(source.getNodePos(), target.getNodePos()); NetEdge edge = this.pipeGraph.getEdge(source, target); - edge.setPredicates(filters); + edge.setPredicate(predicate); + } + + protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbourCover) { + return shutterify(new BasicPredicate(), thisCover, neighbourCover); } - protected abstract Predicate getPredicate(Cover thisCover, Cover neighbourCover); + protected final AbstractEdgePredicate shutterify(AbstractEdgePredicate predicate, @Nullable Cover thisCover, @Nullable Cover neighbourCover) { + if (predicate instanceof BasicPredicate basicPredicate) { + if (thisCover instanceof CoverShutter shutter) { + basicPredicate.setShutteredSource(shutter.isWorkingEnabled()); + } + if (neighbourCover instanceof CoverShutter shutter) { + basicPredicate.setShutteredTarget(shutter.isWorkingEnabled()); + } + } + return predicate; + } public void removeEdge(NodeG source, NodeG target) { if (source.getGroup() != null && source.getGroup().splitEdge(source, target)) { diff --git a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java index f4c428139fc..bda0dfd79e7 100644 --- a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java @@ -60,7 +60,7 @@ @SuppressWarnings("deprecation") public abstract class BlockPipe & IPipeType, - NodeDataType extends INodeData, + NodeDataType extends INodeData, WorldPipeNetType extends WorldPipeNetG> extends BuiltInRenderBlock implements ITileEntityProvider, IFacadeWrapper, IBlockAppearance { diff --git a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java index 199ac7f2696..86863f91849 100644 --- a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java +++ b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java @@ -16,7 +16,7 @@ import java.util.function.Consumer; -public interface IPipeTile & IPipeType, NodeDataType extends INodeData> +public interface IPipeTile & IPipeType, NodeDataType extends INodeData> extends INeighborCache { World getPipeWorld(); diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 6ad464f6f74..1123d753674 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -35,7 +35,7 @@ import static gregtech.api.capability.GregtechDataCodes.*; public abstract class TileEntityPipeBase & IPipeType, - NodeDataType extends INodeData> extends NeighborCacheTileEntityBase + NodeDataType extends INodeData> extends NeighborCacheTileEntityBase implements IPipeTile { protected final PipeCoverableImplementation coverableImplementation = new PipeCoverableImplementation(this); @@ -110,6 +110,7 @@ public BlockPos getPipePos() { public void markDirty() { if (getWorld() != null && getPos() != null) { getWorld().markChunkDirty(getPos(), this); + } } @@ -424,7 +425,8 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { @Override public void onLoad() { super.onLoad(); - this.coverableImplementation.onLoad(); + this.pipeBlock.getWorldPipeNet(this.getWorld()).addNode(this.getPipePos(), this.getNodeData(), + this.getCableMark(), ~(this.getBlockedConnections()), true, this); } protected void writePipeProperties(PacketBuffer buf) { diff --git a/src/main/java/gregtech/api/util/function/QuadConsumer.java b/src/main/java/gregtech/api/util/function/QuadConsumer.java new file mode 100644 index 00000000000..1b8ff8e8f88 --- /dev/null +++ b/src/main/java/gregtech/api/util/function/QuadConsumer.java @@ -0,0 +1,7 @@ +package gregtech.api.util.function; + +@FunctionalInterface +public interface QuadConsumer { + + void accept(T t, U u, S s, G g); +} diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemPredicate.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemPredicate.java new file mode 100644 index 00000000000..f8e3d4d74f6 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemPredicate.java @@ -0,0 +1,84 @@ +package gregtech.common.pipelike.itempipe.net; + +import gregtech.api.pipenet.AbstractEdgePredicate; + +import gregtech.api.util.IDirtyNotifiable; +import gregtech.common.covers.filter.ItemFilterWrapper; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import org.jetbrains.annotations.NotNull; + +public class ItemPredicate extends AbstractEdgePredicate { + + private final static Decoy DECOY = new Decoy(); + + static { + PREDICATES.put("Item", new ItemPredicate()); + } + + protected boolean shutteredSource; + protected boolean shutteredTarget; + + ItemFilterWrapper sourceFilter = new ItemFilterWrapper(DECOY); + ItemFilterWrapper targetFilter; + + public void setSourceFilter(ItemFilterWrapper sourceFilter) { + this.sourceFilter = sourceFilter; + } + + public void setTargetFilter(ItemFilterWrapper targetFilter) { + this.targetFilter = targetFilter; + } + + @Override + public boolean test(Object o) { + if (shutteredSource || shutteredTarget) return false; + if (!(o instanceof ItemStack stack)) return false; + return sourceFilter.testItemStack(stack) && targetFilter.testItemStack(stack); + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + if (shutteredSource) tag.setBoolean("ShutteredSource", true); + if (shutteredTarget) tag.setBoolean("ShutteredTarget", true); + tag.setBoolean("SourceBlacklist", this.sourceFilter.isBlacklistFilter()); + NBTTagCompound filterComponent = new NBTTagCompound(); + this.sourceFilter.getItemFilter().writeToNBT(filterComponent); + tag.setTag("SourceFilter", filterComponent); + tag.setBoolean("TargetBlacklist", this.targetFilter.isBlacklistFilter()); + filterComponent = new NBTTagCompound(); + this.targetFilter.getItemFilter().writeToNBT(filterComponent); + tag.setTag("TargetFilter", filterComponent); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + shutteredSource = nbt.getBoolean("ShutteredSource"); + shutteredTarget = nbt.getBoolean("ShutteredTarget"); + this.sourceFilter.setBlacklistFilter(nbt.getBoolean("SourceBlacklist")); + this.sourceFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("SourceFilter")); + this.targetFilter.setBlacklistFilter(nbt.getBoolean("TargetBlacklist")); + this.targetFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("TargetFilter")); + + } + + @Override + public @NotNull ItemPredicate createPredicate() { + return new ItemPredicate(); + } + + @Override + protected String predicateType() { + return "Item"; + } + + private static class Decoy implements IDirtyNotifiable { + + @Override + public void markAsDirty() {} + } +} diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index 0a29cba6d23..8e5d63ed345 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -1,6 +1,7 @@ package gregtech.common.pipelike.itempipe.net; import gregtech.api.cover.Cover; +import gregtech.api.pipenet.AbstractEdgePredicate; import gregtech.api.pipenet.WorldPipeNet; import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.tile.IPipeTile; @@ -43,20 +44,17 @@ protected Class> getBasePi } @Override - protected Predicate getPredicate(Cover thisCover, Cover neighbourCover) { - return o -> { - if (!(o instanceof ItemStack s)) return false; - boolean b = true; - if (thisCover instanceof CoverItemFilter filter && - filter.getFilterMode() != ItemFilterMode.FILTER_INSERT) { - b = filter.testItemStack(s); - } - if (b && neighbourCover instanceof CoverItemFilter filter && - filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT) { - b = filter.testItemStack(s); - } - return b; - }; + protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbourCover) { + ItemPredicate predicate = new ItemPredicate(); + if (thisCover instanceof CoverItemFilter filter && + filter.getFilterMode() != ItemFilterMode.FILTER_INSERT) { + predicate.setSourceFilter(filter.getItemFilter()); + } + if (neighbourCover instanceof CoverItemFilter filter && + filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT) { + predicate.setTargetFilter(filter.getItemFilter()); + } + return shutterify(predicate, thisCover, neighbourCover); } @Override From 2cf45ba64f9767364160493dd6bb7bb8b087a10f Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 18 Dec 2023 13:50:59 -0700 Subject: [PATCH 013/157] Final item pipenet cleanup --- .../gregtech/api/pipenet/PipeNetWalker.java | 2 - .../gregtech/api/pipenet/WorldPipeNetG.java | 6 +- .../gregtech/api/pipenet/block/BlockPipe.java | 2 - .../api/pipenet/tile/TileEntityPipeBase.java | 4 +- .../pipelike/itempipe/net/ItemNetHandler.java | 2 +- .../pipelike/itempipe/net/ItemNetWalker.java | 132 ------------------ .../pipelike/itempipe/net/ItemPipeNet.java | 73 ---------- .../pipelike/itempipe/net/ItemRoutePath.java | 71 ---------- .../itempipe/tile/TileEntityItemPipe.java | 1 - 9 files changed, 8 insertions(+), 285 deletions(-) delete mode 100644 src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetWalker.java delete mode 100644 src/main/java/gregtech/common/pipelike/itempipe/net/ItemPipeNet.java delete mode 100644 src/main/java/gregtech/common/pipelike/itempipe/net/ItemRoutePath.java diff --git a/src/main/java/gregtech/api/pipenet/PipeNetWalker.java b/src/main/java/gregtech/api/pipenet/PipeNetWalker.java index 3b70d1cf3b4..03dd561cc40 100644 --- a/src/main/java/gregtech/api/pipenet/PipeNetWalker.java +++ b/src/main/java/gregtech/api/pipenet/PipeNetWalker.java @@ -2,7 +2,6 @@ import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.util.GTLog; -import gregtech.common.pipelike.itempipe.net.ItemNetWalker; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; @@ -25,7 +24,6 @@ *

* Do not walk a walker more than once *

- * For example implementations look at {@link ItemNetWalker} */ public abstract class PipeNetWalker> { diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index d26a12ec105..d3ce6553c16 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -165,7 +165,8 @@ public void addNode(BlockPos nodePos, NodeDataType nodeData, int mark, int openC if (heldMTE != null && this.pipeMap.containsKey(nodePos)) { this.syncNode(heldMTE); return; - } else if (heldMTE == null) { + } + if (heldMTE == null) { heldMTE = castTE(this.getWorld().getTileEntity(nodePos)); } NodeG node = new NodeG<>(nodeData, openConnections, mark, isActive, heldMTE, nodePos); @@ -216,6 +217,7 @@ public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean node.setBlocked(side, isBlocked); NodeG nodeOffset = pipeMap.get(nodePos.offset(side)); if (nodeOffset == null) return; + this.predicateEdge(node, nodeOffset, side); if (!node.isBlocked(side) && !nodeOffset.isBlocked(side.getOpposite())) { addEdge(node, nodeOffset, null); @@ -239,6 +241,8 @@ public void updateMark(BlockPos nodePos, int newMark) { continue; if (areMarksCompatible(oldMark, nodeOffset.mark) == areMarksCompatible(newMark, nodeOffset.mark)) continue; + this.predicateEdge(node, nodeOffset, side); + if (areMarksCompatible(newMark, nodeOffset.mark)) { addEdge(node, nodeOffset, null); } else { diff --git a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java index bda0dfd79e7..0344bdf90a0 100644 --- a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java @@ -147,8 +147,6 @@ public void updateTick(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull I if (pipeTile != null) { int activeConnections = pipeTile.getConnections(); boolean isActiveNode = activeConnections != 0; - getWorldPipeNet(worldIn).addNode(pos, createProperties(pipeTile), 0, activeConnections, isActiveNode, - pipeTile); onActiveModeChange(worldIn, pos, isActiveNode, true); } } diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 1123d753674..1e2e0dcce34 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -110,7 +110,7 @@ public BlockPos getPipePos() { public void markDirty() { if (getWorld() != null && getPos() != null) { getWorld().markChunkDirty(getPos(), this); - + getPipeBlock().getWorldPipeNet(getWorld()).syncNode(this); } } @@ -426,7 +426,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { public void onLoad() { super.onLoad(); this.pipeBlock.getWorldPipeNet(this.getWorld()).addNode(this.getPipePos(), this.getNodeData(), - this.getCableMark(), ~(this.getBlockedConnections()), true, this); + this.getCableMark(), ~(this.getBlockedConnections()), false, this); } protected void writePipeProperties(PacketBuffer buf) { diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index c73f8df6461..7efa506aee6 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -467,7 +467,7 @@ private void transferTo(NetPath.FacedNetPath r pipe.getTransferred().merge(routePath.toFacingPos(), amount, Integer::sum); } - private boolean contains(ItemRoutePath routePath, boolean simulate) { + private boolean contains(NetPath.FacedNetPath routePath, boolean simulate) { return simulate ? simulatedTransfersGlobalRoundRobin.containsKey(routePath.toFacingPos()) : pipe.getTransferred().containsKey(routePath.toFacingPos()); } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetWalker.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetWalker.java deleted file mode 100644 index 1ba92d3845e..00000000000 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetWalker.java +++ /dev/null @@ -1,132 +0,0 @@ -package gregtech.common.pipelike.itempipe.net; - -import gregtech.api.cover.Cover; -import gregtech.api.pipenet.PipeNetWalker; -import gregtech.api.unification.material.properties.ItemPipeProperties; -import gregtech.api.util.GTUtility; -import gregtech.common.covers.CoverItemFilter; -import gregtech.common.covers.CoverShutter; -import gregtech.common.covers.ItemFilterMode; -import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; - -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.function.Predicate; - -public class ItemNetWalker extends PipeNetWalker { - - public static List createNetData(World world, BlockPos sourcePipe, EnumFacing faceToSourceHandler) { - if (!(world.getTileEntity(sourcePipe) instanceof TileEntityItemPipe)) { - return null; - } - ItemNetWalker walker = new ItemNetWalker(world, sourcePipe, 1, new ArrayList<>(), null); - walker.sourcePipe = sourcePipe; - walker.facingToHandler = faceToSourceHandler; - walker.traversePipeNet(); - return walker.isFailed() ? null : walker.inventories; - } - - private ItemPipeProperties minProperties; - private final List inventories; - private final List> filters = new ArrayList<>(); - private final EnumMap>> nextFilters = new EnumMap<>(EnumFacing.class); - private BlockPos sourcePipe; - private EnumFacing facingToHandler; - - protected ItemNetWalker(World world, BlockPos sourcePipe, int distance, List inventories, - ItemPipeProperties properties) { - super(world, sourcePipe, distance); - this.inventories = inventories; - this.minProperties = properties; - } - - @Override - protected PipeNetWalker createSubWalker(World world, EnumFacing facingToNextPos, - BlockPos nextPos, int walkedBlocks) { - ItemNetWalker walker = new ItemNetWalker(world, nextPos, walkedBlocks, inventories, minProperties); - walker.facingToHandler = facingToHandler; - walker.sourcePipe = sourcePipe; - walker.filters.addAll(filters); - List> moreFilters = nextFilters.get(facingToNextPos); - if (moreFilters != null && !moreFilters.isEmpty()) { - walker.filters.addAll(moreFilters); - } - return walker; - } - - @Override - protected void checkPipe(TileEntityItemPipe pipeTile, BlockPos pos) { - for (List> filters : nextFilters.values()) { - if (!filters.isEmpty()) { - this.filters.addAll(filters); - } - } - nextFilters.clear(); - ItemPipeProperties pipeProperties = pipeTile.getNodeData(); - if (minProperties == null) { - minProperties = pipeProperties; - } else { - minProperties = new ItemPipeProperties(minProperties.getPriority() + pipeProperties.getPriority(), - Math.min(minProperties.getTransferRate(), pipeProperties.getTransferRate())); - } - } - - @Override - protected void checkNeighbour(TileEntityItemPipe pipeTile, BlockPos pipePos, EnumFacing faceToNeighbour, - @Nullable TileEntity neighbourTile) { - if (neighbourTile == null || - (GTUtility.arePosEqual(pipePos, sourcePipe) && faceToNeighbour == facingToHandler)) { - return; - } - IItemHandler handler = neighbourTile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, - faceToNeighbour.getOpposite()); - if (handler != null) { - List> filters = new ArrayList<>(this.filters); - List> moreFilters = nextFilters.get(faceToNeighbour); - if (moreFilters != null && !moreFilters.isEmpty()) { - filters.addAll(moreFilters); - } - inventories.add(new ItemRoutePath(pipeTile, faceToNeighbour, getWalkedBlocks(), minProperties, filters)); - } - } - - @Override - protected Class getBasePipeClass() { - return TileEntityItemPipe.class; - } - - @Override - protected boolean isValidPipe(TileEntityItemPipe currentPipe, TileEntityItemPipe neighbourPipe, BlockPos pipePos, - EnumFacing faceToNeighbour) { - Cover thisCover = currentPipe.getCoverableImplementation().getCoverAtSide(faceToNeighbour); - Cover neighbourCover = neighbourPipe.getCoverableImplementation().getCoverAtSide(faceToNeighbour.getOpposite()); - List> filters = new ArrayList<>(); - if (thisCover instanceof CoverShutter) { - filters.add(stack -> !((CoverShutter) thisCover).isWorkingEnabled()); - } else if (thisCover instanceof CoverItemFilter && - ((CoverItemFilter) thisCover).getFilterMode() != ItemFilterMode.FILTER_INSERT) { - filters.add(((CoverItemFilter) thisCover)::testItemStack); - } - if (neighbourCover instanceof CoverShutter) { - filters.add(stack -> !((CoverShutter) neighbourCover).isWorkingEnabled()); - } else if (neighbourCover instanceof CoverItemFilter && - ((CoverItemFilter) neighbourCover).getFilterMode() != ItemFilterMode.FILTER_EXTRACT) { - filters.add(((CoverItemFilter) neighbourCover)::testItemStack); - } - if (!filters.isEmpty()) { - nextFilters.put(faceToNeighbour, filters); - } - return true; - } -} diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemPipeNet.java deleted file mode 100644 index c836119c344..00000000000 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemPipeNet.java +++ /dev/null @@ -1,73 +0,0 @@ -package gregtech.common.pipelike.itempipe.net; - -import gregtech.api.pipenet.Node; -import gregtech.api.pipenet.PipeNet; -import gregtech.api.pipenet.WorldPipeNet; -import gregtech.api.unification.material.properties.ItemPipeProperties; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; - -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ItemPipeNet extends PipeNet { - - private final Map> NET_DATA = new HashMap<>(); - - public ItemPipeNet(WorldPipeNet> world) { - super(world); - } - - public List getNetData(BlockPos pipePos, EnumFacing facing) { - List data = NET_DATA.get(pipePos); - if (data == null) { - data = ItemNetWalker.createNetData(getWorldData(), pipePos, facing); - if (data == null) { - // walker failed, don't cache so it tries again on next insertion - return Collections.emptyList(); - } - data.sort(Comparator.comparingInt(inv -> inv.getProperties().getPriority())); - NET_DATA.put(pipePos, data); - } - return data; - } - - @Override - public void onNeighbourUpdate(BlockPos fromPos) { - NET_DATA.clear(); - } - - @Override - public void onPipeConnectionsUpdate() { - NET_DATA.clear(); - } - - @Override - public void onChunkUnload() { - NET_DATA.clear(); - } - - @Override - protected void transferNodeData(Map> transferredNodes, - PipeNet parentNet) { - super.transferNodeData(transferredNodes, parentNet); - NET_DATA.clear(); - ((ItemPipeNet) parentNet).NET_DATA.clear(); - } - - @Override - protected void writeNodeData(ItemPipeProperties nodeData, NBTTagCompound tagCompound) { - tagCompound.setInteger("Resistance", nodeData.getPriority()); - tagCompound.setFloat("Rate", nodeData.getTransferRate()); - } - - @Override - protected ItemPipeProperties readNodeData(NBTTagCompound tagCompound) { - return new ItemPipeProperties(tagCompound.getInteger("Range"), tagCompound.getFloat("Rate")); - } -} diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemRoutePath.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemRoutePath.java deleted file mode 100644 index 518ffad8802..00000000000 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemRoutePath.java +++ /dev/null @@ -1,71 +0,0 @@ -package gregtech.common.pipelike.itempipe.net; - -import gregtech.api.pipenet.IRoutePath; -import gregtech.api.unification.material.properties.ItemPipeProperties; -import gregtech.api.util.FacingPos; -import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; - -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumFacing; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -import org.jetbrains.annotations.NotNull; - -import java.util.List; -import java.util.function.Predicate; - -public class ItemRoutePath implements IRoutePath { - - private final TileEntityItemPipe targetPipe; - private final EnumFacing faceToHandler; - private final int distance; - private final ItemPipeProperties properties; - private final Predicate filters; - - public ItemRoutePath(TileEntityItemPipe targetPipe, EnumFacing facing, int distance, ItemPipeProperties properties, - List> filters) { - this.targetPipe = targetPipe; - this.faceToHandler = facing; - this.distance = distance; - this.properties = properties; - this.filters = stack -> { - for (Predicate filter : filters) - if (!filter.test(stack)) return false; - return true; - }; - } - - @NotNull - @Override - public TileEntityItemPipe getTargetPipe() { - return targetPipe; - } - - @NotNull - @Override - public EnumFacing getTargetFacing() { - return faceToHandler; - } - - @Override - public int getDistance() { - return distance; - } - - public ItemPipeProperties getProperties() { - return properties; - } - - public boolean matchesFilters(ItemStack stack) { - return filters.test(stack); - } - - public IItemHandler getHandler() { - return getTargetCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); - } - - public FacingPos toFacingPos() { - return new FacingPos(getTargetPipePos(), faceToHandler); - } -} diff --git a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java index 9cc4977b4a5..8558e0b7243 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java @@ -6,7 +6,6 @@ import gregtech.api.util.FacingPos; import gregtech.common.pipelike.itempipe.ItemPipeType; import gregtech.common.pipelike.itempipe.net.ItemNetHandler; -import gregtech.common.pipelike.itempipe.net.ItemPipeNet; import gregtech.common.pipelike.itempipe.net.WorldItemPipeNet; import net.minecraft.util.EnumFacing; From 31af6273c860b7c4ae34ea044ddc95ef43ed95eb Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 18 Dec 2023 13:57:09 -0700 Subject: [PATCH 014/157] Allow control over directed graphing --- .../gregtech/api/pipenet/WorldPipeNetG.java | 20 +++++++++++++++---- .../itempipe/net/WorldItemPipeNet.java | 5 +++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index d3ce6553c16..5b6a94f284f 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -25,6 +25,7 @@ import org.jgrapht.GraphPath; import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; import org.jgrapht.graph.DirectedWeightedMultigraph; +import org.jgrapht.graph.SimpleWeightedGraph; import java.lang.ref.WeakReference; import java.util.Collections; @@ -46,7 +47,18 @@ public abstract class WorldPipeNetG public WorldPipeNetG(String name) { super(name); - this.pipeGraph = new DirectedWeightedMultigraph<>(NetEdge.class); + if (isDirected()) + this.pipeGraph = new DirectedWeightedMultigraph<>(NetEdge.class); + else this.pipeGraph = new SimpleWeightedGraph<>(NetEdge.class); + } + + /** + * Override to change whether this net needs directed graph handling. + * Used to respect filter directions in the item net and fluid net, for example. + * @return true if the graph should be directed + */ + protected boolean isDirected() { + return false; } public World getWorld() { @@ -272,7 +284,7 @@ public NodeG getNode(BlockPos pos) { public void addUndirectedEdge(NodeG source, NodeG target) { this.addEdge(source, target, null); - this.addEdge(target, source, null); + if (this.isDirected()) this.addEdge(target, source, null); } public void addEdge(NodeG source, NodeG target, @Nullable AbstractEdgePredicate predicate) { @@ -282,7 +294,7 @@ public void addEdge(NodeG source, NodeG source, NodeG target, double weight) { this.addEdge(source, target, weight, null); - this.addEdge(target, source, weight, null); + if (this.isDirected()) this.addEdge(target, source, weight, null); } public void addEdge(NodeG source, NodeG target, double weight, @Nullable AbstractEdgePredicate predicate) { @@ -316,7 +328,7 @@ public void predicateEdge(BlockPos pos, EnumFacing faceToNeighbour) { public void predicateUndirectedEdge(NodeG source, NodeG target, EnumFacing faceToNeighbour) { this.predicateEdge(source, target, faceToNeighbour); - this.predicateEdge(target, source, faceToNeighbour.getOpposite()); + if (this.isDirected()) this.predicateEdge(target, source, faceToNeighbour.getOpposite()); } public void predicateEdge(NodeG source, NodeG target, EnumFacing faceToNeighbour) { diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index 8e5d63ed345..781b42574e7 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -38,6 +38,11 @@ public WorldItemPipeNet(String name) { super(name); } + @Override + protected boolean isDirected() { + return true; + } + @Override protected Class> getBasePipeClass() { return TileEntityItemPipe.class; From 3bdad1f381d0c481686a0ccfac4c9d8f44811de9 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 18 Dec 2023 15:51:47 -0700 Subject: [PATCH 015/157] laughs in someone else's typo --- .../gregtech/api/capability/GregtechTileCapabilities.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/gregtech/api/capability/GregtechTileCapabilities.java b/src/main/java/gregtech/api/capability/GregtechTileCapabilities.java index 0d7a53cc813..170ec74984f 100644 --- a/src/main/java/gregtech/api/capability/GregtechTileCapabilities.java +++ b/src/main/java/gregtech/api/capability/GregtechTileCapabilities.java @@ -7,6 +7,8 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; +import org.jetbrains.annotations.ApiStatus; + public class GregtechTileCapabilities { @CapabilityInject(IWorkable.class) @@ -36,6 +38,11 @@ public class GregtechTileCapabilities { @CapabilityInject(ILaserContainer.class) public static Capability CAPABILITY_LASER = null; + @CapabilityInject(IOpticalComputationProvider.class) + public static Capability CAPABILITY_COMPUTATION_PROVIDER = null; + + @Deprecated + @ApiStatus.ScheduledForRemoval(inVersion = "2.9") @CapabilityInject(IOpticalComputationProvider.class) public static Capability CABABILITY_COMPUTATION_PROVIDER = null; } From 13b204ce60f9aad1d6a6c9a3968917ae5c11e7fe Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 18 Dec 2023 15:57:29 -0700 Subject: [PATCH 016/157] API for single-path networks, converted optical and laser. --- .../java/gregtech/api/pipenet/NetGroup.java | 2 +- .../java/gregtech/api/pipenet/NetPath.java | 36 ++++++++ src/main/java/gregtech/api/pipenet/NodeG.java | 2 +- .../gregtech/api/pipenet/WorldPipeNetG.java | 64 ++++++++++++-- .../gregtech/api/pipenet/block/IPipeType.java | 2 +- .../MetaTileEntityComputationHatch.java | 6 +- .../itempipe/net/WorldItemPipeNet.java | 4 +- .../common/pipelike/laser/LaserPipeType.java | 4 +- .../pipelike/laser/net/LaserNetHandler.java | 43 +++++---- .../pipelike/laser/net/LaserNetWalker.java | 87 ------------------- .../pipelike/laser/net/LaserPipeNet.java | 69 --------------- .../pipelike/laser/net/LaserRoutePath.java | 66 -------------- .../pipelike/laser/net/WorldLaserPipeNet.java | 32 +++++-- .../laser/tile/TileEntityLaserPipe.java | 37 +------- .../pipelike/optical/BlockOpticalPipe.java | 2 +- .../optical/net/OpticalNetHandler.java | 54 +++++++----- .../optical/net/OpticalNetWalker.java | 72 --------------- .../pipelike/optical/net/OpticalPipeNet.java | 70 --------------- .../optical/net/OpticalRoutePath.java | 53 ----------- .../optical/net/WorldOpticalPipeNet.java | 32 +++++-- .../optical/tile/TileEntityOpticalPipe.java | 43 +-------- 21 files changed, 226 insertions(+), 554 deletions(-) delete mode 100644 src/main/java/gregtech/common/pipelike/laser/net/LaserNetWalker.java delete mode 100644 src/main/java/gregtech/common/pipelike/laser/net/LaserPipeNet.java delete mode 100644 src/main/java/gregtech/common/pipelike/laser/net/LaserRoutePath.java delete mode 100644 src/main/java/gregtech/common/pipelike/optical/net/OpticalNetWalker.java delete mode 100644 src/main/java/gregtech/common/pipelike/optical/net/OpticalPipeNet.java delete mode 100644 src/main/java/gregtech/common/pipelike/optical/net/OpticalRoutePath.java diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 3e814acda69..a12e7b9954e 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -164,7 +164,7 @@ public boolean splitEdge(NodeG source, NodeG> getNodes() { + public Set> getNodes() { return nodes; } diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index cdbd33767f2..0ffae692fa8 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -4,6 +4,8 @@ import gregtech.api.util.FacingPos; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; @@ -29,6 +31,40 @@ public class NetPath & IPipeType, private Iterator facingIterator; + /** + * Generates a loop NetPath for a node + * @param node the node to + */ + public NetPath(NodeG node) { + this.sourceNode = node; + this.targetNode = node; + this.nodeList = new ObjectArrayList<>(1); + this.nodeList.add(node); + this.weight = 0; + this.edgeList = new ObjectArrayList<>(0); + resetFacingIterator(); + } + + /** + * Generates a NetPath from an ordered list of nodes, edges, and a weight. + * Used exclusively for single path generation. + * @param nodes List of nodes. + * @param edges List of edges. + * @param weight Sum weight of the path. + */ + public NetPath(List> nodes, List edges, double weight) { + this.sourceNode = nodes.get(0); + this.targetNode = nodes.get(nodes.size() - 1); + this.nodeList = nodes; + this.weight = weight; + this.edgeList = edges; + resetFacingIterator(); + } + + /** + * Generates a NetPath from a GraphPath + * @param path the GraphPath + */ public NetPath(GraphPath, NetEdge> path) { this.sourceNode = path.getStartVertex(); this.targetNode = path.getEndVertex(); diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index b397ac1ada9..c31c7c1363e 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -80,7 +80,7 @@ public NodeG(NBTTagCompound tag, WorldPipeNetG net) { } @Nullable - NetGroup getGroup() { + public NetGroup getGroup() { return group; } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 5b6a94f284f..6071914e4ca 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -26,10 +26,12 @@ import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; import org.jgrapht.graph.DirectedWeightedMultigraph; import org.jgrapht.graph.SimpleWeightedGraph; +import org.jgrapht.traverse.DepthFirstIterator; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.Comparator; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -55,12 +57,21 @@ public WorldPipeNetG(String name) { /** * Override to change whether this net needs directed graph handling. * Used to respect filter directions in the item net and fluid net, for example. - * @return true if the graph should be directed + * @return True if the graph should be directed. */ protected boolean isDirected() { return false; } + /** + * Override to change whether this net allows only one source and one destination per group. + * Allows for optimizations in path lookup and cache invalidation. + * @return True if the graph should be single-pathed. + */ + protected boolean isSinglePath() { + return false; + } + public World getWorld() { return this.worldRef.get(); } @@ -117,7 +128,8 @@ public List> getPaths( return verifyList(cache, node); } - List> list = this.shortestPaths.getPathsList(node); + List> list = + isSinglePath() ? this.singlePathList(node) : this.shortestPaths.getPathsList(node); return verifyList(node.setPathCache(list), node); } @@ -388,7 +400,8 @@ public boolean markNodeAsActive(BlockPos nodePos, boolean isActive) { } protected void rebuildShortestPaths() { - this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph); + // No need to calculate the ShortestPathsAlgorithm if we are single-pathed. + if (!this.isSinglePath()) this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph); this.validAlgorithmInstance = true; } @@ -452,10 +465,11 @@ public ShortestPathsAlgorithm(Graph, NetEdge> graph) { public List> getPathsList(NodeG source) { if (!graph.containsVertex(source)) { - throw new IllegalArgumentException("graph must contain the source vertex"); + throw new IllegalArgumentException("Graph must contain the source vertex"); } List> paths = new ObjectArrayList<>(); - // if the source has no group, it has no paths. + paths.add(new NetPath<>(source)); + // if the source has no group, it has no paths other than the path to itself. if (source.getGroup() == null) return paths; ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths( Collections.singleton(source), source.getGroup().getNodes()); @@ -475,4 +489,44 @@ public List> getPathsList(NodeG source) { return paths; } } + + /** + * Special path lookup for single-path graphs. + * Allows us to skip calculating the ShortestPathsAlgorithm every time the graph updates. + * @param source Source node for the path. + * @return A list containing one or fewer paths. + */ + private List> singlePathList(NodeG source) { + if (!this.pipeGraph.containsVertex(source)) { + throw new IllegalArgumentException("Graph must contain the source vertex"); + } + List> paths = new ObjectArrayList<>(); + List edges = new ObjectArrayList<>(); + List> nodes = new ObjectArrayList<>(); + nodes.add(source); + NodeG lastNode = null; + NodeG node = source; + NetEdge edge; + double sumWeight = source.data.getWeightFactor(); + boolean valid = true; + while (valid) { + Iterator i = this.pipeGraph.edgesOf(node).iterator(); + if (!i.hasNext()) break; // we've reached the end, exit the loop while still valid + edge = i.next(); + if (edge.getTarget() == lastNode) { + if (i.hasNext()) edge = i.next(); + else break; // we've reached the end, exit the loop while still valid + } else if (i.hasNext()) i.next(); + if (i.hasNext()) valid = false; // third edge detected - that's an invalid group + lastNode = node; + node = (NodeG) edge.getTarget(); + edges.add(edge); + nodes.add(node); + sumWeight += node.data.getWeightFactor(); + } + if (!valid) return paths; + if (paths.size() == 0) paths.add(new NetPath<>(source)); + else paths.add(new NetPath<>(nodes, edges, sumWeight)); + return paths; + } } diff --git a/src/main/java/gregtech/api/pipenet/block/IPipeType.java b/src/main/java/gregtech/api/pipenet/block/IPipeType.java index 89442a6da24..baff9640dc6 100644 --- a/src/main/java/gregtech/api/pipenet/block/IPipeType.java +++ b/src/main/java/gregtech/api/pipenet/block/IPipeType.java @@ -4,7 +4,7 @@ import net.minecraft.util.IStringSerializable; -public interface IPipeType extends IStringSerializable { +public interface IPipeType> extends IStringSerializable { float getThickness(); diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java index 850ea3730be..2ca9502f65d 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java @@ -118,7 +118,7 @@ private IOpticalComputationProvider getOpticalNetProvider() { if (tileEntity == null) return null; if (tileEntity instanceof TileEntityOpticalPipe) { - return tileEntity.getCapability(GregtechTileCapabilities.CABABILITY_COMPUTATION_PROVIDER, + return tileEntity.getCapability(GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER, getFrontFacing().getOpposite()); } return null; @@ -161,8 +161,8 @@ public void registerAbilities(List abilityList) { @Override public T getCapability(Capability capability, EnumFacing side) { - if (side == getFrontFacing() && capability == GregtechTileCapabilities.CABABILITY_COMPUTATION_PROVIDER) { - return GregtechTileCapabilities.CABABILITY_COMPUTATION_PROVIDER.cast(this); + if (side == getFrontFacing() && capability == GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER) { + return GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER.cast(this); } return super.getCapability(capability, side); } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index 781b42574e7..e3257a9c861 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -64,12 +64,12 @@ protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbour @Override protected void writeNodeData(ItemPipeProperties nodeData, NBTTagCompound tagCompound) { - tagCompound.setInteger("Resistance", nodeData.getPriority()); + tagCompound.setInteger("Priority", nodeData.getPriority()); tagCompound.setFloat("Rate", nodeData.getTransferRate()); } @Override protected ItemPipeProperties readNodeData(NBTTagCompound tagCompound) { - return new ItemPipeProperties(tagCompound.getInteger("Range"), tagCompound.getFloat("Rate")); + return new ItemPipeProperties(tagCompound.getInteger("Priority"), tagCompound.getFloat("Rate")); } } diff --git a/src/main/java/gregtech/common/pipelike/laser/LaserPipeType.java b/src/main/java/gregtech/common/pipelike/laser/LaserPipeType.java index b524b392bb1..13cf1398b9b 100644 --- a/src/main/java/gregtech/common/pipelike/laser/LaserPipeType.java +++ b/src/main/java/gregtech/common/pipelike/laser/LaserPipeType.java @@ -2,12 +2,14 @@ import gregtech.api.pipenet.block.IPipeType; +import org.jetbrains.annotations.NotNull; + public enum LaserPipeType implements IPipeType { NORMAL; @Override - public String getName() { + public @NotNull String getName() { return "normal"; } diff --git a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java index d930abaa64e..d5e5cd780dd 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java @@ -1,50 +1,61 @@ package gregtech.common.pipelike.laser.net; +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserContainer; +import gregtech.api.pipenet.NetGroup; +import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.NodeG; +import gregtech.common.pipelike.laser.LaserPipeProperties; +import gregtech.common.pipelike.laser.LaserPipeType; import gregtech.common.pipelike.laser.tile.TileEntityLaserPipe; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; +import java.util.Map; + public class LaserNetHandler implements ILaserContainer { - private LaserPipeNet net; + private final WorldLaserPipeNet net; private final TileEntityLaserPipe pipe; private final EnumFacing facing; - public LaserNetHandler(LaserPipeNet net, @NotNull TileEntityLaserPipe pipe, @Nullable EnumFacing facing) { + public LaserNetHandler(WorldLaserPipeNet net, @NotNull TileEntityLaserPipe pipe, @Nullable EnumFacing facing) { this.net = net; this.pipe = pipe; this.facing = facing; } - public void updateNetwork(LaserPipeNet net) { - this.net = net; - } - private void setPipesActive() { - for (BlockPos pos : net.getAllNodes().keySet()) { - if (pipe.getWorld().getTileEntity(pos) instanceof TileEntityLaserPipe laserPipe) { - laserPipe.setActive(true, 100); + NetGroup group = getNet().getNode(this.pipe.getPipePos()).getGroup(); + if (group != null) { + for (NodeG node : group.getNodes()) { + if (node.heldMTE instanceof TileEntityLaserPipe laserPipe) { + laserPipe.setActive(true, 100); + } } } } @Nullable private ILaserContainer getInnerContainer() { - if (net == null || pipe == null || pipe.isInvalid() || facing == null) { + if (net == null || pipe.isInvalid() || facing == null) { return null; } - LaserRoutePath data = net.getNetData(pipe.getPipePos(), facing); - if (data == null) { - return null; - } + List> data = net.getPaths(this.pipe); + if (data == null || data.size() != 1) return null; + Map connecteds = data.get(0).getTargetTEs(); + if (connecteds.size() != 1) return null; + EnumFacing facing = connecteds.keySet().iterator().next(); - return data.getHandler(); + return connecteds.get(facing).getCapability(GregtechTileCapabilities.CAPABILITY_LASER, facing.getOpposite()); } @Override @@ -101,7 +112,7 @@ public long getInputVoltage() { return 0; } - public LaserPipeNet getNet() { + public WorldLaserPipeNet getNet() { return net; } diff --git a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetWalker.java b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetWalker.java deleted file mode 100644 index 1637f17a3e6..00000000000 --- a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetWalker.java +++ /dev/null @@ -1,87 +0,0 @@ -package gregtech.common.pipelike.laser.net; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.ILaserContainer; -import gregtech.api.pipenet.PipeNetWalker; -import gregtech.api.util.GTUtility; -import gregtech.common.pipelike.laser.tile.TileEntityLaserPipe; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import org.jetbrains.annotations.Nullable; - -public class LaserNetWalker extends PipeNetWalker { - - public static final LaserRoutePath FAILED_MARKER = new LaserRoutePath(null, null, 0); - - @Nullable - public static LaserRoutePath createNetData(World world, BlockPos sourcePipe, EnumFacing faceToSourceHandler) { - LaserNetWalker walker = new LaserNetWalker(world, sourcePipe, 1); - walker.sourcePipe = sourcePipe; - walker.facingToHandler = faceToSourceHandler; - walker.axis = faceToSourceHandler.getAxis(); - walker.traversePipeNet(); - return walker.isFailed() ? FAILED_MARKER : walker.routePath; - } - - private static final EnumFacing[] X_AXIS_FACINGS = { EnumFacing.WEST, EnumFacing.EAST }; - private static final EnumFacing[] Y_AXIS_FACINGS = { EnumFacing.UP, EnumFacing.DOWN }; - private static final EnumFacing[] Z_AXIS_FACINGS = { EnumFacing.NORTH, EnumFacing.SOUTH }; - - private LaserRoutePath routePath; - private BlockPos sourcePipe; - private EnumFacing facingToHandler; - private EnumFacing.Axis axis; - - protected LaserNetWalker(World world, BlockPos sourcePipe, int distance) { - super(world, sourcePipe, distance); - } - - @Override - protected PipeNetWalker createSubWalker(World world, EnumFacing facingToNextPos, - BlockPos nextPos, int walkedBlocks) { - LaserNetWalker walker = new LaserNetWalker(world, nextPos, walkedBlocks); - walker.facingToHandler = facingToHandler; - walker.sourcePipe = sourcePipe; - walker.axis = axis; - return walker; - } - - @Override - protected EnumFacing[] getSurroundingPipeSides() { - return switch (axis) { - case X -> X_AXIS_FACINGS; - case Y -> Y_AXIS_FACINGS; - case Z -> Z_AXIS_FACINGS; - }; - } - - @Override - protected void checkPipe(TileEntityLaserPipe pipeTile, BlockPos pos) {} - - @Override - protected void checkNeighbour(TileEntityLaserPipe pipeTile, BlockPos pipePos, EnumFacing faceToNeighbour, - @Nullable TileEntity neighbourTile) { - if (neighbourTile == null || - (GTUtility.arePosEqual(pipePos, sourcePipe) && faceToNeighbour == facingToHandler)) { - return; - } - - if (((LaserNetWalker) root).routePath == null) { - ILaserContainer handler = neighbourTile.getCapability(GregtechTileCapabilities.CAPABILITY_LASER, - faceToNeighbour.getOpposite()); - if (handler != null) { - ((LaserNetWalker) root).routePath = new LaserRoutePath(pipeTile, faceToNeighbour, getWalkedBlocks()); - stop(); - } - } - } - - @Override - protected Class getBasePipeClass() { - return TileEntityLaserPipe.class; - } -} diff --git a/src/main/java/gregtech/common/pipelike/laser/net/LaserPipeNet.java b/src/main/java/gregtech/common/pipelike/laser/net/LaserPipeNet.java deleted file mode 100644 index 67aef2810ac..00000000000 --- a/src/main/java/gregtech/common/pipelike/laser/net/LaserPipeNet.java +++ /dev/null @@ -1,69 +0,0 @@ -package gregtech.common.pipelike.laser.net; - -import gregtech.api.pipenet.Node; -import gregtech.api.pipenet.PipeNet; -import gregtech.api.pipenet.WorldPipeNet; -import gregtech.common.pipelike.laser.LaserPipeProperties; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; - -public class LaserPipeNet extends PipeNet { - - private final Map netData = new Object2ObjectOpenHashMap<>(); - - public LaserPipeNet(WorldPipeNet> world) { - super(world); - } - - @Nullable - public LaserRoutePath getNetData(BlockPos pipePos, EnumFacing facing) { - if (netData.containsKey(pipePos)) { - return netData.get(pipePos); - } - LaserRoutePath data = LaserNetWalker.createNetData(getWorldData(), pipePos, facing); - if (data == LaserNetWalker.FAILED_MARKER) { - // walker failed, don't cache, so it tries again on next insertion - return null; - } - netData.put(pipePos, data); - return data; - } - - @Override - public void onNeighbourUpdate(BlockPos fromPos) { - netData.clear(); - } - - @Override - public void onPipeConnectionsUpdate() { - netData.clear(); - } - - @Override - public void onChunkUnload() { - netData.clear(); - } - - @Override - protected void transferNodeData(Map> transferredNodes, - PipeNet parentNet) { - super.transferNodeData(transferredNodes, parentNet); - netData.clear(); - ((LaserPipeNet) parentNet).netData.clear(); - } - - @Override - protected void writeNodeData(LaserPipeProperties nodeData, NBTTagCompound tagCompound) {} - - @Override - protected LaserPipeProperties readNodeData(NBTTagCompound tagCompound) { - return LaserPipeProperties.INSTANCE; - } -} diff --git a/src/main/java/gregtech/common/pipelike/laser/net/LaserRoutePath.java b/src/main/java/gregtech/common/pipelike/laser/net/LaserRoutePath.java deleted file mode 100644 index 7e85964662a..00000000000 --- a/src/main/java/gregtech/common/pipelike/laser/net/LaserRoutePath.java +++ /dev/null @@ -1,66 +0,0 @@ -package gregtech.common.pipelike.laser.net; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.ILaserContainer; -import gregtech.api.pipenet.IRoutePath; -import gregtech.common.pipelike.laser.tile.TileEntityLaserPipe; - -import net.minecraft.util.EnumFacing; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -// jabel moment -public class LaserRoutePath implements IRoutePath { - - private final TileEntityLaserPipe targetPipe; - private final EnumFacing faceToHandler; - private final int distance; - - public LaserRoutePath(TileEntityLaserPipe targetPipe, EnumFacing faceToHandler, int distance) { - this.targetPipe = targetPipe; - this.faceToHandler = faceToHandler; - this.distance = distance; - } - - /** - * Gets the current face to handler - * - * @return The face to handler - */ - @NotNull - public EnumFacing getFaceToHandler() { - return faceToHandler; - } - - @NotNull - @Override - public TileEntityLaserPipe getTargetPipe() { - return targetPipe; - } - - @NotNull - @Override - public EnumFacing getTargetFacing() { - return faceToHandler; - } - - /** - * Gets the manhattan distance traveled during walking - * - * @return The distance in blocks - */ - public int getDistance() { - return distance; - } - - /** - * Gets the handler if it exists - * - * @return the handler - */ - @Nullable - public ILaserContainer getHandler() { - return getTargetCapability(GregtechTileCapabilities.CAPABILITY_LASER); - } -} diff --git a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java b/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java index 69545318d36..709eee89717 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java @@ -1,13 +1,20 @@ package gregtech.common.pipelike.laser.net; import gregtech.api.pipenet.WorldPipeNet; +import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.tile.IPipeTile; import gregtech.common.pipelike.laser.LaserPipeProperties; +import gregtech.common.pipelike.laser.LaserPipeType; + +import gregtech.common.pipelike.laser.tile.TileEntityLaserPipe; + +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; -public class WorldLaserPipeNet extends WorldPipeNet { +public class WorldLaserPipeNet extends WorldPipeNetG { private static final String DATA_ID = "gregtech.laser_pipe_net"; @@ -15,6 +22,24 @@ public WorldLaserPipeNet(String name) { super(name); } + @Override + protected boolean isSinglePath() { + return true; + } + + @Override + protected Class> getBasePipeClass() { + return TileEntityLaserPipe.class; + } + + @Override + protected void writeNodeData(LaserPipeProperties nodeData, NBTTagCompound tagCompound) {} + + @Override + protected LaserPipeProperties readNodeData(NBTTagCompound tagCompound) { + return new LaserPipeProperties(); + } + @NotNull public static WorldLaserPipeNet getWorldPipeNet(@NotNull World world) { WorldLaserPipeNet netWorldData = (WorldLaserPipeNet) world.loadData(WorldLaserPipeNet.class, DATA_ID); @@ -25,9 +50,4 @@ public static WorldLaserPipeNet getWorldPipeNet(@NotNull World world) { netWorldData.setWorldAndInit(world); return netWorldData; } - - @Override - protected LaserPipeNet createNetInstance() { - return new LaserPipeNet(this); - } } diff --git a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java b/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java index 759fa494152..5a4e2810a8e 100644 --- a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java +++ b/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java @@ -9,7 +9,6 @@ import gregtech.common.pipelike.laser.LaserPipeProperties; import gregtech.common.pipelike.laser.LaserPipeType; import gregtech.common.pipelike.laser.net.LaserNetHandler; -import gregtech.common.pipelike.laser.net.LaserPipeNet; import gregtech.common.pipelike.laser.net.WorldLaserPipeNet; import net.minecraft.nbt.NBTTagCompound; @@ -22,7 +21,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.ref.WeakReference; import java.util.EnumMap; public class TileEntityLaserPipe extends TileEntityPipeBase { @@ -30,7 +28,6 @@ public class TileEntityLaserPipe extends TileEntityPipeBase handlers = new EnumMap<>(EnumFacing.class); // the LaserNetHandler can only be created on the server, so we have an empty placeholder for the client private final ILaserContainer clientCapability = new DefaultLaserContainer(); - private WeakReference currentPipeNet = new WeakReference<>(null); private LaserNetHandler defaultHandler; private int ticksActive = 0; @@ -53,8 +50,7 @@ public boolean canHaveBlockedFaces() { } private void initHandlers() { - LaserPipeNet net = getLaserPipeNet(); - if (net == null) return; + WorldLaserPipeNet net = WorldLaserPipeNet.getWorldPipeNet(getPipeWorld()); for (EnumFacing facing : EnumFacing.VALUES) { handlers.put(facing, new LaserNetHandler(net, this, facing)); } @@ -72,44 +68,15 @@ public T getCapabilityInternal(Capability capability, @Nullable EnumFacin initHandlers(); } - checkNetwork(); return GregtechTileCapabilities.CAPABILITY_LASER.cast(handlers.getOrDefault(facing, defaultHandler)); } return super.getCapabilityInternal(capability, facing); } - public void checkNetwork() { - if (defaultHandler != null) { - LaserPipeNet current = getLaserPipeNet(); - if (defaultHandler.getNet() != current) { - defaultHandler.updateNetwork(current); - for (LaserNetHandler handler : handlers.values()) { - handler.updateNetwork(current); - } - } - } - } - - public LaserPipeNet getLaserPipeNet() { - if (world == null || world.isRemote) { - return null; - } - LaserPipeNet currentPipeNet = this.currentPipeNet.get(); - if (currentPipeNet != null && currentPipeNet.isValid() && currentPipeNet.containsNode(getPipePos())) { - return currentPipeNet; - } - WorldLaserPipeNet worldNet = (WorldLaserPipeNet) getPipeBlock().getWorldPipeNet(getPipeWorld()); - currentPipeNet = worldNet.getNetFromPos(getPipePos()); - if (currentPipeNet != null) { - this.currentPipeNet = new WeakReference<>(currentPipeNet); - } - return currentPipeNet; - } - @Override public void transferDataFrom(IPipeTile tileEntity) { super.transferDataFrom(tileEntity); - if (getLaserPipeNet() == null) { + if (getPipeBlock().getWorldPipeNet(getPipeWorld()) == null) { return; } diff --git a/src/main/java/gregtech/common/pipelike/optical/BlockOpticalPipe.java b/src/main/java/gregtech/common/pipelike/optical/BlockOpticalPipe.java index 87426fb81de..465c2813014 100644 --- a/src/main/java/gregtech/common/pipelike/optical/BlockOpticalPipe.java +++ b/src/main/java/gregtech/common/pipelike/optical/BlockOpticalPipe.java @@ -121,7 +121,7 @@ public boolean canPipeConnectToBlock(IPipeTile seen) } private void setPipesActive() { - for (BlockPos pos : net.getAllNodes().keySet()) { - if (world.getTileEntity(pos) instanceof TileEntityOpticalPipe opticalPipe) { - opticalPipe.setActive(true, 100); + NetGroup group = getNet().getNode(this.pipe.getPipePos()).getGroup(); + if (group != null) { + for (NodeG node : group.getNodes()) { + if (node.heldMTE instanceof TileEntityOpticalPipe opticalPipe) { + opticalPipe.setActive(true, 100); + } } } } private boolean isNetInvalidForTraversal() { - return net == null || pipe == null || pipe.isInvalid(); + return net == null || pipe.isInvalid() || facing == null; } private boolean traverseRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { if (isNetInvalidForTraversal()) return false; - OpticalRoutePath inv = net.getNetData(pipe.getPipePos(), facing); - if (inv == null) return false; + List> inv = net.getPaths(this.pipe); + if (inv == null || inv.size() != 1) return false; + Map connecteds = inv.get(0).getTargetTEs(); + if (connecteds.size() != 1) return false; + EnumFacing facing = connecteds.keySet().iterator().next(); - IOpticalDataAccessHatch hatch = inv.getDataHatch(); - if (hatch == null || seen.contains(hatch)) return false; + IDataAccessHatch access = connecteds.get(facing).getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, facing.getOpposite()); + if (!(access instanceof IOpticalDataAccessHatch hatch) || seen.contains(hatch)) return false; if (hatch.isTransmitter()) { return hatch.isRecipeAvailable(recipe, seen); @@ -116,10 +127,13 @@ private boolean traverseCanBridge(@NotNull Collection seen) { if (isNetInvalidForTraversal()) return null; - OpticalRoutePath inv = net.getNetData(pipe.getPipePos(), facing); - if (inv == null) return null; + List> inv = net.getPaths(this.pipe); + if (inv == null || inv.size() != 1) return null; + Map connecteds = inv.get(0).getTargetTEs(); + if (connecteds.size() != 1) return null; + EnumFacing facing = connecteds.keySet().iterator().next(); - IOpticalComputationProvider hatch = inv.getComputationHatch(); + IOpticalComputationProvider hatch = connecteds.get(facing).getCapability(GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER, facing.getOpposite());; if (hatch == null || seen.contains(hatch)) return null; return hatch; } diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetWalker.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetWalker.java deleted file mode 100644 index 531f86e0d13..00000000000 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetWalker.java +++ /dev/null @@ -1,72 +0,0 @@ -package gregtech.common.pipelike.optical.net; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.pipenet.PipeNetWalker; -import gregtech.api.util.GTUtility; -import gregtech.common.pipelike.optical.tile.TileEntityOpticalPipe; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import org.jetbrains.annotations.Nullable; - -public class OpticalNetWalker extends PipeNetWalker { - - public static final OpticalRoutePath FAILED_MARKER = new OpticalRoutePath(null, null, 0); - - @Nullable - public static OpticalRoutePath createNetData(World world, BlockPos sourcePipe, EnumFacing faceToSourceHandler) { - OpticalNetWalker walker = new OpticalNetWalker(world, sourcePipe, 1); - walker.sourcePipe = sourcePipe; - walker.facingToHandler = faceToSourceHandler; - walker.traversePipeNet(); - return walker.isFailed() ? FAILED_MARKER : walker.routePath; - } - - private OpticalRoutePath routePath; - private BlockPos sourcePipe; - private EnumFacing facingToHandler; - - protected OpticalNetWalker(World world, BlockPos sourcePipe, int distance) { - super(world, sourcePipe, distance); - } - - @Override - protected PipeNetWalker createSubWalker(World world, EnumFacing facingToNextPos, - BlockPos nextPos, int walkedBlocks) { - OpticalNetWalker walker = new OpticalNetWalker(world, nextPos, walkedBlocks); - walker.facingToHandler = facingToHandler; - walker.sourcePipe = sourcePipe; - return walker; - } - - @Override - protected void checkPipe(TileEntityOpticalPipe pipeTile, BlockPos pos) {} - - @Override - protected void checkNeighbour(TileEntityOpticalPipe pipeTile, BlockPos pipePos, EnumFacing faceToNeighbour, - @Nullable TileEntity neighbourTile) { - if (neighbourTile == null || - (GTUtility.arePosEqual(pipePos, sourcePipe) && faceToNeighbour == facingToHandler)) { - return; - } - - if (((OpticalNetWalker) root).routePath == null) { - if (neighbourTile.hasCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, - faceToNeighbour.getOpposite()) || - neighbourTile.hasCapability(GregtechTileCapabilities.CABABILITY_COMPUTATION_PROVIDER, - faceToNeighbour.getOpposite())) { - ((OpticalNetWalker) root).routePath = new OpticalRoutePath(pipeTile, faceToNeighbour, - getWalkedBlocks()); - stop(); - } - } - } - - @Override - protected Class getBasePipeClass() { - return TileEntityOpticalPipe.class; - } -} diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalPipeNet.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalPipeNet.java deleted file mode 100644 index fceabc6aae6..00000000000 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalPipeNet.java +++ /dev/null @@ -1,70 +0,0 @@ -package gregtech.common.pipelike.optical.net; - -import gregtech.api.pipenet.Node; -import gregtech.api.pipenet.PipeNet; -import gregtech.api.pipenet.WorldPipeNet; -import gregtech.common.pipelike.optical.OpticalPipeProperties; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; - -public class OpticalPipeNet extends PipeNet { - - private final Map NET_DATA = new Object2ObjectOpenHashMap<>(); - - public OpticalPipeNet(WorldPipeNet> world) { - super(world); - } - - @Nullable - public OpticalRoutePath getNetData(BlockPos pipePos, EnumFacing facing) { - if (NET_DATA.containsKey(pipePos)) { - return NET_DATA.get(pipePos); - } - OpticalRoutePath data = OpticalNetWalker.createNetData(getWorldData(), pipePos, facing); - if (data == OpticalNetWalker.FAILED_MARKER) { - // walker failed, don't cache, so it tries again on next insertion - return null; - } - - NET_DATA.put(pipePos, data); - return data; - } - - @Override - public void onNeighbourUpdate(BlockPos fromPos) { - NET_DATA.clear(); - } - - @Override - public void onPipeConnectionsUpdate() { - NET_DATA.clear(); - } - - @Override - public void onChunkUnload() { - NET_DATA.clear(); - } - - @Override - protected void transferNodeData(Map> transferredNodes, - PipeNet parentNet) { - super.transferNodeData(transferredNodes, parentNet); - NET_DATA.clear(); - ((OpticalPipeNet) parentNet).NET_DATA.clear(); - } - - @Override - protected void writeNodeData(OpticalPipeProperties nodeData, NBTTagCompound tagCompound) {} - - @Override - protected OpticalPipeProperties readNodeData(NBTTagCompound tagCompound) { - return OpticalPipeProperties.INSTANCE; - } -} diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalRoutePath.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalRoutePath.java deleted file mode 100644 index 52c89aa97bb..00000000000 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalRoutePath.java +++ /dev/null @@ -1,53 +0,0 @@ -package gregtech.common.pipelike.optical.net; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.IDataAccessHatch; -import gregtech.api.capability.IOpticalComputationProvider; -import gregtech.api.capability.IOpticalDataAccessHatch; -import gregtech.api.pipenet.IRoutePath; -import gregtech.common.pipelike.optical.tile.TileEntityOpticalPipe; - -import net.minecraft.util.EnumFacing; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class OpticalRoutePath implements IRoutePath { - - private final TileEntityOpticalPipe targetPipe; - private final EnumFacing faceToHandler; - private final int distance; - - public OpticalRoutePath(TileEntityOpticalPipe targetPipe, EnumFacing faceToHandler, int distance) { - this.targetPipe = targetPipe; - this.faceToHandler = faceToHandler; - this.distance = distance; - } - - @NotNull - @Override - public TileEntityOpticalPipe getTargetPipe() { - return targetPipe; - } - - @NotNull - @Override - public EnumFacing getTargetFacing() { - return faceToHandler; - } - - public int getDistance() { - return distance; - } - - @Nullable - public IOpticalDataAccessHatch getDataHatch() { - IDataAccessHatch dataAccessHatch = getTargetCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS); - return dataAccessHatch instanceof IOpticalDataAccessHatch opticalHatch ? opticalHatch : null; - } - - @Nullable - public IOpticalComputationProvider getComputationHatch() { - return getTargetCapability(GregtechTileCapabilities.CABABILITY_COMPUTATION_PROVIDER); - } -} diff --git a/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java b/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java index 7fd1dad62be..44a3373e6b9 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java @@ -1,13 +1,20 @@ package gregtech.common.pipelike.optical.net; import gregtech.api.pipenet.WorldPipeNet; +import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.tile.IPipeTile; import gregtech.common.pipelike.optical.OpticalPipeProperties; +import gregtech.common.pipelike.optical.OpticalPipeType; + +import gregtech.common.pipelike.optical.tile.TileEntityOpticalPipe; + +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; -public class WorldOpticalPipeNet extends WorldPipeNet { +public class WorldOpticalPipeNet extends WorldPipeNetG { private static final String DATA_ID = "gregtech.optical_pipe_net"; @@ -15,6 +22,24 @@ public WorldOpticalPipeNet(String name) { super(name); } + @Override + protected boolean isSinglePath() { + return true; + } + + @Override + protected Class> getBasePipeClass() { + return TileEntityOpticalPipe.class; + } + + @Override + protected void writeNodeData(OpticalPipeProperties nodeData, NBTTagCompound tagCompound) {} + + @Override + protected OpticalPipeProperties readNodeData(NBTTagCompound tagCompound) { + return new OpticalPipeProperties(); + } + @NotNull public static WorldOpticalPipeNet getWorldPipeNet(@NotNull World world) { WorldOpticalPipeNet netWorldData = (WorldOpticalPipeNet) world.loadData(WorldOpticalPipeNet.class, DATA_ID); @@ -25,9 +50,4 @@ public static WorldOpticalPipeNet getWorldPipeNet(@NotNull World world) { netWorldData.setWorldAndInit(world); return netWorldData; } - - @Override - protected OpticalPipeNet createNetInstance() { - return new OpticalPipeNet(this); - } } diff --git a/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java b/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java index 43efe04cb56..e9b310ae1b9 100644 --- a/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java +++ b/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java @@ -11,7 +11,6 @@ import gregtech.common.pipelike.optical.OpticalPipeProperties; import gregtech.common.pipelike.optical.OpticalPipeType; import gregtech.common.pipelike.optical.net.OpticalNetHandler; -import gregtech.common.pipelike.optical.net.OpticalPipeNet; import gregtech.common.pipelike.optical.net.WorldOpticalPipeNet; import net.minecraft.network.PacketBuffer; @@ -22,7 +21,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.ref.WeakReference; import java.util.Collection; import java.util.EnumMap; @@ -32,7 +30,6 @@ public class TileEntityOpticalPipe extends TileEntityPipeBase currentPipeNet = new WeakReference<>(null); private OpticalNetHandler defaultHandler; private int ticksActive = 0; @@ -54,8 +51,7 @@ public boolean canHaveBlockedFaces() { } private void initHandlers() { - OpticalPipeNet net = getOpticalPipeNet(); - if (net == null) return; + WorldOpticalPipeNet net = WorldOpticalPipeNet.getWorldPipeNet(getPipeWorld()); for (EnumFacing facing : EnumFacing.VALUES) { handlers.put(facing, new OpticalNetHandler(net, this, facing)); } @@ -72,62 +68,31 @@ public T getCapabilityInternal(Capability capability, @Nullable EnumFacin if (handlers.isEmpty()) initHandlers(); - checkNetwork(); return GregtechTileCapabilities.CAPABILITY_DATA_ACCESS.cast(handlers.getOrDefault(facing, defaultHandler)); } - if (capability == GregtechTileCapabilities.CABABILITY_COMPUTATION_PROVIDER) { + if (capability == GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER) { if (world.isRemote) { - return GregtechTileCapabilities.CABABILITY_COMPUTATION_PROVIDER.cast(clientComputationHandler); + return GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER.cast(clientComputationHandler); } if (handlers.isEmpty()) initHandlers(); - checkNetwork(); - return GregtechTileCapabilities.CABABILITY_COMPUTATION_PROVIDER + return GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER .cast(handlers.getOrDefault(facing, defaultHandler)); } return super.getCapabilityInternal(capability, facing); } - public void checkNetwork() { - if (defaultHandler != null) { - OpticalPipeNet current = getOpticalPipeNet(); - if (defaultHandler.getNet() != current) { - defaultHandler.updateNetwork(current); - for (OpticalNetHandler handler : handlers.values()) { - handler.updateNetwork(current); - } - } - } - } - - public OpticalPipeNet getOpticalPipeNet() { - if (world == null || world.isRemote) - return null; - OpticalPipeNet currentPipeNet = this.currentPipeNet.get(); - if (currentPipeNet != null && currentPipeNet.isValid() && currentPipeNet.containsNode(getPipePos())) - return currentPipeNet; // if current net is valid and does contain position, return it - WorldOpticalPipeNet worldNet = (WorldOpticalPipeNet) getPipeBlock().getWorldPipeNet(getPipeWorld()); - currentPipeNet = worldNet.getNetFromPos(getPipePos()); - if (currentPipeNet != null) { - this.currentPipeNet = new WeakReference<>(currentPipeNet); - } - return currentPipeNet; - } - @Override public void transferDataFrom(IPipeTile tileEntity) { super.transferDataFrom(tileEntity); - if (getOpticalPipeNet() == null) - return; TileEntityOpticalPipe pipe = (TileEntityOpticalPipe) tileEntity; if (!pipe.handlers.isEmpty() && pipe.defaultHandler != null) { // take handlers from old pipe handlers.clear(); handlers.putAll(pipe.handlers); defaultHandler = pipe.defaultHandler; - checkNetwork(); } else { // create new handlers initHandlers(); From 55827da97f8ef17b218664a11af2419728f745b9 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 18 Dec 2023 16:32:52 -0700 Subject: [PATCH 017/157] Wait, the fluid net doesn't exist? --- .../gregtech/api/pipenet/WorldPipeNetG.java | 9 ++-- .../api/pipenet/block/ItemBlockPipe.java | 4 +- .../block/material/BlockMaterialPipe.java | 2 +- .../block/material/IMaterialPipeTile.java | 2 +- .../block/material/IMaterialPipeType.java | 2 +- .../block/material/ItemBlockMaterialPipe.java | 2 +- .../material/TileEntityMaterialPipeBase.java | 2 +- .../pipenet/block/simple/BlockSimplePipe.java | 2 +- .../gregtech/api/pipenet/tile/IPipeTile.java | 4 +- .../pipelike/fluidpipe/net/FluidPipeNet.java | 38 ----------------- .../fluidpipe/net/WorldFluidPipeNet.java | 42 +++++++++++++++++-- .../fluidpipe/tile/TileEntityFluidPipe.java | 20 --------- 12 files changed, 55 insertions(+), 74 deletions(-) delete mode 100644 src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidPipeNet.java diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 6071914e4ca..415eb02d6ab 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -510,16 +510,19 @@ private List> singlePathList(NodeG i = this.pipeGraph.edgesOf(node).iterator(); + Iterator i = this.pipeGraph.outgoingEdgesOf(node).iterator(); if (!i.hasNext()) break; // we've reached the end, exit the loop while still valid edge = i.next(); - if (edge.getTarget() == lastNode) { + // if we are directed, we know that the target is the target. + // if we aren't directed, we need to see if the edge's source was secretly the target + boolean reversedEdge = !this.isDirected() && edge.getSource() == lastNode; + if (edge.getTarget() == lastNode || reversedEdge) { if (i.hasNext()) edge = i.next(); else break; // we've reached the end, exit the loop while still valid } else if (i.hasNext()) i.next(); if (i.hasNext()) valid = false; // third edge detected - that's an invalid group lastNode = node; - node = (NodeG) edge.getTarget(); + node = (NodeG) (reversedEdge ? edge.getSource() : edge.getTarget()); edges.add(edge); nodes.add(node); sumWeight += node.data.getWeightFactor(); diff --git a/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java b/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java index 7b6f56a3877..961cb1307df 100644 --- a/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java @@ -15,8 +15,8 @@ import org.jetbrains.annotations.NotNull; -public class ItemBlockPipe & IPipeType, NodeDataType extends INodeData> - extends ItemBlock { +public class ItemBlockPipe & IPipeType, + NodeDataType extends INodeData> extends ItemBlock { protected final BlockPipe blockPipe; diff --git a/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java b/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java index fda19359089..67223f8c64a 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java @@ -28,7 +28,7 @@ public abstract class BlockMaterialPipe< PipeType extends Enum & IPipeType & IMaterialPipeType, - NodeDataType extends INodeData, + NodeDataType extends INodeData, WorldPipeNetType extends WorldPipeNetG> extends BlockPipe { diff --git a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java b/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java index 4638029e581..9f72c027806 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java +++ b/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java @@ -6,7 +6,7 @@ import gregtech.api.unification.material.Material; public interface IMaterialPipeTile & IPipeType, - NodeDataType extends INodeData> + NodeDataType extends INodeData> extends IPipeTile { Material getPipeMaterial(); diff --git a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeType.java b/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeType.java index 2657dd88799..018ec16785b 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeType.java +++ b/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeType.java @@ -4,7 +4,7 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.unification.ore.OrePrefix; -public interface IMaterialPipeType extends IPipeType { +public interface IMaterialPipeType> extends IPipeType { /** * Determines ore prefix used for this pipe type, which gives pipe ore dictionary key diff --git a/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java b/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java index b186ab5cd7b..d8aaf57d31d 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; public class ItemBlockMaterialPipe & IMaterialPipeType, - NodeDataType extends INodeData> + NodeDataType extends INodeData> extends ItemBlockPipe { public ItemBlockMaterialPipe(BlockMaterialPipe block) { diff --git a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java index dec816518d6..30de56cdf86 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java @@ -16,7 +16,7 @@ import static gregtech.api.capability.GregtechDataCodes.UPDATE_PIPE_MATERIAL; public abstract class TileEntityMaterialPipeBase & IMaterialPipeType, - NodeDataType extends INodeData> extends TileEntityPipeBase + NodeDataType extends INodeData> extends TileEntityPipeBase implements IMaterialPipeTile { private Material pipeMaterial = Materials.Aluminium; diff --git a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java index 22fd9885cf4..7f921023050 100644 --- a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java +++ b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java @@ -10,7 +10,7 @@ import net.minecraft.item.ItemStack; public abstract class BlockSimplePipe & IPipeType, - NodeDataType extends INodeData, + NodeDataType extends INodeData, WorldPipeNetType extends WorldPipeNetG> extends BlockPipe { diff --git a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java index 86863f91849..898752fdb69 100644 --- a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java +++ b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java @@ -16,8 +16,8 @@ import java.util.function.Consumer; -public interface IPipeTile & IPipeType, NodeDataType extends INodeData> - extends INeighborCache { +public interface IPipeTile & IPipeType, + NodeDataType extends INodeData> extends INeighborCache { World getPipeWorld(); diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidPipeNet.java deleted file mode 100644 index e073fc74cce..00000000000 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidPipeNet.java +++ /dev/null @@ -1,38 +0,0 @@ -package gregtech.common.pipelike.fluidpipe.net; - -import gregtech.api.pipenet.PipeNet; -import gregtech.api.pipenet.WorldPipeNet; -import gregtech.api.unification.material.properties.FluidPipeProperties; - -import net.minecraft.nbt.NBTTagCompound; - -public class FluidPipeNet extends PipeNet { - - public FluidPipeNet(WorldPipeNet world) { - super(world); - } - - @Override - protected void writeNodeData(FluidPipeProperties nodeData, NBTTagCompound tagCompound) { - tagCompound.setInteger("max_temperature", nodeData.getMaxFluidTemperature()); - tagCompound.setInteger("throughput", nodeData.getThroughput()); - tagCompound.setBoolean("gas_proof", nodeData.isGasProof()); - tagCompound.setBoolean("acid_proof", nodeData.isAcidProof()); - tagCompound.setBoolean("cryo_proof", nodeData.isCryoProof()); - tagCompound.setBoolean("plasma_proof", nodeData.isPlasmaProof()); - tagCompound.setInteger("channels", nodeData.getTanks()); - } - - @Override - protected FluidPipeProperties readNodeData(NBTTagCompound tagCompound) { - int maxTemperature = tagCompound.getInteger("max_temperature"); - int throughput = tagCompound.getInteger("throughput"); - boolean gasProof = tagCompound.getBoolean("gas_proof"); - boolean acidProof = tagCompound.getBoolean("acid_proof"); - boolean cryoProof = tagCompound.getBoolean("cryo_proof"); - boolean plasmaProof = tagCompound.getBoolean("plasma_proof"); - int channels = tagCompound.getInteger("channels"); - return new FluidPipeProperties(maxTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof, - channels); - } -} diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index 9e58ed1ec14..ac9dc965475 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -1,11 +1,18 @@ package gregtech.common.pipelike.fluidpipe.net; import gregtech.api.pipenet.WorldPipeNet; +import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.common.pipelike.fluidpipe.FluidPipeType; + +import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; + +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; -public class WorldFluidPipeNet extends WorldPipeNet { +public class WorldFluidPipeNet extends WorldPipeNetG { private static final String DATA_ID_BASE = "gregtech.fluid_pipe_net"; @@ -25,7 +32,36 @@ public WorldFluidPipeNet(String name) { } @Override - protected FluidPipeNet createNetInstance() { - return new FluidPipeNet(this); + protected boolean isDirected() { + return true; + } + + @Override + protected Class> getBasePipeClass() { + return TileEntityFluidPipe.class; + } + + @Override + protected void writeNodeData(FluidPipeProperties nodeData, NBTTagCompound tagCompound) { + tagCompound.setInteger("max_temperature", nodeData.getMaxFluidTemperature()); + tagCompound.setInteger("throughput", nodeData.getThroughput()); + tagCompound.setBoolean("gas_proof", nodeData.isGasProof()); + tagCompound.setBoolean("acid_proof", nodeData.isAcidProof()); + tagCompound.setBoolean("cryo_proof", nodeData.isCryoProof()); + tagCompound.setBoolean("plasma_proof", nodeData.isPlasmaProof()); + tagCompound.setInteger("channels", nodeData.getTanks()); + } + + @Override + protected FluidPipeProperties readNodeData(NBTTagCompound tagCompound) { + int maxTemperature = tagCompound.getInteger("max_temperature"); + int throughput = tagCompound.getInteger("throughput"); + boolean gasProof = tagCompound.getBoolean("gas_proof"); + boolean acidProof = tagCompound.getBoolean("acid_proof"); + boolean cryoProof = tagCompound.getBoolean("cryo_proof"); + boolean plasmaProof = tagCompound.getBoolean("plasma_proof"); + int channels = tagCompound.getInteger("channels"); + return new FluidPipeProperties(maxTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof, + channels); } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java index 0a566171bda..21c2b0cdc6e 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java @@ -4,8 +4,6 @@ import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.pipelike.fluidpipe.FluidPipeType; -import gregtech.common.pipelike.fluidpipe.net.FluidPipeNet; -import gregtech.common.pipelike.fluidpipe.net.WorldFluidPipeNet; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; @@ -15,12 +13,9 @@ import net.minecraft.world.World; import net.minecraft.world.WorldServer; -import java.lang.ref.WeakReference; - public class TileEntityFluidPipe extends TileEntityMaterialPipeBase { public static final int FREQUENCY = 5; - private WeakReference currentPipeNet = new WeakReference<>(null); @Override public Class getPipeTypeClass() { @@ -36,21 +31,6 @@ public int getCapacityPerTank() { return getNodeData().getThroughput() * 20; } - public FluidPipeNet getFluidPipeNet() { - if (world == null || world.isRemote) - return null; - FluidPipeNet currentPipeNet = this.currentPipeNet.get(); - if (currentPipeNet != null && currentPipeNet.isValid() && - currentPipeNet.containsNode(getPipePos())) - return currentPipeNet; // if current net is valid and does contain position, return it - WorldFluidPipeNet worldFluidPipeNet = (WorldFluidPipeNet) getPipeBlock().getWorldPipeNet(getPipeWorld()); - currentPipeNet = worldFluidPipeNet.getNetFromPos(getPipePos()); - if (currentPipeNet != null) { - this.currentPipeNet = new WeakReference<>(currentPipeNet); - } - return currentPipeNet; - } - public static void setNeighboursToFire(World world, BlockPos selfPos) { for (EnumFacing side : EnumFacing.VALUES) { if (!GTValues.RNG.nextBoolean()) continue; From cacb0497e26be05177c72207c1a917724eef60f1 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 18 Dec 2023 17:41:05 -0700 Subject: [PATCH 018/157] Finish converting the energy net (central monitor is angry) --- .../api/pipenet/AbstractGroupData.java | 13 ++ .../java/gregtech/api/pipenet/NetGroup.java | 33 +++-- .../java/gregtech/api/pipenet/NetPath.java | 10 +- src/main/java/gregtech/api/pipenet/NodeG.java | 3 +- .../gregtech/api/pipenet/WorldPipeNetG.java | 9 +- .../MetaTileEntityCentralMonitor.java | 39 +++-- .../common/pipelike/cable/BlockCable.java | 8 +- .../pipelike/cable/net/EnergyGroupData.java | 34 +++++ .../common/pipelike/cable/net/EnergyNet.java | 100 ------------- .../pipelike/cable/net/EnergyNetHandler.java | 137 ++++++++++-------- .../pipelike/cable/net/EnergyNetWalker.java | 73 ---------- .../pipelike/cable/net/EnergyRoutePath.java | 54 ------- .../common/pipelike/cable/net/WorldENet.java | 31 ---- .../pipelike/cable/net/WorldEnergyNet.java | 52 +++++++ .../pipelike/cable/tile/TileEntityCable.java | 38 +---- .../pipelike/itempipe/net/ItemNetHandler.java | 5 +- 16 files changed, 241 insertions(+), 398 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/AbstractGroupData.java create mode 100644 src/main/java/gregtech/common/pipelike/cable/net/EnergyGroupData.java delete mode 100644 src/main/java/gregtech/common/pipelike/cable/net/EnergyNet.java delete mode 100644 src/main/java/gregtech/common/pipelike/cable/net/EnergyNetWalker.java delete mode 100644 src/main/java/gregtech/common/pipelike/cable/net/EnergyRoutePath.java delete mode 100644 src/main/java/gregtech/common/pipelike/cable/net/WorldENet.java create mode 100644 src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java diff --git a/src/main/java/gregtech/api/pipenet/AbstractGroupData.java b/src/main/java/gregtech/api/pipenet/AbstractGroupData.java new file mode 100644 index 00000000000..76ca0fee83a --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/AbstractGroupData.java @@ -0,0 +1,13 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.block.IPipeType; + +public abstract class AbstractGroupData & IPipeType, NodeDataType extends INodeData> { + + protected NetGroup group; + + public AbstractGroupData withGroup(NetGroup group) { + this.group = group; + return this; + } +} diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index a12e7b9954e..e17401fb07e 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -12,31 +12,28 @@ public class NetGroup & IPipeType, NodeDataType extends INodeData> { + public final WorldPipeNetG net; + private final Graph, NetEdge> graph; private final Set> nodes; - private long lastUpdate; + private AbstractGroupData data; - public NetGroup(Graph, NetEdge> graph) { + public NetGroup(Graph, NetEdge> graph, WorldPipeNetG net) { this.graph = graph; this.nodes = new ObjectOpenHashSet<>(); + this.net = net; } - public NetGroup(Graph, NetEdge> graph, Set> nodes) { + public NetGroup(Graph, NetEdge> graph, WorldPipeNetG net, + Set> nodes) { this.graph = graph; this.nodes = nodes; + this.net = net; this.nodes.forEach(b -> b.setGroup(this)); } - protected void onNodeConnectionsUpdate() { - this.lastUpdate = System.currentTimeMillis(); - } - - public long getLastUpdate() { - return lastUpdate; - } - private void clear() { this.nodes.clear(); } @@ -118,7 +115,7 @@ public boolean splitNode(NodeG source) { // if 1 or fewer nodes are in the new group, no need to create it. if (targetGroup.size() > 1) { // No need to do more than create it, the involved nodes are automatically updated in constructor - new NetGroup<>(this.graph, targetGroup); + new NetGroup<>(this.graph, this.net, targetGroup); } else { targetGroup.forEach(NodeG::clearGroup); } @@ -152,7 +149,7 @@ public boolean splitEdge(NodeG source, NodeG 1) { // No need to do more than create it, the involved nodes are automatically updated in constructor - new NetGroup<>(this.graph, targetGroup); + new NetGroup<>(this.graph, this.net, targetGroup); } else { targetGroup.forEach(NodeG::clearGroup); } @@ -171,4 +168,14 @@ public Set> getNodes() { protected void clearPathCaches() { this.nodes.forEach(NodeG::clearPathCache); } + + public void initData(AbstractGroupData data) { + if (this.data == null) { + this.data = data.withGroup(this); + } + } + + public AbstractGroupData getData() { + return data; + } } diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index 0ffae692fa8..0cf38f60334 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -16,16 +16,16 @@ import java.util.Map; import java.util.stream.Collectors; -public class NetPath & IPipeType, NodeDataType extends INodeData> { +public final class NetPath & IPipeType, NodeDataType extends INodeData> { - protected final List> nodeList; + private final List> nodeList; private final List edgeList; - protected final NodeG sourceNode; + private final NodeG sourceNode; - protected final NodeG targetNode; + private final NodeG targetNode; - protected final double weight; + private final double weight; private NodeDataType data = null; diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index c31c7c1363e..bfb776156fc 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -84,8 +84,9 @@ public NetGroup getGroup() { return group; } - void setGroup(NetGroup group) { + NetGroup setGroup(NetGroup group) { this.group = group; + return group; } void clearGroup() { diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 415eb02d6ab..02d1d24dd0f 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -312,7 +312,7 @@ public void addUndirectedEdge(NodeG source, NodeG source, NodeG target, double weight, @Nullable AbstractEdgePredicate predicate) { if (pipeGraph.addEdge(source, target) != null) { if (NetGroup.mergeEdge(source, target)) { - new NetGroup<>(this.pipeGraph).addNodes(source, target); + new NetGroup<>(this.pipeGraph, this).addNodes(source, target); } pipeGraph.setEdgeWeight(source, target, weight); if (predicate != null) { @@ -389,6 +389,13 @@ public void removeNode(NodeG node) { this.markDirty(); } + public NetGroup getGroup(BlockPos pos) { + NodeG node = this.getNode(pos); + if (node == null) return null; + if (node.getGroup() == null) return null; + return node.setGroup(new NetGroup<>(this.pipeGraph, this)); + } + public boolean markNodeAsActive(BlockPos nodePos, boolean isActive) { NodeG node = this.pipeMap.get(nodePos); if (node != null && node.isActive != isActive) { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java index 4deeabb9a9f..b9e73bb036b 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java @@ -31,9 +31,6 @@ import gregtech.common.covers.CoverDigitalInterface; import gregtech.common.gui.widget.monitor.WidgetScreenGrid; import gregtech.common.metatileentities.MetaTileEntities; -import gregtech.common.pipelike.cable.net.EnergyNet; -import gregtech.common.pipelike.cable.net.WorldENet; -import gregtech.common.pipelike.cable.tile.TileEntityCable; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; @@ -93,24 +90,24 @@ public MetaTileEntityCentralMonitor(ResourceLocation metaTileEntityId) { } private EnergyNet getEnergyNet() { - if (!this.getWorld().isRemote) { - TileEntity te = getNeighbor(frontFacing.getOpposite()); - if (te instanceof TileEntityCable) { - TileEntityPipeBase tileEntityCable = (TileEntityCable) te; - EnergyNet currentEnergyNet = this.currentEnergyNet.get(); - if (currentEnergyNet != null && currentEnergyNet.isValid() && - currentEnergyNet.containsNode(tileEntityCable.getPipePos())) { - return currentEnergyNet; // return current net if it is still valid - } - WorldENet worldENet = (WorldENet) tileEntityCable.getPipeBlock() - .getWorldPipeNet(tileEntityCable.getPipeWorld()); - currentEnergyNet = worldENet.getNetFromPos(tileEntityCable.getPipePos()); - if (currentEnergyNet != null) { - this.currentEnergyNet = new WeakReference<>(currentEnergyNet); - } - return currentEnergyNet; - } - } +// if (!this.getWorld().isRemote) { +// TileEntity te = getNeighbor(frontFacing.getOpposite()); +// if (te instanceof TileEntityCable) { +// TileEntityPipeBase tileEntityCable = (TileEntityCable) te; +// EnergyNet currentEnergyNet = this.currentEnergyNet.get(); +// if (currentEnergyNet != null && currentEnergyNet.isValid() && +// currentEnergyNet.containsNode(tileEntityCable.getPipePos())) { +// return currentEnergyNet; // return current net if it is still valid +// } +// WorldEnergyNet worldEnergyNet = (WorldEnergyNet) tileEntityCable.getPipeBlock() +// .getWorldPipeNet(tileEntityCable.getPipeWorld()); +// currentEnergyNet = worldEnergyNet.getNetFromPos(tileEntityCable.getPipePos()); +// if (currentEnergyNet != null) { +// this.currentEnergyNet = new WeakReference<>(currentEnergyNet); +// } +// return currentEnergyNet; +// } +// } return null; } diff --git a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java index d384e22e608..842cf95d893 100644 --- a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java @@ -14,7 +14,7 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.CableRenderer; import gregtech.client.renderer.pipe.PipeRenderer; -import gregtech.common.pipelike.cable.net.WorldENet; +import gregtech.common.pipelike.cable.net.WorldEnergyNet; import gregtech.common.pipelike.cable.tile.TileEntityCable; import gregtech.common.pipelike.cable.tile.TileEntityCableTickable; import gregtech.core.advancement.AdvancementTriggers; @@ -47,7 +47,7 @@ import java.util.Map; import java.util.TreeMap; -public class BlockCable extends BlockMaterialPipe +public class BlockCable extends BlockMaterialPipe implements ITileEntityProvider { private final Map enabledMaterials = new TreeMap<>(); @@ -95,8 +95,8 @@ protected WireProperties getFallbackType() { } @Override - public WorldENet getWorldPipeNet(World world) { - return WorldENet.getWorldENet(world); + public WorldEnergyNet getWorldPipeNet(World world) { + return WorldEnergyNet.getWorldEnergyNet(world); } @Override diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyGroupData.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyGroupData.java new file mode 100644 index 00000000000..e4ab958c594 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyGroupData.java @@ -0,0 +1,34 @@ +package gregtech.common.pipelike.cable.net; + +import gregtech.api.pipenet.AbstractGroupData; + +import gregtech.api.unification.material.properties.WireProperties; + +import gregtech.common.pipelike.cable.Insulation; + +import net.minecraft.world.World; + +public class EnergyGroupData extends AbstractGroupData { + + private long lastEnergyFluxPerSec; + private long energyFluxPerSec; + private long lastTime; + + public long getEnergyFluxPerSec() { + World world = this.group.net.getWorld(); + if (world != null && !world.isRemote && (world.getTotalWorldTime() - lastTime) >= 20) { + lastTime = world.getTotalWorldTime(); + clearCache(); + } + return lastEnergyFluxPerSec; + } + + public void addEnergyFluxPerSec(long energy) { + energyFluxPerSec += energy; + } + + public void clearCache() { + lastEnergyFluxPerSec = energyFluxPerSec; + energyFluxPerSec = 0; + } +} diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNet.java deleted file mode 100644 index a56fb565600..00000000000 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNet.java +++ /dev/null @@ -1,100 +0,0 @@ -package gregtech.common.pipelike.cable.net; - -import gregtech.api.pipenet.Node; -import gregtech.api.pipenet.PipeNet; -import gregtech.api.pipenet.WorldPipeNet; -import gregtech.api.unification.material.properties.WireProperties; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Map; - -public class EnergyNet extends PipeNet { - - private long lastEnergyFluxPerSec; - private long energyFluxPerSec; - private long lastTime; - - private final Map> NET_DATA = new Object2ObjectOpenHashMap<>(); - - protected EnergyNet(WorldPipeNet world) { - super(world); - } - - public List getNetData(BlockPos pipePos) { - List data = NET_DATA.get(pipePos); - if (data == null) { - data = EnergyNetWalker.createNetData(getWorldData(), pipePos); - if (data == null) { - // walker failed, don't cache so it tries again on next insertion - return Collections.emptyList(); - } - data.sort(Comparator.comparingInt(EnergyRoutePath::getDistance)); - NET_DATA.put(pipePos, data); - } - return data; - } - - public long getEnergyFluxPerSec() { - World world = getWorldData(); - if (world != null && !world.isRemote && (world.getTotalWorldTime() - lastTime) >= 20) { - lastTime = world.getTotalWorldTime(); - clearCache(); - } - return lastEnergyFluxPerSec; - } - - public void addEnergyFluxPerSec(long energy) { - energyFluxPerSec += energy; - } - - public void clearCache() { - lastEnergyFluxPerSec = energyFluxPerSec; - energyFluxPerSec = 0; - } - - @Override - public void onNeighbourUpdate(BlockPos fromPos) { - NET_DATA.clear(); - } - - @Override - public void onPipeConnectionsUpdate() { - NET_DATA.clear(); - } - - @Override - public void onChunkUnload() { - NET_DATA.clear(); - } - - @Override - protected void transferNodeData(Map> transferredNodes, - PipeNet parentNet) { - super.transferNodeData(transferredNodes, parentNet); - NET_DATA.clear(); - ((EnergyNet) parentNet).NET_DATA.clear(); - } - - @Override - protected void writeNodeData(WireProperties nodeData, NBTTagCompound tagCompound) { - tagCompound.setInteger("voltage", nodeData.getVoltage()); - tagCompound.setInteger("amperage", nodeData.getAmperage()); - tagCompound.setInteger("loss", nodeData.getLossPerBlock()); - } - - @Override - protected WireProperties readNodeData(NBTTagCompound tagCompound) { - int voltage = tagCompound.getInteger("voltage"); - int amperage = tagCompound.getInteger("amperage"); - int lossPerBlock = tagCompound.getInteger("loss"); - return new WireProperties(voltage, amperage, lossPerBlock); - } -} diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java index 181f78b2a96..d96185a5bda 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -1,10 +1,19 @@ package gregtech.common.pipelike.cable.net; +import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IEnergyContainer; +import gregtech.api.pipenet.AbstractGroupData; +import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.NodeG; +import gregtech.api.unification.material.properties.ItemPipeProperties; +import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; +import gregtech.common.pipelike.cable.Insulation; import gregtech.common.pipelike.cable.tile.TileEntityCable; +import gregtech.common.pipelike.itempipe.ItemPipeType; + import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; @@ -16,33 +25,33 @@ public class EnergyNetHandler implements IEnergyContainer { - private EnergyNet net; + private final WorldEnergyNet net; private boolean transfer; private final TileEntityCable cable; private final EnumFacing facing; - public EnergyNetHandler(EnergyNet net, TileEntityCable cable, EnumFacing facing) { - this.net = Objects.requireNonNull(net); - this.cable = Objects.requireNonNull(cable); - this.facing = facing; - } - - public void updateNetwork(EnergyNet net) { + public EnergyNetHandler(WorldEnergyNet net, TileEntityCable cable, EnumFacing facing) { this.net = net; + this.cable = cable; + this.facing = facing; } - public EnergyNet getNet() { + public WorldEnergyNet getNet() { return net; } @Override public long getInputPerSec() { - return net.getEnergyFluxPerSec(); + AbstractGroupData data = net.getGroup(cable.getPipePos()).getData(); + if (!(data instanceof EnergyGroupData e)) return 0; + return e.getEnergyFluxPerSec(); } @Override public long getOutputPerSec() { - return net.getEnergyFluxPerSec(); + AbstractGroupData data = net.getGroup(cable.getPipePos()).getData(); + if (!(data instanceof EnergyGroupData e)) return 0; + return e.getEnergyFluxPerSec(); } @Override @@ -59,65 +68,77 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage } long amperesUsed = 0L; - for (EnergyRoutePath path : net.getNetData(cable.getPos())) { - if (path.getMaxLoss() >= voltage) { + mainloop: + for (NetPath routePath : net.getPaths(cable)) { + routePath.resetFacingIterator(); + // Did you know, the path weight in this case is just the inverse of the loss. + long maxLoss = (long) Math.ceil(1f / routePath.getWeight()); + if (maxLoss >= voltage) { // Will lose all the energy with this path, so don't use it continue; } - - if (GTUtility.arePosEqual(cable.getPos(), path.getTargetPipePos()) && side == path.getTargetFacing()) { - // Do not insert into source handler - continue; - } - - IEnergyContainer dest = path.getHandler(); - if (dest == null) continue; - - EnumFacing facing = path.getTargetFacing().getOpposite(); - if (!dest.inputsEnergy(facing) || dest.getEnergyCanBeInserted() <= 0) continue; - - long pathVoltage = voltage - path.getMaxLoss(); - boolean cableBroken = false; - for (TileEntityCable cable : path.getPath()) { - if (cable.getMaxVoltage() < voltage) { - int heat = (int) (Math.log( - GTUtility.getTierByVoltage(voltage) - GTUtility.getTierByVoltage(cable.getMaxVoltage())) * - 45 + 36.5); - cable.applyHeat(heat); - - cableBroken = cable.isInvalid(); - if (cableBroken) { - // a cable burned away (or insulation melted) - break; + while (routePath.hasNextFacing()) { + NetPath.FacedNetPath path = routePath.nextFacing(); + + // if (GTUtility.arePosEqual(cable.getPos(), path.getTargetNode().getNodePos()) && side == path.getTargetFacing()) { + // // Do not insert into source handler + // continue; + // } + + EnumFacing facing = path.facing.getOpposite(); + + IEnergyContainer dest = path.getTargetTE().getCapability( + GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facing); + if (dest == null) continue; + + if (!dest.inputsEnergy(facing) || dest.getEnergyCanBeInserted() <= 0) continue; + + long pathVoltage = voltage - maxLoss; + boolean cableBroken = false; + for (NodeG node : path.getNodeList()) { + TileEntityCable cable = (TileEntityCable) node.heldMTE; + if (cable.getMaxVoltage() < voltage) { + int heat = (int) (Math.log( + GTUtility.getTierByVoltage(voltage) - + GTUtility.getTierByVoltage(cable.getMaxVoltage())) * + 45 + 36.5); + cable.applyHeat(heat); + + cableBroken = cable.isInvalid(); + if (cableBroken) { + // a cable burned away (or insulation melted) + break; + } + + // limit transfer to cables max and void rest + pathVoltage = Math.min(cable.getMaxVoltage(), pathVoltage); } - - // limit transfer to cables max and void rest - pathVoltage = Math.min(cable.getMaxVoltage(), pathVoltage); } - } - if (cableBroken) continue; + if (cableBroken) continue; - transfer = true; - long amps = dest.acceptEnergyFromNetwork(facing, pathVoltage, amperage - amperesUsed); - transfer = false; - if (amps == 0) continue; + transfer = true; + long amps = dest.acceptEnergyFromNetwork(facing, pathVoltage, amperage - amperesUsed); + transfer = false; + if (amps == 0) continue; - amperesUsed += amps; - long voltageTraveled = voltage; - for (TileEntityCable cable : path.getPath()) { - voltageTraveled -= cable.getNodeData().getLossPerBlock(); - if (voltageTraveled <= 0) break; + amperesUsed += amps; + long voltageTraveled = voltage; + for (NodeG node : path.getNodeList()) { + TileEntityCable cable = (TileEntityCable) node.heldMTE; + voltageTraveled -= cable.getNodeData().getLossPerBlock(); + if (voltageTraveled <= 0) break; - if (!cable.isInvalid()) { - cable.incrementAmperage(amps, voltageTraveled); + if (!cable.isInvalid()) { + cable.incrementAmperage(amps, voltageTraveled); + } } - } - if (amperage == amperesUsed) break; + if (amperage == amperesUsed) break mainloop; + } } - - net.addEnergyFluxPerSec(amperesUsed * voltage); + if (net.getGroup(this.cable.getPipePos()).getData() instanceof EnergyGroupData data) + data.addEnergyFluxPerSec(amperesUsed * voltage); return amperesUsed; } diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetWalker.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetWalker.java deleted file mode 100644 index 9a251b4411f..00000000000 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetWalker.java +++ /dev/null @@ -1,73 +0,0 @@ -package gregtech.common.pipelike.cable.net; - -import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.capability.IEnergyContainer; -import gregtech.api.pipenet.PipeNetWalker; -import gregtech.common.pipelike.cable.tile.TileEntityCable; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import org.apache.commons.lang3.ArrayUtils; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -public class EnergyNetWalker extends PipeNetWalker { - - public static List createNetData(World world, BlockPos sourcePipe) { - if (!(world.getTileEntity(sourcePipe) instanceof TileEntityCable)) { - return null; - } - EnergyNetWalker walker = new EnergyNetWalker(world, sourcePipe, 1, new ArrayList<>()); - walker.traversePipeNet(); - return walker.isFailed() ? null : walker.routes; - } - - private final List routes; - private TileEntityCable[] pipes = {}; - private int loss; - - protected EnergyNetWalker(World world, BlockPos sourcePipe, int walkedBlocks, List routes) { - super(world, sourcePipe, walkedBlocks); - this.routes = routes; - } - - @Override - protected PipeNetWalker createSubWalker(World world, EnumFacing facingToNextPos, BlockPos nextPos, - int walkedBlocks) { - EnergyNetWalker walker = new EnergyNetWalker(world, nextPos, walkedBlocks, routes); - walker.loss = loss; - walker.pipes = pipes; - return walker; - } - - @Override - protected void checkPipe(TileEntityCable pipeTile, BlockPos pos) { - pipes = ArrayUtils.add(pipes, pipeTile); - loss += pipeTile.getNodeData().getLossPerBlock(); - } - - @Override - protected void checkNeighbour(TileEntityCable pipeTile, BlockPos pipePos, EnumFacing faceToNeighbour, - @Nullable TileEntity neighbourTile) { - // assert that the last added pipe is the current pipe - if (pipeTile != pipes[pipes.length - 1]) throw new IllegalStateException( - "The current pipe is not the last added pipe. Something went seriously wrong!"); - if (neighbourTile != null) { - IEnergyContainer container = neighbourTile.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, - faceToNeighbour.getOpposite()); - if (container != null) { - routes.add(new EnergyRoutePath(faceToNeighbour, pipes, getWalkedBlocks(), loss)); - } - } - } - - @Override - protected Class getBasePipeClass() { - return TileEntityCable.class; - } -} diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyRoutePath.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyRoutePath.java deleted file mode 100644 index 83e2c9856d0..00000000000 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyRoutePath.java +++ /dev/null @@ -1,54 +0,0 @@ -package gregtech.common.pipelike.cable.net; - -import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.capability.IEnergyContainer; -import gregtech.api.pipenet.IRoutePath; -import gregtech.common.pipelike.cable.tile.TileEntityCable; - -import net.minecraft.util.EnumFacing; - -import org.jetbrains.annotations.NotNull; - -public class EnergyRoutePath implements IRoutePath { - - private final TileEntityCable targetPipe; - private final EnumFacing destFacing; - private final int distance; - private final TileEntityCable[] path; - private final long maxLoss; - - public EnergyRoutePath(EnumFacing destFacing, TileEntityCable[] path, int distance, long maxLoss) { - this.targetPipe = path[path.length - 1]; - this.destFacing = destFacing; - this.path = path; - this.distance = distance; - this.maxLoss = maxLoss; - } - - @Override - public @NotNull TileEntityCable getTargetPipe() { - return targetPipe; - } - - @Override - public @NotNull EnumFacing getTargetFacing() { - return destFacing; - } - - @Override - public int getDistance() { - return distance; - } - - public long getMaxLoss() { - return maxLoss; - } - - public TileEntityCable[] getPath() { - return path; - } - - public IEnergyContainer getHandler() { - return getTargetCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER); - } -} diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldENet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldENet.java deleted file mode 100644 index 32f06681d65..00000000000 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldENet.java +++ /dev/null @@ -1,31 +0,0 @@ -package gregtech.common.pipelike.cable.net; - -import gregtech.api.pipenet.WorldPipeNet; -import gregtech.api.unification.material.properties.WireProperties; - -import net.minecraft.world.World; - -public class WorldENet extends WorldPipeNet { - - private static final String DATA_ID_BASE = "gregtech.e_net"; - - public static WorldENet getWorldENet(World world) { - final String DATA_ID = getDataID(DATA_ID_BASE, world); - WorldENet eNetWorldData = (WorldENet) world.loadData(WorldENet.class, DATA_ID); - if (eNetWorldData == null) { - eNetWorldData = new WorldENet(DATA_ID); - world.setData(DATA_ID, eNetWorldData); - } - eNetWorldData.setWorldAndInit(world); - return eNetWorldData; - } - - public WorldENet(String name) { - super(name); - } - - @Override - protected EnergyNet createNetInstance() { - return new EnergyNet(this); - } -} diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java new file mode 100644 index 00000000000..c6585e2ed49 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -0,0 +1,52 @@ +package gregtech.common.pipelike.cable.net; + +import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.unification.material.properties.WireProperties; + +import gregtech.common.pipelike.cable.Insulation; + +import gregtech.common.pipelike.cable.tile.TileEntityCable; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; + +public class WorldEnergyNet extends WorldPipeNetG { + + private static final String DATA_ID_BASE = "gregtech.e_net"; + + public static WorldEnergyNet getWorldEnergyNet(World world) { + final String DATA_ID = getDataID(DATA_ID_BASE, world); + WorldEnergyNet eNetWorldData = (WorldEnergyNet) world.loadData(WorldEnergyNet.class, DATA_ID); + if (eNetWorldData == null) { + eNetWorldData = new WorldEnergyNet(DATA_ID); + world.setData(DATA_ID, eNetWorldData); + } + eNetWorldData.setWorldAndInit(world); + return eNetWorldData; + } + + public WorldEnergyNet(String name) { + super(name); + } + + @Override + protected Class> getBasePipeClass() { + return TileEntityCable.class; + } + + @Override + protected void writeNodeData(WireProperties nodeData, NBTTagCompound tagCompound) { + tagCompound.setInteger("voltage", nodeData.getVoltage()); + tagCompound.setInteger("amperage", nodeData.getAmperage()); + tagCompound.setInteger("loss", nodeData.getLossPerBlock()); + } + + @Override + protected WireProperties readNodeData(NBTTagCompound tagCompound) { + int voltage = tagCompound.getInteger("voltage"); + int amperage = tagCompound.getInteger("amperage"); + int lossPerBlock = tagCompound.getInteger("loss"); + return new WireProperties(voltage, amperage, lossPerBlock); + } +} diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java index befdf615466..c8ee74ca3a2 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java @@ -14,9 +14,8 @@ import gregtech.common.blocks.MetaBlocks; import gregtech.common.pipelike.cable.BlockCable; import gregtech.common.pipelike.cable.Insulation; -import gregtech.common.pipelike.cable.net.EnergyNet; import gregtech.common.pipelike.cable.net.EnergyNetHandler; -import gregtech.common.pipelike.cable.net.WorldENet; +import gregtech.common.pipelike.cable.net.WorldEnergyNet; import net.minecraft.init.Blocks; import net.minecraft.nbt.NBTTagCompound; @@ -34,7 +33,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; @@ -54,7 +52,6 @@ public class TileEntityCable extends TileEntityMaterialPipeBase currentEnergyNet = new WeakReference<>(null); @SideOnly(Side.CLIENT) private GTOverheatParticle particle; private int heatQueue; @@ -81,10 +78,7 @@ public boolean canHaveBlockedFaces() { } private void initHandlers() { - EnergyNet net = getEnergyNet(); - if (net == null) { - return; - } + WorldEnergyNet net = WorldEnergyNet.getWorldEnergyNet(getPipeWorld()); for (EnumFacing facing : EnumFacing.VALUES) { handlers.put(facing, new EnergyNetHandler(net, this, facing)); } @@ -260,39 +254,11 @@ public T getCapabilityInternal(Capability capability, @Nullable EnumFacin return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER.cast(clientCapability); if (handlers.isEmpty()) initHandlers(); - checkNetwork(); return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER.cast(handlers.getOrDefault(facing, defaultHandler)); } return super.getCapabilityInternal(capability, facing); } - public void checkNetwork() { - if (defaultHandler != null) { - EnergyNet current = getEnergyNet(); - if (defaultHandler.getNet() != current) { - defaultHandler.updateNetwork(current); - for (EnergyNetHandler handler : handlers.values()) { - handler.updateNetwork(current); - } - } - } - } - - private EnergyNet getEnergyNet() { - if (world == null || world.isRemote) - return null; - EnergyNet currentEnergyNet = this.currentEnergyNet.get(); - if (currentEnergyNet != null && currentEnergyNet.isValid() && - currentEnergyNet.containsNode(getPos())) - return currentEnergyNet; // return current net if it is still valid - WorldENet worldENet = WorldENet.getWorldENet(getWorld()); - currentEnergyNet = worldENet.getNetFromPos(getPos()); - if (currentEnergyNet != null) { - this.currentEnergyNet = new WeakReference<>(currentEnergyNet); - } - return currentEnergyNet; - } - @Override public void onChunkUnload() { super.onChunkUnload(); diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index 7efa506aee6..680fa7f809e 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -152,8 +152,10 @@ private ItemStack insertToHandlers(List routePath = routePathIterator.next(); + routePath.resetFacingIterator(); while (routePath.hasNextFacing()) { NetPath.FacedNetPath facedNetPath = routePath.nextFacing(); int amount = c; @@ -162,7 +164,7 @@ private ItemStack insertToHandlers(List inv : copy) { + inv.resetFacingIterator(); while (inv.hasNextFacing()) { NetPath.FacedNetPath faceInv = inv.nextFacing(); simStack = stack.copy(); From 493ecafd0a5e6962a3c513b9a69b36afc59538ea Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 18 Dec 2023 17:47:14 -0700 Subject: [PATCH 019/157] Lobotomized central monitor --- .../MetaTileEntityCentralMonitor.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java index b9e73bb036b..0c0db6f8b9e 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java @@ -73,7 +73,7 @@ public class MetaTileEntityCentralMonitor extends MultiblockWithDisplayBase impl // run-time data public int width; private long lastUpdate; - private WeakReference currentEnergyNet; +// private WeakReference currentEnergyNet; private List activeNodes; private Set netCovers; private Set remoteCovers; @@ -89,7 +89,7 @@ public MetaTileEntityCentralMonitor(ResourceLocation metaTileEntityId) { super(metaTileEntityId); } - private EnergyNet getEnergyNet() { +// private EnergyNet getEnergyNet() { // if (!this.getWorld().isRemote) { // TileEntity te = getNeighbor(frontFacing.getOpposite()); // if (te instanceof TileEntityCable) { @@ -108,25 +108,25 @@ private EnergyNet getEnergyNet() { // return currentEnergyNet; // } // } - return null; - } +// return null; +// } private void updateNodes() { - EnergyNet energyNet = getEnergyNet(); - if (energyNet == null) { - activeNodes.clear(); - return; - } - if (energyNet.getLastUpdate() == lastUpdate) { - return; - } - lastUpdate = energyNet.getLastUpdate(); - activeNodes.clear(); - energyNet.getAllNodes().forEach((pos, node) -> { - if (node.isActive) { - activeNodes.add(pos); - } - }); +// EnergyNet energyNet = getEnergyNet(); +// if (energyNet == null) { +// activeNodes.clear(); +// return; +// } +// if (energyNet.getLastUpdate() == lastUpdate) { +// return; +// } +// lastUpdate = energyNet.getLastUpdate(); +// activeNodes.clear(); +// energyNet.getAllNodes().forEach((pos, node) -> { +// if (node.isActive) { +// activeNodes.add(pos); +// } +// }); } public void addRemoteCover(FacingPos cover) { @@ -423,7 +423,7 @@ public String[] getDescription() { protected void formStructure(PatternMatchContext context) { super.formStructure(context); lastUpdate = 0; - currentEnergyNet = new WeakReference<>(null); +// currentEnergyNet = new WeakReference<>(null); activeNodes = new ArrayList<>(); netCovers = new HashSet<>(); remoteCovers = new HashSet<>(); From f4ff0752ff7fe436de0e8094580af5a4100747e2 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 19 Dec 2023 23:23:24 -0700 Subject: [PATCH 020/157] That took far too much work. --- .../NeighborCacheTileEntityBase.java | 8 + .../api/pipenet/AbstractGroupData.java | 3 +- .../java/gregtech/api/pipenet/INodeData.java | 3 + .../java/gregtech/api/pipenet/NetEdge.java | 15 +- .../java/gregtech/api/pipenet/NetGroup.java | 75 +++++-- .../java/gregtech/api/pipenet/NetPath.java | 13 +- src/main/java/gregtech/api/pipenet/NodeG.java | 199 ++++++++++++----- .../gregtech/api/pipenet/WorldPipeNetG.java | 186 ++++++++-------- .../gregtech/api/pipenet/block/BlockPipe.java | 7 +- .../material/TileEntityMaterialPipeBase.java | 2 +- .../gregtech/api/pipenet/tile/IPipeTile.java | 15 +- .../tile/PipeCoverableImplementation.java | 2 +- .../api/pipenet/tile/TileEntityPipeBase.java | 208 +++++++++--------- .../properties/FluidPipeProperties.java | 3 +- .../properties/ItemPipeProperties.java | 5 +- .../material/properties/WireProperties.java | 7 +- .../pipelike/cable/net/EnergyNetHandler.java | 22 +- .../pipelike/cable/net/WorldEnergyNet.java | 6 + .../pipelike/cable/tile/TileEntityCable.java | 1 + .../fluidpipe/tile/TileEntityFluidPipe.java | 3 + .../pipelike/itempipe/net/ItemNetHandler.java | 2 +- .../pipelike/laser/LaserPipeProperties.java | 1 + .../pipelike/laser/net/LaserNetHandler.java | 2 +- .../laser/tile/TileEntityLaserPipe.java | 4 +- .../optical/OpticalPipeProperties.java | 1 + .../optical/net/OpticalNetHandler.java | 2 +- .../optical/tile/TileEntityOpticalPipe.java | 2 +- .../debug/DebugPipeNetInfoProvider.java | 11 +- 28 files changed, 491 insertions(+), 317 deletions(-) diff --git a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java index 97200ab8518..ea37e85c017 100644 --- a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java +++ b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java @@ -18,6 +18,14 @@ public abstract class NeighborCacheTileEntityBase extends SyncedTileEntityBase i private final TileEntity[] neighbors = new TileEntity[6]; private boolean neighborsInvalidated = false; + /** + * @param doInvalidationHere set to false if you override {@link NeighborCacheTileEntityBase#invalidateNeighbors()} + * with a method that references something you do not yet have set. + */ + public NeighborCacheTileEntityBase(boolean doInvalidationHere) { + if (doInvalidationHere) invalidateNeighbors(); + } + public NeighborCacheTileEntityBase() { invalidateNeighbors(); } diff --git a/src/main/java/gregtech/api/pipenet/AbstractGroupData.java b/src/main/java/gregtech/api/pipenet/AbstractGroupData.java index 76ca0fee83a..20201723882 100644 --- a/src/main/java/gregtech/api/pipenet/AbstractGroupData.java +++ b/src/main/java/gregtech/api/pipenet/AbstractGroupData.java @@ -2,7 +2,8 @@ import gregtech.api.pipenet.block.IPipeType; -public abstract class AbstractGroupData & IPipeType, NodeDataType extends INodeData> { +public abstract class AbstractGroupData & IPipeType, + NodeDataType extends INodeData> { protected NetGroup group; diff --git a/src/main/java/gregtech/api/pipenet/INodeData.java b/src/main/java/gregtech/api/pipenet/INodeData.java index 2062cdd6970..bee5e1b05bc 100644 --- a/src/main/java/gregtech/api/pipenet/INodeData.java +++ b/src/main/java/gregtech/api/pipenet/INodeData.java @@ -8,5 +8,8 @@ default double getWeightFactor() { return 1; } + /** + * Note - since datas is a set, no summative operations are allowed. + */ T getMinData(Set datas); } diff --git a/src/main/java/gregtech/api/pipenet/NetEdge.java b/src/main/java/gregtech/api/pipenet/NetEdge.java index 59be6bfcc76..86a7ddb18de 100644 --- a/src/main/java/gregtech/api/pipenet/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/NetEdge.java @@ -2,14 +2,12 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.util.function.QuadConsumer; -import gregtech.api.util.function.TriConsumer; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.INBTSerializable; import org.jgrapht.graph.DefaultWeightedEdge; -import java.util.List; import java.util.Map; class NetEdge extends DefaultWeightedEdge implements INBTSerializable { @@ -46,18 +44,19 @@ public NBTTagCompound serializeNBT() { tag.setLong("SourceLongPos", getSource().getLongPos()); tag.setLong("TargetLongPos", getTarget().getLongPos()); tag.setDouble("Weight", getWeight()); - tag.setTag("Predicate", AbstractEdgePredicate.toNBT(predicate)); + if (predicate != null) tag.setTag("Predicate", AbstractEdgePredicate.toNBT(predicate)); tag.setBoolean("InvertedPredicate", isPredicateInverted()); - return null; + return tag; } /** - * Use {@link Builder} instead, this does nothing. + * Use {@link NBTBuilder} instead, this does nothing. */ @Override + @Deprecated public void deserializeNBT(NBTTagCompound nbt) {} - static final class Builder & IPipeType, + static final class NBTBuilder & IPipeType, NodeDataType extends INodeData> { private final NodeG node1; @@ -68,8 +67,8 @@ static final class Builder & IPipeType, NodeG, Double, AbstractEdgePredicate> edgeProducer; - Builder(Map> longPosMap, NBTTagCompound tag, - QuadConsumer, NodeG, Double, AbstractEdgePredicate> edgeProducer) { + NBTBuilder(Map> longPosMap, NBTTagCompound tag, + QuadConsumer, NodeG, Double, AbstractEdgePredicate> edgeProducer) { this.node1 = longPosMap.get(tag.getLong("SourceLongPos")); this.node2 = longPosMap.get(tag.getLong("TargetLongPos")); this.weight = tag.getDouble("Weight"); diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index e17401fb07e..de0c183d8b2 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -3,14 +3,20 @@ import gregtech.api.pipenet.block.IPipeType; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.util.INBTSerializable; + import org.jgrapht.Graph; import org.jgrapht.traverse.BreadthFirstIterator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -public class NetGroup & IPipeType, NodeDataType extends INodeData> { +public class NetGroup & IPipeType, + NodeDataType extends INodeData> implements INBTSerializable { public final WorldPipeNetG net; @@ -18,12 +24,13 @@ public class NetGroup & IPipeType, private final Set> nodes; - private AbstractGroupData data; + private final AbstractGroupData data; public NetGroup(Graph, NetEdge> graph, WorldPipeNetG net) { this.graph = graph; this.nodes = new ObjectOpenHashSet<>(); this.net = net; + this.data = net.getBlankGroupData(); } public NetGroup(Graph, NetEdge> graph, WorldPipeNetG net, @@ -32,6 +39,7 @@ public NetGroup(Graph, NetEdge> graph, WorldPipeNe this.nodes = nodes; this.net = net; this.nodes.forEach(b -> b.setGroup(this)); + this.data = net.getBlankGroupData(); } private void clear() { @@ -65,13 +73,15 @@ protected final void addNodes(NodeG... nodes) { public static boolean mergeEdge(NodeG source, NodeG target) { NetGroup sourceGroup = source.getGroup(); NetGroup targetGroup = target.getGroup(); - if (sourceGroup == targetGroup) return sourceGroup == null; + if (sourceGroup == targetGroup) { + if (sourceGroup == null) return true; + sourceGroup.clearPathCaches(); + return false; + } if (sourceGroup != null) { sourceGroup.mergeNode(target); - sourceGroup.clearPathCaches(); } else { targetGroup.mergeNode(source); - targetGroup.clearPathCaches(); } return false; } @@ -79,9 +89,11 @@ public static boolean mergeEdge(NodeG source, NodeG target) { protected void mergeNode(NodeG node) { NodeG cast = (NodeG) node; if (cast.getGroup() != null) { - this.addNodes(cast.getGroup().getNodes()); - cast.getGroup().clear(); + NetGroup group = cast.getGroup(); + this.addNodes(group.getNodes()); + group.clear(); } else addNode(cast); + this.clearPathCaches(); } /** @@ -93,8 +105,12 @@ protected void mergeNode(NodeG node) { public boolean splitNode(NodeG source) { if (graph.containsVertex(source)) { this.clearPathCaches(); - List> targets = graph.edgesOf(source).stream().map(NetEdge::getTarget) - .collect(Collectors.toList()); + List> targets = graph.outgoingEdgesOf(source).stream().map(a -> { + // handling so undirected graphs don't throw an error + if (net.isDirected()) return a.getTarget(); + if (a.getTarget().getNodePos() != source.getNodePos()) return a.getTarget(); + return a.getSource(); + }).collect(Collectors.toList()); graph.removeVertex(source); while (!targets.isEmpty()) { // get the lastmost target; if this throws a cast exception, something is very wrong with the graph. @@ -136,7 +152,6 @@ public boolean splitEdge(NodeG source, NodeG> targetGroup = new ObjectOpenHashSet<>(); - this.graph.removeEdge(source, target); BreadthFirstIterator, NetEdge> i = new BreadthFirstIterator<>(graph, target); NodeG temp; while (i.hasNext()) { @@ -169,13 +184,43 @@ protected void clearPathCaches() { this.nodes.forEach(NodeG::clearPathCache); } - public void initData(AbstractGroupData data) { - if (this.data == null) { - this.data = data.withGroup(this); + public AbstractGroupData getData() { + return this.data; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + int i = 0; + for (NodeG node : this.nodes) { + tag.setLong(String.valueOf(i), node.getLongPos()); + i++; } + tag.setInteger("NodeCount", i); + return tag; } - public AbstractGroupData getData() { - return data; + /** + * Use {@link NBTBuilder} instead, this does nothing. + */ + @Override + @Deprecated + public void deserializeNBT(NBTTagCompound nbt) {} + + static final class NBTBuilder & IPipeType, + NodeDataType extends INodeData> { + + private final Set> nodes; + + NBTBuilder(Map> longPosMap, NBTTagCompound tag) { + nodes = new ObjectOpenHashSet<>(); + for (int i = 0; i < tag.getInteger("NodeCount"); i++) { + nodes.add(longPosMap.get(tag.getLong(String.valueOf(i)))); + } + } + + void build(Graph, NetEdge> graph, WorldPipeNetG net) { + NetGroup g = new NetGroup<>(graph, net, nodes); + } } } diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index 0cf38f60334..e801399ec9a 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -40,7 +40,7 @@ public NetPath(NodeG node) { this.targetNode = node; this.nodeList = new ObjectArrayList<>(1); this.nodeList.add(node); - this.weight = 0; + this.weight = node.getData().getWeightFactor(); this.edgeList = new ObjectArrayList<>(0); resetFacingIterator(); } @@ -70,7 +70,7 @@ public NetPath(GraphPath, NetEdge> path) { this.targetNode = path.getEndVertex(); this.nodeList = path.getVertexList(); // convert weight to the true value of the involved nodes - this.weight = (path.getWeight() + sourceNode.data.getWeightFactor() + targetNode.data.getWeightFactor()) / 2; + this.weight = (path.getWeight() + sourceNode.getData().getWeightFactor() + targetNode.getData().getWeightFactor()) / 2; this.edgeList = path.getEdgeList(); resetFacingIterator(); } @@ -111,10 +111,10 @@ public double getWeight() { return weight; } - public NodeDataType getData() { + public NodeDataType getMinData() { // generate min data on-demand and cache it, rather than generating for every path always if (this.data == null) { - this.data = sourceNode.data.getMinData(this.nodeList.stream().map(NodeG::getData).collect(Collectors.toSet())); + this.data = sourceNode.getData().getMinData(this.nodeList.stream().map(NodeG::getData).collect(Collectors.toSet())); } return data; } @@ -132,7 +132,8 @@ public static class FacedNetPath & IPipeType, NDT exten public EnumFacing facing; public FacedNetPath(NetPath path, EnumFacing facing) { - new FacedNetPath<>(path, facing); + this.path = path; + this.facing = facing; } public TileEntity getTargetTE() { @@ -159,7 +160,7 @@ public double getWeight() { } public NDT getData() { - return path.getData(); + return path.getMinData(); } public boolean checkPredicate(Object o) { diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index bfb776156fc..898b5a268e3 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -3,8 +3,6 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.nbt.NBTTagCompound; @@ -13,30 +11,34 @@ import net.minecraft.util.math.BlockPos; import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + import org.jetbrains.annotations.Nullable; -import org.jgrapht.GraphPath; import java.lang.ref.WeakReference; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; public class NodeG & IPipeType, NodeDataType extends INodeData> implements INBTSerializable { - public static final int DEFAULT_MARK = 0; + private final WorldPipeNetG net; - public NodeDataType data; + private NodeDataType data; + /** + * Specifies bitmask of active connections. + * Active connections determine visual connections and graph edges. + * An active connection does not always mean an edge is present. + */ + private int activeConnections; /** - * Specifies bitmask of blocked connections - * Node will not connect in blocked direction in any case, - * even if neighbour node mark matches + * Specifies bitmask of blocked connections. + * Blocked connections allow flow in, but not flow out. + * Only allowed on directed graphs. */ - public int openConnections; + private int blockedConnections; /** * Specifies mark of this node * Nodes can connect only if their marks are equal, or if @@ -45,38 +47,49 @@ public class NodeG & IPipeType, No public int mark; public boolean isActive; - // TODO make weak reference - public IPipeTile heldMTE; - /** - * Connected tile entities - */ - private Map> connecteds = new Object2ObjectOpenHashMap<>(6); + private WeakReference> heldMTE; - /** - * CANNOT BE CHANGED DURING THE LIFETIME OF A NODE OR THE GRAPH WILL BREAK (or so I've been told) - */ - private BlockPos nodePos; + private final BlockPos nodePos; private NetGroup group = null; private List> pathCache = null; - public NodeG(NodeDataType data, int openConnections, int mark, boolean isActive, - IPipeTile heldMTE, BlockPos pos) { + public NodeG(NodeDataType data, IPipeTile heldMTE, + WorldPipeNetG net) { this.data = data; - this.openConnections = openConnections; - this.mark = mark; - this.isActive = isActive; - this.heldMTE = heldMTE; - this.nodePos = pos; + this.activeConnections = 0; + this.blockedConnections = 0; + this.mark = 0; + this.isActive = false; + this.heldMTE = new WeakReference<>(heldMTE); + this.nodePos = heldMTE.getPipePos(); + this.net = net; + } + + /** + * Creates a dummy node for client-side information handling. + * Should never be required to reference its net or position. + */ + @SideOnly(Side.CLIENT) + public NodeG(IPipeTile heldMTE) { + this.nodePos = null; + this.net = null; + this.data = null; + this.heldMTE = new WeakReference<>(heldMTE); + this.activeConnections = 0; + this.blockedConnections = 0; } /** * For construction during NBT reading only */ public NodeG(NBTTagCompound tag, WorldPipeNetG net) { + this.nodePos = BlockPos.fromLong(tag.getLong("Pos")); deserializeNBT(tag); this.data = net.readNodeData(tag.getCompoundTag("Data")); + this.net = net; + this.heldMTE = new WeakReference<>(null); } @Nullable @@ -93,35 +106,78 @@ void clearGroup() { this.group = null; } - public void addConnected(EnumFacing facing, TileEntity te) { - this.connecteds.put(facing, new WeakReference<>(te)); - } - public boolean hasConnecteds() { - Optional o = this.connecteds.values().stream().map(a -> a.get() != null).reduce((a, b) -> a || b); - return o.isPresent() && o.get(); + for (EnumFacing facing : EnumFacing.VALUES) { + if (!isOutputAble(facing)) continue; + if (getHeldMTE().getNonPipeNeighbour(facing) != null) return true; + } + return false; } public Map getConnecteds() { - //noinspection DataFlowIssue - return this.connecteds.entrySet().stream().filter(a -> a.getValue().get() != null) - .collect(Collectors.toMap(Map.Entry::getKey, a -> a.getValue().get())); + Map map = new Object2ObjectOpenHashMap<>(6); + for (EnumFacing facing : EnumFacing.VALUES) { + if (!isOutputAble(facing)) continue; + if (getHeldMTE().getNonPipeNeighbour(facing) != null) + map.put(facing, getHeldMTE().getNonPipeNeighbour(facing)); + } + return map; } public TileEntity getConnnected(EnumFacing facing) { - return this.connecteds.get(facing).get(); + return this.getHeldMTE().getNonPipeNeighbour(facing); + } + + public boolean isConnected(EnumFacing facing) { + return (activeConnections & 1 << facing.getIndex()) != 0; + } + + /** + * Should only be used with dummy nodes, otherwise go through the net. + */ + public void setActiveConnections(int activeConnections) { + this.activeConnections = activeConnections; + } + + void setConnected(EnumFacing facing, boolean connect) { + if (connect) { + this.activeConnections |= 1 << facing.getIndex(); + } else { + this.activeConnections &= ~(1 << facing.getIndex()); + } + this.getHeldMTE().onConnectionChange(); + } + + public int getActiveConnections() { + return activeConnections; } public boolean isBlocked(EnumFacing facing) { - return (openConnections & 1 << facing.getIndex()) == 0; + return (blockedConnections & 1 << facing.getIndex()) != 0; } - void setBlocked(EnumFacing facing, boolean isBlocked) { - if (!isBlocked) { - this.openConnections |= 1 << facing.getIndex(); + /** + * Should only be used with dummy nodes, otherwise go through the net. + */ + public void setBlockedConnections(int blockedConnections) { + this.blockedConnections = blockedConnections; + } + + void setBlocked(EnumFacing facing, boolean block) { + if (block) { + this.blockedConnections |= 1 << facing.getIndex(); } else { - this.openConnections &= ~(1 << facing.getIndex()); + this.blockedConnections &= ~(1 << facing.getIndex()); } + this.getHeldMTE().onBlockedChange(); + } + + public int getBlockedConnections() { + return blockedConnections; + } + + boolean isOutputAble(EnumFacing facing) { + return (activeConnections & ~(blockedConnections) & 1 << facing.getIndex()) != 0; } public BlockPos getNodePos() { @@ -132,17 +188,45 @@ public long getLongPos() { return nodePos.toLong(); } - void sync(NodeG node) { - this.data = node.data; - this.mark = node.mark; - this.isActive = node.isActive; - this.openConnections = node.openConnections; - // if heldMTE is not null, then it is more up to date than the graph's version. - if (this.heldMTE == null) { - this.heldMTE = node.heldMTE; - } else { - node.heldMTE = this.heldMTE; + public void setHeldMTE(IPipeTile heldMTE) { + if (this.heldMTE.get() != heldMTE) + this.heldMTE = new WeakReference<>(heldMTE); + } + + /** + * Performs no safety checks. + */ + @Nullable + public IPipeTile getHeldMTEUnsafe() { + return heldMTE.get(); + } + + /** + * Ensures that the returned tile is not null. + */ + public IPipeTile getHeldMTE() { + IPipeTile te = getHeldMTEUnsafe(); + if (te == null) { + te = net.castTE(net.getWorld().getTileEntity(this.nodePos)); + setHeldMTE(te); } + return te; + } + + /** + * Ensures that the returned tile is not null nor invalid. + */ + public IPipeTile getHeldMTESafe() { + IPipeTile te = getHeldMTEUnsafe(); + if (te == null || !te.isValidTile()) { + te = net.castTE(net.getWorld().getTileEntity(this.nodePos)); + setHeldMTE(te); + } + return te; + } + + public void setData(NodeDataType data) { + this.data = data; } public NodeDataType getData() { @@ -174,16 +258,15 @@ public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); tag.setLong("Pos", this.nodePos.toLong()); tag.setInteger("Mark", this.mark); - tag.setInteger("OpenConnections", this.openConnections); + tag.setInteger("OpenConnections", this.activeConnections); tag.setBoolean("IsActive", this.isActive); return tag; } @Override public void deserializeNBT(NBTTagCompound nbt) { - this.nodePos = BlockPos.fromLong(nbt.getLong("Pos")); this.mark = nbt.getInteger("Mark"); - this.openConnections = nbt.getInteger("OpenConnections"); + this.activeConnections = nbt.getInteger("OpenConnections"); this.isActive = nbt.getBoolean("IsActive"); } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 02d1d24dd0f..b22c5b66711 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -7,6 +7,8 @@ import gregtech.common.covers.CoverShutter; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; @@ -24,9 +26,8 @@ import org.jgrapht.Graph; import org.jgrapht.GraphPath; import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; -import org.jgrapht.graph.DirectedWeightedMultigraph; +import org.jgrapht.graph.SimpleDirectedWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph; -import org.jgrapht.traverse.DepthFirstIterator; import java.lang.ref.WeakReference; import java.util.Collections; @@ -34,6 +35,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; public abstract class WorldPipeNetG, @@ -50,13 +52,14 @@ public abstract class WorldPipeNetG public WorldPipeNetG(String name) { super(name); if (isDirected()) - this.pipeGraph = new DirectedWeightedMultigraph<>(NetEdge.class); + this.pipeGraph = new SimpleDirectedWeightedGraph<>(NetEdge.class); else this.pipeGraph = new SimpleWeightedGraph<>(NetEdge.class); } /** * Override to change whether this net needs directed graph handling. * Used to respect filter directions in the item net and fluid net, for example. + * If the graph is not directed, pipes should not support blocked connections. * @return True if the graph should be directed. */ protected boolean isDirected() { @@ -95,7 +98,7 @@ protected void onWorldSet() { } /** - * Preferred override. Only collects a fresh TE from the server if the provided TE is not loaded. + * Preferred override. Only collects a fresh TE from the server if the provided TE is invalid. * * @param tile The {@link TileEntityPipeBase} that paths are being requested for * @return the ordered list of paths associated with the {@link TileEntityPipeBase} @@ -114,12 +117,11 @@ public List> getPaths(BlockPos pos) { return getPaths(this.pipeMap.get(pos), null); } - public List> getPaths( - @Nullable NodeG node, - @Nullable TileEntityPipeBase tile) { + public List> getPaths(@Nullable NodeG node, + @Nullable TileEntityPipeBase tile) { if (node == null) return new ObjectArrayList<>(); - node.heldMTE = tile; + node.setHeldMTE(tile); if (!this.validAlgorithmInstance) this.rebuildShortestPaths(); @@ -145,17 +147,8 @@ protected List> verifyList(List node) { - if (!node.hasConnecteds()) return false; - node.heldMTE = verifyTE(node.getNodePos(), (TileEntity) node.heldMTE); - return node.heldMTE != null; - } - - @Nullable - protected TileEntityPipeBase verifyTE(BlockPos pos, @Nullable TileEntity te) { - if (te == null || te.isInvalid()) { - return castTE(getWorld().getTileEntity(pos)); - } - return castTE(te); + node.getHeldMTESafe(); + return node.hasConnecteds(); } @Nullable @@ -171,50 +164,27 @@ protected TileEntityPipeBase castTE(TileEntity te) { protected abstract Class> getBasePipeClass(); - public void syncNode(IPipeTile pipe) { - NodeG node = this.pipeMap.get(pipe.getPipePos()); - if (node != null) { - node.heldMTE = pipe; - for (EnumFacing facing : EnumFacing.VALUES) { - if (pipeMap.containsKey(node.getNodePos().offset(facing))) continue; - if (node.heldMTE.isConnected(facing)) { - node.addConnected(facing, node.heldMTE.getNeighbor(facing)); - } - } - } + /** + * Make sure to override this if your NetGroups use data. + * @return The correct data variant + */ + protected AbstractGroupData getBlankGroupData() { + return null; } - public void addNode(BlockPos nodePos, NodeDataType nodeData, int mark, int openConnections, boolean isActive, - @Nullable IPipeTile heldMTE) { - if (heldMTE != null && this.pipeMap.containsKey(nodePos)) { - this.syncNode(heldMTE); - return; - } - if (heldMTE == null) { - heldMTE = castTE(this.getWorld().getTileEntity(nodePos)); - } - NodeG node = new NodeG<>(nodeData, openConnections, mark, isActive, heldMTE, nodePos); - if (!canAttachNode(nodeData)) return; - + public NodeG getOrCreateNode(@NotNull IPipeTile mte) { + NodeG node = this.pipeMap.get(mte.getPipePos()); + if (node != null) return node; + if (!canAttachNode(mte.getNodeData())) return null; + node = new NodeG<>(mte.getNodeData(), mte,this); this.addNode(node); - addEdges(node); - } - - private void addEdges(NodeG node) { - for (EnumFacing facing : EnumFacing.VALUES) { - BlockPos offsetPos = node.getNodePos().offset(facing); - NodeG nodeOffset = this.pipeMap.get(offsetPos); - if (nodeOffset != null && this.canNodesConnect(node, facing, nodeOffset)) { - this.addUndirectedEdge(node, nodeOffset); - this.predicateUndirectedEdge(node, nodeOffset, facing); - } - } + return node; } protected final boolean canNodesConnect(NodeG source, EnumFacing nodeFacing, NodeG target) { return areNodeBlockedConnectionsCompatible(source, nodeFacing, target) && - areMarksCompatible(source.mark, target.mark) && areNodesCustomContactable(source.data, target.data); + areMarksCompatible(source.mark, target.mark) && areNodesCustomContactable(source.getData(), target.getData()); } private static boolean areMarksCompatible(int mark1, int mark2) { @@ -223,7 +193,7 @@ private static boolean areMarksCompatible(int mark1, int mark2) { private boolean areNodeBlockedConnectionsCompatible(NodeG source, EnumFacing nodeFacing, NodeG target) { - return !source.isBlocked(nodeFacing) && !target.isBlocked(nodeFacing.getOpposite()); + return !source.isConnected(nodeFacing) && !target.isConnected(nodeFacing.getOpposite()); } protected boolean areNodesCustomContactable(NodeDataType source, NodeDataType target) { @@ -234,17 +204,45 @@ protected boolean canAttachNode(NodeDataType nodeData) { return true; } - public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean isBlocked) { + public void updateActiveConnections(BlockPos nodePos, EnumFacing side, boolean connect) { + NodeG node = pipeMap.get(nodePos); + if (node == null || node.isConnected(side) == connect) return; + + node.setConnected(side, connect); + + NodeG nodeOffset = pipeMap.get(nodePos.offset(side)); + if (nodeOffset == null) return; + + nodeOffset.setConnected(side.getOpposite(), connect); + + if (connect) { + if (!node.isBlocked(side)) { + addEdge(node, nodeOffset, null); + this.predicateEdge(node, nodeOffset, side); + if (!this.isDirected()) return; + } + if (!nodeOffset.isBlocked(side.getOpposite())) { + addEdge(nodeOffset, node, null); + this.predicateEdge(nodeOffset, node, side.getOpposite()); + } + } else { + removeUndirectedEdge(node, nodeOffset); + } + } + + public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean blocked) { + if (!isDirected()) return; // no such thing as blocked connections on undirected graphs. NodeG node = pipeMap.get(nodePos); - if (node == null || node.isBlocked(side) == isBlocked) return; + if (node == null || node.isBlocked(side) == blocked) return; + + node.setBlocked(side, blocked); - node.setBlocked(side, isBlocked); NodeG nodeOffset = pipeMap.get(nodePos.offset(side)); if (nodeOffset == null) return; - this.predicateEdge(node, nodeOffset, side); - if (!node.isBlocked(side) && !nodeOffset.isBlocked(side.getOpposite())) { + if (!blocked) { addEdge(node, nodeOffset, null); + this.predicateEdge(node, nodeOffset, side); } else { removeEdge(node, nodeOffset); } @@ -252,7 +250,6 @@ public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean public void updateMark(BlockPos nodePos, int newMark) { NodeG node = pipeMap.get(nodePos); - if (node == null) return; int oldMark = node.mark; node.mark = newMark; @@ -261,14 +258,13 @@ public void updateMark(BlockPos nodePos, int newMark) { NodeG nodeOffset = pipeMap.get(nodePos.offset(side)); if (nodeOffset == null) continue; if (!areNodeBlockedConnectionsCompatible(node, side, nodeOffset) || - !areNodesCustomContactable(node.data, nodeOffset.data)) + !areNodesCustomContactable(node.getData(), nodeOffset.getData())) continue; if (areMarksCompatible(oldMark, nodeOffset.mark) == areMarksCompatible(newMark, nodeOffset.mark)) continue; - this.predicateEdge(node, nodeOffset, side); - if (areMarksCompatible(newMark, nodeOffset.mark)) { addEdge(node, nodeOffset, null); + this.predicateEdge(node, nodeOffset, side); } else { removeEdge(node, nodeOffset); } @@ -300,7 +296,7 @@ public void addUndirectedEdge(NodeG source, NodeG source, NodeG target, @Nullable AbstractEdgePredicate predicate) { - addEdge(source, target, source.data.getWeightFactor() + target.data.getWeightFactor(), predicate); + addEdge(source, target, source.getData().getWeightFactor() + target.getData().getWeightFactor(), predicate); this.validAlgorithmInstance = false; } @@ -344,8 +340,9 @@ public void predicateUndirectedEdge(NodeG source, NodeG< } public void predicateEdge(NodeG source, NodeG target, EnumFacing faceToNeighbour) { - Cover thisCover = source.heldMTE.getCoverableImplementation().getCoverAtSide(faceToNeighbour); - Cover neighbourCover = target.heldMTE.getCoverableImplementation().getCoverAtSide(faceToNeighbour.getOpposite()); + if (!this.pipeGraph.containsEdge(source, target)) return; + Cover thisCover = source.getHeldMTESafe().getCoverableImplementation().getCoverAtSide(faceToNeighbour); + Cover neighbourCover = target.getHeldMTESafe().getCoverableImplementation().getCoverAtSide(faceToNeighbour.getOpposite()); AbstractEdgePredicate predicate = getPredicate(thisCover, neighbourCover); predicate.setPosInfo(source.getNodePos(), target.getNodePos()); NetEdge edge = this.pipeGraph.getEdge(source, target); @@ -368,6 +365,11 @@ protected final AbstractEdgePredicate shutterify(AbstractEdgePredicate pre return predicate; } + public void removeUndirectedEdge(NodeG source, NodeG target) { + this.removeEdge(source, target); + if (isDirected()) this.removeEdge(target, source); + } + public void removeEdge(NodeG source, NodeG target) { if (source.getGroup() != null && source.getGroup().splitEdge(source, target)) { this.validAlgorithmInstance = false; @@ -379,20 +381,21 @@ public void removeNode(BlockPos pos) { this.removeNode(this.pipeMap.get(pos)); } - public void removeNode(NodeG node) { - if (node.getGroup() != null && node.getGroup().splitNode(node)) { - // if the node has no group, then it isn't connected to anything, and thus the cache is still valid - this.validAlgorithmInstance = false; - } else { - this.pipeGraph.removeVertex(node); + public void removeNode(@Nullable NodeG node) { + if (node != null) { + if (this.pipeGraph.edgesOf(node).size() != 0) this.validAlgorithmInstance = false; + if (node.getGroup() != null) { + node.getGroup().splitNode(node); + } else this.pipeGraph.removeVertex(node); + this.pipeMap.remove(node.getNodePos()); + this.markDirty(); } - this.markDirty(); } public NetGroup getGroup(BlockPos pos) { NodeG node = this.getNode(pos); if (node == null) return null; - if (node.getGroup() == null) return null; + if (node.getGroup() != null) return node.getGroup(); return node.setGroup(new NetGroup<>(this.pipeGraph, this)); } @@ -415,7 +418,6 @@ protected void rebuildShortestPaths() { @Override public void readFromNBT(NBTTagCompound nbt) { NBTTagList allPipeNodes = nbt.getTagList("PipeNodes", Constants.NBT.TAG_COMPOUND); - NBTTagList allNetEdges = nbt.getTagList("NetEdges", Constants.NBT.TAG_COMPOUND); Map> longPosMap = new Long2ObjectOpenHashMap<>(); for (int i = 0; i < allPipeNodes.tagCount(); i++) { NBTTagCompound pNodeTag = allPipeNodes.getCompoundTagAt(i); @@ -423,9 +425,15 @@ public void readFromNBT(NBTTagCompound nbt) { longPosMap.put(node.getLongPos(), node); this.addNodeSilent(node); } + NBTTagList allNetEdges = nbt.getTagList("NetEdges", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < allNetEdges.tagCount(); i++) { NBTTagCompound gEdgeTag = allNetEdges.getCompoundTagAt(i); - new NetEdge.Builder<>(longPosMap, gEdgeTag, this::addEdge).addIfBuildable(); + new NetEdge.NBTBuilder<>(longPosMap, gEdgeTag, this::addEdge).addIfBuildable(); + } + NBTTagList allNetGroups = nbt.getTagList("NetGroups", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < allNetGroups.tagCount(); i++) { + NBTTagCompound gTag = allNetGroups.getCompoundTagAt(i); + new NetGroup.NBTBuilder<>(longPosMap, gTag).build(this.pipeGraph, this); } } @@ -433,10 +441,12 @@ public void readFromNBT(NBTTagCompound nbt) { @Override public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { NBTTagList allPipeNodes = new NBTTagList(); + Set> groups = new ObjectOpenHashSet<>(); for (NodeG node : pipeGraph.vertexSet()) { + groups.add(node.getGroup()); NBTTagCompound nodeTag = node.serializeNBT(); NBTTagCompound dataTag = new NBTTagCompound(); - writeNodeData(node.data, dataTag); + writeNodeData(node.getData(), dataTag); nodeTag.setTag("Data", dataTag); allPipeNodes.appendTag(nodeTag); } @@ -447,6 +457,13 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { allNetEdges.appendTag(edge.serializeNBT()); } compound.setTag("NetEdges", allNetEdges); + + NBTTagList allNetGroups = new NBTTagList(); + for (NetGroup group : groups) { + allNetGroups.appendTag(group.serializeNBT()); + } + compound.setTag("NetGroups", allNetGroups); + return compound; } @@ -481,12 +498,7 @@ public List> getPathsList(NodeG source) { ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths( Collections.singleton(source), source.getGroup().getNodes()); for (NodeG v : source.getGroup().getNodes()) { - // update mutably so that the returned paths are also updated - if (v.equals(source)) { - source.sync(v); - continue; - } - + if (v == source) continue; GraphPath, NetEdge> path = manyToManyPaths.getPath(source, v); if (path != null) { paths.add(new NetPath<>(path)); @@ -514,7 +526,7 @@ private List> singlePathList(NodeG lastNode = null; NodeG node = source; NetEdge edge; - double sumWeight = source.data.getWeightFactor(); + double sumWeight = source.getData().getWeightFactor(); boolean valid = true; while (valid) { Iterator i = this.pipeGraph.outgoingEdgesOf(node).iterator(); @@ -532,7 +544,7 @@ private List> singlePathList(NodeG) (reversedEdge ? edge.getSource() : edge.getTarget()); edges.add(edge); nodes.add(node); - sumWeight += node.data.getWeightFactor(); + sumWeight += node.getData().getWeightFactor(); } if (!valid) return paths; if (paths.size() == 0) paths.add(new NetPath<>(source)); diff --git a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java index 0344bdf90a0..b835bf2c44a 100644 --- a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java @@ -132,7 +132,7 @@ public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull I tileEntities.set(pipeTile); } super.breakBlock(worldIn, pos, state); - getWorldPipeNet(worldIn).removeNode(pos); + if (!worldIn.isRemote) getWorldPipeNet(worldIn).removeNode(pos); } @Override @@ -145,6 +145,7 @@ public void updateTick(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull I @NotNull Random rand) { IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); if (pipeTile != null) { + if (worldIn.isRemote) return; int activeConnections = pipeTile.getConnections(); boolean isActiveNode = activeConnections != 0; onActiveModeChange(worldIn, pos, isActiveNode, true); @@ -169,6 +170,7 @@ public void onBlockPlacedBy(@NotNull World worldIn, @NotNull BlockPos pos, @NotN } } } + } } @@ -408,14 +410,15 @@ public EnumActionResult onPipeToolUsed(World world, BlockPos pos, ItemStack stac boolean isBlocked = pipeTile.isFaceBlocked(coverSide); pipeTile.setFaceBlocked(coverSide, !isBlocked); ToolHelper.playToolSound(stack, entityPlayer); + ToolHelper.damageItem(stack, entityPlayer); } else { boolean isOpen = pipeTile.isConnected(coverSide); pipeTile.setConnection(coverSide, !isOpen, false); if (isOpen != pipeTile.isConnected(coverSide)) { ToolHelper.playToolSound(stack, entityPlayer); + ToolHelper.damageItem(stack, entityPlayer); } } - ToolHelper.damageItem(stack, entityPlayer); return EnumActionResult.SUCCESS; } entityPlayer.swingArm(hand); diff --git a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java index 30de56cdf86..4bb4f3c7b31 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java @@ -98,7 +98,7 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { super.receiveCustomData(discriminator, buf); if (discriminator == UPDATE_PIPE_MATERIAL) { readPipeMaterial(buf); - scheduleChunkForRenderUpdate(); + scheduleRenderUpdate(); } } } diff --git a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java index 898752fdb69..0251240a80f 100644 --- a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java +++ b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java @@ -2,16 +2,21 @@ import gregtech.api.metatileentity.interfaces.INeighborCache; import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NodeG; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.unification.material.Material; import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + import org.jetbrains.annotations.Nullable; import java.util.function.Consumer; @@ -57,6 +62,8 @@ default long getTickTimer() { void setConnection(EnumFacing side, boolean connected, boolean fromNeighbor); + void onConnectionChange(); + // if a face is blocked it will still render as connected, but it won't be able to receive stuff from that direction default boolean canHaveBlockedFaces() { return true; @@ -64,6 +71,8 @@ default boolean canHaveBlockedFaces() { int getBlockedConnections(); + void onBlockedChange(); + boolean isFaceBlocked(EnumFacing side); void setFaceBlocked(EnumFacing side, boolean blocked); @@ -74,6 +83,10 @@ default boolean canHaveBlockedFaces() { NodeDataType getNodeData(); + NodeG getNode(); + + @Nullable TileEntity getNonPipeNeighbour(EnumFacing facing); + PipeCoverableImplementation getCoverableImplementation(); @Nullable @@ -96,6 +109,4 @@ default boolean canHaveBlockedFaces() { void markAsDirty(); boolean isValidTile(); - - void scheduleChunkForRenderUpdate(); } diff --git a/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java b/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java index 6be552bfc95..359e8fafd3d 100644 --- a/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java +++ b/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java @@ -227,7 +227,7 @@ public void readCustomData(int dataId, PacketBuffer buf) { // cover removed event EnumFacing placementSide = EnumFacing.VALUES[buf.readByte()]; this.covers.remove(placementSide); - holder.scheduleChunkForRenderUpdate(); + holder.scheduleRenderUpdate(); } else if (dataId == UPDATE_COVER_DATA_PIPE) { // cover custom data received EnumFacing coverSide = EnumFacing.VALUES[buf.readByte()]; diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 1e2e0dcce34..0a0706ff059 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -6,7 +6,7 @@ import gregtech.api.metatileentity.NeighborCacheTileEntityBase; import gregtech.api.metatileentity.SyncedTileEntityBase; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.NodeG; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.unification.material.Material; @@ -30,6 +30,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; import java.util.function.Consumer; import static gregtech.api.capability.GregtechDataCodes.*; @@ -39,10 +40,18 @@ public abstract class TileEntityPipeBase & IPipe implements IPipeTile { protected final PipeCoverableImplementation coverableImplementation = new PipeCoverableImplementation(this); + /** + * this - no information + * null - neighbor is a pipe + * te - neighbor is the stored value + */ + private final TileEntity[] nonPipeNeighbors = new TileEntity[6]; + private boolean nonPipeNeighborsInvalidated = false; protected int paintingColor = -1; - private int connections = 0; - private int blockedConnections = 0; - private NodeDataType cachedNodeData; + /** + * Our node stores connection data and NodeData data + */ + protected @Nullable NodeG netNode; private BlockPipe pipeBlock; private PipeType pipeType = getPipeTypeClass().getEnumConstants()[0]; @Nullable @@ -50,7 +59,10 @@ public abstract class TileEntityPipeBase & IPipe // set when this pipe is replaced with a ticking variant to redirect sync packets private TileEntityPipeBase tickingPipe; - public TileEntityPipeBase() {} + public TileEntityPipeBase() { + super(false); + invalidateNeighbors(); + } public void setPipeData(BlockPipe pipeBlock, PipeType pipeType) { this.pipeBlock = pipeBlock; @@ -64,7 +76,7 @@ public void setPipeData(BlockPipe pipeBlock, PipeType public void transferDataFrom(IPipeTile tileEntity) { this.pipeType = tileEntity.getPipeType(); this.paintingColor = tileEntity.getPaintingColor(); - this.connections = tileEntity.getConnections(); + this.netNode = tileEntity.getNode(); if (tileEntity instanceof SyncedTileEntityBase pipeBase) { addPacketsFrom(pipeBase); } @@ -72,6 +84,21 @@ public void transferDataFrom(IPipeTile tileEntity) { setFrameMaterial(tileEntity.getFrameMaterial()); } + @Override + public NodeG getNode() { + if (netNode == null) { + if (this.getPipeWorld().isRemote) + netNode = new NodeG<>(this); + else netNode = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()).getOrCreateNode(this); + } + return netNode; + } + + @Override + protected void setWorldCreate(World worldIn) { + this.setWorld(worldIn); + } + public abstract Class getPipeTypeClass(); @Nullable @@ -110,10 +137,38 @@ public BlockPos getPipePos() { public void markDirty() { if (getWorld() != null && getPos() != null) { getWorld().markChunkDirty(getPos(), this); - getPipeBlock().getWorldPipeNet(getWorld()).syncNode(this); } } + @Override + protected void invalidateNeighbors() { + super.invalidateNeighbors(); + if (!this.nonPipeNeighborsInvalidated) { + Arrays.fill(nonPipeNeighbors, this); + this.nonPipeNeighborsInvalidated = true; + } + } + + public @Nullable TileEntity getNonPipeNeighbour(EnumFacing facing) { + if (world == null || pos == null) return null; + int i = facing.getIndex(); + TileEntity neighbor = this.nonPipeNeighbors[i]; + if (neighbor == null) return null; + if (neighbor == this || (neighbor.isInvalid())) { + neighbor = getNeighbor(facing); + if (neighbor instanceof IPipeTile) neighbor = null; + this.nonPipeNeighbors[i] = neighbor; + this.nonPipeNeighborsInvalidated = false; + } + return neighbor; + } + + @Override + public void onNeighborChanged(@NotNull EnumFacing facing) { + super.onNeighborChanged(facing); + this.nonPipeNeighbors[facing.getIndex()] = this; + } + @Override public PipeCoverableImplementation getCoverableImplementation() { return coverableImplementation; @@ -156,7 +211,7 @@ public IPipeTile setSupportsTicking() { @Override public int getConnections() { - return connections; + return this.getNode().getActiveConnections(); } @Override @@ -172,7 +227,7 @@ public int getNumConnections() { @Override public int getBlockedConnections() { - return canHaveBlockedFaces() ? blockedConnections : 0; + return this.getNode().getBlockedConnections(); } @Override @@ -202,7 +257,7 @@ public int getDefaultPaintingColor() { @Override public boolean isConnected(EnumFacing side) { - return isConnected(connections, side); + return this.getNode().isConnected(side); } public static boolean isConnected(int connections, EnumFacing side) { @@ -211,78 +266,45 @@ public static boolean isConnected(int connections, EnumFacing side) { @Override public void setConnection(EnumFacing side, boolean connected, boolean fromNeighbor) { - // fix desync between two connections. Can happen if a pipe side is blocked, and a new pipe is placed next to - // it. if (!getWorld().isRemote) { - if (isConnected(side) == connected) { - return; - } - TileEntity tile = getNeighbor(side); - // block connections if Pipe Types do not match - if (connected && - tile instanceof IPipeTilepipeTile && - pipeTile.getPipeType().getClass() != this.getPipeType().getClass()) { - return; - } - connections = withSideConnection(connections, side, connected); - - updateNetworkConnection(side, connected); - writeCustomData(UPDATE_CONNECTIONS, buffer -> { - buffer.writeVarInt(connections); - }); - markDirty(); - - if (!fromNeighbor && tile instanceof IPipeTilepipeTile) { - syncPipeConnections(side, pipeTile); - } + if (isConnected(side) == connected) return; + getPipeBlock().getWorldPipeNet(getWorld()).updateActiveConnections(getPos(), side, connected); } } - private void syncPipeConnections(EnumFacing side, IPipeTile pipe) { - EnumFacing oppositeSide = side.getOpposite(); - boolean neighbourOpen = pipe.isConnected(oppositeSide); - if (isConnected(side) == neighbourOpen) { - return; - } - if (!neighbourOpen || pipe.getCoverableImplementation().getCoverAtSide(oppositeSide) == null) { - pipe.setConnection(oppositeSide, !neighbourOpen, true); + @Override + public void onConnectionChange() { + if (!getWorld().isRemote) { + this.scheduleRenderUpdate(); + this.markDirty(); + writeCustomData(UPDATE_CONNECTIONS, buffer -> buffer.writeVarInt(this.getConnections())); } } - private void updateNetworkConnection(EnumFacing side, boolean connected) { - WorldPipeNetG worldPipeNet = getPipeBlock().getWorldPipeNet(getWorld()); - worldPipeNet.updateBlockedConnections(getPos(), side, !connected); - } - - protected int withSideConnection(int blockedConnections, EnumFacing side, boolean connected) { - int index = 1 << side.getIndex(); - if (connected) { - return blockedConnections | index; - } else { - return blockedConnections & ~index; + @Override + public void setFaceBlocked(EnumFacing side, boolean blocked) { + if (!getWorld().isRemote && canHaveBlockedFaces()) { + if (isFaceBlocked(side) == blocked) return; + getPipeBlock().getWorldPipeNet(getWorld()).updateBlockedConnections(getPos(), side, blocked); } } @Override - public void setFaceBlocked(EnumFacing side, boolean blocked) { - if (!world.isRemote && canHaveBlockedFaces()) { - blockedConnections = withSideConnection(blockedConnections, side, blocked); - writeCustomData(UPDATE_BLOCKED_CONNECTIONS, buf -> { - buf.writeVarInt(blockedConnections); - }); - markDirty(); - WorldPipeNetG worldPipeNet = getPipeBlock().getWorldPipeNet(getWorld()); - worldPipeNet.updateBlockedConnections(this.getPipePos(), side, blocked); + public void onBlockedChange() { + if (!getWorld().isRemote) { + this.scheduleRenderUpdate(); + this.markDirty(); + writeCustomData(UPDATE_BLOCKED_CONNECTIONS, buf -> buf.writeVarInt(this.getBlockedConnections())); } } @Override public boolean isFaceBlocked(EnumFacing side) { - return isFaceBlocked(blockedConnections, side); + return this.getNode().isBlocked(side); } public static boolean isFaceBlocked(int blockedConnections, EnumFacing side) { - return (blockedConnections & (1 << side.getIndex())) > 0; + return (blockedConnections & (1 << side.getIndex())) != 0; } @Override @@ -292,10 +314,13 @@ public PipeType getPipeType() { @Override public NodeDataType getNodeData() { - if (cachedNodeData == null) { - this.cachedNodeData = getPipeBlock().createProperties(this); + // the only thing standing between this and a stack overflow error + if (this.netNode == null) return getPipeBlock().createProperties(this); + + if (this.getNode().getData() == null) { + this.getNode().setData(getPipeBlock().createProperties(this)); } - return cachedNodeData; + return this.getNode().getData(); } private int getCableMark() { @@ -370,8 +395,8 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { compound.setString("PipeBlock", pipeBlock.getRegistryName().toString()); } compound.setInteger("PipeType", pipeType.ordinal()); - compound.setInteger("Connections", connections); - compound.setInteger("BlockedConnections", blockedConnections); + compound.setInteger("Connections", getNode().getActiveConnections()); + compound.setInteger("BlockedConnections", getNode().getBlockedConnections()); if (isPainted()) { compound.setInteger("InsulationColor", paintingColor); } @@ -395,17 +420,8 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { } this.pipeType = getPipeTypeClass().getEnumConstants()[compound.getInteger("PipeType")]; - if (compound.hasKey("Connections")) { - connections = compound.getInteger("Connections"); - } else if (compound.hasKey("BlockedConnectionsMap")) { - connections = 0; - NBTTagCompound blockedConnectionsTag = compound.getCompoundTag("BlockedConnectionsMap"); - for (String attachmentTypeKey : blockedConnectionsTag.getKeySet()) { - int blockedConnections = blockedConnectionsTag.getInteger(attachmentTypeKey); - connections |= blockedConnections; - } - } - blockedConnections = compound.getInteger("BlockedConnections"); + this.getNode().setActiveConnections(compound.getInteger("Connections")); + this.getNode().setBlockedConnections(compound.getInteger("BlockedConnections")); if (compound.hasKey("InsulationColor")) { this.paintingColor = compound.getInteger("InsulationColor"); @@ -425,8 +441,6 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { @Override public void onLoad() { super.onLoad(); - this.pipeBlock.getWorldPipeNet(this.getWorld()).addNode(this.getPipePos(), this.getNodeData(), - this.getCableMark(), ~(this.getBlockedConnections()), false, this); } protected void writePipeProperties(PacketBuffer buf) { @@ -440,8 +454,8 @@ protected void readPipeProperties(PacketBuffer buf) { @Override public void writeInitialSyncData(PacketBuffer buf) { writePipeProperties(buf); - buf.writeVarInt(connections); - buf.writeVarInt(blockedConnections); + buf.writeVarInt(this.getNode().getActiveConnections()); + buf.writeVarInt(this.getNode().getBlockedConnections()); buf.writeInt(paintingColor); buf.writeVarInt(frameMaterial == null ? -1 : frameMaterial.getRegistry().getNetworkId()); buf.writeVarInt(frameMaterial == null ? -1 : frameMaterial.getId()); @@ -455,8 +469,8 @@ public void receiveInitialSyncData(PacketBuffer buf) { return; } readPipeProperties(buf); - this.connections = buf.readVarInt(); - this.blockedConnections = buf.readVarInt(); + this.getNode().setActiveConnections(buf.readVarInt()); + this.getNode().setBlockedConnections(buf.readVarInt()); this.paintingColor = buf.readInt(); int registryId = buf.readVarInt(); int frameMaterialId = buf.readVarInt(); @@ -480,18 +494,18 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { } if (discriminator == UPDATE_INSULATION_COLOR) { this.paintingColor = buf.readInt(); - scheduleChunkForRenderUpdate(); + scheduleRenderUpdate(); } else if (discriminator == UPDATE_CONNECTIONS) { - this.connections = buf.readVarInt(); - scheduleChunkForRenderUpdate(); + this.getNode().setActiveConnections(buf.readVarInt()); + scheduleRenderUpdate(); } else if (discriminator == SYNC_COVER_IMPLEMENTATION) { this.coverableImplementation.readCustomData(buf.readVarInt(), buf); } else if (discriminator == UPDATE_PIPE_TYPE) { readPipeProperties(buf); - scheduleChunkForRenderUpdate(); + scheduleRenderUpdate(); } else if (discriminator == UPDATE_BLOCKED_CONNECTIONS) { - this.blockedConnections = buf.readVarInt(); - scheduleChunkForRenderUpdate(); + this.getNode().setBlockedConnections(buf.readVarInt()); + scheduleRenderUpdate(); } else if (discriminator == UPDATE_FRAME_MATERIAL) { int registryId = buf.readVarInt(); int frameMaterialId = buf.readVarInt(); @@ -500,7 +514,7 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { } else { this.frameMaterial = null; } - scheduleChunkForRenderUpdate(); + scheduleRenderUpdate(); } } @@ -512,14 +526,6 @@ public void writeCoverCustomData(int id, Consumer writer) { }); } - @Override - public void scheduleChunkForRenderUpdate() { - BlockPos pos = getPos(); - getWorld().markBlockRangeForRenderUpdate( - pos.getX() - 1, pos.getY() - 1, pos.getZ() - 1, - pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1); - } - @Override public void notifyBlockUpdate() { getWorld().notifyNeighborsOfStateChange(getPos(), getBlockType(), true); @@ -539,7 +545,7 @@ public boolean isValidTile() { @Override public boolean shouldRefresh(@NotNull World world, @NotNull BlockPos pos, @NotNull IBlockState oldState, @NotNull IBlockState newSate) { - // always return true to ensure that the Chunk marks the old MTE as invalid + // always return true to ensure that the chunk marks the old MTE as invalid return true; } diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 3f68a1e3603..57e350c889d 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -12,6 +12,7 @@ import org.jetbrains.annotations.UnmodifiableView; import java.util.Collection; +import java.util.List; import java.util.Objects; import java.util.Set; @@ -162,7 +163,7 @@ public FluidPipeProperties getMinData(Set datas) { cryoProof &= data.isCryoProof(); plasmaProof &= data.isPlasmaProof(); } - return new FluidPipeProperties(); + return new FluidPipeProperties(maxFluidTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof); } @Override diff --git a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java index 35294ec56a6..c39fd4c2ff2 100644 --- a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java @@ -2,6 +2,7 @@ import gregtech.api.pipenet.INodeData; +import java.util.List; import java.util.Objects; import java.util.Set; @@ -85,12 +86,10 @@ public double getWeightFactor() { @Override public ItemPipeProperties getMinData(Set datas) { float transferRate = Integer.MAX_VALUE; - int priority = 0; for (ItemPipeProperties data : datas) { transferRate = Math.min(transferRate, data.getTransferRate()); - priority += data.getPriority(); } - return new ItemPipeProperties(priority, transferRate); + return new ItemPipeProperties(-1, transferRate); } @Override diff --git a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java index 2d9d236158a..318fc257a13 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java @@ -4,6 +4,7 @@ import gregtech.api.pipenet.INodeData; import gregtech.api.unification.material.Material; +import java.util.List; import java.util.Objects; import java.util.Set; @@ -147,18 +148,16 @@ public void verifyProperty(MaterialProperties properties) { @Override public double getWeightFactor() { // aren't weighted graphs great? - return 1d / this.getLossPerBlock(); + return this.getLossPerBlock(); } @Override public WireProperties getMinData(Set datas) { int amperage = Integer.MAX_VALUE; - int lossPerBlock = 0; for (WireProperties data : datas) { amperage = Math.min(amperage, data.getAmperage()); - lossPerBlock += data.getLossPerBlock(); } - return new WireProperties(-1, amperage, lossPerBlock); + return new WireProperties(-1, amperage, -1); } @Override diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java index d96185a5bda..c63ed013a9f 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -5,15 +5,12 @@ import gregtech.api.pipenet.AbstractGroupData; import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.NodeG; -import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; import gregtech.common.pipelike.cable.Insulation; import gregtech.common.pipelike.cable.tile.TileEntityCable; -import gregtech.common.pipelike.itempipe.ItemPipeType; - import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; @@ -21,8 +18,6 @@ import net.minecraft.world.World; import net.minecraft.world.WorldServer; -import java.util.Objects; - public class EnergyNetHandler implements IEnergyContainer { private final WorldEnergyNet net; @@ -71,20 +66,14 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage mainloop: for (NetPath routePath : net.getPaths(cable)) { routePath.resetFacingIterator(); - // Did you know, the path weight in this case is just the inverse of the loss. - long maxLoss = (long) Math.ceil(1f / routePath.getWeight()); - if (maxLoss >= voltage) { + // weight = loss + if (routePath.getWeight() >= voltage) { // Will lose all the energy with this path, so don't use it continue; } while (routePath.hasNextFacing()) { NetPath.FacedNetPath path = routePath.nextFacing(); - // if (GTUtility.arePosEqual(cable.getPos(), path.getTargetNode().getNodePos()) && side == path.getTargetFacing()) { - // // Do not insert into source handler - // continue; - // } - EnumFacing facing = path.facing.getOpposite(); IEnergyContainer dest = path.getTargetTE().getCapability( @@ -93,10 +82,10 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage if (!dest.inputsEnergy(facing) || dest.getEnergyCanBeInserted() <= 0) continue; - long pathVoltage = voltage - maxLoss; + long pathVoltage = voltage - (long) routePath.getWeight(); boolean cableBroken = false; for (NodeG node : path.getNodeList()) { - TileEntityCable cable = (TileEntityCable) node.heldMTE; + TileEntityCable cable = (TileEntityCable) node.getHeldMTE(); if (cable.getMaxVoltage() < voltage) { int heat = (int) (Math.log( GTUtility.getTierByVoltage(voltage) - @@ -124,8 +113,9 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage amperesUsed += amps; long voltageTraveled = voltage; + // TODO compress wire path operations into a single for loop for (NodeG node : path.getNodeList()) { - TileEntityCable cable = (TileEntityCable) node.heldMTE; + TileEntityCable cable = (TileEntityCable) node.getHeldMTE(); voltageTraveled -= cable.getNodeData().getLossPerBlock(); if (voltageTraveled <= 0) break; diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java index c6585e2ed49..f5a824e2191 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -1,5 +1,6 @@ package gregtech.common.pipelike.cable.net; +import gregtech.api.pipenet.AbstractGroupData; import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.WireProperties; @@ -35,6 +36,11 @@ protected Class> getBasePipeClas return TileEntityCable.class; } + @Override + protected AbstractGroupData getBlankGroupData() { + return new EnergyGroupData(); + } + @Override protected void writeNodeData(WireProperties nodeData, NBTTagCompound tagCompound) { tagCompound.setInteger("voltage", nodeData.getVoltage()); diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java index c8ee74ca3a2..05e7092e551 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java @@ -4,6 +4,7 @@ import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IEnergyContainer; import gregtech.api.metatileentity.IDataInfoProvider; +import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.unification.material.properties.WireProperties; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java index 21c2b0cdc6e..96db29650a4 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java @@ -1,10 +1,13 @@ package gregtech.common.pipelike.fluidpipe.tile; import gregtech.api.GTValues; +import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.pipelike.fluidpipe.FluidPipeType; +import gregtech.common.pipelike.fluidpipe.net.WorldFluidPipeNet; + import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index 680fa7f809e..60e66e921b5 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -312,7 +312,7 @@ public ItemStack insert(NetPath.FacedNetPath r if (allowed == 0 || !routePath.checkPredicate(stack)) { return stack; } - Cover pipeCover = routePath.getTargetNode().heldMTE.getCoverableImplementation() + Cover pipeCover = routePath.getTargetNode().getHeldMTE().getCoverableImplementation() .getCoverAtSide(routePath.facing); Cover tileCover = getCoverOnNeighbour(routePath.getTargetTE().getPos(), routePath.facing.getOpposite()); diff --git a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java b/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java index 8e4d2bec8b9..37135a7e190 100644 --- a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java +++ b/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java @@ -2,6 +2,7 @@ import gregtech.api.pipenet.INodeData; +import java.util.List; import java.util.Set; public class LaserPipeProperties implements INodeData { diff --git a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java index d5e5cd780dd..25c95eac02f 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java @@ -36,7 +36,7 @@ private void setPipesActive() { NetGroup group = getNet().getNode(this.pipe.getPipePos()).getGroup(); if (group != null) { for (NodeG node : group.getNodes()) { - if (node.heldMTE instanceof TileEntityLaserPipe laserPipe) { + if (node.getHeldMTE() instanceof TileEntityLaserPipe laserPipe) { laserPipe.setActive(true, 100); } } diff --git a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java b/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java index 5a4e2810a8e..2b9db7313fd 100644 --- a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java +++ b/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java @@ -153,7 +153,7 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { super.receiveCustomData(discriminator, buf); if (discriminator == GregtechDataCodes.PIPE_LASER_ACTIVE) { this.isActive = buf.readBoolean(); - scheduleChunkForRenderUpdate(); + scheduleRenderUpdate(); } } @@ -173,7 +173,7 @@ public void writeInitialSyncData(PacketBuffer buf) { public void receiveInitialSyncData(PacketBuffer buf) { super.receiveInitialSyncData(buf); this.isActive = buf.readBoolean(); - scheduleChunkForRenderUpdate(); + scheduleRenderUpdate(); } @NotNull diff --git a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java index b064f7eb83a..77a2b0de3f4 100644 --- a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java +++ b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java @@ -2,6 +2,7 @@ import gregtech.api.pipenet.INodeData; +import java.util.List; import java.util.Set; public class OpticalPipeProperties implements INodeData { diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java index a0abad5ae63..8b469771057 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java @@ -76,7 +76,7 @@ private void setPipesActive() { NetGroup group = getNet().getNode(this.pipe.getPipePos()).getGroup(); if (group != null) { for (NodeG node : group.getNodes()) { - if (node.heldMTE instanceof TileEntityOpticalPipe opticalPipe) { + if (node.getHeldMTE() instanceof TileEntityOpticalPipe opticalPipe) { opticalPipe.setActive(true, 100); } } diff --git a/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java b/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java index e9b310ae1b9..27de8ac31e8 100644 --- a/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java +++ b/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java @@ -155,7 +155,7 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { super.receiveCustomData(discriminator, buf); if (discriminator == GregtechDataCodes.PIPE_OPTICAL_ACTIVE) { this.isActive = buf.readBoolean(); - scheduleChunkForRenderUpdate(); + scheduleRenderUpdate(); } } diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java index 7edf69af532..609435d8168 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java @@ -2,8 +2,8 @@ import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.pipenet.Node; -import gregtech.api.pipenet.PipeNet; +import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -47,16 +47,17 @@ public void addProbeInfo(@NotNull ProbeMode mode, @NotNull IProbeInfo probeInfo, if (tileEntity instanceof TileEntityPipeBase) { IPipeTile pipeTile = (IPipeTile) tileEntity; BlockPipe blockPipe = pipeTile.getPipeBlock(); - PipeNet pipeNet = blockPipe.getWorldPipeNet(world).getNetFromPos(data.getPos()); + WorldPipeNetG pipeNet = blockPipe.getWorldPipeNet(world); if (pipeNet != null) { probeInfo.text("Net: " + pipeNet.hashCode()); probeInfo.text("Node Info: "); StringBuilder builder = new StringBuilder(); - Node node = pipeNet.getAllNodes().get(data.getPos()); + NodeG node = pipeNet.getNode(data.getPos()); builder.append("{") .append("active: ").append(node.isActive) .append(", mark: ").append(node.mark) - .append(", open: ").append(node.openConnections) + .append(", open: ").append(node.getActiveConnections()) + .append(", blocked: ").append(node.getBlockedConnections()) .append("}"); probeInfo.text(builder.toString()); } From f3bb29214b48ad978fd52df7072dcb7b10f05bdc Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 20 Dec 2023 18:39:41 -0700 Subject: [PATCH 021/157] Misc improvements so that the item net works properly. --- ...Predicate.java => BasicEdgePredicate.java} | 10 +- .../api/pipenet/IShutteredEdgePredicate.java | 9 ++ .../java/gregtech/api/pipenet/NetPath.java | 21 +--- src/main/java/gregtech/api/pipenet/NodeG.java | 10 +- .../gregtech/api/pipenet/WorldPipeNetG.java | 24 ++-- .../api/pipenet/tile/TileEntityPipeBase.java | 5 + .../pipelike/cable/net/EnergyNetHandler.java | 8 +- .../itempipe/net/ItemEdgePredicate.java | 109 ++++++++++++++++++ .../pipelike/itempipe/net/ItemNetHandler.java | 46 ++++---- .../pipelike/itempipe/net/ItemPredicate.java | 84 -------------- .../itempipe/net/WorldItemPipeNet.java | 24 +++- 11 files changed, 196 insertions(+), 154 deletions(-) rename src/main/java/gregtech/api/pipenet/{BasicPredicate.java => BasicEdgePredicate.java} (78%) create mode 100644 src/main/java/gregtech/api/pipenet/IShutteredEdgePredicate.java create mode 100644 src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java delete mode 100644 src/main/java/gregtech/common/pipelike/itempipe/net/ItemPredicate.java diff --git a/src/main/java/gregtech/api/pipenet/BasicPredicate.java b/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java similarity index 78% rename from src/main/java/gregtech/api/pipenet/BasicPredicate.java rename to src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java index 9d84f42f02c..c1e012b9efc 100644 --- a/src/main/java/gregtech/api/pipenet/BasicPredicate.java +++ b/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java @@ -4,19 +4,21 @@ import org.jetbrains.annotations.NotNull; -public class BasicPredicate extends AbstractEdgePredicate { +public class BasicEdgePredicate extends AbstractEdgePredicate implements IShutteredEdgePredicate { static { - PREDICATES.put("Basic", new BasicPredicate()); + PREDICATES.put("Basic", new BasicEdgePredicate()); } protected boolean shutteredSource; protected boolean shutteredTarget; + @Override public void setShutteredSource(boolean shutteredSource) { this.shutteredSource = shutteredSource; } + @Override public void setShutteredTarget(boolean shutteredTarget) { this.shutteredTarget = shutteredTarget; } @@ -41,8 +43,8 @@ public void deserializeNBT(NBTTagCompound nbt) { } @Override - public @NotNull BasicPredicate createPredicate() { - return new BasicPredicate(); + public @NotNull BasicEdgePredicate createPredicate() { + return new BasicEdgePredicate(); } @Override diff --git a/src/main/java/gregtech/api/pipenet/IShutteredEdgePredicate.java b/src/main/java/gregtech/api/pipenet/IShutteredEdgePredicate.java new file mode 100644 index 00000000000..c10c7690ee8 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/IShutteredEdgePredicate.java @@ -0,0 +1,9 @@ +package gregtech.api.pipenet; + +public interface IShutteredEdgePredicate { + + void setShutteredSource(boolean shutteredSource); + + void setShutteredTarget(boolean shutteredTarget); + +} diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index e801399ec9a..cd903b2ff78 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -29,8 +29,6 @@ public final class NetPath & IPipeType facingIterator; - /** * Generates a loop NetPath for a node * @param node the node to @@ -42,7 +40,6 @@ public NetPath(NodeG node) { this.nodeList.add(node); this.weight = node.getData().getWeightFactor(); this.edgeList = new ObjectArrayList<>(0); - resetFacingIterator(); } /** @@ -58,7 +55,6 @@ public NetPath(List> nodes, List edges, d this.nodeList = nodes; this.weight = weight; this.edgeList = edges; - resetFacingIterator(); } /** @@ -72,7 +68,6 @@ public NetPath(GraphPath, NetEdge> path) { // convert weight to the true value of the involved nodes this.weight = (path.getWeight() + sourceNode.getData().getWeightFactor() + targetNode.getData().getWeightFactor()) / 2; this.edgeList = path.getEdgeList(); - resetFacingIterator(); } public List> getNodeList() { @@ -87,20 +82,16 @@ public NodeG getTargetNode() { return targetNode; } - public FacedNetPath withFacing(EnumFacing facing) { - return new FacedNetPath<>(this, facing); + public Iterator getFacingIterator() { + return this.getTargetTEs().keySet().iterator(); } - public void resetFacingIterator() { - this.facingIterator = this.getTargetTEs().keySet().iterator(); + public FacedNetPath firstFacing() { + return this.withFacing(this.getFacingIterator().next()); } - public FacedNetPath nextFacing() { - return new FacedNetPath<>(this, this.facingIterator.next()); - } - - public boolean hasNextFacing() { - return this.facingIterator.hasNext(); + public FacedNetPath withFacing(EnumFacing facing) { + return new FacedNetPath<>(this, facing); } public Map getTargetTEs() { diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 898b5a268e3..44ec16a6b44 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -35,7 +35,7 @@ public class NodeG & IPipeType, No private int activeConnections; /** * Specifies bitmask of blocked connections. - * Blocked connections allow flow in, but not flow out. + * Blocked connections allow flow out, but not flow in. * Only allowed on directed graphs. */ private int blockedConnections; @@ -108,7 +108,7 @@ void clearGroup() { public boolean hasConnecteds() { for (EnumFacing facing : EnumFacing.VALUES) { - if (!isOutputAble(facing)) continue; + if (!isConnected(facing)) continue; if (getHeldMTE().getNonPipeNeighbour(facing) != null) return true; } return false; @@ -117,7 +117,7 @@ public boolean hasConnecteds() { public Map getConnecteds() { Map map = new Object2ObjectOpenHashMap<>(6); for (EnumFacing facing : EnumFacing.VALUES) { - if (!isOutputAble(facing)) continue; + if (!isConnected(facing)) continue; if (getHeldMTE().getNonPipeNeighbour(facing) != null) map.put(facing, getHeldMTE().getNonPipeNeighbour(facing)); } @@ -176,10 +176,6 @@ public int getBlockedConnections() { return blockedConnections; } - boolean isOutputAble(EnumFacing facing) { - return (activeConnections & ~(blockedConnections) & 1 << facing.getIndex()) != 0; - } - public BlockPos getNodePos() { return nodePos; } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index b22c5b66711..5552469657c 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -217,13 +217,13 @@ public void updateActiveConnections(BlockPos nodePos, EnumFacing side, boolean c if (connect) { if (!node.isBlocked(side)) { - addEdge(node, nodeOffset, null); - this.predicateEdge(node, nodeOffset, side); + addEdge(nodeOffset, node, null); + this.predicateEdge(nodeOffset, node, side.getOpposite()); if (!this.isDirected()) return; } if (!nodeOffset.isBlocked(side.getOpposite())) { - addEdge(nodeOffset, node, null); - this.predicateEdge(nodeOffset, node, side.getOpposite()); + addEdge(node, nodeOffset, null); + this.predicateEdge(node, nodeOffset, side); } } else { removeUndirectedEdge(node, nodeOffset); @@ -241,10 +241,10 @@ public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean if (nodeOffset == null) return; if (!blocked) { - addEdge(node, nodeOffset, null); - this.predicateEdge(node, nodeOffset, side); + addEdge(nodeOffset, node, null); + this.predicateEdge(nodeOffset, node, side); } else { - removeEdge(node, nodeOffset); + removeEdge(nodeOffset, node); } } @@ -350,16 +350,16 @@ public void predicateEdge(NodeG source, NodeG getPredicate(Cover thisCover, Cover neighbourCover) { - return shutterify(new BasicPredicate(), thisCover, neighbourCover); + return shutterify(new BasicEdgePredicate(), thisCover, neighbourCover); } protected final AbstractEdgePredicate shutterify(AbstractEdgePredicate predicate, @Nullable Cover thisCover, @Nullable Cover neighbourCover) { - if (predicate instanceof BasicPredicate basicPredicate) { + if (predicate instanceof IShutteredEdgePredicate shutteredEdgePredicate) { if (thisCover instanceof CoverShutter shutter) { - basicPredicate.setShutteredSource(shutter.isWorkingEnabled()); + shutteredEdgePredicate.setShutteredSource(shutter.isWorkingEnabled()); } if (neighbourCover instanceof CoverShutter shutter) { - basicPredicate.setShutteredTarget(shutter.isWorkingEnabled()); + shutteredEdgePredicate.setShutteredTarget(shutter.isWorkingEnabled()); } } return predicate; @@ -443,7 +443,7 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { NBTTagList allPipeNodes = new NBTTagList(); Set> groups = new ObjectOpenHashSet<>(); for (NodeG node : pipeGraph.vertexSet()) { - groups.add(node.getGroup()); + if (node.getGroup() != null) groups.add(node.getGroup()); NBTTagCompound nodeTag = node.serializeNBT(); NBTTagCompound dataTag = new NBTTagCompound(); writeNodeData(node.getData(), dataTag); diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 0a0706ff059..82f532ae9d1 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -535,6 +535,11 @@ public void notifyBlockUpdate() { @Override public void markAsDirty() { markDirty(); + // this most notably gets called when the covers of a pipe get updated, aka the edge predicates need syncing. + for (EnumFacing facing : EnumFacing.VALUES) { + if (!isConnected(facing)) continue; + this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()).predicateEdge(this.getPipePos(), facing); + } } @Override diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java index c63ed013a9f..3982a768bad 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -18,6 +18,8 @@ import net.minecraft.world.World; import net.minecraft.world.WorldServer; +import java.util.Iterator; + public class EnergyNetHandler implements IEnergyContainer { private final WorldEnergyNet net; @@ -65,14 +67,14 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage long amperesUsed = 0L; mainloop: for (NetPath routePath : net.getPaths(cable)) { - routePath.resetFacingIterator(); + Iterator iterator = routePath.getFacingIterator(); // weight = loss if (routePath.getWeight() >= voltage) { // Will lose all the energy with this path, so don't use it continue; } - while (routePath.hasNextFacing()) { - NetPath.FacedNetPath path = routePath.nextFacing(); + while (iterator.hasNext()) { + NetPath.FacedNetPath path = routePath.withFacing(iterator.next()); EnumFacing facing = path.facing.getOpposite(); diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java new file mode 100644 index 00000000000..dd336630bc5 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java @@ -0,0 +1,109 @@ +package gregtech.common.pipelike.itempipe.net; + +import gregtech.api.pipenet.AbstractEdgePredicate; + +import gregtech.api.pipenet.IShutteredEdgePredicate; +import gregtech.api.util.IDirtyNotifiable; +import gregtech.common.covers.filter.FilterTypeRegistry; +import gregtech.common.covers.filter.ItemFilterWrapper; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import org.jetbrains.annotations.NotNull; + +public class ItemEdgePredicate extends AbstractEdgePredicate implements IShutteredEdgePredicate { + + private final static Decoy DECOY = new Decoy(); + + static { + PREDICATES.put("Item", new ItemEdgePredicate()); + } + + protected boolean shutteredSource; + protected boolean shutteredTarget; + + ItemFilterWrapper sourceFilter = new ItemFilterWrapper(DECOY); + ItemFilterWrapper targetFilter = new ItemFilterWrapper(DECOY); + + @Override + public void setShutteredSource(boolean shutteredSource) { + this.shutteredSource = shutteredSource; + } + + @Override + public void setShutteredTarget(boolean shutteredTarget) { + this.shutteredTarget = shutteredTarget; + } + + public void setSourceFilter(ItemFilterWrapper sourceFilter) { + this.sourceFilter = sourceFilter; + } + + public void setTargetFilter(ItemFilterWrapper targetFilter) { + this.targetFilter = targetFilter; + } + + @Override + public boolean test(Object o) { + if (shutteredSource || shutteredTarget) return false; + if (!(o instanceof ItemStack stack)) return false; + return sourceFilter.testItemStack(stack) && targetFilter.testItemStack(stack); + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + if (shutteredSource) tag.setBoolean("ShutteredSource", true); + if (shutteredTarget) tag.setBoolean("ShutteredTarget", true); + NBTTagCompound filterComponent; + tag.setBoolean("SourceBlacklist", this.sourceFilter.isBlacklistFilter()); + if (this.sourceFilter.getItemFilter() != null) { + filterComponent = new NBTTagCompound(); + tag.setInteger("SourceFilterType", FilterTypeRegistry.getIdForItemFilter(this.sourceFilter.getItemFilter())); + this.sourceFilter.getItemFilter().writeToNBT(filterComponent); + tag.setTag("SourceFilter", filterComponent); + } + tag.setBoolean("TargetBlacklist", this.targetFilter.isBlacklistFilter()); + if (this.targetFilter.getItemFilter() != null) { + filterComponent = new NBTTagCompound(); + tag.setInteger("TargetFilterType", FilterTypeRegistry.getIdForItemFilter(this.targetFilter.getItemFilter())); + this.targetFilter.getItemFilter().writeToNBT(filterComponent); + tag.setTag("TargetFilter", filterComponent); + } + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + shutteredSource = nbt.getBoolean("ShutteredSource"); + shutteredTarget = nbt.getBoolean("ShutteredTarget"); + if (nbt.hasKey("SourceFilter")) { + this.sourceFilter.setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("SourceFilterType"))); + this.sourceFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("SourceFilter")); + this.sourceFilter.setBlacklistFilter(nbt.getBoolean("SourceBlacklist")); + } + if (nbt.hasKey("TargetFilter")) { + this.targetFilter.setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("TargetFilterType"))); + this.targetFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("TargetFilter")); + this.targetFilter.setBlacklistFilter(nbt.getBoolean("TargetBlacklist")); + } + + } + + @Override + public @NotNull ItemEdgePredicate createPredicate() { + return new ItemEdgePredicate(); + } + + @Override + protected String predicateType() { + return "Item"; + } + + private static class Decoy implements IDirtyNotifiable { + + @Override + public void markAsDirty() {} + } +} diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index 60e66e921b5..bdce46cc583 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -110,7 +110,7 @@ public static boolean checkImportCover(Cover cover, boolean onPipe, ItemStack st public ItemStack insertFirst(ItemStack stack, boolean simulate) { for (NetPath inv : net.getPaths(pipe)) { - stack = insert(inv.nextFacing(), stack, simulate); + stack = insert(inv.firstFacing(), stack, simulate); if (stack.isEmpty()) return ItemStack.EMPTY; } @@ -122,7 +122,7 @@ public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean glo if (routePaths.isEmpty()) return stack; if (routePaths.size() == 1 && routePaths.get(0).getTargetTEs().size() == 1) { - return insert(routePaths.get(0).nextFacing(), stack, simulate); + return insert(routePaths.get(0).firstFacing(), stack, simulate); } List> routePathsCopy = new ArrayList<>(routePaths); @@ -155,9 +155,10 @@ private ItemStack insertToHandlers(List routePath = routePathIterator.next(); - routePath.resetFacingIterator(); - while (routePath.hasNextFacing()) { - NetPath.FacedNetPath facedNetPath = routePath.nextFacing(); + Iterator iterator = routePath.getFacingIterator(); + while (iterator.hasNext()) { + NetPath.FacedNetPath facedNetPath = + routePath.withFacing(iterator.next()); int amount = c; if (m > 0) { amount++; @@ -193,9 +194,9 @@ private ItemStack insertToHandlersEnhanced(List inv : copy) { - inv.resetFacingIterator(); - while (inv.hasNextFacing()) { - NetPath.FacedNetPath faceInv = inv.nextFacing(); + Iterator iterator = inv.getFacingIterator(); + while (iterator.hasNext()) { + NetPath.FacedNetPath faceInv = inv.withFacing(iterator.next()); simStack = stack.copy(); int ins = stack.getCount() - insert(faceInv, simStack, true, true).getCount(); if (ins <= 0) @@ -314,7 +315,7 @@ public ItemStack insert(NetPath.FacedNetPath r } Cover pipeCover = routePath.getTargetNode().getHeldMTE().getCoverableImplementation() .getCoverAtSide(routePath.facing); - Cover tileCover = getCoverOnNeighbour(routePath.getTargetTE().getPos(), routePath.facing.getOpposite()); + Cover tileCover = getCoverOnNeighbour(routePath.getTargetNode().getNodePos(), routePath.facing.getOpposite()); if (pipeCover != null) { testHandler.setStackInSlot(0, stack.copy()); @@ -327,21 +328,20 @@ public ItemStack insert(NetPath.FacedNetPath r } testHandler.setStackInSlot(0, ItemStack.EMPTY); } - if (routePath.getTargetTE() instanceof IItemHandler neighbourHandler) { - if (pipeCover instanceof CoverRoboticArm && - ((CoverRoboticArm) pipeCover).getConveyorMode() == CoverConveyor.ConveyorMode.EXPORT) { - return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) pipeCover, stack, simulate, allowed, - ignoreLimit); - } - if (tileCover instanceof CoverRoboticArm && - ((CoverRoboticArm) tileCover).getConveyorMode() == CoverConveyor.ConveyorMode.IMPORT) { - return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) tileCover, stack, simulate, allowed, - ignoreLimit); - } - - return insert(neighbourHandler, stack, simulate, allowed, ignoreLimit); + IItemHandler neighbourHandler = + routePath.getTargetTE().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, routePath.facing); + if (pipeCover instanceof CoverRoboticArm && + ((CoverRoboticArm) pipeCover).getConveyorMode() == CoverConveyor.ConveyorMode.EXPORT) { + return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) pipeCover, stack, simulate, allowed, + ignoreLimit); } - return stack; + if (tileCover instanceof CoverRoboticArm && + ((CoverRoboticArm) tileCover).getConveyorMode() == CoverConveyor.ConveyorMode.IMPORT) { + return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) tileCover, stack, simulate, allowed, + ignoreLimit); + } + + return insert(neighbourHandler, stack, simulate, allowed, ignoreLimit); } private ItemStack insert(IItemHandler handler, ItemStack stack, boolean simulate, int allowed, diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemPredicate.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemPredicate.java deleted file mode 100644 index f8e3d4d74f6..00000000000 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemPredicate.java +++ /dev/null @@ -1,84 +0,0 @@ -package gregtech.common.pipelike.itempipe.net; - -import gregtech.api.pipenet.AbstractEdgePredicate; - -import gregtech.api.util.IDirtyNotifiable; -import gregtech.common.covers.filter.ItemFilterWrapper; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; - -import org.jetbrains.annotations.NotNull; - -public class ItemPredicate extends AbstractEdgePredicate { - - private final static Decoy DECOY = new Decoy(); - - static { - PREDICATES.put("Item", new ItemPredicate()); - } - - protected boolean shutteredSource; - protected boolean shutteredTarget; - - ItemFilterWrapper sourceFilter = new ItemFilterWrapper(DECOY); - ItemFilterWrapper targetFilter; - - public void setSourceFilter(ItemFilterWrapper sourceFilter) { - this.sourceFilter = sourceFilter; - } - - public void setTargetFilter(ItemFilterWrapper targetFilter) { - this.targetFilter = targetFilter; - } - - @Override - public boolean test(Object o) { - if (shutteredSource || shutteredTarget) return false; - if (!(o instanceof ItemStack stack)) return false; - return sourceFilter.testItemStack(stack) && targetFilter.testItemStack(stack); - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tag = new NBTTagCompound(); - if (shutteredSource) tag.setBoolean("ShutteredSource", true); - if (shutteredTarget) tag.setBoolean("ShutteredTarget", true); - tag.setBoolean("SourceBlacklist", this.sourceFilter.isBlacklistFilter()); - NBTTagCompound filterComponent = new NBTTagCompound(); - this.sourceFilter.getItemFilter().writeToNBT(filterComponent); - tag.setTag("SourceFilter", filterComponent); - tag.setBoolean("TargetBlacklist", this.targetFilter.isBlacklistFilter()); - filterComponent = new NBTTagCompound(); - this.targetFilter.getItemFilter().writeToNBT(filterComponent); - tag.setTag("TargetFilter", filterComponent); - return tag; - } - - @Override - public void deserializeNBT(NBTTagCompound nbt) { - shutteredSource = nbt.getBoolean("ShutteredSource"); - shutteredTarget = nbt.getBoolean("ShutteredTarget"); - this.sourceFilter.setBlacklistFilter(nbt.getBoolean("SourceBlacklist")); - this.sourceFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("SourceFilter")); - this.targetFilter.setBlacklistFilter(nbt.getBoolean("TargetBlacklist")); - this.targetFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("TargetFilter")); - - } - - @Override - public @NotNull ItemPredicate createPredicate() { - return new ItemPredicate(); - } - - @Override - protected String predicateType() { - return "Item"; - } - - private static class Decoy implements IDirtyNotifiable { - - @Override - public void markAsDirty() {} - } -} diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index e3257a9c861..4eda0642f17 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -2,24 +2,21 @@ import gregtech.api.cover.Cover; import gregtech.api.pipenet.AbstractEdgePredicate; -import gregtech.api.pipenet.WorldPipeNet; import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.ItemPipeProperties; +import gregtech.common.covers.CoverConveyor; import gregtech.common.covers.CoverItemFilter; -import gregtech.common.covers.CoverShutter; import gregtech.common.covers.ItemFilterMode; +import gregtech.common.covers.ManualImportExportMode; import gregtech.common.pipelike.itempipe.ItemPipeType; import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; -import java.util.function.Predicate; - public class WorldItemPipeNet extends WorldPipeNetG { private static final String DATA_ID = "gregtech.item_pipe_net"; @@ -50,7 +47,7 @@ protected Class> getBasePi @Override protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbourCover) { - ItemPredicate predicate = new ItemPredicate(); + ItemEdgePredicate predicate = new ItemEdgePredicate(); if (thisCover instanceof CoverItemFilter filter && filter.getFilterMode() != ItemFilterMode.FILTER_INSERT) { predicate.setSourceFilter(filter.getItemFilter()); @@ -59,6 +56,21 @@ protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbour filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT) { predicate.setTargetFilter(filter.getItemFilter()); } + if (thisCover instanceof CoverConveyor conveyor) { + if (conveyor.getManualImportExportMode() == ManualImportExportMode.DISABLED) { + predicate.setShutteredSource(true); + } else if (conveyor.getManualImportExportMode() == ManualImportExportMode.FILTERED) { + predicate.setSourceFilter(conveyor.getItemFilterContainer().getFilterWrapper()); + } + } + if (neighbourCover instanceof CoverConveyor conveyor) { + if (conveyor.getManualImportExportMode() == ManualImportExportMode.DISABLED) { + predicate.setShutteredTarget(true); + } else if (conveyor.getManualImportExportMode() == ManualImportExportMode.FILTERED) { + predicate.setTargetFilter(conveyor.getItemFilterContainer().getFilterWrapper()); + } + } + // TODO should robot arms apply rate limits to edge predicates? return shutterify(predicate, thisCover, neighbourCover); } From 42ed1469c5c3d89164b16cd7aa5858e05bc1ff20 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 20 Dec 2023 19:18:35 -0700 Subject: [PATCH 022/157] Stack overflow moment --- .../gregtech/api/pipenet/tile/TileEntityPipeBase.java | 9 +++------ .../java/gregtech/common/covers/CoverFluidFilter.java | 2 +- .../java/gregtech/common/covers/CoverItemFilter.java | 2 +- .../common/covers/filter/FluidFilterContainer.java | 2 +- .../common/covers/filter/FluidFilterWrapper.java | 5 +++-- .../common/covers/filter/ItemFilterContainer.java | 4 ++-- .../gregtech/common/covers/filter/ItemFilterWrapper.java | 5 +++-- .../common/pipelike/itempipe/net/ItemEdgePredicate.java | 4 ++-- 8 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 82f532ae9d1..629786552db 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -494,18 +494,14 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { } if (discriminator == UPDATE_INSULATION_COLOR) { this.paintingColor = buf.readInt(); - scheduleRenderUpdate(); } else if (discriminator == UPDATE_CONNECTIONS) { this.getNode().setActiveConnections(buf.readVarInt()); - scheduleRenderUpdate(); } else if (discriminator == SYNC_COVER_IMPLEMENTATION) { this.coverableImplementation.readCustomData(buf.readVarInt(), buf); } else if (discriminator == UPDATE_PIPE_TYPE) { readPipeProperties(buf); - scheduleRenderUpdate(); } else if (discriminator == UPDATE_BLOCKED_CONNECTIONS) { this.getNode().setBlockedConnections(buf.readVarInt()); - scheduleRenderUpdate(); } else if (discriminator == UPDATE_FRAME_MATERIAL) { int registryId = buf.readVarInt(); int frameMaterialId = buf.readVarInt(); @@ -514,8 +510,8 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { } else { this.frameMaterial = null; } - scheduleRenderUpdate(); - } + } else return; + scheduleRenderUpdate(); } @Override @@ -536,6 +532,7 @@ public void notifyBlockUpdate() { public void markAsDirty() { markDirty(); // this most notably gets called when the covers of a pipe get updated, aka the edge predicates need syncing. + if (getWorld().isRemote) return; for (EnumFacing facing : EnumFacing.VALUES) { if (!isConnected(facing)) continue; this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()).predicateEdge(this.getPipePos(), facing); diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index cd5d06ee5a4..0307d993b23 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -137,7 +137,7 @@ public void writeToNBT(@NotNull NBTTagCompound tagCompound) { public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.filterMode = FluidFilterMode.values()[tagCompound.getInteger("FilterMode")]; - this.fluidFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); + this.fluidFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist"), true); this.fluidFilter.getFluidFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); } diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 656fe17f5d8..e447b6f7bd2 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -124,7 +124,7 @@ public void writeToNBT(@NotNull NBTTagCompound tagCompound) { public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.filterMode = ItemFilterMode.values()[tagCompound.getInteger("FilterMode")]; - this.itemFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); + this.itemFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist"), true); this.itemFilter.getItemFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); } diff --git a/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java b/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java index 41beb67b6d6..4ecbb429a22 100644 --- a/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java +++ b/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java @@ -120,7 +120,7 @@ public NBTTagCompound serializeNBT() { @Override public void deserializeNBT(NBTTagCompound tagCompound) { this.filterInventory.deserializeNBT(tagCompound.getCompoundTag("FilterInventory")); - this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); + this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist"), true); if (filterWrapper.getFluidFilter() != null) { this.filterWrapper.getFluidFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); } diff --git a/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java b/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java index 2ef1f76a32e..a4b99e89e3a 100644 --- a/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java +++ b/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java @@ -36,7 +36,7 @@ public void initUI(int y, Consumer widgetGroup) { public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { ServerWidgetGroup blacklistButton = new ServerWidgetGroup(() -> getFluidFilter() != null); blacklistButton.addWidget(new ToggleButtonWidget(144, y, 18, 18, GuiTextures.BUTTON_BLACKLIST, - this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) + this::isBlacklistFilter, a -> this.setBlacklistFilter(a, false)).setPredicate(showBlacklistButton) .setTooltipText("cover.filter.blacklist")); widgetGroup.accept(blacklistButton); } @@ -65,8 +65,9 @@ public void onFilterInstanceChange() { dirtyNotifiable.markAsDirty(); } - public void setBlacklistFilter(boolean blacklistFilter) { + public void setBlacklistFilter(boolean blacklistFilter, boolean nbtLoad) { isBlacklistFilter = blacklistFilter; + if (nbtLoad) return; dirtyNotifiable.markAsDirty(); } diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java b/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java index 71be9ff14d3..8f74c642dad 100644 --- a/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java +++ b/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java @@ -98,7 +98,7 @@ protected void onFilterSlotChange(boolean notify) { if (newItemFilter == null) { if (currentItemFilter != null) { filterWrapper.setItemFilter(null); - filterWrapper.setBlacklistFilter(false); + filterWrapper.setBlacklistFilter(false, false); if (notify) filterWrapper.onFilterInstanceChange(); } } else if (currentItemFilter == null || @@ -155,7 +155,7 @@ public NBTTagCompound serializeNBT() { @Override public void deserializeNBT(NBTTagCompound tagCompound) { this.filterInventory.deserializeNBT(tagCompound.getCompoundTag("FilterInventory")); - this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); + this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist"), true); setMaxStackSize(tagCompound.getInteger("MaxStackSize")); setTransferStackSize(tagCompound.getInteger("TransferStackSize")); if (filterWrapper.getItemFilter() != null) { diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java b/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java index d11905e00b5..28417a96f9a 100644 --- a/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java +++ b/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java @@ -31,7 +31,7 @@ public void initUI(int y, Consumer widgetGroup) { public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { ServerWidgetGroup blacklistButton = new ServerWidgetGroup(() -> getItemFilter() != null); blacklistButton.addWidget(new ToggleButtonWidget(144, y, 20, 20, GuiTextures.BUTTON_BLACKLIST, - this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) + this::isBlacklistFilter, a -> this.setBlacklistFilter(a, false)).setPredicate(showBlacklistButton) .setTooltipText("cover.filter.blacklist")); widgetGroup.accept(blacklistButton); } @@ -67,8 +67,9 @@ public void setMaxStackSize(int maxStackSize) { dirtyNotifiable.markAsDirty(); } - public void setBlacklistFilter(boolean blacklistFilter) { + public void setBlacklistFilter(boolean blacklistFilter, boolean nbtLoad) { isBlacklistFilter = blacklistFilter; + if (nbtLoad) return; onFilterInstanceChange(); dirtyNotifiable.markAsDirty(); } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java index dd336630bc5..7974336aa11 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java @@ -81,12 +81,12 @@ public void deserializeNBT(NBTTagCompound nbt) { if (nbt.hasKey("SourceFilter")) { this.sourceFilter.setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("SourceFilterType"))); this.sourceFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("SourceFilter")); - this.sourceFilter.setBlacklistFilter(nbt.getBoolean("SourceBlacklist")); + this.sourceFilter.setBlacklistFilter(nbt.getBoolean("SourceBlacklist"), true); } if (nbt.hasKey("TargetFilter")) { this.targetFilter.setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("TargetFilterType"))); this.targetFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("TargetFilter")); - this.targetFilter.setBlacklistFilter(nbt.getBoolean("TargetBlacklist")); + this.targetFilter.setBlacklistFilter(nbt.getBoolean("TargetBlacklist"), true); } } From f7955c9832e3bf0500e4afb898c564f0fab609d5 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 20 Dec 2023 19:36:43 -0700 Subject: [PATCH 023/157] Oops. --- src/main/java/gregtech/api/pipenet/WorldPipeNetG.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 5552469657c..5226d101363 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -547,8 +547,7 @@ private List> singlePathList(NodeG(source)); - else paths.add(new NetPath<>(nodes, edges, sumWeight)); + paths.add(new NetPath<>(nodes, edges, sumWeight)); return paths; } } From 9d4e2a297535dab563982d6260dc35954b125c0e Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 20 Dec 2023 19:50:43 -0700 Subject: [PATCH 024/157] More stack overflow, yay! --- .../java/gregtech/common/covers/CoverItemFilter.java | 2 +- .../common/covers/CoverItemVoidingAdvanced.java | 4 ++-- .../java/gregtech/common/covers/CoverRoboticArm.java | 4 ++-- .../common/covers/filter/ItemFilterContainer.java | 12 ++++++------ .../common/covers/filter/ItemFilterWrapper.java | 3 ++- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index e447b6f7bd2..8589e863fc1 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -50,7 +50,7 @@ public CoverItemFilter(@NotNull CoverDefinition definition, @NotNull CoverableVi this.texture = texture; this.itemFilter = new ItemFilterWrapper(this); this.itemFilter.setItemFilter(itemFilter); - this.itemFilter.setMaxStackSize(1); + this.itemFilter.setMaxStackSize(1, false); } public void setFilterMode(ItemFilterMode filterMode) { diff --git a/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java b/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java index 62d2844aaa3..9bdb1d60ab6 100644 --- a/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java +++ b/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java @@ -141,8 +141,8 @@ public void initFilterUI(int y, Consumer widgetGroup) { stackSizeGroup.addWidget(new TextFieldWidget2(113, 41, 31, 20, () -> String.valueOf(itemFilterContainer.getTransferStackSize()), val -> { if (val != null && !val.isEmpty()) - itemFilterContainer.setTransferStackSize( - MathHelper.clamp(Integer.parseInt(val), 1, voidingMode.maxStackSize)); + itemFilterContainer.setTransferStackSize(MathHelper.clamp(Integer.parseInt(val), + 1, voidingMode.maxStackSize), false); }) .setCentered(true) .setNumbersOnly(1, Integer.MAX_VALUE) diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 902ffcd62f4..3fe05856b9c 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -208,8 +208,8 @@ protected ModularUI buildUI(Builder builder, EntityPlayer player) { stackSizeGroup.addWidget(new TextFieldWidget2(113, 77, 31, 20, () -> String.valueOf(itemFilterContainer.getTransferStackSize()), val -> { if (val != null && !val.isEmpty()) - itemFilterContainer.setTransferStackSize( - MathHelper.clamp(Integer.parseInt(val), 1, transferMode.maxStackSize)); + itemFilterContainer.setTransferStackSize(MathHelper.clamp(Integer.parseInt(val), + 1, transferMode.maxStackSize), false); }) .setNumbersOnly(1, transferMode.maxStackSize) .setMaxLength(4) diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java b/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java index 8f74c642dad..55957d4332a 100644 --- a/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java +++ b/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java @@ -59,7 +59,7 @@ public ItemFilterWrapper getFilterWrapper() { } private void onFilterInstanceChange() { - this.filterWrapper.setMaxStackSize(getTransferStackSize()); + this.filterWrapper.setMaxStackSize(getTransferStackSize(), false); } public int getMaxStackSize() { @@ -73,13 +73,13 @@ public int getTransferStackSize() { return transferStackSize; } - public void setTransferStackSize(int transferStackSize) { + public void setTransferStackSize(int transferStackSize, boolean nbtLoad) { this.transferStackSize = MathHelper.clamp(transferStackSize, 1, getMaxStackSize()); - this.filterWrapper.setMaxStackSize(getTransferStackSize()); + this.filterWrapper.setMaxStackSize(getTransferStackSize(), nbtLoad); } public void adjustTransferStackSize(int amount) { - setTransferStackSize(transferStackSize + amount); + setTransferStackSize(transferStackSize + amount, false); } public void initUI(int y, Consumer widgetGroup) { @@ -110,7 +110,7 @@ protected void onFilterSlotChange(boolean notify) { public void setMaxStackSize(int maxStackSizeLimit) { this.maxStackSizeLimit = maxStackSizeLimit; - setTransferStackSize(transferStackSize); + setTransferStackSize(transferStackSize, false); } public boolean showGlobalTransferLimitSlider() { @@ -157,7 +157,7 @@ public void deserializeNBT(NBTTagCompound tagCompound) { this.filterInventory.deserializeNBT(tagCompound.getCompoundTag("FilterInventory")); this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist"), true); setMaxStackSize(tagCompound.getInteger("MaxStackSize")); - setTransferStackSize(tagCompound.getInteger("TransferStackSize")); + setTransferStackSize(tagCompound.getInteger("TransferStackSize"), true); if (filterWrapper.getItemFilter() != null) { this.filterWrapper.getItemFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); } diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java b/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java index 28417a96f9a..d59ab8283d0 100644 --- a/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java +++ b/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java @@ -61,8 +61,9 @@ public void onFilterInstanceChange() { dirtyNotifiable.markAsDirty(); } - public void setMaxStackSize(int maxStackSize) { + public void setMaxStackSize(int maxStackSize, boolean nbtLoad) { this.maxStackSize = maxStackSize; + if (nbtLoad) return; onFilterInstanceChange(); dirtyNotifiable.markAsDirty(); } From 3dc22d73d0fd8c47cd3582ccb2ec7d944c871db2 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 20 Dec 2023 20:02:21 -0700 Subject: [PATCH 025/157] Deprecation of now obsolete API --- src/main/java/gregtech/api/pipenet/IRoutePath.java | 3 +++ src/main/java/gregtech/api/pipenet/Node.java | 4 ++++ src/main/java/gregtech/api/pipenet/NodeG.java | 2 ++ src/main/java/gregtech/api/pipenet/PipeNet.java | 3 +++ src/main/java/gregtech/api/pipenet/PipeNetWalker.java | 3 +++ src/main/java/gregtech/api/pipenet/WorldPipeNet.java | 3 +++ src/main/java/gregtech/api/pipenet/WorldPipeNetG.java | 2 +- .../gregtech/api/pipenet/block/simple/BlockSimplePipe.java | 2 ++ .../gregtech/api/pipenet/block/simple/EmptyNodeData.java | 4 ++++ .../gregtech/api/pipenet/longdist/LongDistanceNetwork.java | 4 +++- .../gregtech/api/pipenet/tickable/TickableWorldPipeNet.java | 3 +++ .../pipenet/tickable/TickableWorldPipeNetEventHandler.java | 5 +++++ 12 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/IRoutePath.java b/src/main/java/gregtech/api/pipenet/IRoutePath.java index 31b5ac9f15e..166e5b8f39a 100644 --- a/src/main/java/gregtech/api/pipenet/IRoutePath.java +++ b/src/main/java/gregtech/api/pipenet/IRoutePath.java @@ -7,9 +7,12 @@ import net.minecraft.util.math.BlockPos; import net.minecraftforge.common.capabilities.Capability; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.9") public interface IRoutePath> { @NotNull diff --git a/src/main/java/gregtech/api/pipenet/Node.java b/src/main/java/gregtech/api/pipenet/Node.java index 6e3e07c5a74..2fb139d779e 100644 --- a/src/main/java/gregtech/api/pipenet/Node.java +++ b/src/main/java/gregtech/api/pipenet/Node.java @@ -2,10 +2,14 @@ import net.minecraft.util.EnumFacing; +import org.jetbrains.annotations.ApiStatus; + /** * Represents a single node in network of pipes * It can have blocked connections and be active or not */ +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.9") public final class Node { public static final int DEFAULT_MARK = 0; diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 44ec16a6b44..6f53ef2d471 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -24,6 +24,8 @@ public class NodeG & IPipeType, NodeDataType extends INodeData> implements INBTSerializable { + public static final int DEFAULT_MARK = 0; + private final WorldPipeNetG net; private NodeDataType data; diff --git a/src/main/java/gregtech/api/pipenet/PipeNet.java b/src/main/java/gregtech/api/pipenet/PipeNet.java index 536b2a23b81..8beea2d4193 100644 --- a/src/main/java/gregtech/api/pipenet/PipeNet.java +++ b/src/main/java/gregtech/api/pipenet/PipeNet.java @@ -14,6 +14,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import org.jetbrains.annotations.ApiStatus; import java.util.ArrayDeque; import java.util.Collections; @@ -23,6 +24,8 @@ import java.util.Map.Entry; import java.util.Set; +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.9") public abstract class PipeNet implements INBTSerializable { protected final WorldPipeNet> worldData; diff --git a/src/main/java/gregtech/api/pipenet/PipeNetWalker.java b/src/main/java/gregtech/api/pipenet/PipeNetWalker.java index 03dd561cc40..56a76e1ee7d 100644 --- a/src/main/java/gregtech/api/pipenet/PipeNetWalker.java +++ b/src/main/java/gregtech/api/pipenet/PipeNetWalker.java @@ -9,6 +9,7 @@ import net.minecraft.world.World; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -25,6 +26,8 @@ * Do not walk a walker more than once *

*/ +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.9") public abstract class PipeNetWalker> { protected PipeNetWalker root; diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/pipenet/WorldPipeNet.java index 03211cc377c..fc9f8467a63 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNet.java @@ -11,6 +11,7 @@ import net.minecraft.world.storage.WorldSavedData; import net.minecraftforge.common.util.Constants.NBT; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import java.lang.ref.WeakReference; @@ -20,6 +21,8 @@ import java.util.List; import java.util.Map; +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.9") public abstract class WorldPipeNet> extends WorldSavedData { private WeakReference worldRef = new WeakReference<>(null); diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 5226d101363..5a44179cd9b 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -188,7 +188,7 @@ protected final boolean canNodesConnect(NodeG source, En } private static boolean areMarksCompatible(int mark1, int mark2) { - return mark1 == mark2 || mark1 == Node.DEFAULT_MARK || mark2 == Node.DEFAULT_MARK; + return mark1 == mark2 || mark1 == NodeG.DEFAULT_MARK || mark2 == NodeG.DEFAULT_MARK; } private boolean areNodeBlockedConnectionsCompatible(NodeG source, EnumFacing nodeFacing, diff --git a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java index 7f921023050..a3466cf9fdb 100644 --- a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java +++ b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java @@ -9,6 +9,8 @@ import net.minecraft.item.ItemStack; +import org.jetbrains.annotations.ApiStatus; + public abstract class BlockSimplePipe & IPipeType, NodeDataType extends INodeData, WorldPipeNetType extends WorldPipeNetG> diff --git a/src/main/java/gregtech/api/pipenet/block/simple/EmptyNodeData.java b/src/main/java/gregtech/api/pipenet/block/simple/EmptyNodeData.java index af6b6a9e076..7be0f955629 100644 --- a/src/main/java/gregtech/api/pipenet/block/simple/EmptyNodeData.java +++ b/src/main/java/gregtech/api/pipenet/block/simple/EmptyNodeData.java @@ -1,5 +1,9 @@ package gregtech.api.pipenet.block.simple; +import org.jetbrains.annotations.ApiStatus; + +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.9") @SuppressWarnings("ALL") public class EmptyNodeData { diff --git a/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java b/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java index 486d6b9e5b4..425bd54e402 100644 --- a/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java +++ b/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java @@ -2,6 +2,8 @@ import gregtech.api.pipenet.WorldPipeNet; +import gregtech.api.pipenet.WorldPipeNetG; + import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -331,7 +333,7 @@ public static WorldData get(World world) { if (worldData != null) { return worldData; } - String DATA_ID = WorldPipeNet.getDataID("long_dist_pipe", world); + String DATA_ID = WorldPipeNetG.getDataID("long_dist_pipe", world); WorldData netWorldData = (WorldData) world.loadData(WorldData.class, DATA_ID); if (netWorldData == null) { netWorldData = new WorldData(DATA_ID); diff --git a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java index 14246888d7a..0fcd26e631e 100644 --- a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java +++ b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java @@ -9,10 +9,13 @@ import net.minecraft.world.chunk.Chunk; import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.ApiStatus; import java.util.*; import java.util.stream.Collectors; +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.9") public abstract class TickableWorldPipeNet & ITickable> extends WorldPipeNet { diff --git a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java index 8ee0e7d61bd..7b34be78f99 100644 --- a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java +++ b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java @@ -8,11 +8,16 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent.WorldTickEvent; +import org.jetbrains.annotations.ApiStatus; + import java.util.ArrayList; import java.util.List; import java.util.function.Function; import java.util.stream.Stream; + +@Deprecated +@ApiStatus.ScheduledForRemoval(inVersion = "2.9") @EventBusSubscriber(modid = GTValues.MODID) public class TickableWorldPipeNetEventHandler { From 026bad7b132f6e67a9ed2d61cdb752886d819844 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 20 Dec 2023 20:15:43 -0700 Subject: [PATCH 026/157] Remove them spots --- .../api/pipenet/AbstractEdgePredicate.java | 6 +- .../api/pipenet/IShutteredEdgePredicate.java | 1 - .../java/gregtech/api/pipenet/NetGroup.java | 3 +- .../java/gregtech/api/pipenet/NetPath.java | 21 +++-- src/main/java/gregtech/api/pipenet/NodeG.java | 7 +- .../gregtech/api/pipenet/WorldPipeNetG.java | 47 ++++++----- .../pipenet/block/simple/BlockSimplePipe.java | 2 - .../pipenet/longdist/LongDistanceNetwork.java | 2 - .../TickableWorldPipeNetEventHandler.java | 1 - .../gregtech/api/pipenet/tile/IPipeTile.java | 6 +- .../api/pipenet/tile/TileEntityPipeBase.java | 2 +- .../properties/FluidPipeProperties.java | 1 - .../properties/ItemPipeProperties.java | 1 - .../material/properties/WireProperties.java | 1 - .../MetaTileEntityCentralMonitor.java | 77 +++++++++---------- .../pipelike/cable/net/EnergyGroupData.java | 2 - .../pipelike/cable/net/WorldEnergyNet.java | 2 - .../pipelike/cable/tile/TileEntityCable.java | 1 - .../fluidpipe/net/WorldFluidPipeNet.java | 3 - .../fluidpipe/tile/TileEntityFluidPipe.java | 3 - .../itempipe/net/ItemEdgePredicate.java | 14 ++-- .../pipelike/itempipe/net/ItemNetHandler.java | 26 ++++--- .../itempipe/net/WorldItemPipeNet.java | 2 - .../itempipe/tile/TileEntityItemPipe.java | 1 - .../pipelike/laser/LaserPipeProperties.java | 1 - .../pipelike/laser/net/LaserNetHandler.java | 2 - .../pipelike/laser/net/WorldLaserPipeNet.java | 3 - .../optical/OpticalPipeProperties.java | 1 - .../optical/net/OpticalNetHandler.java | 13 ++-- .../optical/net/WorldOpticalPipeNet.java | 3 - 30 files changed, 120 insertions(+), 135 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java b/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java index 28fb1d93481..d903b2e6e40 100644 --- a/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java @@ -1,18 +1,18 @@ package gregtech.api.pipenet; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; import net.minecraftforge.common.util.INBTSerializable; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Map; import java.util.function.Predicate; -public abstract class AbstractEdgePredicate> implements Predicate, INBTSerializable { +public abstract class AbstractEdgePredicate> + implements Predicate, INBTSerializable { protected static final Map> PREDICATES = new Object2ObjectOpenHashMap<>(); diff --git a/src/main/java/gregtech/api/pipenet/IShutteredEdgePredicate.java b/src/main/java/gregtech/api/pipenet/IShutteredEdgePredicate.java index c10c7690ee8..106ec1a7b86 100644 --- a/src/main/java/gregtech/api/pipenet/IShutteredEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/IShutteredEdgePredicate.java @@ -5,5 +5,4 @@ public interface IShutteredEdgePredicate { void setShutteredSource(boolean shutteredSource); void setShutteredTarget(boolean shutteredTarget); - } diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index de0c183d8b2..04e7a15cd3f 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -2,11 +2,10 @@ import gregtech.api.pipenet.block.IPipeType; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.INBTSerializable; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jgrapht.Graph; import org.jgrapht.traverse.BreadthFirstIterator; diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index cd903b2ff78..66cdf949871 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -1,14 +1,12 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; - import gregtech.api.util.FacingPos; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.GraphPath; import java.util.Iterator; @@ -16,7 +14,8 @@ import java.util.Map; import java.util.stream.Collectors; -public final class NetPath & IPipeType, NodeDataType extends INodeData> { +public final class NetPath & IPipeType, + NodeDataType extends INodeData> { private final List> nodeList; private final List edgeList; @@ -31,6 +30,7 @@ public final class NetPath & IPipeType node) { @@ -45,8 +45,9 @@ public NetPath(NodeG node) { /** * Generates a NetPath from an ordered list of nodes, edges, and a weight. * Used exclusively for single path generation. - * @param nodes List of nodes. - * @param edges List of edges. + * + * @param nodes List of nodes. + * @param edges List of edges. * @param weight Sum weight of the path. */ public NetPath(List> nodes, List edges, double weight) { @@ -59,6 +60,7 @@ public NetPath(List> nodes, List edges, d /** * Generates a NetPath from a GraphPath + * * @param path the GraphPath */ public NetPath(GraphPath, NetEdge> path) { @@ -66,7 +68,8 @@ public NetPath(GraphPath, NetEdge> path) { this.targetNode = path.getEndVertex(); this.nodeList = path.getVertexList(); // convert weight to the true value of the involved nodes - this.weight = (path.getWeight() + sourceNode.getData().getWeightFactor() + targetNode.getData().getWeightFactor()) / 2; + this.weight = (path.getWeight() + sourceNode.getData().getWeightFactor() + + targetNode.getData().getWeightFactor()) / 2; this.edgeList = path.getEdgeList(); } @@ -105,7 +108,8 @@ public double getWeight() { public NodeDataType getMinData() { // generate min data on-demand and cache it, rather than generating for every path always if (this.data == null) { - this.data = sourceNode.getData().getMinData(this.nodeList.stream().map(NodeG::getData).collect(Collectors.toSet())); + this.data = sourceNode.getData() + .getMinData(this.nodeList.stream().map(NodeG::getData).collect(Collectors.toSet())); } return data; } @@ -130,6 +134,7 @@ public FacedNetPath(NetPath path, EnumFacing facing) { public TileEntity getTargetTE() { return path.getTargetTEs().get(facing); } + public List> getNodeList() { return path.getNodeList(); } diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 6f53ef2d471..93c3b8d4a64 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -3,17 +3,15 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraftforge.common.util.INBTSerializable; - import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; @@ -21,7 +19,8 @@ import java.util.Map; import java.util.Objects; -public class NodeG & IPipeType, NodeDataType extends INodeData> +public class NodeG & IPipeType, + NodeDataType extends INodeData> implements INBTSerializable { public static final int DEFAULT_MARK = 0; diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 5a44179cd9b..1ae02a2faa7 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -4,11 +4,8 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; - import gregtech.common.covers.CoverShutter; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; @@ -21,6 +18,7 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; @@ -60,6 +58,7 @@ public WorldPipeNetG(String name) { * Override to change whether this net needs directed graph handling. * Used to respect filter directions in the item net and fluid net, for example. * If the graph is not directed, pipes should not support blocked connections. + * * @return True if the graph should be directed. */ protected boolean isDirected() { @@ -69,6 +68,7 @@ protected boolean isDirected() { /** * Override to change whether this net allows only one source and one destination per group. * Allows for optimizations in path lookup and cache invalidation. + * * @return True if the graph should be single-pathed. */ protected boolean isSinglePath() { @@ -130,8 +130,8 @@ public List> getPaths(@Nullable NodeG> list = - isSinglePath() ? this.singlePathList(node) : this.shortestPaths.getPathsList(node); + List> list = isSinglePath() ? this.singlePathList(node) : + this.shortestPaths.getPathsList(node); return verifyList(node.setPathCache(list), node); } @@ -139,9 +139,9 @@ public List> getPaths(@Nullable NodeG> verifyList(List> list, - NodeG source) { + NodeG source) { if (!verifyNode(source)) return new ObjectArrayList<>(); return list.stream().filter(a -> verifyNode(a.getTargetNode())).collect(Collectors.toList()); } @@ -153,7 +153,7 @@ protected boolean verifyNode(NodeG node) { @Nullable protected TileEntityPipeBase castTE(TileEntity te) { - if (te instanceof TileEntityPipeBase pipe) { + if (te instanceof TileEntityPipeBasepipe) { if (!getBasePipeClass().isAssignableFrom(pipe.getClass())) { return null; } @@ -166,6 +166,7 @@ protected TileEntityPipeBase castTE(TileEntity te) { /** * Make sure to override this if your NetGroups use data. + * * @return The correct data variant */ protected AbstractGroupData getBlankGroupData() { @@ -176,7 +177,7 @@ public NodeG getOrCreateNode(@NotNull IPipeTile node = this.pipeMap.get(mte.getPipePos()); if (node != null) return node; if (!canAttachNode(mte.getNodeData())) return null; - node = new NodeG<>(mte.getNodeData(), mte,this); + node = new NodeG<>(mte.getNodeData(), mte, this); this.addNode(node); return node; } @@ -184,7 +185,8 @@ public NodeG getOrCreateNode(@NotNull IPipeTile source, EnumFacing nodeFacing, NodeG target) { return areNodeBlockedConnectionsCompatible(source, nodeFacing, target) && - areMarksCompatible(source.mark, target.mark) && areNodesCustomContactable(source.getData(), target.getData()); + areMarksCompatible(source.mark, target.mark) && + areNodesCustomContactable(source.getData(), target.getData()); } private static boolean areMarksCompatible(int mark1, int mark2) { @@ -295,17 +297,20 @@ public void addUndirectedEdge(NodeG source, NodeG source, NodeG target, @Nullable AbstractEdgePredicate predicate) { + public void addEdge(NodeG source, NodeG target, + @Nullable AbstractEdgePredicate predicate) { addEdge(source, target, source.getData().getWeightFactor() + target.getData().getWeightFactor(), predicate); this.validAlgorithmInstance = false; } - public void addUndirectedEdge(NodeG source, NodeG target, double weight) { + public void addUndirectedEdge(NodeG source, NodeG target, + double weight) { this.addEdge(source, target, weight, null); if (this.isDirected()) this.addEdge(target, source, weight, null); } - public void addEdge(NodeG source, NodeG target, double weight, @Nullable AbstractEdgePredicate predicate) { + public void addEdge(NodeG source, NodeG target, double weight, + @Nullable AbstractEdgePredicate predicate) { if (pipeGraph.addEdge(source, target) != null) { if (NetGroup.mergeEdge(source, target)) { new NetGroup<>(this.pipeGraph, this).addNodes(source, target); @@ -334,15 +339,18 @@ public void predicateEdge(BlockPos pos, EnumFacing faceToNeighbour) { this.predicateEdge(source, target, faceToNeighbour); } - public void predicateUndirectedEdge(NodeG source, NodeG target, EnumFacing faceToNeighbour) { + public void predicateUndirectedEdge(NodeG source, NodeG target, + EnumFacing faceToNeighbour) { this.predicateEdge(source, target, faceToNeighbour); if (this.isDirected()) this.predicateEdge(target, source, faceToNeighbour.getOpposite()); } - public void predicateEdge(NodeG source, NodeG target, EnumFacing faceToNeighbour) { + public void predicateEdge(NodeG source, NodeG target, + EnumFacing faceToNeighbour) { if (!this.pipeGraph.containsEdge(source, target)) return; Cover thisCover = source.getHeldMTESafe().getCoverableImplementation().getCoverAtSide(faceToNeighbour); - Cover neighbourCover = target.getHeldMTESafe().getCoverableImplementation().getCoverAtSide(faceToNeighbour.getOpposite()); + Cover neighbourCover = target.getHeldMTESafe().getCoverableImplementation() + .getCoverAtSide(faceToNeighbour.getOpposite()); AbstractEdgePredicate predicate = getPredicate(thisCover, neighbourCover); predicate.setPosInfo(source.getNodePos(), target.getNodePos()); NetEdge edge = this.pipeGraph.getEdge(source, target); @@ -353,7 +361,8 @@ protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbour return shutterify(new BasicEdgePredicate(), thisCover, neighbourCover); } - protected final AbstractEdgePredicate shutterify(AbstractEdgePredicate predicate, @Nullable Cover thisCover, @Nullable Cover neighbourCover) { + protected final AbstractEdgePredicate shutterify(AbstractEdgePredicate predicate, @Nullable Cover thisCover, + @Nullable Cover neighbourCover) { if (predicate instanceof IShutteredEdgePredicate shutteredEdgePredicate) { if (thisCover instanceof CoverShutter shutter) { shutteredEdgePredicate.setShutteredSource(shutter.isWorkingEnabled()); @@ -480,7 +489,8 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); // CHManyToManyShortestPaths is a very good algorithm because our graph will be extremely sparse. - protected static final class ShortestPathsAlgorithm & IPipeType, NDT extends INodeData> + protected static final class ShortestPathsAlgorithm & IPipeType, + NDT extends INodeData> extends CHManyToManyShortestPaths, NetEdge> { public ShortestPathsAlgorithm(Graph, NetEdge> graph) { @@ -512,6 +522,7 @@ public List> getPathsList(NodeG source) { /** * Special path lookup for single-path graphs. * Allows us to skip calculating the ShortestPathsAlgorithm every time the graph updates. + * * @param source Source node for the path. * @return A list containing one or fewer paths. */ diff --git a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java index a3466cf9fdb..7f921023050 100644 --- a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java +++ b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java @@ -9,8 +9,6 @@ import net.minecraft.item.ItemStack; -import org.jetbrains.annotations.ApiStatus; - public abstract class BlockSimplePipe & IPipeType, NodeDataType extends INodeData, WorldPipeNetType extends WorldPipeNetG> diff --git a/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java b/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java index 425bd54e402..6ae366e6bb6 100644 --- a/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java +++ b/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java @@ -1,7 +1,5 @@ package gregtech.api.pipenet.longdist; -import gregtech.api.pipenet.WorldPipeNet; - import gregtech.api.pipenet.WorldPipeNetG; import net.minecraft.nbt.NBTBase; diff --git a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java index 7b34be78f99..f1b9f64aa23 100644 --- a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java +++ b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java @@ -15,7 +15,6 @@ import java.util.function.Function; import java.util.stream.Stream; - @Deprecated @ApiStatus.ScheduledForRemoval(inVersion = "2.9") @EventBusSubscriber(modid = GTValues.MODID) diff --git a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java index 0251240a80f..4660839c988 100644 --- a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java +++ b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java @@ -14,9 +14,6 @@ import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - import org.jetbrains.annotations.Nullable; import java.util.function.Consumer; @@ -85,7 +82,8 @@ default boolean canHaveBlockedFaces() { NodeG getNode(); - @Nullable TileEntity getNonPipeNeighbour(EnumFacing facing); + @Nullable + TileEntity getNonPipeNeighbour(EnumFacing facing); PipeCoverableImplementation getCoverableImplementation(); diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 629786552db..077f9428e69 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -156,7 +156,7 @@ protected void invalidateNeighbors() { if (neighbor == null) return null; if (neighbor == this || (neighbor.isInvalid())) { neighbor = getNeighbor(facing); - if (neighbor instanceof IPipeTile) neighbor = null; + if (neighbor instanceof IPipeTile) neighbor = null; this.nonPipeNeighbors[i] = neighbor; this.nonPipeNeighborsInvalidated = false; } diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 57e350c889d..e39635bc55e 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -12,7 +12,6 @@ import org.jetbrains.annotations.UnmodifiableView; import java.util.Collection; -import java.util.List; import java.util.Objects; import java.util.Set; diff --git a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java index c39fd4c2ff2..f60d5c33bed 100644 --- a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java @@ -2,7 +2,6 @@ import gregtech.api.pipenet.INodeData; -import java.util.List; import java.util.Objects; import java.util.Set; diff --git a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java index 318fc257a13..195e9a8d93e 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java @@ -4,7 +4,6 @@ import gregtech.api.pipenet.INodeData; import gregtech.api.unification.material.Material; -import java.util.List; import java.util.Objects; import java.util.Set; diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java index 0c0db6f8b9e..919e9bcca85 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java @@ -60,7 +60,6 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; -import java.lang.ref.WeakReference; import java.util.*; import static gregtech.api.util.RelativeDirection.*; @@ -73,7 +72,7 @@ public class MetaTileEntityCentralMonitor extends MultiblockWithDisplayBase impl // run-time data public int width; private long lastUpdate; -// private WeakReference currentEnergyNet; + // private WeakReference currentEnergyNet; private List activeNodes; private Set netCovers; private Set remoteCovers; @@ -89,44 +88,44 @@ public MetaTileEntityCentralMonitor(ResourceLocation metaTileEntityId) { super(metaTileEntityId); } -// private EnergyNet getEnergyNet() { -// if (!this.getWorld().isRemote) { -// TileEntity te = getNeighbor(frontFacing.getOpposite()); -// if (te instanceof TileEntityCable) { -// TileEntityPipeBase tileEntityCable = (TileEntityCable) te; -// EnergyNet currentEnergyNet = this.currentEnergyNet.get(); -// if (currentEnergyNet != null && currentEnergyNet.isValid() && -// currentEnergyNet.containsNode(tileEntityCable.getPipePos())) { -// return currentEnergyNet; // return current net if it is still valid -// } -// WorldEnergyNet worldEnergyNet = (WorldEnergyNet) tileEntityCable.getPipeBlock() -// .getWorldPipeNet(tileEntityCable.getPipeWorld()); -// currentEnergyNet = worldEnergyNet.getNetFromPos(tileEntityCable.getPipePos()); -// if (currentEnergyNet != null) { -// this.currentEnergyNet = new WeakReference<>(currentEnergyNet); -// } -// return currentEnergyNet; -// } -// } -// return null; -// } + // private EnergyNet getEnergyNet() { + // if (!this.getWorld().isRemote) { + // TileEntity te = getNeighbor(frontFacing.getOpposite()); + // if (te instanceof TileEntityCable) { + // TileEntityPipeBase tileEntityCable = (TileEntityCable) te; + // EnergyNet currentEnergyNet = this.currentEnergyNet.get(); + // if (currentEnergyNet != null && currentEnergyNet.isValid() && + // currentEnergyNet.containsNode(tileEntityCable.getPipePos())) { + // return currentEnergyNet; // return current net if it is still valid + // } + // WorldEnergyNet worldEnergyNet = (WorldEnergyNet) tileEntityCable.getPipeBlock() + // .getWorldPipeNet(tileEntityCable.getPipeWorld()); + // currentEnergyNet = worldEnergyNet.getNetFromPos(tileEntityCable.getPipePos()); + // if (currentEnergyNet != null) { + // this.currentEnergyNet = new WeakReference<>(currentEnergyNet); + // } + // return currentEnergyNet; + // } + // } + // return null; + // } private void updateNodes() { -// EnergyNet energyNet = getEnergyNet(); -// if (energyNet == null) { -// activeNodes.clear(); -// return; -// } -// if (energyNet.getLastUpdate() == lastUpdate) { -// return; -// } -// lastUpdate = energyNet.getLastUpdate(); -// activeNodes.clear(); -// energyNet.getAllNodes().forEach((pos, node) -> { -// if (node.isActive) { -// activeNodes.add(pos); -// } -// }); + // EnergyNet energyNet = getEnergyNet(); + // if (energyNet == null) { + // activeNodes.clear(); + // return; + // } + // if (energyNet.getLastUpdate() == lastUpdate) { + // return; + // } + // lastUpdate = energyNet.getLastUpdate(); + // activeNodes.clear(); + // energyNet.getAllNodes().forEach((pos, node) -> { + // if (node.isActive) { + // activeNodes.add(pos); + // } + // }); } public void addRemoteCover(FacingPos cover) { @@ -423,7 +422,7 @@ public String[] getDescription() { protected void formStructure(PatternMatchContext context) { super.formStructure(context); lastUpdate = 0; -// currentEnergyNet = new WeakReference<>(null); + // currentEnergyNet = new WeakReference<>(null); activeNodes = new ArrayList<>(); netCovers = new HashSet<>(); remoteCovers = new HashSet<>(); diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyGroupData.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyGroupData.java index e4ab958c594..34e1c6bec83 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyGroupData.java @@ -1,9 +1,7 @@ package gregtech.common.pipelike.cable.net; import gregtech.api.pipenet.AbstractGroupData; - import gregtech.api.unification.material.properties.WireProperties; - import gregtech.common.pipelike.cable.Insulation; import net.minecraft.world.World; diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java index f5a824e2191..4466153d388 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -4,9 +4,7 @@ import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.WireProperties; - import gregtech.common.pipelike.cable.Insulation; - import gregtech.common.pipelike.cable.tile.TileEntityCable; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java index 05e7092e551..c8ee74ca3a2 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java @@ -4,7 +4,6 @@ import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IEnergyContainer; import gregtech.api.metatileentity.IDataInfoProvider; -import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.unification.material.properties.WireProperties; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index ac9dc965475..fd676b6684a 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -1,12 +1,9 @@ package gregtech.common.pipelike.fluidpipe.net; -import gregtech.api.pipenet.WorldPipeNet; import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; - import gregtech.common.pipelike.fluidpipe.FluidPipeType; - import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java index 96db29650a4..21c2b0cdc6e 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java @@ -1,13 +1,10 @@ package gregtech.common.pipelike.fluidpipe.tile; import gregtech.api.GTValues; -import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.pipelike.fluidpipe.FluidPipeType; -import gregtech.common.pipelike.fluidpipe.net.WorldFluidPipeNet; - import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java index 7974336aa11..0239e14f180 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java @@ -1,7 +1,6 @@ package gregtech.common.pipelike.itempipe.net; import gregtech.api.pipenet.AbstractEdgePredicate; - import gregtech.api.pipenet.IShutteredEdgePredicate; import gregtech.api.util.IDirtyNotifiable; import gregtech.common.covers.filter.FilterTypeRegistry; @@ -60,14 +59,16 @@ public NBTTagCompound serializeNBT() { tag.setBoolean("SourceBlacklist", this.sourceFilter.isBlacklistFilter()); if (this.sourceFilter.getItemFilter() != null) { filterComponent = new NBTTagCompound(); - tag.setInteger("SourceFilterType", FilterTypeRegistry.getIdForItemFilter(this.sourceFilter.getItemFilter())); + tag.setInteger("SourceFilterType", + FilterTypeRegistry.getIdForItemFilter(this.sourceFilter.getItemFilter())); this.sourceFilter.getItemFilter().writeToNBT(filterComponent); tag.setTag("SourceFilter", filterComponent); } tag.setBoolean("TargetBlacklist", this.targetFilter.isBlacklistFilter()); if (this.targetFilter.getItemFilter() != null) { filterComponent = new NBTTagCompound(); - tag.setInteger("TargetFilterType", FilterTypeRegistry.getIdForItemFilter(this.targetFilter.getItemFilter())); + tag.setInteger("TargetFilterType", + FilterTypeRegistry.getIdForItemFilter(this.targetFilter.getItemFilter())); this.targetFilter.getItemFilter().writeToNBT(filterComponent); tag.setTag("TargetFilter", filterComponent); } @@ -79,16 +80,17 @@ public void deserializeNBT(NBTTagCompound nbt) { shutteredSource = nbt.getBoolean("ShutteredSource"); shutteredTarget = nbt.getBoolean("ShutteredTarget"); if (nbt.hasKey("SourceFilter")) { - this.sourceFilter.setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("SourceFilterType"))); + this.sourceFilter + .setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("SourceFilterType"))); this.sourceFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("SourceFilter")); this.sourceFilter.setBlacklistFilter(nbt.getBoolean("SourceBlacklist"), true); } if (nbt.hasKey("TargetFilter")) { - this.targetFilter.setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("TargetFilterType"))); + this.targetFilter + .setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("TargetFilterType"))); this.targetFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("TargetFilter")); this.targetFilter.setBlacklistFilter(nbt.getBoolean("TargetBlacklist"), true); } - } @Override diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index bdce46cc583..519d265b59d 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -146,7 +146,8 @@ public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean glo * @param simulate simulate * @return remainder */ - private ItemStack insertToHandlers(List> copy, ItemStack stack, boolean simulate) { + private ItemStack insertToHandlers(List> copy, ItemStack stack, + boolean simulate) { Iterator> routePathIterator = copy.listIterator(); int inserted = 0; int count = stack.getCount(); @@ -157,8 +158,8 @@ private ItemStack insertToHandlers(List routePath = routePathIterator.next(); Iterator iterator = routePath.getFacingIterator(); while (iterator.hasNext()) { - NetPath.FacedNetPath facedNetPath = - routePath.withFacing(iterator.next()); + NetPath.FacedNetPath facedNetPath = routePath + .withFacing(iterator.next()); int amount = c; if (m > 0) { amount++; @@ -186,7 +187,8 @@ private ItemStack insertToHandlers(List> copy, ItemStack stack, int dest, boolean simulate) { + private ItemStack insertToHandlersEnhanced(List> copy, ItemStack stack, + int dest, boolean simulate) { List transferred = new ArrayList<>(); IntList steps = new IntArrayList(); int min = Integer.MAX_VALUE; @@ -303,11 +305,13 @@ private ItemStack insertToHandlersEnhanced(List routePath, ItemStack stack, boolean simulate) { + public ItemStack insert(NetPath.FacedNetPath routePath, ItemStack stack, + boolean simulate) { return insert(routePath, stack, simulate, false); } - public ItemStack insert(NetPath.FacedNetPath routePath, ItemStack stack, boolean simulate, boolean ignoreLimit) { + public ItemStack insert(NetPath.FacedNetPath routePath, ItemStack stack, + boolean simulate, boolean ignoreLimit) { int allowed = ignoreLimit ? stack.getCount() : checkTransferable(routePath.getData().getTransferRate(), stack.getCount(), simulate); if (allowed == 0 || !routePath.checkPredicate(stack)) { @@ -328,8 +332,8 @@ public ItemStack insert(NetPath.FacedNetPath r } testHandler.setStackInSlot(0, ItemStack.EMPTY); } - IItemHandler neighbourHandler = - routePath.getTargetTE().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, routePath.facing); + IItemHandler neighbourHandler = routePath.getTargetTE() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, routePath.facing); if (pipeCover instanceof CoverRoboticArm && ((CoverRoboticArm) pipeCover).getConveyorMode() == CoverConveyor.ConveyorMode.EXPORT) { return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) pipeCover, stack, simulate, allowed, @@ -463,7 +467,8 @@ public int getSlotLimit(int i) { return 64; } - private void transferTo(NetPath.FacedNetPath routePath, boolean simulate, int amount) { + private void transferTo(NetPath.FacedNetPath routePath, boolean simulate, + int amount) { if (simulate) simulatedTransfersGlobalRoundRobin.merge(routePath.toFacingPos(), amount, Integer::sum); else @@ -501,7 +506,8 @@ private static class EnhancedRoundRobinData { private int transferred; private int toTransfer = 0; - private EnhancedRoundRobinData(NetPath.FacedNetPath routePath, int maxInsertable, int transferred) { + private EnhancedRoundRobinData(NetPath.FacedNetPath routePath, + int maxInsertable, int transferred) { this.maxInsertable = maxInsertable; this.transferred = transferred; this.routePath = routePath; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index 4eda0642f17..b7cf38235f7 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -5,13 +5,11 @@ import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.ItemPipeProperties; - import gregtech.common.covers.CoverConveyor; import gregtech.common.covers.CoverItemFilter; import gregtech.common.covers.ItemFilterMode; import gregtech.common.covers.ManualImportExportMode; import gregtech.common.pipelike.itempipe.ItemPipeType; - import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java index 8558e0b7243..b19f71551ad 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java @@ -18,7 +18,6 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.jetbrains.annotations.Nullable; -import java.lang.ref.WeakReference; import java.util.EnumMap; public class TileEntityItemPipe extends TileEntityMaterialPipeBase { diff --git a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java b/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java index 37135a7e190..8e4d2bec8b9 100644 --- a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java +++ b/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java @@ -2,7 +2,6 @@ import gregtech.api.pipenet.INodeData; -import java.util.List; import java.util.Set; public class LaserPipeProperties implements INodeData { diff --git a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java index 25c95eac02f..c8a22d2e05f 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java @@ -1,6 +1,5 @@ package gregtech.common.pipelike.laser.net; -import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserContainer; import gregtech.api.pipenet.NetGroup; @@ -12,7 +11,6 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java b/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java index 709eee89717..75726142c9f 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java @@ -1,12 +1,9 @@ package gregtech.common.pipelike.laser.net; -import gregtech.api.pipenet.WorldPipeNet; import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.common.pipelike.laser.LaserPipeProperties; - import gregtech.common.pipelike.laser.LaserPipeType; - import gregtech.common.pipelike.laser.tile.TileEntityLaserPipe; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java index 77a2b0de3f4..b064f7eb83a 100644 --- a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java +++ b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java @@ -2,7 +2,6 @@ import gregtech.api.pipenet.INodeData; -import java.util.List; import java.util.Set; public class OpticalPipeProperties implements INodeData { diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java index 8b469771057..0e68df838f3 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java @@ -8,16 +8,12 @@ import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.NodeG; import gregtech.api.recipes.Recipe; -import gregtech.common.pipelike.laser.LaserPipeProperties; -import gregtech.common.pipelike.laser.LaserPipeType; import gregtech.common.pipelike.optical.OpticalPipeProperties; import gregtech.common.pipelike.optical.OpticalPipeType; import gregtech.common.pipelike.optical.tile.TileEntityOpticalPipe; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,7 +29,8 @@ public class OpticalNetHandler implements IDataAccessHatch, IOpticalComputationP private final WorldOpticalPipeNet net; - public OpticalNetHandler(WorldOpticalPipeNet net, @NotNull TileEntityOpticalPipe pipe, @Nullable EnumFacing facing) { + public OpticalNetHandler(WorldOpticalPipeNet net, @NotNull TileEntityOpticalPipe pipe, + @Nullable EnumFacing facing) { this.net = net; this.pipe = pipe; this.facing = facing; @@ -96,7 +93,8 @@ private boolean traverseRecipeAvailable(@NotNull Recipe recipe, @NotNull Collect if (connecteds.size() != 1) return false; EnumFacing facing = connecteds.keySet().iterator().next(); - IDataAccessHatch access = connecteds.get(facing).getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, facing.getOpposite()); + IDataAccessHatch access = connecteds.get(facing).getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, + facing.getOpposite()); if (!(access instanceof IOpticalDataAccessHatch hatch) || seen.contains(hatch)) return false; if (hatch.isTransmitter()) { @@ -133,7 +131,8 @@ private IOpticalComputationProvider getComputationProvider(@NotNull Collection Date: Wed, 20 Dec 2023 21:17:47 -0700 Subject: [PATCH 027/157] Old world compat --- .../gregtech/api/pipenet/WorldPipeNetG.java | 6 +++- .../api/pipenet/tile/TileEntityPipeBase.java | 33 ++++++++++++++++++- .../fluidpipe/net/WorldFluidPipeNet.java | 2 +- .../itempipe/net/WorldItemPipeNet.java | 2 +- 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 1ae02a2faa7..63e54ff7cd6 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -61,7 +61,7 @@ public WorldPipeNetG(String name) { * * @return True if the graph should be directed. */ - protected boolean isDirected() { + public boolean isDirected() { return false; } @@ -288,6 +288,7 @@ public void addNode(NodeG node) { this.markDirty(); } + @Nullable public NodeG getNode(BlockPos pos) { return this.pipeMap.get(pos); } @@ -426,6 +427,9 @@ protected void rebuildShortestPaths() { @Override public void readFromNBT(NBTTagCompound nbt) { + if (!nbt.hasKey("NetEdges")) { + return; + } NBTTagList allPipeNodes = nbt.getTagList("PipeNodes", Constants.NBT.TAG_COMPOUND); Map> longPosMap = new Long2ObjectOpenHashMap<>(); for (int i = 0; i < allPipeNodes.tagCount(); i++) { diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 077f9428e69..ca4c52171fc 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -7,6 +7,7 @@ import gregtech.api.metatileentity.SyncedTileEntityBase; import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.unification.material.Material; @@ -394,6 +395,7 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { // noinspection ConstantConditions compound.setString("PipeBlock", pipeBlock.getRegistryName().toString()); } + compound.setInteger("PipeNetVersion", 2); compound.setInteger("PipeType", pipeType.ordinal()); compound.setInteger("Connections", getNode().getActiveConnections()); compound.setInteger("BlockedConnections", getNode().getBlockedConnections()); @@ -420,9 +422,38 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { } this.pipeType = getPipeTypeClass().getEnumConstants()[compound.getInteger("PipeType")]; - this.getNode().setActiveConnections(compound.getInteger("Connections")); + if (compound.hasKey("Connections")) { + this.getNode().setActiveConnections(compound.getInteger("Connections")); + } else if (compound.hasKey("BlockedConnectionsMap")) { + int connections = 0; + NBTTagCompound blockedConnectionsTag = compound.getCompoundTag("BlockedConnectionsMap"); + for (String attachmentTypeKey : blockedConnectionsTag.getKeySet()) { + int blockedConnections = blockedConnectionsTag.getInteger(attachmentTypeKey); + connections |= blockedConnections; + } + this.getNode().setActiveConnections(connections); + } this.getNode().setBlockedConnections(compound.getInteger("BlockedConnections")); + if (!compound.hasKey("PipeNetVersion")) { + for (EnumFacing facing : EnumFacing.VALUES) { + WorldPipeNetG net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); + NodeG nodeOffset = net.getNode(this.getPipePos().offset(facing)); + if (nodeOffset == null) continue; + if (net.isDirected()) { + // offset node might've been read before us, so we have to cover for it. + if (nodeOffset.isConnected(facing.getOpposite())) { + net.addEdge(nodeOffset, this.getNode(), null); + net.predicateEdge(nodeOffset, this.getNode(), facing.getOpposite()); + } + } + if (this.isConnected(facing)) { + net.addEdge(this.getNode(), nodeOffset, null); + net.predicateEdge(this.getNode(), nodeOffset, facing); + } + } + } + if (compound.hasKey("InsulationColor")) { this.paintingColor = compound.getInteger("InsulationColor"); } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index fd676b6684a..98dd52dc330 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -29,7 +29,7 @@ public WorldFluidPipeNet(String name) { } @Override - protected boolean isDirected() { + public boolean isDirected() { return true; } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index b7cf38235f7..d8384ba5394 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -34,7 +34,7 @@ public WorldItemPipeNet(String name) { } @Override - protected boolean isDirected() { + public boolean isDirected() { return true; } From 6af7e66725b7aeeac9bcbb9decc2a35f8c4731ce Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 20 Dec 2023 21:44:39 -0700 Subject: [PATCH 028/157] Less invasive & more generalized solution to stack overflow --- .../api/pipenet/tile/TileEntityPipeBase.java | 6 +++++- .../gregtech/common/covers/CoverFluidFilter.java | 2 +- .../gregtech/common/covers/CoverItemFilter.java | 4 ++-- .../common/covers/CoverItemVoidingAdvanced.java | 4 ++-- .../gregtech/common/covers/CoverRoboticArm.java | 4 ++-- .../covers/filter/FluidFilterContainer.java | 2 +- .../common/covers/filter/FluidFilterWrapper.java | 5 ++--- .../covers/filter/ItemFilterContainer.java | 16 ++++++++-------- .../common/covers/filter/ItemFilterWrapper.java | 8 +++----- .../pipelike/itempipe/net/ItemEdgePredicate.java | 4 ++-- 10 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index ca4c52171fc..f307ff1a610 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -60,6 +60,8 @@ public abstract class TileEntityPipeBase & IPipe // set when this pipe is replaced with a ticking variant to redirect sync packets private TileEntityPipeBase tickingPipe; + private boolean nbtLoad = false; + public TileEntityPipeBase() { super(false); invalidateNeighbors(); @@ -409,6 +411,7 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { @Override public void readFromNBT(@NotNull NBTTagCompound compound) { + this.nbtLoad = true; if (this.tickingPipe != null) { this.tickingPipe.readFromNBT(compound); return; @@ -467,6 +470,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { // one of the covers set the pipe to ticking, and we need to send over the rest of the covers this.coverableImplementation.transferDataTo(this.tickingPipe.coverableImplementation); } + this.nbtLoad = false; } @Override @@ -563,7 +567,7 @@ public void notifyBlockUpdate() { public void markAsDirty() { markDirty(); // this most notably gets called when the covers of a pipe get updated, aka the edge predicates need syncing. - if (getWorld().isRemote) return; + if (getWorld().isRemote || this.nbtLoad) return; for (EnumFacing facing : EnumFacing.VALUES) { if (!isConnected(facing)) continue; this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()).predicateEdge(this.getPipePos(), facing); diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index 0307d993b23..cd5d06ee5a4 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -137,7 +137,7 @@ public void writeToNBT(@NotNull NBTTagCompound tagCompound) { public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.filterMode = FluidFilterMode.values()[tagCompound.getInteger("FilterMode")]; - this.fluidFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist"), true); + this.fluidFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); this.fluidFilter.getFluidFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); } diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 8589e863fc1..656fe17f5d8 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -50,7 +50,7 @@ public CoverItemFilter(@NotNull CoverDefinition definition, @NotNull CoverableVi this.texture = texture; this.itemFilter = new ItemFilterWrapper(this); this.itemFilter.setItemFilter(itemFilter); - this.itemFilter.setMaxStackSize(1, false); + this.itemFilter.setMaxStackSize(1); } public void setFilterMode(ItemFilterMode filterMode) { @@ -124,7 +124,7 @@ public void writeToNBT(@NotNull NBTTagCompound tagCompound) { public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); this.filterMode = ItemFilterMode.values()[tagCompound.getInteger("FilterMode")]; - this.itemFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist"), true); + this.itemFilter.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); this.itemFilter.getItemFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); } diff --git a/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java b/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java index 9bdb1d60ab6..62d2844aaa3 100644 --- a/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java +++ b/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java @@ -141,8 +141,8 @@ public void initFilterUI(int y, Consumer widgetGroup) { stackSizeGroup.addWidget(new TextFieldWidget2(113, 41, 31, 20, () -> String.valueOf(itemFilterContainer.getTransferStackSize()), val -> { if (val != null && !val.isEmpty()) - itemFilterContainer.setTransferStackSize(MathHelper.clamp(Integer.parseInt(val), - 1, voidingMode.maxStackSize), false); + itemFilterContainer.setTransferStackSize( + MathHelper.clamp(Integer.parseInt(val), 1, voidingMode.maxStackSize)); }) .setCentered(true) .setNumbersOnly(1, Integer.MAX_VALUE) diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 3fe05856b9c..902ffcd62f4 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -208,8 +208,8 @@ protected ModularUI buildUI(Builder builder, EntityPlayer player) { stackSizeGroup.addWidget(new TextFieldWidget2(113, 77, 31, 20, () -> String.valueOf(itemFilterContainer.getTransferStackSize()), val -> { if (val != null && !val.isEmpty()) - itemFilterContainer.setTransferStackSize(MathHelper.clamp(Integer.parseInt(val), - 1, transferMode.maxStackSize), false); + itemFilterContainer.setTransferStackSize( + MathHelper.clamp(Integer.parseInt(val), 1, transferMode.maxStackSize)); }) .setNumbersOnly(1, transferMode.maxStackSize) .setMaxLength(4) diff --git a/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java b/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java index 4ecbb429a22..41beb67b6d6 100644 --- a/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java +++ b/src/main/java/gregtech/common/covers/filter/FluidFilterContainer.java @@ -120,7 +120,7 @@ public NBTTagCompound serializeNBT() { @Override public void deserializeNBT(NBTTagCompound tagCompound) { this.filterInventory.deserializeNBT(tagCompound.getCompoundTag("FilterInventory")); - this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist"), true); + this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); if (filterWrapper.getFluidFilter() != null) { this.filterWrapper.getFluidFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); } diff --git a/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java b/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java index a4b99e89e3a..2ef1f76a32e 100644 --- a/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java +++ b/src/main/java/gregtech/common/covers/filter/FluidFilterWrapper.java @@ -36,7 +36,7 @@ public void initUI(int y, Consumer widgetGroup) { public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { ServerWidgetGroup blacklistButton = new ServerWidgetGroup(() -> getFluidFilter() != null); blacklistButton.addWidget(new ToggleButtonWidget(144, y, 18, 18, GuiTextures.BUTTON_BLACKLIST, - this::isBlacklistFilter, a -> this.setBlacklistFilter(a, false)).setPredicate(showBlacklistButton) + this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) .setTooltipText("cover.filter.blacklist")); widgetGroup.accept(blacklistButton); } @@ -65,9 +65,8 @@ public void onFilterInstanceChange() { dirtyNotifiable.markAsDirty(); } - public void setBlacklistFilter(boolean blacklistFilter, boolean nbtLoad) { + public void setBlacklistFilter(boolean blacklistFilter) { isBlacklistFilter = blacklistFilter; - if (nbtLoad) return; dirtyNotifiable.markAsDirty(); } diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java b/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java index 55957d4332a..71be9ff14d3 100644 --- a/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java +++ b/src/main/java/gregtech/common/covers/filter/ItemFilterContainer.java @@ -59,7 +59,7 @@ public ItemFilterWrapper getFilterWrapper() { } private void onFilterInstanceChange() { - this.filterWrapper.setMaxStackSize(getTransferStackSize(), false); + this.filterWrapper.setMaxStackSize(getTransferStackSize()); } public int getMaxStackSize() { @@ -73,13 +73,13 @@ public int getTransferStackSize() { return transferStackSize; } - public void setTransferStackSize(int transferStackSize, boolean nbtLoad) { + public void setTransferStackSize(int transferStackSize) { this.transferStackSize = MathHelper.clamp(transferStackSize, 1, getMaxStackSize()); - this.filterWrapper.setMaxStackSize(getTransferStackSize(), nbtLoad); + this.filterWrapper.setMaxStackSize(getTransferStackSize()); } public void adjustTransferStackSize(int amount) { - setTransferStackSize(transferStackSize + amount, false); + setTransferStackSize(transferStackSize + amount); } public void initUI(int y, Consumer widgetGroup) { @@ -98,7 +98,7 @@ protected void onFilterSlotChange(boolean notify) { if (newItemFilter == null) { if (currentItemFilter != null) { filterWrapper.setItemFilter(null); - filterWrapper.setBlacklistFilter(false, false); + filterWrapper.setBlacklistFilter(false); if (notify) filterWrapper.onFilterInstanceChange(); } } else if (currentItemFilter == null || @@ -110,7 +110,7 @@ protected void onFilterSlotChange(boolean notify) { public void setMaxStackSize(int maxStackSizeLimit) { this.maxStackSizeLimit = maxStackSizeLimit; - setTransferStackSize(transferStackSize, false); + setTransferStackSize(transferStackSize); } public boolean showGlobalTransferLimitSlider() { @@ -155,9 +155,9 @@ public NBTTagCompound serializeNBT() { @Override public void deserializeNBT(NBTTagCompound tagCompound) { this.filterInventory.deserializeNBT(tagCompound.getCompoundTag("FilterInventory")); - this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist"), true); + this.filterWrapper.setBlacklistFilter(tagCompound.getBoolean("IsBlacklist")); setMaxStackSize(tagCompound.getInteger("MaxStackSize")); - setTransferStackSize(tagCompound.getInteger("TransferStackSize"), true); + setTransferStackSize(tagCompound.getInteger("TransferStackSize")); if (filterWrapper.getItemFilter() != null) { this.filterWrapper.getItemFilter().readFromNBT(tagCompound.getCompoundTag("Filter")); } diff --git a/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java b/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java index d59ab8283d0..d11905e00b5 100644 --- a/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java +++ b/src/main/java/gregtech/common/covers/filter/ItemFilterWrapper.java @@ -31,7 +31,7 @@ public void initUI(int y, Consumer widgetGroup) { public void blacklistUI(int y, Consumer widgetGroup, BooleanSupplier showBlacklistButton) { ServerWidgetGroup blacklistButton = new ServerWidgetGroup(() -> getItemFilter() != null); blacklistButton.addWidget(new ToggleButtonWidget(144, y, 20, 20, GuiTextures.BUTTON_BLACKLIST, - this::isBlacklistFilter, a -> this.setBlacklistFilter(a, false)).setPredicate(showBlacklistButton) + this::isBlacklistFilter, this::setBlacklistFilter).setPredicate(showBlacklistButton) .setTooltipText("cover.filter.blacklist")); widgetGroup.accept(blacklistButton); } @@ -61,16 +61,14 @@ public void onFilterInstanceChange() { dirtyNotifiable.markAsDirty(); } - public void setMaxStackSize(int maxStackSize, boolean nbtLoad) { + public void setMaxStackSize(int maxStackSize) { this.maxStackSize = maxStackSize; - if (nbtLoad) return; onFilterInstanceChange(); dirtyNotifiable.markAsDirty(); } - public void setBlacklistFilter(boolean blacklistFilter, boolean nbtLoad) { + public void setBlacklistFilter(boolean blacklistFilter) { isBlacklistFilter = blacklistFilter; - if (nbtLoad) return; onFilterInstanceChange(); dirtyNotifiable.markAsDirty(); } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java index 0239e14f180..8101c607e03 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java @@ -83,13 +83,13 @@ public void deserializeNBT(NBTTagCompound nbt) { this.sourceFilter .setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("SourceFilterType"))); this.sourceFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("SourceFilter")); - this.sourceFilter.setBlacklistFilter(nbt.getBoolean("SourceBlacklist"), true); + this.sourceFilter.setBlacklistFilter(nbt.getBoolean("SourceBlacklist")); } if (nbt.hasKey("TargetFilter")) { this.targetFilter .setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("TargetFilterType"))); this.targetFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("TargetFilter")); - this.targetFilter.setBlacklistFilter(nbt.getBoolean("TargetBlacklist"), true); + this.targetFilter.setBlacklistFilter(nbt.getBoolean("TargetBlacklist")); } } From 1fa8dbdee4064e5017866c548d53d812b2c8ed45 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 21 Dec 2023 15:47:33 -0700 Subject: [PATCH 029/157] Fix NodeData not setting correctly for material pipes --- src/main/java/gregtech/api/pipenet/NetPath.java | 4 +++- src/main/java/gregtech/api/pipenet/NodeG.java | 4 +++- .../pipenet/block/material/TileEntityMaterialPipeBase.java | 1 + .../gregtech/common/pipelike/cable/net/WorldEnergyNet.java | 6 +++++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index 66cdf949871..c3b7ea31969 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -115,8 +115,10 @@ public NodeDataType getMinData() { } public boolean checkPredicate(Object o) { - for (NetEdge edge : this.edgeList) + for (NetEdge edge : this.edgeList) { + if (edge.getPredicate() == null) continue; if (!edge.getPredicate().test(o)) return false; + } return true; } diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 93c3b8d4a64..c728d0714ed 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -70,7 +70,7 @@ public NodeG(NodeDataType data, IPipeTile heldMTE, /** * Creates a dummy node for client-side information handling. - * Should never be required to reference its net or position. + * Should never be required to reference its net, data, or position. */ @SideOnly(Side.CLIENT) public NodeG(IPipeTile heldMTE) { @@ -256,6 +256,7 @@ public NBTTagCompound serializeNBT() { tag.setLong("Pos", this.nodePos.toLong()); tag.setInteger("Mark", this.mark); tag.setInteger("OpenConnections", this.activeConnections); + tag.setInteger("BlockedConnections", this.blockedConnections); tag.setBoolean("IsActive", this.isActive); return tag; } @@ -264,6 +265,7 @@ public NBTTagCompound serializeNBT() { public void deserializeNBT(NBTTagCompound nbt) { this.mark = nbt.getInteger("Mark"); this.activeConnections = nbt.getInteger("OpenConnections"); + this.blockedConnections = nbt.getInteger("BlockedConnections"); this.isActive = nbt.getBoolean("IsActive"); } diff --git a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java index 4bb4f3c7b31..fe535f791cc 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java @@ -71,6 +71,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { if (this.pipeMaterial == null) { this.pipeMaterial = registry.getFallbackMaterial(); } + this.getNode().setData(getPipeBlock().createProperties(this)); } private void writePipeMaterial(@NotNull PacketBuffer buf) { diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java index 4466153d388..16885d6cdfb 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -44,6 +44,8 @@ protected void writeNodeData(WireProperties nodeData, NBTTagCompound tagCompound tagCompound.setInteger("voltage", nodeData.getVoltage()); tagCompound.setInteger("amperage", nodeData.getAmperage()); tagCompound.setInteger("loss", nodeData.getLossPerBlock()); + tagCompound.setInteger("critical", nodeData.getSuperconductorCriticalTemperature()); + tagCompound.setBoolean("supercond", nodeData.isSuperconductor()); } @Override @@ -51,6 +53,8 @@ protected WireProperties readNodeData(NBTTagCompound tagCompound) { int voltage = tagCompound.getInteger("voltage"); int amperage = tagCompound.getInteger("amperage"); int lossPerBlock = tagCompound.getInteger("loss"); - return new WireProperties(voltage, amperage, lossPerBlock); + int critical = tagCompound.getInteger("critical"); + boolean supercond = tagCompound.getBoolean("supercond"); + return new WireProperties(voltage, amperage, lossPerBlock, supercond, critical); } } From 6eba12ffe582727881aa79854dabd6ac97704cdd Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 21 Dec 2023 16:25:50 -0700 Subject: [PATCH 030/157] Fix old net conversion setting incorrect edge weights --- .../material/TileEntityMaterialPipeBase.java | 1 + .../api/pipenet/tile/TileEntityPipeBase.java | 44 ++++++++++--------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java index fe535f791cc..a2aa9197546 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java @@ -72,6 +72,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { this.pipeMaterial = registry.getFallbackMaterial(); } this.getNode().setData(getPipeBlock().createProperties(this)); + if (!compound.hasKey("PipeNetVersion")) doOldNetSetup(); } private void writePipeMaterial(@NotNull PacketBuffer buf) { diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index f307ff1a610..35e3f49ecf7 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -411,7 +411,6 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { @Override public void readFromNBT(@NotNull NBTTagCompound compound) { - this.nbtLoad = true; if (this.tickingPipe != null) { this.tickingPipe.readFromNBT(compound); return; @@ -425,6 +424,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { } this.pipeType = getPipeTypeClass().getEnumConstants()[compound.getInteger("PipeType")]; + this.nbtLoad = true; if (compound.hasKey("Connections")) { this.getNode().setActiveConnections(compound.getInteger("Connections")); } else if (compound.hasKey("BlockedConnectionsMap")) { @@ -437,25 +437,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { this.getNode().setActiveConnections(connections); } this.getNode().setBlockedConnections(compound.getInteger("BlockedConnections")); - - if (!compound.hasKey("PipeNetVersion")) { - for (EnumFacing facing : EnumFacing.VALUES) { - WorldPipeNetG net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); - NodeG nodeOffset = net.getNode(this.getPipePos().offset(facing)); - if (nodeOffset == null) continue; - if (net.isDirected()) { - // offset node might've been read before us, so we have to cover for it. - if (nodeOffset.isConnected(facing.getOpposite())) { - net.addEdge(nodeOffset, this.getNode(), null); - net.predicateEdge(nodeOffset, this.getNode(), facing.getOpposite()); - } - } - if (this.isConnected(facing)) { - net.addEdge(this.getNode(), nodeOffset, null); - net.predicateEdge(this.getNode(), nodeOffset, facing); - } - } - } + this.nbtLoad = false; if (compound.hasKey("InsulationColor")) { this.paintingColor = compound.getInteger("InsulationColor"); @@ -470,7 +452,27 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { // one of the covers set the pipe to ticking, and we need to send over the rest of the covers this.coverableImplementation.transferDataTo(this.tickingPipe.coverableImplementation); } - this.nbtLoad = false; + + if (!compound.hasKey("PipeNetVersion") && !compound.hasKey("PipeMaterial")) doOldNetSetup(); + } + + protected void doOldNetSetup() { + for (EnumFacing facing : EnumFacing.VALUES) { + WorldPipeNetG net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); + NodeG nodeOffset = net.getNode(this.getPipePos().offset(facing)); + if (nodeOffset == null) continue; + if (net.isDirected()) { + // offset node might've been read before us, so we have to cover for it. + if (nodeOffset.isConnected(facing.getOpposite())) { + net.addEdge(nodeOffset, this.getNode(), null); + net.predicateEdge(nodeOffset, this.getNode(), facing.getOpposite()); + } + } + if (this.isConnected(facing)) { + net.addEdge(this.getNode(), nodeOffset, null); + net.predicateEdge(this.getNode(), nodeOffset, facing); + } + } } @Override From 62d3ac545157eb47bb75ea1f7c860a9bfa6fb88c Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 21 Dec 2023 16:59:28 -0700 Subject: [PATCH 031/157] Fix central monitor --- .../api/pipenet/tile/TileEntityPipeBase.java | 2 +- .../MetaTileEntityCentralMonitor.java | 95 +------------------ .../loaders/recipe/MiscRecipeLoader.java | 19 ++-- 3 files changed, 12 insertions(+), 104 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 35e3f49ecf7..54b140b211f 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -437,7 +437,6 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { this.getNode().setActiveConnections(connections); } this.getNode().setBlockedConnections(compound.getInteger("BlockedConnections")); - this.nbtLoad = false; if (compound.hasKey("InsulationColor")) { this.paintingColor = compound.getInteger("InsulationColor"); @@ -452,6 +451,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { // one of the covers set the pipe to ticking, and we need to send over the rest of the covers this.coverableImplementation.transferDataTo(this.tickingPipe.coverableImplementation); } + this.nbtLoad = false; if (!compound.hasKey("PipeNetVersion") && !compound.hasKey("PipeMaterial")) doOldNetSetup(); } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java index 919e9bcca85..cb99c16f75e 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java @@ -72,9 +72,6 @@ public class MetaTileEntityCentralMonitor extends MultiblockWithDisplayBase impl // run-time data public int width; private long lastUpdate; - // private WeakReference currentEnergyNet; - private List activeNodes; - private Set netCovers; private Set remoteCovers; @SideOnly(Side.CLIENT) public List parts; @@ -88,46 +85,6 @@ public MetaTileEntityCentralMonitor(ResourceLocation metaTileEntityId) { super(metaTileEntityId); } - // private EnergyNet getEnergyNet() { - // if (!this.getWorld().isRemote) { - // TileEntity te = getNeighbor(frontFacing.getOpposite()); - // if (te instanceof TileEntityCable) { - // TileEntityPipeBase tileEntityCable = (TileEntityCable) te; - // EnergyNet currentEnergyNet = this.currentEnergyNet.get(); - // if (currentEnergyNet != null && currentEnergyNet.isValid() && - // currentEnergyNet.containsNode(tileEntityCable.getPipePos())) { - // return currentEnergyNet; // return current net if it is still valid - // } - // WorldEnergyNet worldEnergyNet = (WorldEnergyNet) tileEntityCable.getPipeBlock() - // .getWorldPipeNet(tileEntityCable.getPipeWorld()); - // currentEnergyNet = worldEnergyNet.getNetFromPos(tileEntityCable.getPipePos()); - // if (currentEnergyNet != null) { - // this.currentEnergyNet = new WeakReference<>(currentEnergyNet); - // } - // return currentEnergyNet; - // } - // } - // return null; - // } - - private void updateNodes() { - // EnergyNet energyNet = getEnergyNet(); - // if (energyNet == null) { - // activeNodes.clear(); - // return; - // } - // if (energyNet.getLastUpdate() == lastUpdate) { - // return; - // } - // lastUpdate = energyNet.getLastUpdate(); - // activeNodes.clear(); - // energyNet.getAllNodes().forEach((pos, node) -> { - // if (node.isActive) { - // activeNodes.add(pos); - // } - // }); - } - public void addRemoteCover(FacingPos cover) { if (remoteCovers != null) { if (remoteCovers.add(cover)) { @@ -138,29 +95,7 @@ public void addRemoteCover(FacingPos cover) { private boolean checkCovers() { boolean dirty = false; - updateNodes(); - Set checkCovers = new HashSet<>(); World world = this.getWorld(); - for (BlockPos pos : activeNodes) { - TileEntity tileEntityCable = world.getTileEntity(pos); - if (!(tileEntityCable instanceof TileEntityPipeBase)) { - continue; - } - for (EnumFacing facing : EnumFacing.VALUES) { - if (((IPipeTile) tileEntityCable).isConnected(facing)) { - TileEntity tileEntity = world.getTileEntity(pos.offset(facing)); - if (tileEntity instanceof IGregTechTileEntity) { - MetaTileEntity metaTileEntity = ((IGregTechTileEntity) tileEntity).getMetaTileEntity(); - if (metaTileEntity != null) { - Cover cover = metaTileEntity.getCoverAtSide(facing.getOpposite()); - if (cover instanceof CoverDigitalInterface digitalInterface && digitalInterface.isProxy()) { - checkCovers.add(new FacingPos(metaTileEntity.getPos(), cover.getAttachedSide())); - } - } - } - } - } - } Iterator iterator = remoteCovers.iterator(); while (iterator.hasNext()) { FacingPos blockPosFace = iterator.next(); @@ -177,23 +112,10 @@ private boolean checkCovers() { iterator.remove(); dirty = true; } - if (checkCovers.size() != netCovers.size() || !netCovers.containsAll(checkCovers)) { - netCovers = checkCovers; - dirty = true; - } return dirty; } private void writeCovers(PacketBuffer buf) { - if (netCovers == null) { - buf.writeInt(0); - } else { - buf.writeInt(netCovers.size()); - for (FacingPos cover : netCovers) { - buf.writeBlockPos(cover.getPos()); - buf.writeByte(cover.getFacing().getIndex()); - } - } if (remoteCovers == null) { buf.writeInt(0); } else { @@ -206,13 +128,8 @@ private void writeCovers(PacketBuffer buf) { } private void readCovers(PacketBuffer buf) { - netCovers = new HashSet<>(); remoteCovers = new HashSet<>(); int size = buf.readInt(); - for (int i = 0; i < size; i++) { - netCovers.add(new FacingPos(buf.readBlockPos(), EnumFacing.byIndex(buf.readByte()))); - } - size = buf.readInt(); for (int i = 0; i < size; i++) { remoteCovers.add(new FacingPos(buf.readBlockPos(), EnumFacing.byIndex(buf.readByte()))); } @@ -381,14 +298,7 @@ protected void updateFormedValid() { } public Set getAllCovers() { - Set allCovers = new HashSet<>(); - if (netCovers != null) { - allCovers.addAll(netCovers); - } - if (remoteCovers != null) { - allCovers.addAll(remoteCovers); - } - return allCovers; + return remoteCovers; } @Override @@ -422,9 +332,6 @@ public String[] getDescription() { protected void formStructure(PatternMatchContext context) { super.formStructure(context); lastUpdate = 0; - // currentEnergyNet = new WeakReference<>(null); - activeNodes = new ArrayList<>(); - netCovers = new HashSet<>(); remoteCovers = new HashSet<>(); inputEnergy = new EnergyContainerList(this.getAbilities(MultiblockAbility.INPUT_ENERGY)); width = 0; diff --git a/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java index fb3b3173dc4..0944790e398 100644 --- a/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java @@ -273,16 +273,17 @@ public static void init() { .buildAndRegister(); ASSEMBLER_RECIPES.recipeBuilder().duration(100).EUt(VA[HV]) - .inputs(MetaItems.COVER_SCREEN.getStackForm()) - .input(plate, Aluminium) - .input(circuit, MarkerMaterials.Tier.MV) - .input(screw, StainlessSteel, 4) + .inputs(COVER_DIGITAL_INTERFACE.getStackForm()) + .inputs(WIRELESS.getStackForm()) .fluidInputs(Polyethylene.getFluid(L)) - .outputs(COVER_DIGITAL_INTERFACE.getStackForm()) + .outputs(COVER_DIGITAL_INTERFACE_WIRELESS.getStackForm()) .buildAndRegister(); ASSEMBLER_RECIPES.recipeBuilder().duration(100).EUt(VA[HV]) - .inputs(COVER_DIGITAL_INTERFACE.getStackForm()) + .inputs(MetaItems.COVER_SCREEN.getStackForm()) + .input(plate, Aluminium) + .input(circuit, MarkerMaterials.Tier.MV) + .input(screw, StainlessSteel, 2) .inputs(WIRELESS.getStackForm()) .fluidInputs(Polyethylene.getFluid(L)) .outputs(COVER_DIGITAL_INTERFACE_WIRELESS.getStackForm()) @@ -322,9 +323,9 @@ public static void init() { // terminal ASSEMBLER_RECIPES.recipeBuilder().duration(100).EUt(VA[MV]) - .input(circuit, MarkerMaterials.Tier.MV, 4) - .input(EMITTER_MV, 2) - .input(SENSOR_MV, 2) + .input(circuit, MarkerMaterials.Tier.LV, 4) + .input(EMITTER_MV) + .input(SENSOR_MV) .input(plate, StainlessSteel) .fluidInputs(Polyethylene.getFluid(L)) .outputs(WIRELESS.getStackForm()) From 08aebe6fe392124c50ab8113bf20142db7877a43 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 27 Dec 2023 11:19:22 -0700 Subject: [PATCH 032/157] I didn't spotless the central monitor ;-; --- .../electric/centralmonitor/MetaTileEntityCentralMonitor.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java index cb99c16f75e..c3d772a2469 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java @@ -19,8 +19,6 @@ import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.api.util.FacingPos; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; From 87e6c44dc2c649c08aa78b4fd54dcddd784ec2f1 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 27 Dec 2023 11:36:51 -0700 Subject: [PATCH 033/157] This is all your fault Tech --- .../api/pipenet/tile/TileEntityPipeBase.java | 14 -------------- .../pipelike/cable/tile/TileEntityCable.java | 6 ------ .../pipelike/itempipe/tile/TileEntityItemPipe.java | 6 ------ .../pipelike/laser/tile/TileEntityLaserPipe.java | 6 ------ .../optical/tile/TileEntityOpticalPipe.java | 6 ------ 5 files changed, 38 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 54b140b211f..3fca0e612e1 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -27,7 +27,6 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.Constants.NBT; -import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -588,19 +587,6 @@ public boolean shouldRefresh(@NotNull World world, @NotNull BlockPos pos, @NotNu return true; } - @MustBeInvokedByOverriders - @Override - public void onChunkUnload() { - super.onChunkUnload(); - if (!world.isRemote) { - WorldPipeNet worldPipeNet = getPipeBlock().getWorldPipeNet(getWorld()); - PipeNet net = worldPipeNet.getNetFromPos(pos); - if (net != null) { - net.onChunkUnload(); - } - } - } - public void doExplosion(float explosionPower) { getWorld().setBlockToAir(getPos()); if (!getWorld().isRemote) { diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java index c8ee74ca3a2..e8af710b987 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java @@ -259,12 +259,6 @@ public T getCapabilityInternal(Capability capability, @Nullable EnumFacin return super.getCapabilityInternal(capability, facing); } - @Override - public void onChunkUnload() { - super.onChunkUnload(); - this.handlers.clear(); - } - @Override public int getDefaultPaintingColor() { return 0x404040; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java index b19f71551ad..53eac210e24 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java @@ -119,10 +119,4 @@ public int getTransferredItems() { updateTransferredState(); return this.transferredItems; } - - @Override - public void onChunkUnload() { - super.onChunkUnload(); - this.handlers.clear(); - } } diff --git a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java b/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java index 2b9db7313fd..533ca3cef92 100644 --- a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java +++ b/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java @@ -191,12 +191,6 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { } } - @Override - public void onChunkUnload() { - super.onChunkUnload(); - this.handlers.clear(); - } - private static class DefaultLaserContainer implements ILaserContainer { @Override diff --git a/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java b/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java index 27de8ac31e8..3a730e2e81f 100644 --- a/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java +++ b/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java @@ -159,12 +159,6 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { } } - @Override - public void onChunkUnload() { - super.onChunkUnload(); - this.handlers.clear(); - } - private static class DefaultDataHandler implements IDataAccessHatch { @Override From a43231055814f34bfc0bb198b5e648d9f3bae96a Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 17 Jan 2024 12:54:15 -0700 Subject: [PATCH 034/157] Various refactors & prep for nonticking fluid pipes --- .../java/gregtech/api/pipenet/NetEdge.java | 6 +- .../java/gregtech/api/pipenet/NetPath.java | 16 +- src/main/java/gregtech/api/pipenet/NodeG.java | 13 ++ .../api/pipenet/WorldPipeFlowNetG.java | 23 +++ .../gregtech/api/pipenet/WorldPipeNetG.java | 145 +++++------------- .../api/pipenet/alg/MaximumFlowAlgorithm.java | 111 ++++++++++++++ .../api/pipenet/alg/NetAlgorithm.java | 32 ++++ .../pipenet/alg/ShortestPathsAlgorithm.java | 47 ++++++ .../api/pipenet/alg/SinglePathAlgorithm.java | 62 ++++++++ .../pipelike/cable/net/WorldEnergyNet.java | 2 +- .../fluidpipe/net/WorldFluidPipeNet.java | 10 +- .../itempipe/net/WorldItemPipeNet.java | 7 +- .../pipelike/laser/net/WorldLaserPipeNet.java | 7 +- .../optical/net/WorldOpticalPipeNet.java | 7 +- 14 files changed, 343 insertions(+), 145 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java create mode 100644 src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java create mode 100644 src/main/java/gregtech/api/pipenet/alg/NetAlgorithm.java create mode 100644 src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java create mode 100644 src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java diff --git a/src/main/java/gregtech/api/pipenet/NetEdge.java b/src/main/java/gregtech/api/pipenet/NetEdge.java index 86a7ddb18de..a87964fbcaa 100644 --- a/src/main/java/gregtech/api/pipenet/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/NetEdge.java @@ -10,7 +10,7 @@ import java.util.Map; -class NetEdge extends DefaultWeightedEdge implements INBTSerializable { +public final class NetEdge extends DefaultWeightedEdge implements INBTSerializable { private AbstractEdgePredicate predicate; private boolean invertedPredicate; @@ -29,12 +29,12 @@ public boolean isPredicateInverted() { } @Override - protected NodeG getSource() { + public NodeG getSource() { return (NodeG) super.getSource(); } @Override - protected NodeG getTarget() { + public NodeG getTarget() { return (NodeG) super.getTarget(); } diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index c3b7ea31969..edd9d9886eb 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -14,17 +14,17 @@ import java.util.Map; import java.util.stream.Collectors; -public final class NetPath & IPipeType, +public class NetPath & IPipeType, NodeDataType extends INodeData> { - private final List> nodeList; - private final List edgeList; + private List> nodeList; + private List edgeList; - private final NodeG sourceNode; + private NodeG sourceNode; - private final NodeG targetNode; + private NodeG targetNode; - private final double weight; + private double weight; private NodeDataType data = null; @@ -45,7 +45,7 @@ public NetPath(NodeG node) { /** * Generates a NetPath from an ordered list of nodes, edges, and a weight. * Used exclusively for single path generation. - * + * * @param nodes List of nodes. * @param edges List of edges. * @param weight Sum weight of the path. @@ -73,6 +73,8 @@ public NetPath(GraphPath, NetEdge> path) { this.edgeList = path.getEdgeList(); } + protected NetPath() {} + public List> getNodeList() { return nodeList; } diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index c728d0714ed..9f39720aab4 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -82,6 +82,19 @@ public NodeG(IPipeTile heldMTE) { this.blockedConnections = 0; } + /** + * Creates a dummy node for flow network calculations. + * Should never be required to reference its net, data, mte, or position. + */ + public NodeG() { + this.nodePos = null; + this.net = null; + this.data = null; + this.heldMTE = new WeakReference<>(null); + this.activeConnections = 0; + this.blockedConnections = 0; + } + /** * For construction during NBT reading only */ diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java new file mode 100644 index 00000000000..5dc939ab1ba --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java @@ -0,0 +1,23 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; +import gregtech.api.pipenet.block.IPipeType; + +public abstract class WorldPipeFlowNetG, + PipeType extends Enum & IPipeType> extends WorldPipeNetG { + + /** + * @param isDirected Determines whether this net needs directed graph handling. + * Used to respect filter directions in the item net and fluid net, for example. + * If the graph is not directed, pipes should not support blocked connections. + */ + public WorldPipeFlowNetG(String name, boolean isDirected) { + super(name, isDirected, false); + } + + @Override + protected void rebuildNetAlgorithm() { + this.netAlgorithm.setAlg(new MaximumFlowAlgorithm<>(pipeGraph, netAlgorithm)); + this.validAlgorithmInstance = true; + } +} diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 63e54ff7cd6..4afe9c7c980 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -1,6 +1,10 @@ package gregtech.api.pipenet; import gregtech.api.cover.Cover; +import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; +import gregtech.api.pipenet.alg.NetAlgorithm; +import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; +import gregtech.api.pipenet.alg.SinglePathAlgorithm; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -22,15 +26,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; -import org.jgrapht.GraphPath; -import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; import org.jgrapht.graph.SimpleDirectedWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph; import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -39,40 +38,39 @@ public abstract class WorldPipeNetG, PipeType extends Enum & IPipeType> extends WorldSavedData { + private final boolean isDirected; + private final boolean isSinglePath; + private WeakReference worldRef = new WeakReference<>(null); - private final Graph, NetEdge> pipeGraph; - private final Map> pipeMap = new Object2ObjectOpenHashMap<>(); + // TODO move graph & algorithm into NetGroup to reduce unnecessary algorithm cost + final Graph, NetEdge> pipeGraph; + final Map> pipeMap = new Object2ObjectOpenHashMap<>(); - private ShortestPathsAlgorithm shortestPaths; + final NetAlgorithm.NetAlgorithmWrapper netAlgorithm; - private boolean validAlgorithmInstance = false; + boolean validAlgorithmInstance = false; - public WorldPipeNetG(String name) { + /** + * @param isDirected Determines whether this net needs directed graph handling. + * Used to respect filter directions in the item net and fluid net, for example. + * If the graph is not directed, pipes should not support blocked connections. + * @param isSinglePath Determines whether this net allows only one source and one destination per group. + * Allows for optimizations in path lookup and cache invalidation. + */ + public WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath) { super(name); if (isDirected()) this.pipeGraph = new SimpleDirectedWeightedGraph<>(NetEdge.class); else this.pipeGraph = new SimpleWeightedGraph<>(NetEdge.class); + this.netAlgorithm = new NetAlgorithm.NetAlgorithmWrapper<>(); + this.isDirected = isDirected; + this.isSinglePath = isSinglePath; } - - /** - * Override to change whether this net needs directed graph handling. - * Used to respect filter directions in the item net and fluid net, for example. - * If the graph is not directed, pipes should not support blocked connections. - * - * @return True if the graph should be directed. - */ - public boolean isDirected() { - return false; + public final boolean isDirected() { + return isDirected; } - - /** - * Override to change whether this net allows only one source and one destination per group. - * Allows for optimizations in path lookup and cache invalidation. - * - * @return True if the graph should be single-pathed. - */ - protected boolean isSinglePath() { - return false; + public final boolean isSinglePath() { + return isSinglePath; } public World getWorld() { @@ -94,7 +92,7 @@ public static String getDataID(final String baseID, final World world) { } protected void onWorldSet() { - this.rebuildShortestPaths(); + this.rebuildNetAlgorithm(); } /** @@ -123,15 +121,14 @@ public List> getPaths(@Nullable NodeG> cache = node.getPathCache(); if (cache != null) { return verifyList(cache, node); } - List> list = isSinglePath() ? this.singlePathList(node) : - this.shortestPaths.getPathsList(node); + List> list = this.netAlgorithm.getPathsList(node); return verifyList(node.setPathCache(list), node); } @@ -419,9 +416,12 @@ public boolean markNodeAsActive(BlockPos nodePos, boolean isActive) { return false; } - protected void rebuildShortestPaths() { - // No need to calculate the ShortestPathsAlgorithm if we are single-pathed. - if (!this.isSinglePath()) this.shortestPaths = new ShortestPathsAlgorithm<>(pipeGraph); + protected void rebuildNetAlgorithm() { + if (!this.isSinglePath()) { + this.netAlgorithm.setAlg(new ShortestPathsAlgorithm<>(pipeGraph)); + } else { + this.netAlgorithm.setAlg(new SinglePathAlgorithm<>(pipeGraph, isDirected())); + } this.validAlgorithmInstance = true; } @@ -492,77 +492,4 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { */ protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); - // CHManyToManyShortestPaths is a very good algorithm because our graph will be extremely sparse. - protected static final class ShortestPathsAlgorithm & IPipeType, - NDT extends INodeData> - extends CHManyToManyShortestPaths, NetEdge> { - - public ShortestPathsAlgorithm(Graph, NetEdge> graph) { - super(graph); - } - - public List> getPathsList(NodeG source) { - if (!graph.containsVertex(source)) { - throw new IllegalArgumentException("Graph must contain the source vertex"); - } - List> paths = new ObjectArrayList<>(); - paths.add(new NetPath<>(source)); - // if the source has no group, it has no paths other than the path to itself. - if (source.getGroup() == null) return paths; - ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths( - Collections.singleton(source), source.getGroup().getNodes()); - for (NodeG v : source.getGroup().getNodes()) { - if (v == source) continue; - GraphPath, NetEdge> path = manyToManyPaths.getPath(source, v); - if (path != null) { - paths.add(new NetPath<>(path)); - } - } - paths.sort(Comparator.comparingDouble(NetPath::getWeight)); - return paths; - } - } - - /** - * Special path lookup for single-path graphs. - * Allows us to skip calculating the ShortestPathsAlgorithm every time the graph updates. - * - * @param source Source node for the path. - * @return A list containing one or fewer paths. - */ - private List> singlePathList(NodeG source) { - if (!this.pipeGraph.containsVertex(source)) { - throw new IllegalArgumentException("Graph must contain the source vertex"); - } - List> paths = new ObjectArrayList<>(); - List edges = new ObjectArrayList<>(); - List> nodes = new ObjectArrayList<>(); - nodes.add(source); - NodeG lastNode = null; - NodeG node = source; - NetEdge edge; - double sumWeight = source.getData().getWeightFactor(); - boolean valid = true; - while (valid) { - Iterator i = this.pipeGraph.outgoingEdgesOf(node).iterator(); - if (!i.hasNext()) break; // we've reached the end, exit the loop while still valid - edge = i.next(); - // if we are directed, we know that the target is the target. - // if we aren't directed, we need to see if the edge's source was secretly the target - boolean reversedEdge = !this.isDirected() && edge.getSource() == lastNode; - if (edge.getTarget() == lastNode || reversedEdge) { - if (i.hasNext()) edge = i.next(); - else break; // we've reached the end, exit the loop while still valid - } else if (i.hasNext()) i.next(); - if (i.hasNext()) valid = false; // third edge detected - that's an invalid group - lastNode = node; - node = (NodeG) (reversedEdge ? edge.getSource() : edge.getTarget()); - edges.add(edge); - nodes.add(node); - sumWeight += node.getData().getWeightFactor(); - } - if (!valid) return paths; - paths.add(new NetPath<>(nodes, edges, sumWeight)); - return paths; - } } diff --git a/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java new file mode 100644 index 00000000000..1b9f7826dbc --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java @@ -0,0 +1,111 @@ +package gregtech.api.pipenet.alg; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetEdge; +import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.block.IPipeType; + +import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jgrapht.Graph; +import org.jgrapht.GraphPath; +import org.jgrapht.alg.flow.PushRelabelMFImpl; + +import java.util.List; +import java.util.Map; + +public final class MaximumFlowAlgorithm & IPipeType, NDT extends INodeData> + extends PushRelabelMFImpl, NetEdge> implements NetAlgorithm { + + private final NetAlgorithmWrapper wrapper; + + private NodeG superSource = new NodeG<>(); + private Map, Double> activeSources = new Object2DoubleOpenHashMap<>(); + + private NodeG superSink = new NodeG<>(); + private Map, Double> activeSinks = new Object2DoubleOpenHashMap<>(); + + + public MaximumFlowAlgorithm(Graph, NetEdge> network, NetAlgorithmWrapper wrapper) { + super(network); + this.wrapper = wrapper; + } + + @Override + public List> getPathsList(NodeG source) { + if (!network.containsVertex(source)) { + throw new IllegalArgumentException("Graph must contain the source vertex"); + } + List> paths = new ObjectArrayList<>(); + paths.add(new NetPath<>(source)); + // if the source has no group, it has no paths other than the path to itself. + if (source.getGroup() == null) return paths; + + for (NodeG v : source.getGroup().getNodes()) { + if (v == source) continue; + paths.add(new FlowPath<>(wrapper)); + } + return paths; + } + + /** + * Prime the edges to the super nodes to prepare for calculations. + */ + private void activate() { + for (Map.Entry, Double> source : activeSources.entrySet()) { + network.setEdgeWeight(superSource, source.getKey(), source.getValue()); + } + for (Map.Entry, Double> sink : activeSinks.entrySet()) { + network.setEdgeWeight(superSink, sink.getKey(), sink.getValue()); + } + } + + /** + * Zero out the edges to the super nodes to prevent other calculations from using them. + */ + private void deactivate() { + for (Map.Entry, Double> source : activeSources.entrySet()) { + network.setEdgeWeight(superSource, source.getKey(), 0); + } + for (Map.Entry, Double> sink : activeSinks.entrySet()) { + network.setEdgeWeight(superSink, sink.getKey(), 0); + } + } + + public void setSource(NodeG source, double amount) { + if (amount <= 0) { + activeSources.remove(source); + return; + } + activeSources.put(source, amount); + } + + public void setSink(NodeG sink, double amount) { + if (amount <= 0) { + activeSinks.remove(sink); + return; + } + activeSinks.put(sink, amount); + } + + public static final class FlowPath & IPipeType, + NodeDataType extends INodeData> extends NetPath { + + private final NetAlgorithmWrapper alg; + + public FlowPath(NetAlgorithmWrapper alg) { + super(); + this.alg = alg; + } + + // this roundabout method is necessary since a new MaximumFlowAlgorithm is created every time the graph changes. + private MaximumFlowAlgorithm getAlg() { + if (alg.getAlg() instanceof MaximumFlowAlgorithm algorithm) { + return algorithm; + } else { + throw new IllegalStateException("A WorldPipeNetG was changed away from a flow graph during runtime!"); + } + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/alg/NetAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/NetAlgorithm.java new file mode 100644 index 00000000000..a471311db38 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/alg/NetAlgorithm.java @@ -0,0 +1,32 @@ +package gregtech.api.pipenet.alg; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.block.IPipeType; + +import java.util.List; + +public interface NetAlgorithm & IPipeType, NDT extends INodeData> { + + List> getPathsList(NodeG source); + + class NetAlgorithmWrapper & IPipeType, + NodeDataType extends INodeData> { + + NetAlgorithm alg; + + public void setAlg(NetAlgorithm alg) { + this.alg = alg; + } + + public NetAlgorithm getAlg() { + return alg; + } + + public List> getPathsList(NodeG source) { + if (alg == null) return null; + return alg.getPathsList(source); + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java new file mode 100644 index 00000000000..00ada61dbd5 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java @@ -0,0 +1,47 @@ +package gregtech.api.pipenet.alg; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetEdge; +import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.block.IPipeType; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jgrapht.Graph; +import org.jgrapht.GraphPath; +import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public final class ShortestPathsAlgorithm & IPipeType, + NDT extends INodeData> extends CHManyToManyShortestPaths, NetEdge> + implements NetAlgorithm { + + public ShortestPathsAlgorithm(Graph, NetEdge> graph) { + super(graph); + } + + @Override + public List> getPathsList(NodeG source) { + if (!graph.containsVertex(source)) { + throw new IllegalArgumentException("Graph must contain the source vertex"); + } + List> paths = new ObjectArrayList<>(); + paths.add(new NetPath<>(source)); + // if the source has no group, it has no paths other than the path to itself. + if (source.getGroup() == null) return paths; + ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths( + Collections.singleton(source), source.getGroup().getNodes()); + for (NodeG v : source.getGroup().getNodes()) { + if (v == source) continue; + GraphPath, NetEdge> path = manyToManyPaths.getPath(source, v); + if (path != null) { + paths.add(new NetPath<>(path)); + } + } + paths.sort(Comparator.comparingDouble(NetPath::getWeight)); + return paths; + } +} diff --git a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java new file mode 100644 index 00000000000..649eaf73577 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java @@ -0,0 +1,62 @@ +package gregtech.api.pipenet.alg; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetEdge; +import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.block.IPipeType; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jgrapht.Graph; + +import java.util.Iterator; +import java.util.List; + +public final class SinglePathAlgorithm & IPipeType, NDT extends INodeData> + implements NetAlgorithm { + + private final Graph, NetEdge> graph; + private final boolean isDirected; + + public SinglePathAlgorithm(Graph, NetEdge> graph, boolean isDirected) { + this.graph = graph; + this.isDirected = isDirected; + } + + @Override + public List> getPathsList(NodeG source) { + if (!this.graph.containsVertex(source)) { + throw new IllegalArgumentException("Graph must contain the source vertex"); + } + List> paths = new ObjectArrayList<>(); + List edges = new ObjectArrayList<>(); + List> nodes = new ObjectArrayList<>(); + nodes.add(source); + NodeG lastNode = null; + NodeG node = source; + NetEdge edge; + double sumWeight = source.getData().getWeightFactor(); + boolean valid = true; + while (valid) { + Iterator i = this.graph.outgoingEdgesOf(node).iterator(); + if (!i.hasNext()) break; // we've reached the end, exit the loop while still valid + edge = i.next(); + // if we are directed, we know that the target is the target. + // if we aren't directed, we need to see if the edge's source was secretly the target + boolean reversedEdge = !isDirected && edge.getSource() == lastNode; + if (edge.getTarget() == lastNode || reversedEdge) { + if (i.hasNext()) edge = i.next(); + else break; // we've reached the end, exit the loop while still valid + } else if (i.hasNext()) i.next(); + if (i.hasNext()) valid = false; // third edge detected - that's an invalid group + lastNode = node; + node = (NodeG) (reversedEdge ? edge.getSource() : edge.getTarget()); + edges.add(edge); + nodes.add(node); + sumWeight += node.getData().getWeightFactor(); + } + if (!valid) return paths; + paths.add(new NetPath<>(nodes, edges, sumWeight)); + return paths; + } +} diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java index 16885d6cdfb..5c24c460441 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -26,7 +26,7 @@ public static WorldEnergyNet getWorldEnergyNet(World world) { } public WorldEnergyNet(String name) { - super(name); + super(name, false, false); } @Override diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index 98dd52dc330..7c12558fe06 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -1,5 +1,6 @@ package gregtech.common.pipelike.fluidpipe.net; +import gregtech.api.pipenet.WorldPipeFlowNetG; import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; @@ -9,7 +10,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; -public class WorldFluidPipeNet extends WorldPipeNetG { +public class WorldFluidPipeNet extends WorldPipeFlowNetG { private static final String DATA_ID_BASE = "gregtech.fluid_pipe_net"; @@ -25,12 +26,7 @@ public static WorldFluidPipeNet getWorldPipeNet(World world) { } public WorldFluidPipeNet(String name) { - super(name); - } - - @Override - public boolean isDirected() { - return true; + super(name, true); } @Override diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index d8384ba5394..39668db849b 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -30,12 +30,7 @@ public static WorldItemPipeNet getWorldPipeNet(World world) { } public WorldItemPipeNet(String name) { - super(name); - } - - @Override - public boolean isDirected() { - return true; + super(name, true, false); } @Override diff --git a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java b/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java index 75726142c9f..5299262521e 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java @@ -16,12 +16,7 @@ public class WorldLaserPipeNet extends WorldPipeNetG Date: Wed, 17 Jan 2024 20:41:28 -0700 Subject: [PATCH 035/157] Fluid channels mostly done --- .../gregtech/api/pipenet/FlowChannel.java | 63 ++++++++++ .../java/gregtech/api/pipenet/INodeData.java | 4 + .../java/gregtech/api/pipenet/NetGroup.java | 24 +++- src/main/java/gregtech/api/pipenet/NodeG.java | 41 +++++++ .../api/pipenet/WorldPipeFlowNetG.java | 74 +++++++++++- .../gregtech/api/pipenet/WorldPipeNetG.java | 2 +- .../api/pipenet/alg/MaximumFlowAlgorithm.java | 27 +---- .../pipelike/fluidpipe/net/FluidChannel.java | 110 ++++++++++++++++++ 8 files changed, 313 insertions(+), 32 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/FlowChannel.java create mode 100644 src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java diff --git a/src/main/java/gregtech/api/pipenet/FlowChannel.java b/src/main/java/gregtech/api/pipenet/FlowChannel.java new file mode 100644 index 00000000000..10c3d7ebe98 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/FlowChannel.java @@ -0,0 +1,63 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.block.IPipeType; + +import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.common.pipelike.fluidpipe.FluidPipeType; + +import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; +import org.jgrapht.Graph; + +import java.util.Map; +import java.util.function.Function; + +public abstract class FlowChannel & IPipeType, NDT extends INodeData> { + + protected final Graph, NetEdge> network; + + protected NodeG superSource = new NodeG<>(); + protected Map, Double> activeSources = new Object2DoubleOpenHashMap<>(); + + protected NodeG superSink = new NodeG<>(); + protected Map, Double> activeSinks = new Object2DoubleOpenHashMap<>(); + + public FlowChannel(Graph, NetEdge> network) { + this.network = network; + } + + public abstract void evaluate(); + + /** + * Prime the edges to the super nodes to prepare for calculations. + */ + protected void activate() { + for (Map.Entry, Double> source : activeSources.entrySet()) { + network.setEdgeWeight(superSource, source.getKey(), source.getValue()); + } + for (Map.Entry, Double> sink : activeSinks.entrySet()) { + network.setEdgeWeight(sink.getKey(), superSink, sink.getValue()); + } + } + + /** + * Zero out the edges to the super nodes to prevent other calculations from using them. + */ + protected void deactivate() { + for (Map.Entry, Double> source : activeSources.entrySet()) { + network.setEdgeWeight(superSource, source.getKey(), 0); + } + for (Map.Entry, Double> sink : activeSinks.entrySet()) { + network.setEdgeWeight(sink.getKey(), superSink, 0); + } + } + + public void adjustSource(NodeG source, Function adjuster) { + activeSources.compute(source, (k, v) -> (v == null) ? adjuster.apply(0d) : adjuster.apply(v)); + if (activeSources.get(source) <= 0) activeSources.remove(source); + } + + public void adjustSink(NodeG sink, Function adjuster) { + activeSinks.compute(sink, (k, v) -> (v == null) ? adjuster.apply(0d) : adjuster.apply(v)); + if (activeSinks.get(sink) <= 0) activeSinks.remove(sink); + } +} diff --git a/src/main/java/gregtech/api/pipenet/INodeData.java b/src/main/java/gregtech/api/pipenet/INodeData.java index bee5e1b05bc..ebff1d85d79 100644 --- a/src/main/java/gregtech/api/pipenet/INodeData.java +++ b/src/main/java/gregtech/api/pipenet/INodeData.java @@ -4,6 +4,10 @@ public interface INodeData> { + default int getChannelMax() { + return 1; + } + default double getWeightFactor() { return 1; } diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 04e7a15cd3f..0717efb0fd6 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -2,10 +2,13 @@ import gregtech.api.pipenet.block.IPipeType; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.INBTSerializable; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; import org.jgrapht.traverse.BreadthFirstIterator; @@ -22,6 +25,7 @@ public class NetGroup & IPipeType, private final Graph, NetEdge> graph; private final Set> nodes; + private final Map> channels = new Object2ObjectOpenHashMap<>(); private final AbstractGroupData data; @@ -74,7 +78,7 @@ public static boolean mergeEdge(NodeG source, NodeG target) { NetGroup targetGroup = target.getGroup(); if (sourceGroup == targetGroup) { if (sourceGroup == null) return true; - sourceGroup.clearPathCaches(); + sourceGroup.clearCaches(); return false; } if (sourceGroup != null) { @@ -92,7 +96,7 @@ protected void mergeNode(NodeG node) { this.addNodes(group.getNodes()); group.clear(); } else addNode(cast); - this.clearPathCaches(); + this.clearCaches(); } /** @@ -103,7 +107,7 @@ protected void mergeNode(NodeG node) { */ public boolean splitNode(NodeG source) { if (graph.containsVertex(source)) { - this.clearPathCaches(); + this.clearCaches(); List> targets = graph.outgoingEdgesOf(source).stream().map(a -> { // handling so undirected graphs don't throw an error if (net.isDirected()) return a.getTarget(); @@ -149,7 +153,7 @@ public boolean splitNode(NodeG source) { */ public boolean splitEdge(NodeG source, NodeG target) { if (graph.removeEdge(source, target) != null) { - this.clearPathCaches(); + this.clearCaches(); Set> targetGroup = new ObjectOpenHashSet<>(); BreadthFirstIterator, NetEdge> i = new BreadthFirstIterator<>(graph, target); NodeG temp; @@ -179,14 +183,24 @@ public Set> getNodes() { return nodes; } - protected void clearPathCaches() { + protected void clearCaches() { this.nodes.forEach(NodeG::clearPathCache); + this.channels.clear(); } public AbstractGroupData getData() { return this.data; } + protected void setChannel(Object key, FlowChannel channel) { + this.channels.put(key, channel); + } + + @Nullable + protected FlowChannel getChannel(Object key) { + return this.channels.get(key); + } + @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 9f39720aab4..e45be65af77 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -3,6 +3,11 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; @@ -18,6 +23,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; public class NodeG & IPipeType, NodeDataType extends INodeData> @@ -54,6 +60,11 @@ public class NodeG & IPipeType, private NetGroup group = null; + /** + * Stores the channels that this node is involved with. Used exclusively for flow graphs. + */ + private final Set> channels = new ObjectOpenHashSet<>(); + private List> pathCache = null; public NodeG(NodeDataType data, IPipeTile heldMTE, @@ -263,6 +274,36 @@ public void clearPathCache() { this.pathCache = null; } + /** + * @param channel The channel to test. Can be null to check only if there is space for another channel. + * @return {@code true} if the provided channel can be supported by the node. + */ + public boolean canSupportChannel(FlowChannel channel) { + return this.channels.size() < this.data.getChannelMax() || this.channels.contains(channel); + } + + /** + * Adds a channel to a node's collection. Cannot go over the node's chnnael limit. + * @param channel the channel to add. + * @return {@code true} if the channel was added. + */ + public boolean addChannel(FlowChannel channel) { + if (this.channels.size() < this.data.getChannelMax()) { + this.channels.add(channel); + return true; + } + return false; + } + + /** + * Removes a channel from a node's collection. + * @param channel the channel to remove. + * @return {@code true} if the channel was in the node's collection. + */ + public boolean removeChannel(FlowChannel channel) { + return this.channels.remove(channel); + } + @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java index 5dc939ab1ba..13e086e25e8 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java @@ -3,6 +3,11 @@ import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; import gregtech.api.pipenet.block.IPipeType; +import net.minecraftforge.fluids.Fluid; + +import org.jgrapht.graph.SimpleDirectedWeightedGraph; +import org.jgrapht.graph.SimpleWeightedGraph; + public abstract class WorldPipeFlowNetG, PipeType extends Enum & IPipeType> extends WorldPipeNetG { @@ -13,11 +18,78 @@ public abstract class WorldPipeFlowNetG(); + else this.pipeGraph = new FlowUndirected<>(); } @Override protected void rebuildNetAlgorithm() { - this.netAlgorithm.setAlg(new MaximumFlowAlgorithm<>(pipeGraph, netAlgorithm)); + this.netAlgorithm.setAlg(new MaximumFlowAlgorithm<>(pipeGraph)); this.validAlgorithmInstance = true; } + + public interface IFlowGraph, PT extends Enum & IPipeType> { + + void setTestObject(Object object); + + void setQueryingChannel(FlowChannel channel); + } + + protected static class FlowUndirected, PT extends Enum & IPipeType> + extends SimpleWeightedGraph, NetEdge> implements IFlowGraph { + + Object testObject; + FlowChannel queryingChannel; + + public FlowUndirected() { + super(NetEdge.class); + } + + // this overcomplicated workaround is due to not enough protected/public visibilities. + @Override + public double getEdgeWeight(NetEdge netEdge) { + return netEdge.getPredicate().test(testObject) ? super.getEdgeWeight(netEdge) : 0; + } + + @Override + public void setTestObject(Object object) { + this.testObject = object; + } + + @Override + public void setQueryingChannel(FlowChannel channel) { + this.queryingChannel = channel; + } + } + + protected static class FlowDirected, PT extends Enum & IPipeType> + extends SimpleDirectedWeightedGraph, NetEdge> implements IFlowGraph { + + Object testObject; + FlowChannel queryingChannel; + + public FlowDirected() { + super(NetEdge.class); + } + + // this overcomplicated workaround is due to not enough protected/public visibilities. + @Override + public double getEdgeWeight(NetEdge netEdge) { + // Both source and target must support the channel, and the netEdge predicate must allow our object. + return ((NodeG) netEdge.getSource()).canSupportChannel(queryingChannel) && + ((NodeG) netEdge.getTarget()).canSupportChannel(queryingChannel) && + netEdge.getPredicate().test(testObject) ? super.getEdgeWeight(netEdge) : 0; + } + + @Override + public void setTestObject(Object object) { + this.testObject = object; + } + + @Override + public void setQueryingChannel(FlowChannel channel) { + this.queryingChannel = channel; + } + } } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 4afe9c7c980..4c8dc267681 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -43,7 +43,7 @@ public abstract class WorldPipeNetG private WeakReference worldRef = new WeakReference<>(null); // TODO move graph & algorithm into NetGroup to reduce unnecessary algorithm cost - final Graph, NetEdge> pipeGraph; + Graph, NetEdge> pipeGraph; final Map> pipeMap = new Object2ObjectOpenHashMap<>(); final NetAlgorithm.NetAlgorithmWrapper netAlgorithm; diff --git a/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java index 1b9f7826dbc..4d3af09c585 100644 --- a/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java @@ -18,8 +18,6 @@ public final class MaximumFlowAlgorithm & IPipeType, NDT extends INodeData> extends PushRelabelMFImpl, NetEdge> implements NetAlgorithm { - private final NetAlgorithmWrapper wrapper; - private NodeG superSource = new NodeG<>(); private Map, Double> activeSources = new Object2DoubleOpenHashMap<>(); @@ -27,9 +25,8 @@ public final class MaximumFlowAlgorithm & IPipeType, ND private Map, Double> activeSinks = new Object2DoubleOpenHashMap<>(); - public MaximumFlowAlgorithm(Graph, NetEdge> network, NetAlgorithmWrapper wrapper) { + public MaximumFlowAlgorithm(Graph, NetEdge> network) { super(network); - this.wrapper = wrapper; } @Override @@ -44,7 +41,7 @@ public List> getPathsList(NodeG source) { for (NodeG v : source.getGroup().getNodes()) { if (v == source) continue; - paths.add(new FlowPath<>(wrapper)); +// paths.add(new FlowPath<>(wrapper)); } return paths; } @@ -88,24 +85,4 @@ public void setSink(NodeG sink, double amount) { } activeSinks.put(sink, amount); } - - public static final class FlowPath & IPipeType, - NodeDataType extends INodeData> extends NetPath { - - private final NetAlgorithmWrapper alg; - - public FlowPath(NetAlgorithmWrapper alg) { - super(); - this.alg = alg; - } - - // this roundabout method is necessary since a new MaximumFlowAlgorithm is created every time the graph changes. - private MaximumFlowAlgorithm getAlg() { - if (alg.getAlg() instanceof MaximumFlowAlgorithm algorithm) { - return algorithm; - } else { - throw new IllegalStateException("A WorldPipeNetG was changed away from a flow graph during runtime!"); - } - } - } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java new file mode 100644 index 00000000000..fc8979a8ac3 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -0,0 +1,110 @@ +package gregtech.common.pipelike.fluidpipe.net; + +import gregtech.api.pipenet.FlowChannel; +import gregtech.api.pipenet.NetEdge; +import gregtech.api.pipenet.NodeG; + +import gregtech.api.pipenet.WorldPipeFlowNetG; +import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; + +import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.common.pipelike.fluidpipe.FluidPipeType; + +import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipeTickable; + +import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; + +import org.jgrapht.Graph; + +import java.util.Map; +import java.util.Set; +import java.util.function.Function; + +public class FluidChannel extends FlowChannel { + + private FluidStack fluid; + + private MaximumFlowAlgorithm alg = null; + + private Set> oldNodes = null; + + public FluidChannel(Graph, NetEdge> network, Fluid fluid) { + super(network); + this.fluid = new FluidStack(fluid, 1); + } + + public void setFluid(Fluid fluid) { + this.fluid = new FluidStack(fluid, 1); + } + + @Override + public void evaluate() { + activate(); + + if (network instanceof WorldPipeFlowNetG.IFlowGraph graph) { + graph.setTestObject(fluid.getFluid()); + } + else throw new IllegalStateException("Attempted to do flow calculations on a non-flow graph!"); + + if (alg == null) alg = new MaximumFlowAlgorithm<>(network); + + double max = alg.calculateMaximumFlow(superSource, superSink); + Map flows = alg.getFlowMap(); + Map, Double> inMap = new Object2DoubleOpenHashMap<>(); + Map, Double> outMap = new Object2DoubleOpenHashMap<>(); + Set> nodes = new ObjectOpenHashSet<>(); + + for (Map.Entry flow : flows.entrySet()) { + if (flow.getValue() == 0) continue; + inMap.merge(flow.getKey().getTarget(), flow.getValue(), Double::sum); + outMap.merge(flow.getKey().getSource(), flow.getValue(), Double::sum); + nodes.add((NodeG) flow.getKey().getSource()); + nodes.add((NodeG) flow.getKey().getTarget()); + } + + for (NodeG node : nodes) { + // dataless nodes are only the superSource and superSink + if (node.getData() == null) continue; + if (!node.addChannel(this)) + throw new IllegalStateException("Node rejected channel despite approving it earlier!"); + if (!node.getData().test(fluid)) { + // destroyethify + if (node.getHeldMTE() instanceof TileEntityFluidPipeTickable f) { + f.checkAndDestroy(fluid); + } + } + } + + oldNodes.removeAll(nodes); + for (NodeG oldNode : oldNodes) { + oldNode.removeChannel(this); + } + oldNodes = nodes; + for (Map.Entry, Double> sink : activeSinks.entrySet()) { + if (sink.getKey().getHeldMTE() instanceof TileEntityFluidPipeTickable f) { + double flow = outMap.getOrDefault(sink.getKey(), 0d); + // insert flow to the node's neighbors + } + } + + deactivate(); + } + + @Override + public void adjustSource(NodeG source, Function adjuster) { + this.alg = null; + super.adjustSource(source, adjuster); + } + + @Override + public void adjustSink(NodeG sink, Function adjuster) { + this.alg = null; + super.adjustSink(sink, adjuster); + } + +} From 6d8574ab3bd87d005552c8feedb7d4330f8910f7 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 19 Jan 2024 13:20:47 -0700 Subject: [PATCH 036/157] Fluid channels done question mark --- .../gregtech/api/pipenet/FlowChannel.java | 73 +++++++++++---- .../java/gregtech/api/pipenet/NetGroup.java | 8 +- src/main/java/gregtech/api/pipenet/NodeG.java | 1 + .../pipelike/fluidpipe/net/FluidChannel.java | 91 ++++++++++++++++--- .../pipelike/fluidpipe/net/PipeTankList.java | 4 +- .../tile/TileEntityFluidPipeTickable.java | 62 +++++++------ .../pipelike/itempipe/net/ItemNetHandler.java | 2 +- 7 files changed, 173 insertions(+), 68 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/FlowChannel.java b/src/main/java/gregtech/api/pipenet/FlowChannel.java index 10c3d7ebe98..8459a886d7d 100644 --- a/src/main/java/gregtech/api/pipenet/FlowChannel.java +++ b/src/main/java/gregtech/api/pipenet/FlowChannel.java @@ -2,24 +2,27 @@ import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.unification.material.properties.FluidPipeProperties; -import gregtech.common.pipelike.fluidpipe.FluidPipeType; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.util.EnumFacing; -import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; import org.jgrapht.Graph; import java.util.Map; -import java.util.function.Function; +import java.util.Set; public abstract class FlowChannel & IPipeType, NDT extends INodeData> { protected final Graph, NetEdge> network; protected NodeG superSource = new NodeG<>(); - protected Map, Double> activeSources = new Object2DoubleOpenHashMap<>(); + protected Set> activeSources = new ObjectOpenHashSet<>(); protected NodeG superSink = new NodeG<>(); - protected Map, Double> activeSinks = new Object2DoubleOpenHashMap<>(); + protected Set> activeSinks = new ObjectOpenHashSet<>(); + + protected Map, Byte> receiveSidesMap = new Object2ObjectOpenHashMap<>(); public FlowChannel(Graph, NetEdge> network) { this.network = network; @@ -31,11 +34,15 @@ public FlowChannel(Graph, NetEdge> network) { * Prime the edges to the super nodes to prepare for calculations. */ protected void activate() { - for (Map.Entry, Double> source : activeSources.entrySet()) { - network.setEdgeWeight(superSource, source.getKey(), source.getValue()); + for (NodeG source : activeSources) { + double v = getSourceValue(source); + network.setEdgeWeight(superSource, source, v); + if (v == 0) removeSource(source); } - for (Map.Entry, Double> sink : activeSinks.entrySet()) { - network.setEdgeWeight(sink.getKey(), superSink, sink.getValue()); + for (NodeG sink : activeSinks) { + double v = getSinkValue(sink); + network.setEdgeWeight(sink, superSink, v); + if (v == 0) removeSink(sink); } } @@ -43,21 +50,47 @@ protected void activate() { * Zero out the edges to the super nodes to prevent other calculations from using them. */ protected void deactivate() { - for (Map.Entry, Double> source : activeSources.entrySet()) { - network.setEdgeWeight(superSource, source.getKey(), 0); + for (NodeG source : activeSources) { + network.setEdgeWeight(superSource, source, 0); } - for (Map.Entry, Double> sink : activeSinks.entrySet()) { - network.setEdgeWeight(sink.getKey(), superSink, 0); + for (NodeG sink : activeSinks) { + network.setEdgeWeight(sink, superSink, 0); } } - public void adjustSource(NodeG source, Function adjuster) { - activeSources.compute(source, (k, v) -> (v == null) ? adjuster.apply(0d) : adjuster.apply(v)); - if (activeSources.get(source) <= 0) activeSources.remove(source); + protected abstract double getSourceValue(NodeG source); + protected abstract double getSinkValue(NodeG sink); + + public void addSource(NodeG source) { + this.activeSources.add(source); + this.network.addEdge(this.superSource, source); + } + + public void addReceiveSide(NodeG node, EnumFacing side) { + this.receiveSidesMap.compute(node, (k, v) -> { + if (v == null) { + byte a = 0; + a |= (1 << side.getIndex()); + return a; + } + byte a = v; + a |= (1 << side.getIndex()); + return a; + }); + } + + public void removeSource(NodeG source) { + this.activeSources.remove(source); + this.network.removeEdge(this.superSource, source); + } + + public void addSink(NodeG sink) { + this.activeSources.add(sink); + this.network.addEdge(sink, this.superSink); } - public void adjustSink(NodeG sink, Function adjuster) { - activeSinks.compute(sink, (k, v) -> (v == null) ? adjuster.apply(0d) : adjuster.apply(v)); - if (activeSinks.get(sink) <= 0) activeSinks.remove(sink); + public void removeSink(NodeG sink) { + this.activeSources.remove(sink); + this.network.removeEdge(sink, this.superSink); } } diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 0717efb0fd6..d52bd3a51dd 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -188,16 +188,20 @@ protected void clearCaches() { this.channels.clear(); } + public Graph, NetEdge> getGraph() { + return graph; + } + public AbstractGroupData getData() { return this.data; } - protected void setChannel(Object key, FlowChannel channel) { + public void setChannel(Object key, FlowChannel channel) { this.channels.put(key, channel); } @Nullable - protected FlowChannel getChannel(Object key) { + public FlowChannel getChannel(Object key) { return this.channels.get(key); } diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index e45be65af77..6ac3424a123 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -117,6 +117,7 @@ public NodeG(NBTTagCompound tag, WorldPipeNetG net) { this.heldMTE = new WeakReference<>(null); } + // TODO guarantee every node has a group @Nullable public NetGroup getGroup() { return group; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java index fc8979a8ac3..cc1c65faf04 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -2,6 +2,7 @@ import gregtech.api.pipenet.FlowChannel; import gregtech.api.pipenet.NetEdge; +import gregtech.api.pipenet.NetGroup; import gregtech.api.pipenet.NodeG; import gregtech.api.pipenet.WorldPipeFlowNetG; @@ -16,14 +17,19 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; + +import net.minecraftforge.fluids.capability.IFluidHandler; + import org.jgrapht.Graph; import java.util.Map; import java.util.Set; -import java.util.function.Function; public class FluidChannel extends FlowChannel { @@ -46,14 +52,16 @@ public void setFluid(Fluid fluid) { public void evaluate() { activate(); - if (network instanceof WorldPipeFlowNetG.IFlowGraph graph) { + if (network instanceof WorldPipeFlowNetG.IFlowGraph graph) { graph.setTestObject(fluid.getFluid()); + ((WorldPipeFlowNetG.IFlowGraph) graph) + .setQueryingChannel(this); } else throw new IllegalStateException("Attempted to do flow calculations on a non-flow graph!"); if (alg == null) alg = new MaximumFlowAlgorithm<>(network); - double max = alg.calculateMaximumFlow(superSource, superSink); + alg.calculateMaximumFlow(superSource, superSink); Map flows = alg.getFlowMap(); Map, Double> inMap = new Object2DoubleOpenHashMap<>(); Map, Double> outMap = new Object2DoubleOpenHashMap<>(); @@ -85,26 +93,81 @@ public void evaluate() { oldNode.removeChannel(this); } oldNodes = nodes; - for (Map.Entry, Double> sink : activeSinks.entrySet()) { - if (sink.getKey().getHeldMTE() instanceof TileEntityFluidPipeTickable f) { - double flow = outMap.getOrDefault(sink.getKey(), 0d); - // insert flow to the node's neighbors - } + + // Everything should be properly balanced at this point due to earlier operations. + // If something is off, it's too late to fix. + for (NodeG source : activeSources) { + double flow = inMap.getOrDefault(source, 0d); + if (flow != 0) + pullFromNode(source, (int) flow, true); + } + for (NodeG sink : activeSinks) { + double flow = outMap.getOrDefault(sink, 0d); + if (flow != 0) + pushToNode(sink, (int) flow, true); } deactivate(); } @Override - public void adjustSource(NodeG source, Function adjuster) { - this.alg = null; - super.adjustSource(source, adjuster); + protected double getSourceValue(NodeG source) { + return pullFromNode(source, Integer.MAX_VALUE, false); + } + + private double pullFromNode(NodeG source, int amount, boolean doDrain) { + FluidStack stack = null; + if (source.getHeldMTE() instanceof TileEntityFluidPipeTickable f) { + IFluidHandler handler = f.getCapability( + CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + if (handler != null) { + stack = handler.drain(new FluidStack(this.fluid.getFluid(), amount), doDrain); + } + } + return stack != null ? stack.amount : 0; } @Override - public void adjustSink(NodeG sink, Function adjuster) { - this.alg = null; - super.adjustSink(sink, adjuster); + protected double getSinkValue(NodeG sink) { + return pushToNode(sink, Integer.MAX_VALUE, false); } + private double pushToNode(NodeG sink, int amount, boolean doFill) { + int flow = 0; + if (sink.getHeldMTE() instanceof TileEntityFluidPipeTickable f) { + int fill; + Byte receiveSides = this.receiveSidesMap.get(sink); + for (Map.Entry connected : sink.getConnecteds().entrySet()) { + if (receiveSides != null) { + int facing = (1 << connected.getKey().getIndex()); + if ((receiveSides & facing) != 0) { + if (doFill) this.receiveSidesMap.compute(sink, (k, v) -> { + assert v != null; + // bitwise XOR to remove this side from the map + return (byte) (v ^ facing); + }); + continue; + } + } + // TODO check our and their cover + IFluidHandler handler = connected.getValue().getCapability( + CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, connected.getKey().getOpposite()); + if (handler != null) { + fill = handler.fill(new FluidStack(this.fluid.getFluid(), amount), doFill); + flow += fill; + amount -= fill; + } + } + } + return flow; + } + + public static FluidChannel getChannelFromGroup(Fluid key, NetGroup group) { + FluidChannel channel = (FluidChannel) group.getChannel(key); + if (channel == null) { + channel = new FluidChannel(group.getGraph(), key); + group.setChannel(key, channel); + } + return channel; + } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java index b9b695026b8..0b8a50e2fff 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java @@ -78,7 +78,7 @@ private int fill(FluidStack resource, boolean doFill, int channel) { newFluid.amount = Math.min(pipe.getCapacityPerTank(), newFluid.amount); if (doFill) { tank.setFluid(newFluid); - pipe.receivedFrom(facing); + pipe.receivedFrom(newFluid.getFluid(), facing); pipe.checkAndDestroy(newFluid); } return newFluid.amount; @@ -88,7 +88,7 @@ private int fill(FluidStack resource, boolean doFill, int channel) { if (toAdd > 0) { if (doFill) { currentFluid.amount += toAdd; - pipe.receivedFrom(facing); + pipe.receivedFrom(currentFluid.getFluid(), facing); pipe.checkAndDestroy(currentFluid); } return toAdd; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java index 038fef391f8..4c837d971fe 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java @@ -14,6 +14,7 @@ import gregtech.api.util.TextFormattingUtil; import gregtech.common.covers.CoverPump; import gregtech.common.covers.ManualImportExportMode; +import gregtech.common.pipelike.fluidpipe.net.FluidChannel; import gregtech.common.pipelike.fluidpipe.net.PipeTankList; import net.minecraft.entity.EntityLivingBase; @@ -72,34 +73,34 @@ public T getCapabilityInternal(Capability capability, @Nullable EnumFacin @Override public void update() { - timer++; +// timer++; getCoverableImplementation().update(); - if (!world.isRemote && getOffsetTimer() % FREQUENCY == 0) { - lastReceivedFrom &= 63; - if (lastReceivedFrom == 63) { - lastReceivedFrom = 0; - } - - boolean shouldDistribute = (oldLastReceivedFrom == lastReceivedFrom); - int tanks = getNodeData().getTanks(); - for (int i = 0, j = GTValues.RNG.nextInt(tanks); i < tanks; i++) { - int index = (i + j) % tanks; - FluidTank tank = getFluidTanks()[index]; - FluidStack fluid = tank.getFluid(); - if (fluid == null) - continue; - if (fluid.amount <= 0) { - tank.setFluid(null); - continue; - } - - if (shouldDistribute) { - distributeFluid(index, tank, fluid); - lastReceivedFrom = 0; - } - } - oldLastReceivedFrom = lastReceivedFrom; - } +// if (!world.isRemote && getOffsetTimer() % FREQUENCY == 0) { +// lastReceivedFrom &= 63; +// if (lastReceivedFrom == 63) { +// lastReceivedFrom = 0; +// } +// +// boolean shouldDistribute = (oldLastReceivedFrom == lastReceivedFrom); +// int tanks = getNodeData().getTanks(); +// for (int i = 0, j = GTValues.RNG.nextInt(tanks); i < tanks; i++) { +// int index = (i + j) % tanks; +// FluidTank tank = getFluidTanks()[index]; +// FluidStack fluid = tank.getFluid(); +// if (fluid == null) +// continue; +// if (fluid.amount <= 0) { +// tank.setFluid(null); +// continue; +// } +// +// if (shouldDistribute) { +// distributeFluid(index, tank, fluid); +// lastReceivedFrom = 0; +// } +// } +// oldLastReceivedFrom = lastReceivedFrom; +// } } @Override @@ -357,9 +358,12 @@ private IFluidHandler getFluidHandlerAt(EnumFacing facing, EnumFacing oppositeSi return tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, oppositeSide); } - public void receivedFrom(EnumFacing facing) { + public void receivedFrom(Fluid fluid, EnumFacing facing) { + // on fluid received, add us as a source to the proper channel + FluidChannel channel = FluidChannel.getChannelFromGroup(fluid, this.getNode().getGroup()); + channel.addSource(this.getNode()); if (facing != null) { - lastReceivedFrom |= (1 << facing.getIndex()); + channel.addReceiveSide(this.getNode(), facing); } } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index 519d265b59d..a53dadbe5b5 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -333,7 +333,7 @@ public ItemStack insert(NetPath.FacedNetPath r testHandler.setStackInSlot(0, ItemStack.EMPTY); } IItemHandler neighbourHandler = routePath.getTargetTE() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, routePath.facing); + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, routePath.facing.getOpposite()); if (pipeCover instanceof CoverRoboticArm && ((CoverRoboticArm) pipeCover).getConveyorMode() == CoverConveyor.ConveyorMode.EXPORT) { return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) pipeCover, stack, simulate, allowed, From 2470f9ff452119d21b3d410b89c9263ac206a479 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 19 Jan 2024 13:33:17 -0700 Subject: [PATCH 037/157] Ensure nodes have a group on query --- .../java/gregtech/api/pipenet/NetGroup.java | 17 ++++++++--------- src/main/java/gregtech/api/pipenet/NodeG.java | 16 ++++++++++------ .../gregtech/api/pipenet/WorldPipeNetG.java | 15 ++++++--------- .../api/pipenet/alg/MaximumFlowAlgorithm.java | 5 ++--- .../api/pipenet/alg/ShortestPathsAlgorithm.java | 6 +++--- .../tile/TileEntityFluidPipeTickable.java | 2 +- .../pipelike/laser/net/LaserNetHandler.java | 2 +- .../pipelike/optical/net/OpticalNetHandler.java | 2 +- 8 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index d52bd3a51dd..05ba08d7b60 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -71,28 +71,27 @@ protected final void addNodes(NodeG... nodes) { * * @param source the source node of the edge * @param target the target node of the edge - * @return True if both nodes belonged to no group, and no merge could be conducted. */ - public static boolean mergeEdge(NodeG source, NodeG target) { - NetGroup sourceGroup = source.getGroup(); - NetGroup targetGroup = target.getGroup(); + public static void mergeEdge(NodeG source, NodeG target) { + NetGroup sourceGroup = source.getGroupUnsafe(); + NetGroup targetGroup = target.getGroupUnsafe(); if (sourceGroup == targetGroup) { - if (sourceGroup == null) return true; + if (sourceGroup == null) { + sourceGroup = source.getGroupSafe(); + } sourceGroup.clearCaches(); - return false; } if (sourceGroup != null) { sourceGroup.mergeNode(target); } else { targetGroup.mergeNode(source); } - return false; } protected void mergeNode(NodeG node) { NodeG cast = (NodeG) node; - if (cast.getGroup() != null) { - NetGroup group = cast.getGroup(); + if (cast.getGroupUnsafe() != null) { + NetGroup group = cast.getGroupUnsafe(); this.addNodes(group.getNodes()); group.clear(); } else addNode(cast); diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 6ac3424a123..9dce2328a99 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -3,9 +3,6 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.nbt.NBTTagCompound; @@ -117,10 +114,17 @@ public NodeG(NBTTagCompound tag, WorldPipeNetG net) { this.heldMTE = new WeakReference<>(null); } - // TODO guarantee every node has a group + public NetGroup getGroupSafe() { + if (this.group == null) { + new NetGroup<>(this.net.pipeGraph, this.net).addNodes(this); + // addNodes automatically sets our group to the new group + } + return this.group; + } + @Nullable - public NetGroup getGroup() { - return group; + public NetGroup getGroupUnsafe() { + return this.group; } NetGroup setGroup(NetGroup group) { diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 4c8dc267681..0333379e175 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -1,7 +1,6 @@ package gregtech.api.pipenet; import gregtech.api.cover.Cover; -import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; import gregtech.api.pipenet.alg.NetAlgorithm; import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; import gregtech.api.pipenet.alg.SinglePathAlgorithm; @@ -310,9 +309,7 @@ public void addUndirectedEdge(NodeG source, NodeG source, NodeG target, double weight, @Nullable AbstractEdgePredicate predicate) { if (pipeGraph.addEdge(source, target) != null) { - if (NetGroup.mergeEdge(source, target)) { - new NetGroup<>(this.pipeGraph, this).addNodes(source, target); - } + NetGroup.mergeEdge(source, target); pipeGraph.setEdgeWeight(source, target, weight); if (predicate != null) { pipeGraph.getEdge(source, target).setPredicate(predicate); @@ -378,7 +375,7 @@ public void removeUndirectedEdge(NodeG source, NodeG source, NodeG target) { - if (source.getGroup() != null && source.getGroup().splitEdge(source, target)) { + if (source.getGroupSafe() != null && source.getGroupSafe().splitEdge(source, target)) { this.validAlgorithmInstance = false; this.markDirty(); } @@ -391,8 +388,8 @@ public void removeNode(BlockPos pos) { public void removeNode(@Nullable NodeG node) { if (node != null) { if (this.pipeGraph.edgesOf(node).size() != 0) this.validAlgorithmInstance = false; - if (node.getGroup() != null) { - node.getGroup().splitNode(node); + if (node.getGroupSafe() != null) { + node.getGroupSafe().splitNode(node); } else this.pipeGraph.removeVertex(node); this.pipeMap.remove(node.getNodePos()); this.markDirty(); @@ -402,7 +399,7 @@ public void removeNode(@Nullable NodeG node) { public NetGroup getGroup(BlockPos pos) { NodeG node = this.getNode(pos); if (node == null) return null; - if (node.getGroup() != null) return node.getGroup(); + if (node.getGroupSafe() != null) return node.getGroupSafe(); return node.setGroup(new NetGroup<>(this.pipeGraph, this)); } @@ -456,7 +453,7 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { NBTTagList allPipeNodes = new NBTTagList(); Set> groups = new ObjectOpenHashSet<>(); for (NodeG node : pipeGraph.vertexSet()) { - if (node.getGroup() != null) groups.add(node.getGroup()); + if (node.getGroupSafe() != null) groups.add(node.getGroupSafe()); NBTTagCompound nodeTag = node.serializeNBT(); NBTTagCompound dataTag = new NBTTagCompound(); writeNodeData(node.getData(), dataTag); diff --git a/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java index 4d3af09c585..86ab6d25dcf 100644 --- a/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java @@ -9,7 +9,6 @@ import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.Graph; -import org.jgrapht.GraphPath; import org.jgrapht.alg.flow.PushRelabelMFImpl; import java.util.List; @@ -37,9 +36,9 @@ public List> getPathsList(NodeG source) { List> paths = new ObjectArrayList<>(); paths.add(new NetPath<>(source)); // if the source has no group, it has no paths other than the path to itself. - if (source.getGroup() == null) return paths; + if (source.getGroupSafe() == null) return paths; - for (NodeG v : source.getGroup().getNodes()) { + for (NodeG v : source.getGroupSafe().getNodes()) { if (v == source) continue; // paths.add(new FlowPath<>(wrapper)); } diff --git a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java index 00ada61dbd5..951bc09d9f5 100644 --- a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java @@ -31,10 +31,10 @@ public List> getPathsList(NodeG source) { List> paths = new ObjectArrayList<>(); paths.add(new NetPath<>(source)); // if the source has no group, it has no paths other than the path to itself. - if (source.getGroup() == null) return paths; + if (source.getGroupUnsafe() == null) return paths; ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths( - Collections.singleton(source), source.getGroup().getNodes()); - for (NodeG v : source.getGroup().getNodes()) { + Collections.singleton(source), source.getGroupSafe().getNodes()); + for (NodeG v : source.getGroupSafe().getNodes()) { if (v == source) continue; GraphPath, NetEdge> path = manyToManyPaths.getPath(source, v); if (path != null) { diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java index 4c837d971fe..d75972ec1c7 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java @@ -360,7 +360,7 @@ private IFluidHandler getFluidHandlerAt(EnumFacing facing, EnumFacing oppositeSi public void receivedFrom(Fluid fluid, EnumFacing facing) { // on fluid received, add us as a source to the proper channel - FluidChannel channel = FluidChannel.getChannelFromGroup(fluid, this.getNode().getGroup()); + FluidChannel channel = FluidChannel.getChannelFromGroup(fluid, this.getNode().getGroupSafe()); channel.addSource(this.getNode()); if (facing != null) { channel.addReceiveSide(this.getNode(), facing); diff --git a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java index c8a22d2e05f..a7102854c04 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java @@ -31,7 +31,7 @@ public LaserNetHandler(WorldLaserPipeNet net, @NotNull TileEntityLaserPipe pipe, } private void setPipesActive() { - NetGroup group = getNet().getNode(this.pipe.getPipePos()).getGroup(); + NetGroup group = getNet().getNode(this.pipe.getPipePos()).getGroupSafe(); if (group != null) { for (NodeG node : group.getNodes()) { if (node.getHeldMTE() instanceof TileEntityLaserPipe laserPipe) { diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java index 0e68df838f3..ebc361578e0 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java @@ -70,7 +70,7 @@ public boolean canBridge(@NotNull Collection seen) } private void setPipesActive() { - NetGroup group = getNet().getNode(this.pipe.getPipePos()).getGroup(); + NetGroup group = getNet().getNode(this.pipe.getPipePos()).getGroupSafe(); if (group != null) { for (NodeG node : group.getNodes()) { if (node.getHeldMTE() instanceof TileEntityOpticalPipe opticalPipe) { From 8b4e2c2624b44133c5252f93a7498cc90bfbf2f4 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 19 Jan 2024 14:13:46 -0700 Subject: [PATCH 038/157] Channel sink cover checks --- .../gregtech/api/pipenet/FlowChannel.java | 19 ++++++++++++ .../pipelike/fluidpipe/net/FluidChannel.java | 31 +++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/FlowChannel.java b/src/main/java/gregtech/api/pipenet/FlowChannel.java index 8459a886d7d..5f1ee814e2c 100644 --- a/src/main/java/gregtech/api/pipenet/FlowChannel.java +++ b/src/main/java/gregtech/api/pipenet/FlowChannel.java @@ -1,12 +1,19 @@ package gregtech.api.pipenet; +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.cover.Cover; +import gregtech.api.cover.CoverHolder; import gregtech.api.pipenet.block.IPipeType; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; import java.util.Map; @@ -93,4 +100,16 @@ public void removeSink(NodeG sink) { this.activeSources.remove(sink); this.network.removeEdge(sink, this.superSink); } + + @Nullable + protected static Cover getCoverOnNeighbour(NodeG node, EnumFacing facing) { + TileEntity tile = node.getConnnected(facing); + if (tile != null) { + CoverHolder coverHolder = tile.getCapability(GregtechTileCapabilities.CAPABILITY_COVER_HOLDER, + facing.getOpposite()); + if (coverHolder == null) return null; + return coverHolder.getCoverAtSide(facing.getOpposite()); + } + return null; + } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java index cc1c65faf04..7d8997fe40d 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -1,5 +1,6 @@ package gregtech.common.pipelike.fluidpipe.net; +import gregtech.api.cover.Cover; import gregtech.api.pipenet.FlowChannel; import gregtech.api.pipenet.NetEdge; import gregtech.api.pipenet.NetGroup; @@ -9,6 +10,11 @@ import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.common.covers.CoverPump; +import gregtech.common.covers.CoverShutter; +import gregtech.common.covers.ManualImportExportMode; +import gregtech.common.covers.filter.FluidFilter; +import gregtech.common.covers.filter.FluidFilterContainer; import gregtech.common.pipelike.fluidpipe.FluidPipeType; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipeTickable; @@ -149,11 +155,13 @@ private double pushToNode(NodeG sink, int am continue; } } - // TODO check our and their cover + Cover thisCover = sink.getHeldMTE().getCoverableImplementation().getCoverAtSide(connected.getKey()); + Cover themCover = getCoverOnNeighbour(sink, connected.getKey().getOpposite()); + int transferMax = evaluateCover(themCover, evaluateCover(thisCover, amount)); IFluidHandler handler = connected.getValue().getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, connected.getKey().getOpposite()); if (handler != null) { - fill = handler.fill(new FluidStack(this.fluid.getFluid(), amount), doFill); + fill = handler.fill(new FluidStack(this.fluid.getFluid(), transferMax), doFill); flow += fill; amount -= fill; } @@ -162,6 +170,25 @@ private double pushToNode(NodeG sink, int am return flow; } + private int evaluateCover(Cover cover, int transferMax) { + if (cover instanceof CoverPump p) { + switch (p.getManualImportExportMode()) { + case DISABLED -> { + return 0; + } + case FILTERED -> { + if (!p.getFluidFilterContainer().testFluidStack(this.fluid)) return 0; + } + } + return Math.min(transferMax, p.getTransferRate()); + } + if (cover instanceof FluidFilter f) { + return f.testFluid(this.fluid) ? transferMax : 0; + } + if (cover instanceof CoverShutter) return 0; + return transferMax; + } + public static FluidChannel getChannelFromGroup(Fluid key, NetGroup group) { FluidChannel channel = (FluidChannel) group.getChannel(key); if (channel == null) { From 1072796e2a95e671f3c15e8176f0bf01a15292a6 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 19 Jan 2024 22:58:02 -0700 Subject: [PATCH 039/157] Channel - group integration --- .../gregtech/api/pipenet/FlowChannel.java | 64 ++++++++------ .../api/pipenet/FlowChannelManager.java | 88 +++++++++++++++++++ .../java/gregtech/api/pipenet/NetGroup.java | 69 ++++++++++----- .../api/pipenet/WorldPipeFlowNetG.java | 2 +- .../gregtech/api/pipenet/WorldPipeNetG.java | 17 ++++ .../pipelike/fluidpipe/net/FluidChannel.java | 16 +++- 6 files changed, 206 insertions(+), 50 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/FlowChannelManager.java diff --git a/src/main/java/gregtech/api/pipenet/FlowChannel.java b/src/main/java/gregtech/api/pipenet/FlowChannel.java index 5f1ee814e2c..4bd033e73f2 100644 --- a/src/main/java/gregtech/api/pipenet/FlowChannel.java +++ b/src/main/java/gregtech/api/pipenet/FlowChannel.java @@ -11,8 +11,6 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; - import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; @@ -23,18 +21,21 @@ public abstract class FlowChannel & IPipeType, NDT exte protected final Graph, NetEdge> network; - protected NodeG superSource = new NodeG<>(); - protected Set> activeSources = new ObjectOpenHashSet<>(); + protected final Set> activeSources = new ObjectOpenHashSet<>(); - protected NodeG superSink = new NodeG<>(); - protected Set> activeSinks = new ObjectOpenHashSet<>(); + protected final Map, Byte> receiveSidesMap = new Object2ObjectOpenHashMap<>(); - protected Map, Byte> receiveSidesMap = new Object2ObjectOpenHashMap<>(); + protected FlowChannelManager manager; public FlowChannel(Graph, NetEdge> network) { this.network = network; } + FlowChannel setManager(FlowChannelManager manager) { + this.manager = manager; + return this; + } + public abstract void evaluate(); /** @@ -43,13 +44,12 @@ public FlowChannel(Graph, NetEdge> network) { protected void activate() { for (NodeG source : activeSources) { double v = getSourceValue(source); - network.setEdgeWeight(superSource, source, v); + network.setEdgeWeight(this.manager.getSuperSource(), source, v); if (v == 0) removeSource(source); } - for (NodeG sink : activeSinks) { + for (NodeG sink : this.manager.getActiveSinks()) { double v = getSinkValue(sink); - network.setEdgeWeight(sink, superSink, v); - if (v == 0) removeSink(sink); + network.setEdgeWeight(sink, this.manager.getSuperSink(), v); } } @@ -58,10 +58,10 @@ protected void activate() { */ protected void deactivate() { for (NodeG source : activeSources) { - network.setEdgeWeight(superSource, source, 0); + network.setEdgeWeight(this.manager.getSuperSource(), source, 0); } - for (NodeG sink : activeSinks) { - network.setEdgeWeight(sink, superSink, 0); + for (NodeG sink : this.manager.getActiveSinks()) { + network.setEdgeWeight(sink, this.manager.getSuperSink(), 0); } } @@ -70,7 +70,7 @@ protected void deactivate() { public void addSource(NodeG source) { this.activeSources.add(source); - this.network.addEdge(this.superSource, source); + this.network.addEdge(this.manager.getSuperSource(), source); } public void addReceiveSide(NodeG node, EnumFacing side) { @@ -88,17 +88,7 @@ public void addReceiveSide(NodeG node, EnumFacing side) { public void removeSource(NodeG source) { this.activeSources.remove(source); - this.network.removeEdge(this.superSource, source); - } - - public void addSink(NodeG sink) { - this.activeSources.add(sink); - this.network.addEdge(sink, this.superSink); - } - - public void removeSink(NodeG sink) { - this.activeSources.remove(sink); - this.network.removeEdge(sink, this.superSink); + this.network.removeEdge(this.manager.getSuperSource(), source); } @Nullable @@ -112,4 +102,26 @@ protected static Cover getCoverOnNeighbour(NodeG node, EnumFacing facing) } return null; } + + protected FlowChannel merge(FlowChannel otherChannel) { + this.activeSources.addAll(otherChannel.activeSources); + for (Map.Entry, Byte> entry : otherChannel.receiveSidesMap.entrySet()) { + this.receiveSidesMap.merge(entry.getKey(), entry.getValue(), (a, b) -> (byte) (a | b)); + } + return this; + } + + protected void removeNodes(Set> nodes) { + this.activeSources.removeAll(nodes); + for (NodeG node : nodes) { + this.receiveSidesMap.remove(node); + } + } + + protected void removeNode(NodeG node) { + this.activeSources.remove(node); + this.receiveSidesMap.remove(node); + } + + protected abstract FlowChannel getNew(); } diff --git a/src/main/java/gregtech/api/pipenet/FlowChannelManager.java b/src/main/java/gregtech/api/pipenet/FlowChannelManager.java new file mode 100644 index 00000000000..c3da6924003 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/FlowChannelManager.java @@ -0,0 +1,88 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.block.IPipeType; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.Set; + +public class FlowChannelManager & IPipeType, + NodeDataType extends INodeData> { + + protected final NodeG superSource = new NodeG<>(); + protected final NodeG superSink = new NodeG<>(); + + protected final Set> activeSinks = new ObjectOpenHashSet<>(); + + private final Map> channels = new Object2ObjectOpenHashMap<>(); + + /** + * Updates active nodes based on the active nodes of another manager. + */ + public FlowChannelManager merge(FlowChannelManager otherManager) { + this.activeSinks.addAll(otherManager.activeSinks); + for (Map.Entry> entry : otherManager.channels.entrySet()) { + this.channels.merge(entry.getKey(), entry.getValue(), FlowChannel::merge); + } + return this; + } + + /** + * Generates a new manager that filters this manager's active nodes by removing the provided nodes. + */ + public FlowChannelManager subManager(Set> nodes) { + FlowChannelManager newManager = new FlowChannelManager<>(); + newManager.channels.putAll(this.channels); + newManager.channels.forEach((key, value) -> { + value.setManager(newManager); + value.activeSources.removeAll(nodes); + for (NodeG node : nodes) { + value.receiveSidesMap.remove(node); + } + }); + newManager.activeSinks.addAll(this.activeSinks); + newManager.activeSinks.removeAll(nodes); + return newManager; + } + + /** + * Filters this manager's active nodes by removing the provided nodes. + */ + public void removeNodes(Set> nodes) { + this.activeSinks.removeAll(nodes); + this.channels.forEach((key, value) -> value.removeNodes(nodes)); + } + + public void removeNode(NodeG node) { + this.activeSinks.remove(node); + this.channels.forEach((key, value) -> value.removeNode(node)); + } + + public NodeG getSuperSource() { + return superSource; + } + + public NodeG getSuperSink() { + return superSink; + } + + public Set> getActiveSinks() { + return activeSinks; + } + + public void setChannel(Object key, FlowChannel channel) { + this.channels.put(key, channel.setManager(this)); + } + + @Nullable + public FlowChannel getChannel(Object key) { + return this.channels.get(key); + } + + public void removeChannel(Object key) { + this.channels.remove(key); + } +} diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 05ba08d7b60..68e68865a7d 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -2,8 +2,6 @@ import gregtech.api.pipenet.block.IPipeType; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.INBTSerializable; @@ -25,7 +23,9 @@ public class NetGroup & IPipeType, private final Graph, NetEdge> graph; private final Set> nodes; - private final Map> channels = new Object2ObjectOpenHashMap<>(); + + @Nullable + private FlowChannelManager channelManager = null; private final AbstractGroupData data; @@ -47,6 +47,7 @@ public NetGroup(Graph, NetEdge> graph, WorldPipeNe private void clear() { this.nodes.clear(); + this.channelManager = null; } protected void addNode(NodeG node) { @@ -78,21 +79,27 @@ public static void mergeEdge(NodeG source, NodeG target) { if (sourceGroup == targetGroup) { if (sourceGroup == null) { sourceGroup = source.getGroupSafe(); + } else { + sourceGroup.clearCaches(); + return; } - sourceGroup.clearCaches(); } if (sourceGroup != null) { sourceGroup.mergeNode(target); } else { + assert targetGroup != null; targetGroup.mergeNode(source); } } protected void mergeNode(NodeG node) { NodeG cast = (NodeG) node; - if (cast.getGroupUnsafe() != null) { - NetGroup group = cast.getGroupUnsafe(); + NetGroup group = cast.getGroupUnsafe(); + if (group != null) { this.addNodes(group.getNodes()); + if (this.net.isFlow()) { + this.getChannelManager().merge(group.getChannelManager()); + } group.clear(); } else addNode(cast); this.clearCaches(); @@ -114,6 +121,10 @@ public boolean splitNode(NodeG source) { return a.getSource(); }).collect(Collectors.toList()); graph.removeVertex(source); + this.nodes.remove(source); + if (this.net.isFlow()) { + this.getChannelManager().removeNode(source); + } while (!targets.isEmpty()) { // get the lastmost target; if this throws a cast exception, something is very wrong with the graph. NodeG target = (NodeG) targets @@ -130,12 +141,15 @@ public boolean splitNode(NodeG source) { targets.remove(temp); } this.nodes.removeAll(targetGroup); - // if 1 or fewer nodes are in the new group, no need to create it. - if (targetGroup.size() > 1) { - // No need to do more than create it, the involved nodes are automatically updated in constructor - new NetGroup<>(this.graph, this.net, targetGroup); - } else { - targetGroup.forEach(NodeG::clearGroup); + if (targetGroup.size() > 0) { + if (this.net.isFlow()) { + // remove our owned nodes from their manager, and remove their nodes from our manager. + new NetGroup<>(this.graph, this.net, targetGroup) + .setChannelManager(this.getChannelManager().subManager(this.nodes)); + this.getChannelManager().removeNodes(targetGroup); + } else { + new NetGroup<>(this.graph, this.net, targetGroup); + } } } return true; @@ -163,12 +177,15 @@ public boolean splitEdge(NodeG source, NodeG 1) { - // No need to do more than create it, the involved nodes are automatically updated in constructor - new NetGroup<>(this.graph, this.net, targetGroup); - } else { - targetGroup.forEach(NodeG::clearGroup); + if (targetGroup.size() > 0) { + if (this.net.isFlow()) { + // remove our owned nodes from their manager, and remove their nodes from our manager. + new NetGroup<>(this.graph, this.net, targetGroup) + .setChannelManager(this.getChannelManager().subManager(this.nodes)); + this.getChannelManager().removeNodes(targetGroup); + } else { + new NetGroup<>(this.graph, this.net, targetGroup); + } } return true; } @@ -184,7 +201,6 @@ public Set> getNodes() { protected void clearCaches() { this.nodes.forEach(NodeG::clearPathCache); - this.channels.clear(); } public Graph, NetEdge> getGraph() { @@ -196,12 +212,23 @@ public AbstractGroupData getData() { } public void setChannel(Object key, FlowChannel channel) { - this.channels.put(key, channel); + this.getChannelManager().setChannel(key, channel); } @Nullable public FlowChannel getChannel(Object key) { - return this.channels.get(key); + return this.getChannelManager().getChannel(key); + } + + private void setChannelManager(FlowChannelManager manager) { + this.channelManager = manager; + } + + private FlowChannelManager getChannelManager() { + if (this.channelManager == null) { + this.channelManager = new FlowChannelManager<>(); + } + return this.channelManager; } @Override diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java index 13e086e25e8..c9210644790 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java @@ -17,7 +17,7 @@ public abstract class WorldPipeFlowNetG(); else this.pipeGraph = new FlowUndirected<>(); diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 0333379e175..a4b2e60fdcc 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -39,6 +39,7 @@ public abstract class WorldPipeNetG private final boolean isDirected; private final boolean isSinglePath; + private final boolean isFlow; private WeakReference worldRef = new WeakReference<>(null); // TODO move graph & algorithm into NetGroup to reduce unnecessary algorithm cost @@ -64,13 +65,29 @@ public WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath) { this.netAlgorithm = new NetAlgorithm.NetAlgorithmWrapper<>(); this.isDirected = isDirected; this.isSinglePath = isSinglePath; + this.isFlow = false; } + + WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath, boolean isFlow) { + super(name); + if (isDirected()) + this.pipeGraph = new SimpleDirectedWeightedGraph<>(NetEdge.class); + else this.pipeGraph = new SimpleWeightedGraph<>(NetEdge.class); + this.netAlgorithm = new NetAlgorithm.NetAlgorithmWrapper<>(); + this.isDirected = isDirected; + this.isSinglePath = isSinglePath; + this.isFlow = isFlow; + } + public final boolean isDirected() { return isDirected; } public final boolean isSinglePath() { return isSinglePath; } + public final boolean isFlow() { + return isFlow; + } public World getWorld() { return this.worldRef.get(); diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java index 7d8997fe40d..8654589cbce 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -2,6 +2,7 @@ import gregtech.api.cover.Cover; import gregtech.api.pipenet.FlowChannel; +import gregtech.api.pipenet.FlowChannelManager; import gregtech.api.pipenet.NetEdge; import gregtech.api.pipenet.NetGroup; import gregtech.api.pipenet.NodeG; @@ -56,6 +57,12 @@ public void setFluid(Fluid fluid) { @Override public void evaluate() { + // Kill this channel if we have no more active sources + if (this.activeSources.size() == 0) { + this.manager.removeChannel(this.fluid.getFluid()); + return; + } + activate(); if (network instanceof WorldPipeFlowNetG.IFlowGraph graph) { @@ -67,7 +74,7 @@ public void evaluate() { if (alg == null) alg = new MaximumFlowAlgorithm<>(network); - alg.calculateMaximumFlow(superSource, superSink); + alg.calculateMaximumFlow(this.manager.getSuperSource(), this.manager.getSuperSink()); Map flows = alg.getFlowMap(); Map, Double> inMap = new Object2DoubleOpenHashMap<>(); Map, Double> outMap = new Object2DoubleOpenHashMap<>(); @@ -107,7 +114,7 @@ public void evaluate() { if (flow != 0) pullFromNode(source, (int) flow, true); } - for (NodeG sink : activeSinks) { + for (NodeG sink : this.manager.getActiveSinks()) { double flow = outMap.getOrDefault(sink, 0d); if (flow != 0) pushToNode(sink, (int) flow, true); @@ -197,4 +204,9 @@ public static FluidChannel getChannelFromGroup(Fluid key, NetGroup getNew() { + return new FluidChannel(this.network, this.fluid.getFluid()); + } } From e91fb3769e0eafd1cf05b6413e687cc69d1f2e22 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 19 Jan 2024 22:59:55 -0700 Subject: [PATCH 040/157] Oh yea, spotless exists --- .../gregtech/api/pipenet/FlowChannel.java | 6 +-- .../java/gregtech/api/pipenet/NetGroup.java | 2 +- src/main/java/gregtech/api/pipenet/NodeG.java | 5 +- .../api/pipenet/WorldPipeFlowNetG.java | 14 ++--- .../gregtech/api/pipenet/WorldPipeNetG.java | 3 +- .../api/pipenet/alg/MaximumFlowAlgorithm.java | 6 +-- .../pipenet/alg/ShortestPathsAlgorithm.java | 2 +- .../api/pipenet/alg/SinglePathAlgorithm.java | 2 +- .../common/pipelike/cable/BlockCable.java | 2 +- .../pipelike/fluidpipe/net/FluidChannel.java | 21 ++------ .../fluidpipe/net/WorldFluidPipeNet.java | 1 - .../tile/TileEntityFluidPipeTickable.java | 54 +++++++++---------- .../optical/net/OpticalNetHandler.java | 3 +- 13 files changed, 56 insertions(+), 65 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/FlowChannel.java b/src/main/java/gregtech/api/pipenet/FlowChannel.java index 4bd033e73f2..d38661fd1ee 100644 --- a/src/main/java/gregtech/api/pipenet/FlowChannel.java +++ b/src/main/java/gregtech/api/pipenet/FlowChannel.java @@ -5,12 +5,11 @@ import gregtech.api.cover.CoverHolder; import gregtech.api.pipenet.block.IPipeType; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; @@ -66,6 +65,7 @@ protected void deactivate() { } protected abstract double getSourceValue(NodeG source); + protected abstract double getSinkValue(NodeG sink); public void addSource(NodeG source) { diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 68e68865a7d..8c08996b893 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -181,7 +181,7 @@ public boolean splitEdge(NodeG source, NodeG(this.graph, this.net, targetGroup) - .setChannelManager(this.getChannelManager().subManager(this.nodes)); + .setChannelManager(this.getChannelManager().subManager(this.nodes)); this.getChannelManager().removeNodes(targetGroup); } else { new NetGroup<>(this.graph, this.net, targetGroup); diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 9dce2328a99..736bc40a858 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -3,8 +3,6 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; @@ -14,6 +12,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; @@ -289,6 +288,7 @@ public boolean canSupportChannel(FlowChannel channel) { /** * Adds a channel to a node's collection. Cannot go over the node's chnnael limit. + * * @param channel the channel to add. * @return {@code true} if the channel was added. */ @@ -302,6 +302,7 @@ public boolean addChannel(FlowChannel channel) { /** * Removes a channel from a node's collection. + * * @param channel the channel to remove. * @return {@code true} if the channel was in the node's collection. */ diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java index c9210644790..b91711cfeed 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java @@ -3,8 +3,6 @@ import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; import gregtech.api.pipenet.block.IPipeType; -import net.minecraftforge.fluids.Fluid; - import org.jgrapht.graph.SimpleDirectedWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph; @@ -12,9 +10,9 @@ public abstract class WorldPipeFlowNetG & IPipeType> extends WorldPipeNetG { /** - * @param isDirected Determines whether this net needs directed graph handling. - * Used to respect filter directions in the item net and fluid net, for example. - * If the graph is not directed, pipes should not support blocked connections. + * @param isDirected Determines whether this net needs directed graph handling. + * Used to respect filter directions in the item net and fluid net, for example. + * If the graph is not directed, pipes should not support blocked connections. */ public WorldPipeFlowNetG(String name, boolean isDirected) { super(name, isDirected, false, true); @@ -37,7 +35,8 @@ public interface IFlowGraph, PT extends Enum & IP } protected static class FlowUndirected, PT extends Enum & IPipeType> - extends SimpleWeightedGraph, NetEdge> implements IFlowGraph { + extends SimpleWeightedGraph, NetEdge> + implements IFlowGraph { Object testObject; FlowChannel queryingChannel; @@ -64,7 +63,8 @@ public void setQueryingChannel(FlowChannel channel) { } protected static class FlowDirected, PT extends Enum & IPipeType> - extends SimpleDirectedWeightedGraph, NetEdge> implements IFlowGraph { + extends SimpleDirectedWeightedGraph, NetEdge> + implements IFlowGraph { Object testObject; FlowChannel queryingChannel; diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index a4b2e60fdcc..3bb4f9e77d9 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -82,9 +82,11 @@ public WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath) { public final boolean isDirected() { return isDirected; } + public final boolean isSinglePath() { return isSinglePath; } + public final boolean isFlow() { return isFlow; } @@ -505,5 +507,4 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { * Used for reading persistent node data */ protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); - } diff --git a/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java index 86ab6d25dcf..17a4b5ed1a7 100644 --- a/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java @@ -15,7 +15,8 @@ import java.util.Map; public final class MaximumFlowAlgorithm & IPipeType, NDT extends INodeData> - extends PushRelabelMFImpl, NetEdge> implements NetAlgorithm { + extends PushRelabelMFImpl, NetEdge> + implements NetAlgorithm { private NodeG superSource = new NodeG<>(); private Map, Double> activeSources = new Object2DoubleOpenHashMap<>(); @@ -23,7 +24,6 @@ public final class MaximumFlowAlgorithm & IPipeType, ND private NodeG superSink = new NodeG<>(); private Map, Double> activeSinks = new Object2DoubleOpenHashMap<>(); - public MaximumFlowAlgorithm(Graph, NetEdge> network) { super(network); } @@ -40,7 +40,7 @@ public List> getPathsList(NodeG source) { for (NodeG v : source.getGroupSafe().getNodes()) { if (v == source) continue; -// paths.add(new FlowPath<>(wrapper)); + // paths.add(new FlowPath<>(wrapper)); } return paths; } diff --git a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java index 951bc09d9f5..d9805d8e033 100644 --- a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java @@ -17,7 +17,7 @@ public final class ShortestPathsAlgorithm & IPipeType, NDT extends INodeData> extends CHManyToManyShortestPaths, NetEdge> - implements NetAlgorithm { + implements NetAlgorithm { public ShortestPathsAlgorithm(Graph, NetEdge> graph) { super(graph); diff --git a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java index 649eaf73577..62299dfb40d 100644 --- a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java @@ -13,7 +13,7 @@ import java.util.List; public final class SinglePathAlgorithm & IPipeType, NDT extends INodeData> - implements NetAlgorithm { + implements NetAlgorithm { private final Graph, NetEdge> graph; private final boolean isDirected; diff --git a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java index f13613cb591..f2b8112f024 100644 --- a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java @@ -13,8 +13,8 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.CableRenderer; import gregtech.client.renderer.pipe.PipeRenderer; -import gregtech.common.pipelike.cable.net.WorldEnergyNet; import gregtech.common.creativetab.GTCreativeTabs; +import gregtech.common.pipelike.cable.net.WorldEnergyNet; import gregtech.common.pipelike.cable.tile.TileEntityCable; import gregtech.common.pipelike.cable.tile.TileEntityCableTickable; import gregtech.core.advancement.AdvancementTriggers; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java index 8654589cbce..b138483a638 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -2,37 +2,27 @@ import gregtech.api.cover.Cover; import gregtech.api.pipenet.FlowChannel; -import gregtech.api.pipenet.FlowChannelManager; import gregtech.api.pipenet.NetEdge; import gregtech.api.pipenet.NetGroup; import gregtech.api.pipenet.NodeG; - import gregtech.api.pipenet.WorldPipeFlowNetG; import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; - import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.covers.CoverPump; import gregtech.common.covers.CoverShutter; -import gregtech.common.covers.ManualImportExportMode; import gregtech.common.covers.filter.FluidFilter; -import gregtech.common.covers.filter.FluidFilterContainer; import gregtech.common.pipelike.fluidpipe.FluidPipeType; - import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipeTickable; -import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; - import net.minecraftforge.fluids.capability.CapabilityFluidHandler; - import net.minecraftforge.fluids.capability.IFluidHandler; +import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jgrapht.Graph; import java.util.Map; @@ -65,12 +55,11 @@ public void evaluate() { activate(); - if (network instanceof WorldPipeFlowNetG.IFlowGraph graph) { + if (network instanceof WorldPipeFlowNetG.IFlowGraphgraph) { graph.setTestObject(fluid.getFluid()); ((WorldPipeFlowNetG.IFlowGraph) graph) .setQueryingChannel(this); - } - else throw new IllegalStateException("Attempted to do flow calculations on a non-flow graph!"); + } else throw new IllegalStateException("Attempted to do flow calculations on a non-flow graph!"); if (alg == null) alg = new MaximumFlowAlgorithm<>(network); @@ -87,7 +76,7 @@ public void evaluate() { nodes.add((NodeG) flow.getKey().getSource()); nodes.add((NodeG) flow.getKey().getTarget()); } - + for (NodeG node : nodes) { // dataless nodes are only the superSource and superSink if (node.getData() == null) continue; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index 7c12558fe06..300b15897bd 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -1,7 +1,6 @@ package gregtech.common.pipelike.fluidpipe.net; import gregtech.api.pipenet.WorldPipeFlowNetG; -import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.pipelike.fluidpipe.FluidPipeType; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java index d75972ec1c7..5ab17d8f9e7 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java @@ -73,34 +73,34 @@ public T getCapabilityInternal(Capability capability, @Nullable EnumFacin @Override public void update() { -// timer++; + // timer++; getCoverableImplementation().update(); -// if (!world.isRemote && getOffsetTimer() % FREQUENCY == 0) { -// lastReceivedFrom &= 63; -// if (lastReceivedFrom == 63) { -// lastReceivedFrom = 0; -// } -// -// boolean shouldDistribute = (oldLastReceivedFrom == lastReceivedFrom); -// int tanks = getNodeData().getTanks(); -// for (int i = 0, j = GTValues.RNG.nextInt(tanks); i < tanks; i++) { -// int index = (i + j) % tanks; -// FluidTank tank = getFluidTanks()[index]; -// FluidStack fluid = tank.getFluid(); -// if (fluid == null) -// continue; -// if (fluid.amount <= 0) { -// tank.setFluid(null); -// continue; -// } -// -// if (shouldDistribute) { -// distributeFluid(index, tank, fluid); -// lastReceivedFrom = 0; -// } -// } -// oldLastReceivedFrom = lastReceivedFrom; -// } + // if (!world.isRemote && getOffsetTimer() % FREQUENCY == 0) { + // lastReceivedFrom &= 63; + // if (lastReceivedFrom == 63) { + // lastReceivedFrom = 0; + // } + // + // boolean shouldDistribute = (oldLastReceivedFrom == lastReceivedFrom); + // int tanks = getNodeData().getTanks(); + // for (int i = 0, j = GTValues.RNG.nextInt(tanks); i < tanks; i++) { + // int index = (i + j) % tanks; + // FluidTank tank = getFluidTanks()[index]; + // FluidStack fluid = tank.getFluid(); + // if (fluid == null) + // continue; + // if (fluid.amount <= 0) { + // tank.setFluid(null); + // continue; + // } + // + // if (shouldDistribute) { + // distributeFluid(index, tank, fluid); + // lastReceivedFrom = 0; + // } + // } + // oldLastReceivedFrom = lastReceivedFrom; + // } } @Override diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java index ebc361578e0..ab788d4b036 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java @@ -70,7 +70,8 @@ public boolean canBridge(@NotNull Collection seen) } private void setPipesActive() { - NetGroup group = getNet().getNode(this.pipe.getPipePos()).getGroupSafe(); + NetGroup group = getNet().getNode(this.pipe.getPipePos()) + .getGroupSafe(); if (group != null) { for (NodeG node : group.getNodes()) { if (node.getHeldMTE() instanceof TileEntityOpticalPipe opticalPipe) { From a7d2b48dac0d084c406085a7b26feace5e502b65 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 19 Jan 2024 23:11:16 -0700 Subject: [PATCH 041/157] Sink registration --- .../java/gregtech/api/pipenet/NetGroup.java | 22 ++++++++++++++++--- src/main/java/gregtech/api/pipenet/NodeG.java | 1 + 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 8c08996b893..7e19a2c2efd 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -3,6 +3,7 @@ import gregtech.api.pipenet.block.IPipeType; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.INBTSerializable; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; @@ -53,17 +54,32 @@ private void clear() { protected void addNode(NodeG node) { this.nodes.add(node); node.setGroup(this); + this.connectionChange(node); } protected void addNodes(Set> nodes) { this.nodes.addAll(nodes); - nodes.forEach(a -> a.setGroup(this)); + nodes.forEach(a -> { + a.setGroup(this); + this.connectionChange(a); + }); } @SafeVarargs protected final void addNodes(NodeG... nodes) { for (NodeG node : nodes) { this.addNode(node); + this.connectionChange(node); + } + } + + public void connectionChange(NodeG node) { + if (!this.net.isFlow()) return; + // if it has non-pipe TE connections, we need to treat it as an active sink. Very wide definition. + if (node.getConnecteds().size() != 0) { + this.getChannelManager().getActiveSinks().add(node); + } else { + this.getChannelManager().getActiveSinks().remove(node); } } @@ -141,7 +157,7 @@ public boolean splitNode(NodeG source) { targets.remove(temp); } this.nodes.removeAll(targetGroup); - if (targetGroup.size() > 0) { + if (targetGroup.size() != 0) { if (this.net.isFlow()) { // remove our owned nodes from their manager, and remove their nodes from our manager. new NetGroup<>(this.graph, this.net, targetGroup) @@ -177,7 +193,7 @@ public boolean splitEdge(NodeG source, NodeG 0) { + if (targetGroup.size() != 0) { if (this.net.isFlow()) { // remove our owned nodes from their manager, and remove their nodes from our manager. new NetGroup<>(this.graph, this.net, targetGroup) diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 736bc40a858..7c062350d0b 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -175,6 +175,7 @@ void setConnected(EnumFacing facing, boolean connect) { this.activeConnections &= ~(1 << facing.getIndex()); } this.getHeldMTE().onConnectionChange(); + this.getGroupSafe().connectionChange(this); } public int getActiveConnections() { From 28c01cb949954768217f55c3279e5654c8c28622 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 19 Jan 2024 23:19:53 -0700 Subject: [PATCH 042/157] Remove some unnecessary things --- .../api/pipenet/WorldPipeFlowNetG.java | 14 ++-- .../gregtech/api/pipenet/WorldPipeNetG.java | 9 ++- .../api/pipenet/alg/MaximumFlowAlgorithm.java | 69 ++----------------- .../api/pipenet/alg/NetAlgorithm.java | 1 + .../pipelike/fluidpipe/net/FluidChannel.java | 1 + 5 files changed, 22 insertions(+), 72 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java index b91711cfeed..dcc67bfc424 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java @@ -3,9 +3,14 @@ import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.tile.TileEntityPipeBase; + +import org.jetbrains.annotations.Nullable; import org.jgrapht.graph.SimpleDirectedWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph; +import java.util.List; + public abstract class WorldPipeFlowNetG, PipeType extends Enum & IPipeType> extends WorldPipeNetG { @@ -15,16 +20,17 @@ public abstract class WorldPipeFlowNetG(); else this.pipeGraph = new FlowUndirected<>(); } @Override - protected void rebuildNetAlgorithm() { - this.netAlgorithm.setAlg(new MaximumFlowAlgorithm<>(pipeGraph)); - this.validAlgorithmInstance = true; + public List> getPaths(@Nullable NodeG node, + @Nullable TileEntityPipeBase tile) { + throw new IllegalStateException("Cannot get paths from a flow network. " + + "Must locally instantiate algorithm and evaluate; look at the FluidChannel class as an example."); } public interface IFlowGraph, PT extends Enum & IPipeType> { diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index 3bb4f9e77d9..dda393a9e25 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -68,15 +68,18 @@ public WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath) { this.isFlow = false; } - WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath, boolean isFlow) { + /** + * Override ONLY for use by {@link WorldPipeFlowNetG} + */ + WorldPipeNetG(boolean isDirected, boolean isSinglePath, String name) { super(name); if (isDirected()) this.pipeGraph = new SimpleDirectedWeightedGraph<>(NetEdge.class); else this.pipeGraph = new SimpleWeightedGraph<>(NetEdge.class); - this.netAlgorithm = new NetAlgorithm.NetAlgorithmWrapper<>(); + this.netAlgorithm = null; this.isDirected = isDirected; this.isSinglePath = isSinglePath; - this.isFlow = isFlow; + this.isFlow = true; } public final boolean isDirected() { diff --git a/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java index 17a4b5ed1a7..63df23fabdf 100644 --- a/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java @@ -14,74 +14,13 @@ import java.util.List; import java.util.Map; +/** + * Secretly just {@link PushRelabelMFImpl}, but may be modified in the future. + */ public final class MaximumFlowAlgorithm & IPipeType, NDT extends INodeData> - extends PushRelabelMFImpl, NetEdge> - implements NetAlgorithm { - - private NodeG superSource = new NodeG<>(); - private Map, Double> activeSources = new Object2DoubleOpenHashMap<>(); - - private NodeG superSink = new NodeG<>(); - private Map, Double> activeSinks = new Object2DoubleOpenHashMap<>(); + extends PushRelabelMFImpl, NetEdge> { public MaximumFlowAlgorithm(Graph, NetEdge> network) { super(network); } - - @Override - public List> getPathsList(NodeG source) { - if (!network.containsVertex(source)) { - throw new IllegalArgumentException("Graph must contain the source vertex"); - } - List> paths = new ObjectArrayList<>(); - paths.add(new NetPath<>(source)); - // if the source has no group, it has no paths other than the path to itself. - if (source.getGroupSafe() == null) return paths; - - for (NodeG v : source.getGroupSafe().getNodes()) { - if (v == source) continue; - // paths.add(new FlowPath<>(wrapper)); - } - return paths; - } - - /** - * Prime the edges to the super nodes to prepare for calculations. - */ - private void activate() { - for (Map.Entry, Double> source : activeSources.entrySet()) { - network.setEdgeWeight(superSource, source.getKey(), source.getValue()); - } - for (Map.Entry, Double> sink : activeSinks.entrySet()) { - network.setEdgeWeight(superSink, sink.getKey(), sink.getValue()); - } - } - - /** - * Zero out the edges to the super nodes to prevent other calculations from using them. - */ - private void deactivate() { - for (Map.Entry, Double> source : activeSources.entrySet()) { - network.setEdgeWeight(superSource, source.getKey(), 0); - } - for (Map.Entry, Double> sink : activeSinks.entrySet()) { - network.setEdgeWeight(superSink, sink.getKey(), 0); - } - } - - public void setSource(NodeG source, double amount) { - if (amount <= 0) { - activeSources.remove(source); - return; - } - activeSources.put(source, amount); - } - - public void setSink(NodeG sink, double amount) { - if (amount <= 0) { - activeSinks.remove(sink); - return; - } - activeSinks.put(sink, amount); - } } diff --git a/src/main/java/gregtech/api/pipenet/alg/NetAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/NetAlgorithm.java index a471311db38..90f589ad849 100644 --- a/src/main/java/gregtech/api/pipenet/alg/NetAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/NetAlgorithm.java @@ -7,6 +7,7 @@ import java.util.List; +@FunctionalInterface public interface NetAlgorithm & IPipeType, NDT extends INodeData> { List> getPathsList(NodeG source); diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java index b138483a638..7912518a563 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -86,6 +86,7 @@ public void evaluate() { // destroyethify if (node.getHeldMTE() instanceof TileEntityFluidPipeTickable f) { f.checkAndDestroy(fluid); + // TODO implement fluid leakage? } } } From fd8d17c3f4ffda6153d4480504e3c62a8052897d Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 22 Jan 2024 08:08:24 -0700 Subject: [PATCH 043/157] Move stuff from tickable Fpipe class to normal Fpipe class --- .../pipelike/fluidpipe/BlockFluidPipe.java | 11 +- .../pipelike/fluidpipe/net/FluidChannel.java | 9 +- .../pipelike/fluidpipe/net/PipeTankList.java | 4 +- .../fluidpipe/tile/TileEntityFluidPipe.java | 330 +++++++++++- .../tile/TileEntityFluidPipeTickable.java | 509 ++++-------------- 5 files changed, 448 insertions(+), 415 deletions(-) diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java index 31d5d8ef646..c6d37c4ece2 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java @@ -131,14 +131,13 @@ public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @No @NotNull Entity entityIn) { if (worldIn.isRemote) return; TileEntityFluidPipe pipe = (TileEntityFluidPipe) getPipeTileEntity(worldIn, pos); - if (pipe instanceof TileEntityFluidPipeTickable && pipe.getFrameMaterial() == null && - ((TileEntityFluidPipeTickable) pipe).getOffsetTimer() % 10 == 0) { + if (pipe.getFrameMaterial() == null && pipe.getOffsetTimer() % 10 == 0) { if (entityIn instanceof EntityLivingBase) { - if (((TileEntityFluidPipeTickable) pipe).getFluidTanks().length > 1) { + if (pipe.getFluidTanks().length > 1) { // apply temperature damage for the hottest and coldest pipe (multi fluid pipes) int maxTemperature = Integer.MIN_VALUE; int minTemperature = Integer.MAX_VALUE; - for (FluidTank tank : ((TileEntityFluidPipeTickable) pipe).getFluidTanks()) { + for (FluidTank tank : pipe.getFluidTanks()) { if (tank.getFluid() != null && tank.getFluid().amount > 0) { maxTemperature = Math.max(maxTemperature, tank.getFluid().getFluid().getTemperature(tank.getFluid())); @@ -153,7 +152,7 @@ public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @No EntityDamageUtil.applyTemperatureDamage((EntityLivingBase) entityIn, minTemperature, 1.0F, 5); } } else { - FluidTank tank = ((TileEntityFluidPipeTickable) pipe).getFluidTanks()[0]; + FluidTank tank = pipe.getFluidTanks()[0]; if (tank.getFluid() != null && tank.getFluid().amount > 0) { // Apply temperature damage for the pipe (single fluid pipes) EntityDamageUtil.applyTemperatureDamage((EntityLivingBase) entityIn, @@ -166,7 +165,7 @@ public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @No @Override public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { - return new TileEntityFluidPipeTickable(); // fluid pipes are always ticking + return supportsTicking ? new TileEntityFluidPipeTickable() : new TileEntityFluidPipe(); } @Override diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java index 7912518a563..3ed532ae75e 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -12,6 +12,7 @@ import gregtech.common.covers.CoverShutter; import gregtech.common.covers.filter.FluidFilter; import gregtech.common.pipelike.fluidpipe.FluidPipeType; +import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipeTickable; import net.minecraft.tileentity.TileEntity; @@ -84,7 +85,7 @@ public void evaluate() { throw new IllegalStateException("Node rejected channel despite approving it earlier!"); if (!node.getData().test(fluid)) { // destroyethify - if (node.getHeldMTE() instanceof TileEntityFluidPipeTickable f) { + if (node.getHeldMTE() instanceof TileEntityFluidPipe f) { f.checkAndDestroy(fluid); // TODO implement fluid leakage? } @@ -120,7 +121,7 @@ protected double getSourceValue(NodeG source private double pullFromNode(NodeG source, int amount, boolean doDrain) { FluidStack stack = null; - if (source.getHeldMTE() instanceof TileEntityFluidPipeTickable f) { + if (source.getHeldMTE() instanceof TileEntityFluidPipe f) { IFluidHandler handler = f.getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); if (handler != null) { @@ -137,7 +138,7 @@ protected double getSinkValue(NodeG sink) { private double pushToNode(NodeG sink, int amount, boolean doFill) { int flow = 0; - if (sink.getHeldMTE() instanceof TileEntityFluidPipeTickable f) { + if (sink.getHeldMTE() instanceof TileEntityFluidPipe f) { int fill; Byte receiveSides = this.receiveSidesMap.get(sink); for (Map.Entry connected : sink.getConnecteds().entrySet()) { @@ -152,7 +153,7 @@ private double pushToNode(NodeG sink, int am continue; } } - Cover thisCover = sink.getHeldMTE().getCoverableImplementation().getCoverAtSide(connected.getKey()); + Cover thisCover = f.getCoverableImplementation().getCoverAtSide(connected.getKey()); Cover themCover = getCoverOnNeighbour(sink, connected.getKey().getOpposite()); int transferMax = evaluateCover(themCover, evaluateCover(thisCover, amount)); IFluidHandler handler = connected.getValue().getCapability( diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java index 0b8a50e2fff..f7a7cc92b28 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java @@ -18,14 +18,14 @@ public class PipeTankList implements IFluidHandler, Iterable { - private final TileEntityFluidPipeTickable pipe; + private final TileEntityFluidPipe pipe; private final FluidTank[] tanks; private IFluidTankProperties[] properties; private final EnumFacing facing; public PipeTankList(TileEntityFluidPipe pipe, EnumFacing facing, FluidTank... fluidTanks) { this.tanks = fluidTanks; - this.pipe = (TileEntityFluidPipeTickable) pipe; + this.pipe = pipe; this.facing = facing; } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java index 21c2b0cdc6e..79c5b4b8fa6 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java @@ -1,21 +1,273 @@ package gregtech.common.pipelike.fluidpipe.tile; import gregtech.api.GTValues; +import gregtech.api.fluids.FluidConstants; +import gregtech.api.fluids.FluidState; +import gregtech.api.fluids.attribute.AttributedFluid; +import gregtech.api.fluids.attribute.FluidAttribute; +import gregtech.api.metatileentity.IDataInfoProvider; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.api.util.EntityDamageUtil; +import gregtech.api.util.TextFormattingUtil; import gregtech.common.pipelike.fluidpipe.FluidPipeType; +import gregtech.common.pipelike.fluidpipe.net.FluidChannel; +import gregtech.common.pipelike.fluidpipe.net.PipeTankList; + import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.Blocks; +import net.minecraft.init.SoundEvents; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.Style; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraft.world.WorldServer; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; + +import net.minecraftforge.fluids.capability.IFluidHandler; + +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -public class TileEntityFluidPipe extends TileEntityMaterialPipeBase { +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; - public static final int FREQUENCY = 5; +public class TileEntityFluidPipe extends TileEntityMaterialPipeBase + implements IDataInfoProvider { + + private PipeTankList pipeTankList; + private final EnumMap tankLists = new EnumMap<>(EnumFacing.class); + private FluidTank[] fluidTanks; + private final int offset = GTValues.RNG.nextInt(20); + + public long getOffsetTimer() { + return FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter() + offset; + } + + @Nullable + @Override + public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { + if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { + PipeTankList tankList = getTankList(facing); + if (tankList == null) + return null; + return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(tankList); + } + return super.getCapabilityInternal(capability, facing); + } + + public void checkAndDestroy(@NotNull FluidStack stack) { + Fluid fluid = stack.getFluid(); + FluidPipeProperties prop = getNodeData(); + + boolean burning = prop.getMaxFluidTemperature() < fluid.getTemperature(stack); + boolean leaking = !prop.isGasProof() && fluid.isGaseous(stack); + boolean shattering = !prop.isCryoProof() && fluid.getTemperature() < FluidConstants.CRYOGENIC_FLUID_THRESHOLD; + boolean corroding = false; + boolean melting = false; + + if (fluid instanceof AttributedFluid attributedFluid) { + FluidState state = attributedFluid.getState(); + if (!prop.canContain(state)) { + leaking = state == FluidState.GAS; + melting = state == FluidState.PLASMA; + } + + // carrying plasmas which are too hot when plasma proof does not burn pipes + if (burning && state == FluidState.PLASMA && prop.canContain(FluidState.PLASMA)) { + burning = false; + } + + for (FluidAttribute attribute : attributedFluid.getAttributes()) { + if (!prop.canContain(attribute)) { + // corrodes if the pipe can't handle the attribute, even if it's not an acid + corroding = true; + } + } + } + + if (burning || leaking || corroding || shattering || melting) { + destroyPipe(stack, burning, leaking, corroding, shattering, melting); + } + } + + public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, boolean isCorroding, + boolean isShattering, boolean isMelting) { + // prevent the sound from spamming when filled from anything not a pipe + if (getOffsetTimer() % 10 == 0) { + world.playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); + } + + if (isLeaking) { + TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.SMOKE_NORMAL, + 7 + GTValues.RNG.nextInt(2)); + + // voids 10% + stack.amount = Math.max(0, stack.amount * 9 / 10); + + // apply heat damage in area surrounding the pipe + if (getOffsetTimer() % 20 == 0) { + List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(getPipePos()).grow(2)); + for (EntityLivingBase entityLivingBase : entities) { + EntityDamageUtil.applyTemperatureDamage(entityLivingBase, stack.getFluid().getTemperature(stack), + 2.0F, 10); + } + } + + // chance to do a small explosion + if (GTValues.RNG.nextInt(isBurning ? 3 : 7) == 0) { + this.doExplosion(1.0f + GTValues.RNG.nextFloat()); + } + } + + if (isCorroding) { + TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.CRIT_MAGIC, + 3 + GTValues.RNG.nextInt(2)); + + // voids 25% + stack.amount = Math.max(0, stack.amount * 3 / 4); + + // apply chemical damage in area surrounding the pipe + if (getOffsetTimer() % 20 == 0) { + List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(getPipePos()).grow(1)); + for (EntityLivingBase entityLivingBase : entities) { + EntityDamageUtil.applyChemicalDamage(entityLivingBase, 2); + } + } + + // 1/10 chance to void everything and destroy the pipe + if (GTValues.RNG.nextInt(10) == 0) { + stack.amount = 0; + world.setBlockToAir(pos); + } + } + + if (isBurning || isMelting) { + TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.FLAME, + (isMelting ? 7 : 3) + GTValues.RNG.nextInt(2)); + + // voids 75% + stack.amount = Math.max(0, stack.amount / 4); + + // 1/4 chance to burn everything around it + if (GTValues.RNG.nextInt(4) == 0) { + TileEntityFluidPipe.setNeighboursToFire(world, pos); + } + + // apply heat damage in area surrounding the pipe + if (isMelting && getOffsetTimer() % 20 == 0) { + List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(getPipePos()).grow(2)); + for (EntityLivingBase entityLivingBase : entities) { + EntityDamageUtil.applyTemperatureDamage(entityLivingBase, stack.getFluid().getTemperature(stack), + 2.0F, 10); + } + } + + // 1/10 chance to void everything and burn the pipe + if (GTValues.RNG.nextInt(10) == 0) { + stack.amount = 0; + world.setBlockState(pos, Blocks.FIRE.getDefaultState()); + } + } + + if (isShattering) { + TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.CLOUD, + 3 + GTValues.RNG.nextInt(2)); + + // voids 75% + stack.amount = Math.max(0, stack.amount / 4); + + // apply frost damage in area surrounding the pipe + if (getOffsetTimer() % 20 == 0) { + List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(getPipePos()).grow(2)); + for (EntityLivingBase entityLivingBase : entities) { + EntityDamageUtil.applyTemperatureDamage(entityLivingBase, stack.getFluid().getTemperature(stack), + 2.0F, 10); + } + } + + // 1/10 chance to void everything and freeze the pipe + if (GTValues.RNG.nextInt(10) == 0) { + stack.amount = 0; + world.setBlockToAir(pos); + } + } + } + + public void receivedFrom(Fluid fluid, EnumFacing facing) { + // on fluid received, add us as a source to the proper channel + FluidChannel channel = FluidChannel.getChannelFromGroup(fluid, this.getNode().getGroupSafe()); + channel.addSource(this.getNode()); + if (facing != null) { + channel.addReceiveSide(this.getNode(), facing); + } + } + + public FluidStack getContainedFluid(int channel) { + if (channel < 0 || channel >= getFluidTanks().length) return null; + return getFluidTanks()[channel].getFluid(); + } + + private void createTanksList() { + fluidTanks = new FluidTank[getNodeData().getTanks()]; + for (int i = 0; i < getNodeData().getTanks(); i++) { + fluidTanks[i] = new FluidTank(getCapacityPerTank()); + } + pipeTankList = new PipeTankList(this, null, fluidTanks); + for (EnumFacing facing : EnumFacing.VALUES) { + tankLists.put(facing, new PipeTankList(this, facing, fluidTanks)); + } + } + + public PipeTankList getTankList() { + if (pipeTankList == null || fluidTanks == null) { + createTanksList(); + } + return pipeTankList; + } + + public PipeTankList getTankList(EnumFacing facing) { + if (tankLists.isEmpty() || fluidTanks == null) { + createTanksList(); + } + return tankLists.getOrDefault(facing, pipeTankList); + } + + public FluidTank[] getFluidTanks() { + if (pipeTankList == null || fluidTanks == null) { + createTanksList(); + } + return fluidTanks; + } + + public FluidStack[] getContainedFluids() { + FluidStack[] fluids = new FluidStack[getFluidTanks().length]; + for (int i = 0; i < fluids.length; i++) { + fluids[i] = fluidTanks[i].getFluid(); + } + return fluids; + } @Override public Class getPipeTypeClass() { @@ -57,4 +309,78 @@ public static void spawnParticles(World worldIn, BlockPos pos, EnumFacing direct 0.1); } } + + @NotNull + @Override + public NBTTagCompound writeToNBT(@NotNull NBTTagCompound nbt) { + super.writeToNBT(nbt); + NBTTagList list = new NBTTagList(); + for (int i = 0; i < getFluidTanks().length; i++) { + FluidStack stack1 = getContainedFluid(i); + NBTTagCompound fluidTag = new NBTTagCompound(); + if (stack1 == null || stack1.amount <= 0) + fluidTag.setBoolean("isNull", true); + else + stack1.writeToNBT(fluidTag); + list.appendTag(fluidTag); + } + nbt.setTag("Fluids", list); + return nbt; + } + + @Override + public void readFromNBT(@NotNull NBTTagCompound nbt) { + super.readFromNBT(nbt); + NBTTagList list = (NBTTagList) nbt.getTag("Fluids"); + createTanksList(); + for (int i = 0; i < list.tagCount(); i++) { + NBTTagCompound tag = list.getCompoundTagAt(i); + if (!tag.getBoolean("isNull")) { + fluidTanks[i].setFluid(FluidStack.loadFluidStackFromNBT(tag)); + } + } + } + + @NotNull + @Override + public List getDataInfo() { + List list = new ArrayList<>(); + + FluidStack[] fluids = this.getContainedFluids(); + if (fluids != null) { + boolean allTanksEmpty = true; + for (int i = 0; i < fluids.length; i++) { + if (fluids[i] != null) { + if (fluids[i].getFluid() == null) + continue; + + allTanksEmpty = false; + list.add(new TextComponentTranslation("behavior.tricorder.tank", i, + new TextComponentTranslation(TextFormattingUtil.formatNumbers(fluids[i].amount)) + .setStyle(new Style().setColor(TextFormatting.GREEN)), + new TextComponentTranslation(TextFormattingUtil.formatNumbers(this.getCapacityPerTank())) + .setStyle(new Style().setColor(TextFormatting.YELLOW)), + new TextComponentTranslation(fluids[i].getFluid().getLocalizedName(fluids[i])) + .setStyle(new Style().setColor(TextFormatting.GOLD)))); + } + } + + if (allTanksEmpty) + list.add(new TextComponentTranslation("behavior.tricorder.tanks_empty")); + } + return list; + } + + private static class FluidTransaction { + + public final IFluidHandler target; + public final IFluidHandler pipeTank; + public int amount; + + private FluidTransaction(IFluidHandler target, IFluidHandler pipeTank, int amount) { + this.target = target; + this.pipeTank = pipeTank; + this.amount = amount; + } + } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java index 5ab17d8f9e7..97b3ece73d5 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java @@ -46,30 +46,7 @@ import java.util.EnumMap; import java.util.List; -public class TileEntityFluidPipeTickable extends TileEntityFluidPipe implements ITickable, IDataInfoProvider { - - public byte lastReceivedFrom = 0, oldLastReceivedFrom = 0; - private PipeTankList pipeTankList; - private final EnumMap tankLists = new EnumMap<>(EnumFacing.class); - private FluidTank[] fluidTanks; - private long timer = 0L; - private final int offset = GTValues.RNG.nextInt(20); - - public long getOffsetTimer() { - return timer + offset; - } - - @Nullable - @Override - public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { - if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { - PipeTankList tankList = getTankList(facing); - if (tankList == null) - return null; - return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(tankList); - } - return super.getCapabilityInternal(capability, facing); - } +public class TileEntityFluidPipeTickable extends TileEntityFluidPipe implements ITickable { @Override public void update() { @@ -108,381 +85,111 @@ public boolean supportsTicking() { return true; } - private void distributeFluid(int channel, FluidTank tank, FluidStack fluid) { - // Tank, From, Amount to receive - List tanks = new ArrayList<>(); - int amount = fluid.amount; - - FluidStack maxFluid = fluid.copy(); - double availableCapacity = 0; - - for (byte i = 0, j = (byte) GTValues.RNG.nextInt(6); i < 6; i++) { - // Get a list of tanks accepting fluids, and what side they're on - byte side = (byte) ((i + j) % 6); - EnumFacing facing = EnumFacing.VALUES[side]; - - if (!isConnected(facing) || (lastReceivedFrom & (1 << side)) != 0) { - continue; - } - - TileEntity neighbor = getNeighbor(facing); - if (neighbor == null) continue; - IFluidHandler fluidHandler = neighbor.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - facing.getOpposite()); - if (fluidHandler == null) continue; - - IFluidHandler pipeTank = tank; - Cover cover = getCoverableImplementation().getCoverAtSide(facing); - - // pipeTank should only be determined by the cover attached to the actual pipe - if (cover != null) { - pipeTank = cover.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, pipeTank); - // Shutter covers return null capability when active, so check here to prevent NPE - if (pipeTank == null || checkForPumpCover(cover)) continue; - } else { - CoverableView coverable = neighbor.getCapability(GregtechTileCapabilities.CAPABILITY_COVER_HOLDER, - facing.getOpposite()); - if (coverable != null) { - cover = coverable.getCoverAtSide(facing.getOpposite()); - if (checkForPumpCover(cover)) continue; - } - } - - FluidStack drainable = pipeTank.drain(maxFluid, false); - if (drainable == null || drainable.amount <= 0) { - continue; - } - - int filled = Math.min(fluidHandler.fill(maxFluid, false), drainable.amount); - - if (filled > 0) { - tanks.add(new FluidTransaction(fluidHandler, pipeTank, filled)); - availableCapacity += filled; - } - maxFluid.amount = amount; // Because some mods do actually modify input fluid stack - } - - if (availableCapacity <= 0) - return; - - // How much of this fluid is available for distribution? - final double maxAmount = Math.min(getCapacityPerTank() / 2, fluid.amount); - - // Now distribute - for (FluidTransaction transaction : tanks) { - if (availableCapacity > maxAmount) { - transaction.amount = (int) Math.floor(transaction.amount * maxAmount / availableCapacity); // Distribute - // fluids - // based on - // percentage - // available - // space at - // destination - } - if (transaction.amount == 0) { - if (tank.getFluidAmount() <= 0) break; // If there is no more stored fluid, stop transferring to prevent - // dupes - transaction.amount = 1; // If the percent is not enough to give at least 1L, try to give 1L - } else if (transaction.amount < 0) { - continue; - } - - FluidStack toInsert = fluid.copy(); - toInsert.amount = transaction.amount; - - int inserted = transaction.target.fill(toInsert, true); - if (inserted > 0) { - transaction.pipeTank.drain(inserted, true); - } - } - } - - private boolean checkForPumpCover(@Nullable Cover cover) { - if (cover instanceof CoverPump coverPump) { - int pipeThroughput = getNodeData().getThroughput() * 20; - if (coverPump.getTransferRate() > pipeThroughput) { - coverPump.setTransferRate(pipeThroughput); - } - return coverPump.getManualImportExportMode() == ManualImportExportMode.DISABLED; - } - return false; - } - - public void checkAndDestroy(@NotNull FluidStack stack) { - Fluid fluid = stack.getFluid(); - FluidPipeProperties prop = getNodeData(); - - boolean burning = prop.getMaxFluidTemperature() < fluid.getTemperature(stack); - boolean leaking = !prop.isGasProof() && fluid.isGaseous(stack); - boolean shattering = !prop.isCryoProof() && fluid.getTemperature() < FluidConstants.CRYOGENIC_FLUID_THRESHOLD; - boolean corroding = false; - boolean melting = false; - - if (fluid instanceof AttributedFluid attributedFluid) { - FluidState state = attributedFluid.getState(); - if (!prop.canContain(state)) { - leaking = state == FluidState.GAS; - melting = state == FluidState.PLASMA; - } - - // carrying plasmas which are too hot when plasma proof does not burn pipes - if (burning && state == FluidState.PLASMA && prop.canContain(FluidState.PLASMA)) { - burning = false; - } - - for (FluidAttribute attribute : attributedFluid.getAttributes()) { - if (!prop.canContain(attribute)) { - // corrodes if the pipe can't handle the attribute, even if it's not an acid - corroding = true; - } - } - } - - if (burning || leaking || corroding || shattering || melting) { - destroyPipe(stack, burning, leaking, corroding, shattering, melting); - } - } - - public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, boolean isCorroding, - boolean isShattering, boolean isMelting) { - // prevent the sound from spamming when filled from anything not a pipe - if (getOffsetTimer() % 10 == 0) { - world.playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); - } - - if (isLeaking) { - TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.SMOKE_NORMAL, - 7 + GTValues.RNG.nextInt(2)); - - // voids 10% - stack.amount = Math.max(0, stack.amount * 9 / 10); - - // apply heat damage in area surrounding the pipe - if (getOffsetTimer() % 20 == 0) { - List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, - new AxisAlignedBB(getPipePos()).grow(2)); - for (EntityLivingBase entityLivingBase : entities) { - EntityDamageUtil.applyTemperatureDamage(entityLivingBase, stack.getFluid().getTemperature(stack), - 2.0F, 10); - } - } - - // chance to do a small explosion - if (GTValues.RNG.nextInt(isBurning ? 3 : 7) == 0) { - this.doExplosion(1.0f + GTValues.RNG.nextFloat()); - } - } - - if (isCorroding) { - TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.CRIT_MAGIC, - 3 + GTValues.RNG.nextInt(2)); - - // voids 25% - stack.amount = Math.max(0, stack.amount * 3 / 4); - - // apply chemical damage in area surrounding the pipe - if (getOffsetTimer() % 20 == 0) { - List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, - new AxisAlignedBB(getPipePos()).grow(1)); - for (EntityLivingBase entityLivingBase : entities) { - EntityDamageUtil.applyChemicalDamage(entityLivingBase, 2); - } - } - - // 1/10 chance to void everything and destroy the pipe - if (GTValues.RNG.nextInt(10) == 0) { - stack.amount = 0; - world.setBlockToAir(pos); - } - } - - if (isBurning || isMelting) { - TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.FLAME, - (isMelting ? 7 : 3) + GTValues.RNG.nextInt(2)); - - // voids 75% - stack.amount = Math.max(0, stack.amount / 4); - - // 1/4 chance to burn everything around it - if (GTValues.RNG.nextInt(4) == 0) { - TileEntityFluidPipe.setNeighboursToFire(world, pos); - } - - // apply heat damage in area surrounding the pipe - if (isMelting && getOffsetTimer() % 20 == 0) { - List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, - new AxisAlignedBB(getPipePos()).grow(2)); - for (EntityLivingBase entityLivingBase : entities) { - EntityDamageUtil.applyTemperatureDamage(entityLivingBase, stack.getFluid().getTemperature(stack), - 2.0F, 10); - } - } - - // 1/10 chance to void everything and burn the pipe - if (GTValues.RNG.nextInt(10) == 0) { - stack.amount = 0; - world.setBlockState(pos, Blocks.FIRE.getDefaultState()); - } - } - - if (isShattering) { - TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.CLOUD, - 3 + GTValues.RNG.nextInt(2)); - - // voids 75% - stack.amount = Math.max(0, stack.amount / 4); - - // apply frost damage in area surrounding the pipe - if (getOffsetTimer() % 20 == 0) { - List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, - new AxisAlignedBB(getPipePos()).grow(2)); - for (EntityLivingBase entityLivingBase : entities) { - EntityDamageUtil.applyTemperatureDamage(entityLivingBase, stack.getFluid().getTemperature(stack), - 2.0F, 10); - } - } - - // 1/10 chance to void everything and freeze the pipe - if (GTValues.RNG.nextInt(10) == 0) { - stack.amount = 0; - world.setBlockToAir(pos); - } - } - } - - private IFluidHandler getFluidHandlerAt(EnumFacing facing, EnumFacing oppositeSide) { - TileEntity tile = world.getTileEntity(pos.offset(facing)); - if (tile == null) { - return null; - } - return tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, oppositeSide); - } - - public void receivedFrom(Fluid fluid, EnumFacing facing) { - // on fluid received, add us as a source to the proper channel - FluidChannel channel = FluidChannel.getChannelFromGroup(fluid, this.getNode().getGroupSafe()); - channel.addSource(this.getNode()); - if (facing != null) { - channel.addReceiveSide(this.getNode(), facing); - } - } - - public FluidStack getContainedFluid(int channel) { - if (channel < 0 || channel >= getFluidTanks().length) return null; - return getFluidTanks()[channel].getFluid(); - } - - private void createTanksList() { - fluidTanks = new FluidTank[getNodeData().getTanks()]; - for (int i = 0; i < getNodeData().getTanks(); i++) { - fluidTanks[i] = new FluidTank(getCapacityPerTank()); - } - pipeTankList = new PipeTankList(this, null, fluidTanks); - for (EnumFacing facing : EnumFacing.VALUES) { - tankLists.put(facing, new PipeTankList(this, facing, fluidTanks)); - } - } - - public PipeTankList getTankList() { - if (pipeTankList == null || fluidTanks == null) { - createTanksList(); - } - return pipeTankList; - } - - public PipeTankList getTankList(EnumFacing facing) { - if (tankLists.isEmpty() || fluidTanks == null) { - createTanksList(); - } - return tankLists.getOrDefault(facing, pipeTankList); - } - - public FluidTank[] getFluidTanks() { - if (pipeTankList == null || fluidTanks == null) { - createTanksList(); - } - return fluidTanks; - } - - public FluidStack[] getContainedFluids() { - FluidStack[] fluids = new FluidStack[getFluidTanks().length]; - for (int i = 0; i < fluids.length; i++) { - fluids[i] = fluidTanks[i].getFluid(); - } - return fluids; - } - - @NotNull - @Override - public NBTTagCompound writeToNBT(@NotNull NBTTagCompound nbt) { - super.writeToNBT(nbt); - NBTTagList list = new NBTTagList(); - for (int i = 0; i < getFluidTanks().length; i++) { - FluidStack stack1 = getContainedFluid(i); - NBTTagCompound fluidTag = new NBTTagCompound(); - if (stack1 == null || stack1.amount <= 0) - fluidTag.setBoolean("isNull", true); - else - stack1.writeToNBT(fluidTag); - list.appendTag(fluidTag); - } - nbt.setTag("Fluids", list); - return nbt; - } - - @Override - public void readFromNBT(@NotNull NBTTagCompound nbt) { - super.readFromNBT(nbt); - NBTTagList list = (NBTTagList) nbt.getTag("Fluids"); - createTanksList(); - for (int i = 0; i < list.tagCount(); i++) { - NBTTagCompound tag = list.getCompoundTagAt(i); - if (!tag.getBoolean("isNull")) { - fluidTanks[i].setFluid(FluidStack.loadFluidStackFromNBT(tag)); - } - } - } - - @NotNull - @Override - public List getDataInfo() { - List list = new ArrayList<>(); - - FluidStack[] fluids = this.getContainedFluids(); - if (fluids != null) { - boolean allTanksEmpty = true; - for (int i = 0; i < fluids.length; i++) { - if (fluids[i] != null) { - if (fluids[i].getFluid() == null) - continue; - - allTanksEmpty = false; - list.add(new TextComponentTranslation("behavior.tricorder.tank", i, - new TextComponentTranslation(TextFormattingUtil.formatNumbers(fluids[i].amount)) - .setStyle(new Style().setColor(TextFormatting.GREEN)), - new TextComponentTranslation(TextFormattingUtil.formatNumbers(this.getCapacityPerTank())) - .setStyle(new Style().setColor(TextFormatting.YELLOW)), - new TextComponentTranslation(fluids[i].getFluid().getLocalizedName(fluids[i])) - .setStyle(new Style().setColor(TextFormatting.GOLD)))); - } - } - - if (allTanksEmpty) - list.add(new TextComponentTranslation("behavior.tricorder.tanks_empty")); - } - return list; - } - - private static class FluidTransaction { - - public final IFluidHandler target; - public final IFluidHandler pipeTank; - public int amount; - - private FluidTransaction(IFluidHandler target, IFluidHandler pipeTank, int amount) { - this.target = target; - this.pipeTank = pipeTank; - this.amount = amount; - } - } +// private void distributeFluid(int channel, FluidTank tank, FluidStack fluid) { +// // Tank, From, Amount to receive +// List tanks = new ArrayList<>(); +// int amount = fluid.amount; +// +// FluidStack maxFluid = fluid.copy(); +// double availableCapacity = 0; +// +// for (byte i = 0, j = (byte) GTValues.RNG.nextInt(6); i < 6; i++) { +// // Get a list of tanks accepting fluids, and what side they're on +// byte side = (byte) ((i + j) % 6); +// EnumFacing facing = EnumFacing.VALUES[side]; +// +// if (!isConnected(facing) || (lastReceivedFrom & (1 << side)) != 0) { +// continue; +// } +// +// TileEntity neighbor = getNeighbor(facing); +// if (neighbor == null) continue; +// IFluidHandler fluidHandler = neighbor.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, +// facing.getOpposite()); +// if (fluidHandler == null) continue; +// +// IFluidHandler pipeTank = tank; +// Cover cover = getCoverableImplementation().getCoverAtSide(facing); +// +// // pipeTank should only be determined by the cover attached to the actual pipe +// if (cover != null) { +// pipeTank = cover.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, pipeTank); +// // Shutter covers return null capability when active, so check here to prevent NPE +// if (pipeTank == null || checkForPumpCover(cover)) continue; +// } else { +// CoverableView coverable = neighbor.getCapability(GregtechTileCapabilities.CAPABILITY_COVER_HOLDER, +// facing.getOpposite()); +// if (coverable != null) { +// cover = coverable.getCoverAtSide(facing.getOpposite()); +// if (checkForPumpCover(cover)) continue; +// } +// } +// +// FluidStack drainable = pipeTank.drain(maxFluid, false); +// if (drainable == null || drainable.amount <= 0) { +// continue; +// } +// +// int filled = Math.min(fluidHandler.fill(maxFluid, false), drainable.amount); +// +// if (filled > 0) { +// tanks.add(new FluidTransaction(fluidHandler, pipeTank, filled)); +// availableCapacity += filled; +// } +// maxFluid.amount = amount; // Because some mods do actually modify input fluid stack +// } +// +// if (availableCapacity <= 0) +// return; +// +// // How much of this fluid is available for distribution? +// final double maxAmount = Math.min(getCapacityPerTank() / 2, fluid.amount); +// +// // Now distribute +// for (FluidTransaction transaction : tanks) { +// if (availableCapacity > maxAmount) { +// transaction.amount = (int) Math.floor(transaction.amount * maxAmount / availableCapacity); // Distribute +// // fluids +// // based on +// // percentage +// // available +// // space at +// // destination +// } +// if (transaction.amount == 0) { +// if (tank.getFluidAmount() <= 0) break; // If there is no more stored fluid, stop transferring to prevent +// // dupes +// transaction.amount = 1; // If the percent is not enough to give at least 1L, try to give 1L +// } else if (transaction.amount < 0) { +// continue; +// } +// +// FluidStack toInsert = fluid.copy(); +// toInsert.amount = transaction.amount; +// +// int inserted = transaction.target.fill(toInsert, true); +// if (inserted > 0) { +// transaction.pipeTank.drain(inserted, true); +// } +// } +// } + +// private boolean checkForPumpCover(@Nullable Cover cover) { +// if (cover instanceof CoverPump coverPump) { +// int pipeThroughput = getNodeData().getThroughput() * 20; +// if (coverPump.getTransferRate() > pipeThroughput) { +// coverPump.setTransferRate(pipeThroughput); +// } +// return coverPump.getManualImportExportMode() == ManualImportExportMode.DISABLED; +// } +// return false; +// } +// +// private IFluidHandler getFluidHandlerAt(EnumFacing facing, EnumFacing oppositeSide) { +// TileEntity tile = world.getTileEntity(pos.offset(facing)); +// if (tile == null) { +// return null; +// } +// return tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, oppositeSide); +// } } From c00ee72c9f1243c722fc3cd9e426814ec0d4ad87 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 22 Jan 2024 08:42:44 -0700 Subject: [PATCH 044/157] Ticker (wait I thought this was supposed to be tickless) --- .../api/pipenet/FlowChannelManager.java | 10 +++++ .../api/pipenet/FlowChannelTicker.java | 39 +++++++++++++++++++ .../fluidpipe/tile/TileEntityFluidPipe.java | 20 +++------- 3 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/FlowChannelTicker.java diff --git a/src/main/java/gregtech/api/pipenet/FlowChannelManager.java b/src/main/java/gregtech/api/pipenet/FlowChannelManager.java index c3da6924003..3b54ba8fd04 100644 --- a/src/main/java/gregtech/api/pipenet/FlowChannelManager.java +++ b/src/main/java/gregtech/api/pipenet/FlowChannelManager.java @@ -2,6 +2,8 @@ import gregtech.api.pipenet.block.IPipeType; +import gregtech.common.pipelike.fluidpipe.net.FluidChannel; + import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Nullable; @@ -19,6 +21,14 @@ public class FlowChannelManager & IPipeType> channels = new Object2ObjectOpenHashMap<>(); + public FlowChannelManager() { + FlowChannelTicker.addManager(this); + } + + public void tick() { + channels.forEach((k, v) -> v.evaluate()); + } + /** * Updates active nodes based on the active nodes of another manager. */ diff --git a/src/main/java/gregtech/api/pipenet/FlowChannelTicker.java b/src/main/java/gregtech/api/pipenet/FlowChannelTicker.java new file mode 100644 index 00000000000..c961f6f5210 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/FlowChannelTicker.java @@ -0,0 +1,39 @@ +package gregtech.api.pipenet; + +import gregtech.api.GTValues; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.world.World; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +import java.lang.ref.WeakReference; +import java.util.Set; + +// Ok, I admit, truly tickless fluidpipes would mean sacrificing behavior. I'd have to make them act like itempipes. +// To get true 'flow' behavior, all sources and all destinations must be defined, then a single evaluation performed. +@Mod.EventBusSubscriber(modid = GTValues.MODID) +public final class FlowChannelTicker { + + private final static Set>> MANAGERS = new ObjectOpenHashSet<>(); + + @SubscribeEvent + public static void onServerTick(TickEvent.ServerTickEvent event) { + if (FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter() % 20 != 0) return; + for (WeakReference> ref : MANAGERS) { + FlowChannelManager manager = ref.get(); + if (manager != null) { + manager.tick(); + } else { + MANAGERS.remove(ref); + } + } + } + + public static void addManager(FlowChannelManager manager) { + MANAGERS.add(new WeakReference<>(manager)); + } +} diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java index 79c5b4b8fa6..f7d199d7513 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java @@ -336,7 +336,12 @@ public void readFromNBT(@NotNull NBTTagCompound nbt) { for (int i = 0; i < list.tagCount(); i++) { NBTTagCompound tag = list.getCompoundTagAt(i); if (!tag.getBoolean("isNull")) { - fluidTanks[i].setFluid(FluidStack.loadFluidStackFromNBT(tag)); + FluidStack stack = FluidStack.loadFluidStackFromNBT(tag); + if (stack == null) continue; + fluidTanks[i].setFluid(stack); + // the best part is that this naturally gives us backwards compatibility. + FluidChannel channel = FluidChannel.getChannelFromGroup(stack.getFluid(), this.getNode().getGroupSafe()); + channel.addSource(this.getNode()); } } } @@ -370,17 +375,4 @@ public List getDataInfo() { } return list; } - - private static class FluidTransaction { - - public final IFluidHandler target; - public final IFluidHandler pipeTank; - public int amount; - - private FluidTransaction(IFluidHandler target, IFluidHandler pipeTank, int amount) { - this.target = target; - this.pipeTank = pipeTank; - this.amount = amount; - } - } } From 886bad462b5ce3e734b48b191a84028509b58997 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 23 Jan 2024 10:19:03 -0700 Subject: [PATCH 045/157] Prevent nbt contamination by flow net calculation helpers --- .../api/pipenet/FlowChannelManager.java | 17 +++--- .../java/gregtech/api/pipenet/NetGroup.java | 2 +- .../api/pipenet/WorldPipeFlowNetG.java | 56 ++++++++++++++++++- .../gregtech/api/pipenet/WorldPipeNetG.java | 2 +- 4 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/FlowChannelManager.java b/src/main/java/gregtech/api/pipenet/FlowChannelManager.java index 3b54ba8fd04..7d0c455c25b 100644 --- a/src/main/java/gregtech/api/pipenet/FlowChannelManager.java +++ b/src/main/java/gregtech/api/pipenet/FlowChannelManager.java @@ -2,10 +2,9 @@ import gregtech.api.pipenet.block.IPipeType; -import gregtech.common.pipelike.fluidpipe.net.FluidChannel; - import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import org.jetbrains.annotations.Nullable; import java.util.Map; @@ -14,15 +13,15 @@ public class FlowChannelManager & IPipeType, NodeDataType extends INodeData> { - protected final NodeG superSource = new NodeG<>(); - protected final NodeG superSink = new NodeG<>(); + private final WorldPipeFlowNetG net; protected final Set> activeSinks = new ObjectOpenHashSet<>(); private final Map> channels = new Object2ObjectOpenHashMap<>(); - public FlowChannelManager() { - FlowChannelTicker.addManager(this); + public FlowChannelManager(WorldPipeFlowNetG net) { + this.net = net; + FlowChannelTicker.addManager(net.getWorld(), this); } public void tick() { @@ -44,7 +43,7 @@ public FlowChannelManager merge(FlowChannelManager subManager(Set> nodes) { - FlowChannelManager newManager = new FlowChannelManager<>(); + FlowChannelManager newManager = new FlowChannelManager<>(this.net); newManager.channels.putAll(this.channels); newManager.channels.forEach((key, value) -> { value.setManager(newManager); @@ -72,11 +71,11 @@ public void removeNode(NodeG node) { } public NodeG getSuperSource() { - return superSource; + return this.net.getSuperSource(); } public NodeG getSuperSink() { - return superSink; + return this.net.getSuperSink(); } public Set> getActiveSinks() { diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 7e19a2c2efd..31b920af1f8 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -242,7 +242,7 @@ private void setChannelManager(FlowChannelManager manage private FlowChannelManager getChannelManager() { if (this.channelManager == null) { - this.channelManager = new FlowChannelManager<>(); + this.channelManager = new FlowChannelManager<>((WorldPipeFlowNetG) this.net); } return this.channelManager; } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java index dcc67bfc424..5d400e940a7 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java @@ -1,19 +1,29 @@ package gregtech.api.pipenet; -import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.TileEntityPipeBase; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.nbt.NBTTagCompound; + +import net.minecraft.nbt.NBTTagList; + +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.graph.SimpleDirectedWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph; import java.util.List; +import java.util.Set; public abstract class WorldPipeFlowNetG, PipeType extends Enum & IPipeType> extends WorldPipeNetG { + private final NodeG superSource = new NodeG<>(); + private final NodeG superSink = new NodeG<>(); + /** * @param isDirected Determines whether this net needs directed graph handling. * Used to respect filter directions in the item net and fluid net, for example. @@ -24,6 +34,8 @@ public WorldPipeFlowNetG(String name, boolean isDirected) { if (isDirected()) this.pipeGraph = new FlowDirected<>(); else this.pipeGraph = new FlowUndirected<>(); + this.pipeGraph.addVertex(superSource); + this.pipeGraph.addVertex(superSink); } @Override @@ -33,6 +45,48 @@ public List> getPaths(@Nullable NodeG> groups = new ObjectOpenHashSet<>(); + for (NodeG node : pipeGraph.vertexSet()) { + // prevent contamination by our supernodes + if (node == superSource || node == superSink) continue; + if (node.getGroupUnsafe() != null) groups.add(node.getGroupUnsafe()); + NBTTagCompound nodeTag = node.serializeNBT(); + NBTTagCompound dataTag = new NBTTagCompound(); + writeNodeData(node.getData(), dataTag); + nodeTag.setTag("Data", dataTag); + allPipeNodes.appendTag(nodeTag); + } + compound.setTag("PipeNodes", allPipeNodes); + + NBTTagList allNetEdges = new NBTTagList(); + for (NetEdge edge : pipeGraph.edgeSet()) { + // prevent contamination by our manager edges + if (edge.getSource() == superSource || edge.getTarget() == superSource || + edge.getSource() == superSink || edge.getTarget() == superSink) continue; + allNetEdges.appendTag(edge.serializeNBT()); + } + compound.setTag("NetEdges", allNetEdges); + + NBTTagList allNetGroups = new NBTTagList(); + for (NetGroup group : groups) { + allNetGroups.appendTag(group.serializeNBT()); + } + compound.setTag("NetGroups", allNetGroups); + + return compound; + } + + public NodeG getSuperSource() { + return superSource; + } + + public NodeG getSuperSink() { + return superSink; + } + public interface IFlowGraph, PT extends Enum & IPipeType> { void setTestObject(Object object); diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index dda393a9e25..a1a5bd3c881 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -475,7 +475,7 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { NBTTagList allPipeNodes = new NBTTagList(); Set> groups = new ObjectOpenHashSet<>(); for (NodeG node : pipeGraph.vertexSet()) { - if (node.getGroupSafe() != null) groups.add(node.getGroupSafe()); + if (node.getGroupUnsafe() != null) groups.add(node.getGroupUnsafe()); NBTTagCompound nodeTag = node.serializeNBT(); NBTTagCompound dataTag = new NBTTagCompound(); writeNodeData(node.getData(), dataTag); From fcd2c927c5c6c407791ec22f08e6e9441b8e9c78 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 23 Jan 2024 10:19:48 -0700 Subject: [PATCH 046/157] Improve ticker & spotlessify --- .../api/pipenet/FlowChannelManager.java | 1 - .../api/pipenet/FlowChannelTicker.java | 34 ++- .../java/gregtech/api/pipenet/NetGroup.java | 1 - .../api/pipenet/WorldPipeFlowNetG.java | 8 +- .../api/pipenet/alg/MaximumFlowAlgorithm.java | 6 - .../pipelike/fluidpipe/net/FluidChannel.java | 1 - .../pipelike/fluidpipe/net/PipeTankList.java | 1 - .../fluidpipe/tile/TileEntityFluidPipe.java | 9 +- .../tile/TileEntityFluidPipeTickable.java | 256 ++++++++---------- 9 files changed, 136 insertions(+), 181 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/FlowChannelManager.java b/src/main/java/gregtech/api/pipenet/FlowChannelManager.java index 7d0c455c25b..c917646803e 100644 --- a/src/main/java/gregtech/api/pipenet/FlowChannelManager.java +++ b/src/main/java/gregtech/api/pipenet/FlowChannelManager.java @@ -4,7 +4,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import org.jetbrains.annotations.Nullable; import java.util.Map; diff --git a/src/main/java/gregtech/api/pipenet/FlowChannelTicker.java b/src/main/java/gregtech/api/pipenet/FlowChannelTicker.java index c961f6f5210..1318d4eff49 100644 --- a/src/main/java/gregtech/api/pipenet/FlowChannelTicker.java +++ b/src/main/java/gregtech/api/pipenet/FlowChannelTicker.java @@ -2,15 +2,17 @@ import gregtech.api.GTValues; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.world.World; -import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArraySet; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import java.lang.ref.WeakReference; +import java.util.Map; import java.util.Set; // Ok, I admit, truly tickless fluidpipes would mean sacrificing behavior. I'd have to make them act like itempipes. @@ -18,22 +20,34 @@ @Mod.EventBusSubscriber(modid = GTValues.MODID) public final class FlowChannelTicker { - private final static Set>> MANAGERS = new ObjectOpenHashSet<>(); + private final static Map>>> MANAGERS = new Object2ObjectOpenHashMap<>(); + private final static Map TICK_COUNTS = new Object2ObjectOpenHashMap<>(); + + private final static Set>> EMPTY = new ObjectArraySet<>(0); @SubscribeEvent - public static void onServerTick(TickEvent.ServerTickEvent event) { - if (FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter() % 20 != 0) return; - for (WeakReference> ref : MANAGERS) { + public static void onWorldTick(TickEvent.WorldTickEvent event) { + if (event.world.isRemote) return; + TICK_COUNTS.compute(event.world, (k, v) -> { + if (v == null) v = 0; + return v % 10 + 1; + }); + if (TICK_COUNTS.get(event.world) != 10) return; + + for (WeakReference> ref : MANAGERS.getOrDefault(event.world, EMPTY)) { FlowChannelManager manager = ref.get(); if (manager != null) { manager.tick(); } else { - MANAGERS.remove(ref); + MANAGERS.get(event.world).remove(ref); } } } - public static void addManager(FlowChannelManager manager) { - MANAGERS.add(new WeakReference<>(manager)); + public static void addManager(World world, FlowChannelManager manager) { + if (!MANAGERS.containsKey(world)) { + MANAGERS.put(world, new ObjectOpenHashSet<>()); + } + MANAGERS.get(world).add(new WeakReference<>(manager)); } } diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 31b920af1f8..cb938c9c0af 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -3,7 +3,6 @@ import gregtech.api.pipenet.block.IPipeType; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.util.INBTSerializable; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java index 5d400e940a7..772e9eb35ad 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java @@ -1,15 +1,12 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; - import gregtech.api.pipenet.tile.TileEntityPipeBase; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.nbt.NBTTagList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.graph.SimpleDirectedWeightedGraph; @@ -65,7 +62,8 @@ public List> getPaths(@Nullable NodeG - implements IDataInfoProvider { + implements IDataInfoProvider { private PipeTankList pipeTankList; private final EnumMap tankLists = new EnumMap<>(EnumFacing.class); @@ -340,7 +336,8 @@ public void readFromNBT(@NotNull NBTTagCompound nbt) { if (stack == null) continue; fluidTanks[i].setFluid(stack); // the best part is that this naturally gives us backwards compatibility. - FluidChannel channel = FluidChannel.getChannelFromGroup(stack.getFluid(), this.getNode().getGroupSafe()); + FluidChannel channel = FluidChannel.getChannelFromGroup(stack.getFluid(), + this.getNode().getGroupSafe()); channel.addSource(this.getNode()); } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java index 97b3ece73d5..773007be383 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java @@ -1,50 +1,6 @@ package gregtech.common.pipelike.fluidpipe.tile; -import gregtech.api.GTValues; -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.cover.Cover; -import gregtech.api.cover.CoverableView; -import gregtech.api.fluids.FluidConstants; -import gregtech.api.fluids.FluidState; -import gregtech.api.fluids.attribute.AttributedFluid; -import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.metatileentity.IDataInfoProvider; -import gregtech.api.unification.material.properties.FluidPipeProperties; -import gregtech.api.util.EntityDamageUtil; -import gregtech.api.util.TextFormattingUtil; -import gregtech.common.covers.CoverPump; -import gregtech.common.covers.ManualImportExportMode; -import gregtech.common.pipelike.fluidpipe.net.FluidChannel; -import gregtech.common.pipelike.fluidpipe.net.PipeTankList; - -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.Blocks; -import net.minecraft.init.SoundEvents; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ITickable; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.Style; -import net.minecraft.util.text.TextComponentTranslation; -import net.minecraft.util.text.TextFormatting; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; public class TileEntityFluidPipeTickable extends TileEntityFluidPipe implements ITickable { @@ -85,111 +41,111 @@ public boolean supportsTicking() { return true; } -// private void distributeFluid(int channel, FluidTank tank, FluidStack fluid) { -// // Tank, From, Amount to receive -// List tanks = new ArrayList<>(); -// int amount = fluid.amount; -// -// FluidStack maxFluid = fluid.copy(); -// double availableCapacity = 0; -// -// for (byte i = 0, j = (byte) GTValues.RNG.nextInt(6); i < 6; i++) { -// // Get a list of tanks accepting fluids, and what side they're on -// byte side = (byte) ((i + j) % 6); -// EnumFacing facing = EnumFacing.VALUES[side]; -// -// if (!isConnected(facing) || (lastReceivedFrom & (1 << side)) != 0) { -// continue; -// } -// -// TileEntity neighbor = getNeighbor(facing); -// if (neighbor == null) continue; -// IFluidHandler fluidHandler = neighbor.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, -// facing.getOpposite()); -// if (fluidHandler == null) continue; -// -// IFluidHandler pipeTank = tank; -// Cover cover = getCoverableImplementation().getCoverAtSide(facing); -// -// // pipeTank should only be determined by the cover attached to the actual pipe -// if (cover != null) { -// pipeTank = cover.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, pipeTank); -// // Shutter covers return null capability when active, so check here to prevent NPE -// if (pipeTank == null || checkForPumpCover(cover)) continue; -// } else { -// CoverableView coverable = neighbor.getCapability(GregtechTileCapabilities.CAPABILITY_COVER_HOLDER, -// facing.getOpposite()); -// if (coverable != null) { -// cover = coverable.getCoverAtSide(facing.getOpposite()); -// if (checkForPumpCover(cover)) continue; -// } -// } -// -// FluidStack drainable = pipeTank.drain(maxFluid, false); -// if (drainable == null || drainable.amount <= 0) { -// continue; -// } -// -// int filled = Math.min(fluidHandler.fill(maxFluid, false), drainable.amount); -// -// if (filled > 0) { -// tanks.add(new FluidTransaction(fluidHandler, pipeTank, filled)); -// availableCapacity += filled; -// } -// maxFluid.amount = amount; // Because some mods do actually modify input fluid stack -// } -// -// if (availableCapacity <= 0) -// return; -// -// // How much of this fluid is available for distribution? -// final double maxAmount = Math.min(getCapacityPerTank() / 2, fluid.amount); -// -// // Now distribute -// for (FluidTransaction transaction : tanks) { -// if (availableCapacity > maxAmount) { -// transaction.amount = (int) Math.floor(transaction.amount * maxAmount / availableCapacity); // Distribute -// // fluids -// // based on -// // percentage -// // available -// // space at -// // destination -// } -// if (transaction.amount == 0) { -// if (tank.getFluidAmount() <= 0) break; // If there is no more stored fluid, stop transferring to prevent -// // dupes -// transaction.amount = 1; // If the percent is not enough to give at least 1L, try to give 1L -// } else if (transaction.amount < 0) { -// continue; -// } -// -// FluidStack toInsert = fluid.copy(); -// toInsert.amount = transaction.amount; -// -// int inserted = transaction.target.fill(toInsert, true); -// if (inserted > 0) { -// transaction.pipeTank.drain(inserted, true); -// } -// } -// } + // private void distributeFluid(int channel, FluidTank tank, FluidStack fluid) { + // // Tank, From, Amount to receive + // List tanks = new ArrayList<>(); + // int amount = fluid.amount; + // + // FluidStack maxFluid = fluid.copy(); + // double availableCapacity = 0; + // + // for (byte i = 0, j = (byte) GTValues.RNG.nextInt(6); i < 6; i++) { + // // Get a list of tanks accepting fluids, and what side they're on + // byte side = (byte) ((i + j) % 6); + // EnumFacing facing = EnumFacing.VALUES[side]; + // + // if (!isConnected(facing) || (lastReceivedFrom & (1 << side)) != 0) { + // continue; + // } + // + // TileEntity neighbor = getNeighbor(facing); + // if (neighbor == null) continue; + // IFluidHandler fluidHandler = neighbor.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + // facing.getOpposite()); + // if (fluidHandler == null) continue; + // + // IFluidHandler pipeTank = tank; + // Cover cover = getCoverableImplementation().getCoverAtSide(facing); + // + // // pipeTank should only be determined by the cover attached to the actual pipe + // if (cover != null) { + // pipeTank = cover.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, pipeTank); + // // Shutter covers return null capability when active, so check here to prevent NPE + // if (pipeTank == null || checkForPumpCover(cover)) continue; + // } else { + // CoverableView coverable = neighbor.getCapability(GregtechTileCapabilities.CAPABILITY_COVER_HOLDER, + // facing.getOpposite()); + // if (coverable != null) { + // cover = coverable.getCoverAtSide(facing.getOpposite()); + // if (checkForPumpCover(cover)) continue; + // } + // } + // + // FluidStack drainable = pipeTank.drain(maxFluid, false); + // if (drainable == null || drainable.amount <= 0) { + // continue; + // } + // + // int filled = Math.min(fluidHandler.fill(maxFluid, false), drainable.amount); + // + // if (filled > 0) { + // tanks.add(new FluidTransaction(fluidHandler, pipeTank, filled)); + // availableCapacity += filled; + // } + // maxFluid.amount = amount; // Because some mods do actually modify input fluid stack + // } + // + // if (availableCapacity <= 0) + // return; + // + // // How much of this fluid is available for distribution? + // final double maxAmount = Math.min(getCapacityPerTank() / 2, fluid.amount); + // + // // Now distribute + // for (FluidTransaction transaction : tanks) { + // if (availableCapacity > maxAmount) { + // transaction.amount = (int) Math.floor(transaction.amount * maxAmount / availableCapacity); // Distribute + // // fluids + // // based on + // // percentage + // // available + // // space at + // // destination + // } + // if (transaction.amount == 0) { + // if (tank.getFluidAmount() <= 0) break; // If there is no more stored fluid, stop transferring to prevent + // // dupes + // transaction.amount = 1; // If the percent is not enough to give at least 1L, try to give 1L + // } else if (transaction.amount < 0) { + // continue; + // } + // + // FluidStack toInsert = fluid.copy(); + // toInsert.amount = transaction.amount; + // + // int inserted = transaction.target.fill(toInsert, true); + // if (inserted > 0) { + // transaction.pipeTank.drain(inserted, true); + // } + // } + // } -// private boolean checkForPumpCover(@Nullable Cover cover) { -// if (cover instanceof CoverPump coverPump) { -// int pipeThroughput = getNodeData().getThroughput() * 20; -// if (coverPump.getTransferRate() > pipeThroughput) { -// coverPump.setTransferRate(pipeThroughput); -// } -// return coverPump.getManualImportExportMode() == ManualImportExportMode.DISABLED; -// } -// return false; -// } -// -// private IFluidHandler getFluidHandlerAt(EnumFacing facing, EnumFacing oppositeSide) { -// TileEntity tile = world.getTileEntity(pos.offset(facing)); -// if (tile == null) { -// return null; -// } -// return tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, oppositeSide); -// } + // private boolean checkForPumpCover(@Nullable Cover cover) { + // if (cover instanceof CoverPump coverPump) { + // int pipeThroughput = getNodeData().getThroughput() * 20; + // if (coverPump.getTransferRate() > pipeThroughput) { + // coverPump.setTransferRate(pipeThroughput); + // } + // return coverPump.getManualImportExportMode() == ManualImportExportMode.DISABLED; + // } + // return false; + // } + // + // private IFluidHandler getFluidHandlerAt(EnumFacing facing, EnumFacing oppositeSide) { + // TileEntity tile = world.getTileEntity(pos.offset(facing)); + // if (tile == null) { + // return null; + // } + // return tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, oppositeSide); + // } } From bb55064c54499db3fa46ebf18b4ac3e1445f9478 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 23 Jan 2024 10:23:57 -0700 Subject: [PATCH 047/157] Fix undirected flow nets not using the proper edge weight fetcher --- src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java index 772e9eb35ad..d801b595df5 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java @@ -106,7 +106,10 @@ public FlowUndirected() { // this overcomplicated workaround is due to not enough protected/public visibilities. @Override public double getEdgeWeight(NetEdge netEdge) { - return netEdge.getPredicate().test(testObject) ? super.getEdgeWeight(netEdge) : 0; + // Both source and target must support the channel, and the netEdge predicate must allow our object. + return ((NodeG) netEdge.getSource()).canSupportChannel(queryingChannel) && + ((NodeG) netEdge.getTarget()).canSupportChannel(queryingChannel) && + netEdge.getPredicate().test(testObject) ? super.getEdgeWeight(netEdge) : 0; } @Override From 6148b69942aebcd297da74ef4e4c45d2887da5f9 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 23 Jan 2024 10:30:12 -0700 Subject: [PATCH 048/157] Implement fluidpipe channel capacity scaling --- .../java/gregtech/api/pipenet/INodeData.java | 2 +- src/main/java/gregtech/api/pipenet/NodeG.java | 4 ++-- .../properties/FluidPipeProperties.java | 21 +++---------------- 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/INodeData.java b/src/main/java/gregtech/api/pipenet/INodeData.java index ebff1d85d79..4515f84c54a 100644 --- a/src/main/java/gregtech/api/pipenet/INodeData.java +++ b/src/main/java/gregtech/api/pipenet/INodeData.java @@ -4,7 +4,7 @@ public interface INodeData> { - default int getChannelMax() { + default int getChannelMaxCount() { return 1; } diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 7c062350d0b..71e245d3e97 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -284,7 +284,7 @@ public void clearPathCache() { * @return {@code true} if the provided channel can be supported by the node. */ public boolean canSupportChannel(FlowChannel channel) { - return this.channels.size() < this.data.getChannelMax() || this.channels.contains(channel); + return this.channels.size() < this.data.getChannelMaxCount() || this.channels.contains(channel); } /** @@ -294,7 +294,7 @@ public boolean canSupportChannel(FlowChannel channel) { * @return {@code true} if the channel was added. */ public boolean addChannel(FlowChannel channel) { - if (this.channels.size() < this.data.getChannelMax()) { + if (this.channels.size() < this.data.getChannelMaxCount()) { this.channels.add(channel); return true; } diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index e39635bc55e..885f4653748 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -141,28 +141,13 @@ public void setPlasmaProof(boolean plasmaProof) { } @Override - public double getWeightFactor() { - // behold 170, the magic number - return Math.pow(2, (int) (Double.MAX_EXPONENT / (Math.log(this.getThroughput()) * 170))); + public int getChannelMaxCount() { + return this.tanks; } @Override public FluidPipeProperties getMinData(Set datas) { - int maxFluidTemperature = Integer.MAX_VALUE; - int throughput = Integer.MAX_VALUE; - boolean gasProof = true; - boolean acidProof = true; - boolean cryoProof = true; - boolean plasmaProof = true; - for (FluidPipeProperties data : datas) { - maxFluidTemperature = Math.min(maxFluidTemperature, data.getMaxFluidTemperature()); - throughput = Math.min(throughput, data.getThroughput()); - gasProof &= data.isGasProof(); - acidProof &= data.isAcidProof(); - cryoProof &= data.isCryoProof(); - plasmaProof &= data.isPlasmaProof(); - } - return new FluidPipeProperties(maxFluidTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof); + return null; } @Override From ab6c9ab225099645b6281087ec93f857941f3831 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 10 Feb 2024 15:18:07 -0700 Subject: [PATCH 049/157] Bunch of fixes (but not enough) --- .../gregtech/api/pipenet/INBTBuilder.java | 7 ++ .../java/gregtech/api/pipenet/NetEdge.java | 10 ++- .../java/gregtech/api/pipenet/NetGroup.java | 86 ++++++++++++++++--- .../java/gregtech/api/pipenet/NetPath.java | 1 - src/main/java/gregtech/api/pipenet/NodeG.java | 18 +++- .../gregtech/api/pipenet/WorldPipeNetG.java | 52 +++++++---- .../api/pipenet/{ => flow}/FlowChannel.java | 21 ++++- .../{ => flow}/FlowChannelManager.java | 44 +++++++++- .../pipenet/{ => flow}/FlowChannelTicker.java | 19 ++-- .../pipenet/{ => flow}/WorldPipeFlowNetG.java | 74 ++++++++++++++-- .../api/pipenet/tile/TileEntityPipeBase.java | 4 +- .../properties/FluidPipeProperties.java | 7 ++ .../pipelike/fluidpipe/net/FluidChannel.java | 19 ++-- .../fluidpipe/net/WorldFluidPipeNet.java | 9 +- .../loaders/recipe/MiscRecipeLoader.java | 19 ++-- 15 files changed, 311 insertions(+), 79 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/INBTBuilder.java rename src/main/java/gregtech/api/pipenet/{ => flow}/FlowChannel.java (88%) rename src/main/java/gregtech/api/pipenet/{ => flow}/FlowChannelManager.java (66%) rename src/main/java/gregtech/api/pipenet/{ => flow}/FlowChannelTicker.java (72%) rename src/main/java/gregtech/api/pipenet/{ => flow}/WorldPipeFlowNetG.java (72%) diff --git a/src/main/java/gregtech/api/pipenet/INBTBuilder.java b/src/main/java/gregtech/api/pipenet/INBTBuilder.java new file mode 100644 index 00000000000..19381d1615d --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/INBTBuilder.java @@ -0,0 +1,7 @@ +package gregtech.api.pipenet; + +@FunctionalInterface +public interface INBTBuilder { + + void build(); +} diff --git a/src/main/java/gregtech/api/pipenet/NetEdge.java b/src/main/java/gregtech/api/pipenet/NetEdge.java index a87964fbcaa..b992a519e48 100644 --- a/src/main/java/gregtech/api/pipenet/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/NetEdge.java @@ -9,6 +9,7 @@ import org.jgrapht.graph.DefaultWeightedEdge; import java.util.Map; +import java.util.function.Predicate; public final class NetEdge extends DefaultWeightedEdge implements INBTSerializable { @@ -20,7 +21,9 @@ public void setPredicate(AbstractEdgePredicate predicate) { this.invertedPredicate = predicate.sourcePos != this.getSource().getNodePos(); } - public AbstractEdgePredicate getPredicate() { + public Predicate getPredicate() { + // if we don't have a predicate, just assume that we're good. + if (predicate == null) return (a) -> true; return predicate; } @@ -57,7 +60,7 @@ public NBTTagCompound serializeNBT() { public void deserializeNBT(NBTTagCompound nbt) {} static final class NBTBuilder & IPipeType, - NodeDataType extends INodeData> { + NodeDataType extends INodeData> implements INBTBuilder { private final NodeG node1; private final NodeG node2; @@ -82,7 +85,8 @@ static final class NBTBuilder & IPipeType... nodes) { public void connectionChange(NodeG node) { if (!this.net.isFlow()) return; - // if it has non-pipe TE connections, we need to treat it as an active sink. Very wide definition. - if (node.getConnecteds().size() != 0) { - this.getChannelManager().getActiveSinks().add(node); + Map map = node.getConnecteds(); + // if map is null, then we're in world data load phase - do nothing + if (map == null) return; + if (map.size() != 0) { + this.getChannelManager().addSink(node); } else { - this.getChannelManager().getActiveSinks().remove(node); + this.getChannelManager().removeSink(node); } } @@ -127,7 +136,8 @@ protected void mergeNode(NodeG node) { * @return Whether the node existed in the graph */ public boolean splitNode(NodeG source) { - if (graph.containsVertex(source)) { + if (this.graph.containsVertex(source)) { + this.prepSplit(); this.clearCaches(); List> targets = graph.outgoingEdgesOf(source).stream().map(a -> { // handling so undirected graphs don't throw an error @@ -135,7 +145,7 @@ public boolean splitNode(NodeG source) { if (a.getTarget().getNodePos() != source.getNodePos()) return a.getTarget(); return a.getSource(); }).collect(Collectors.toList()); - graph.removeVertex(source); + this.graph.removeVertex(source); this.nodes.remove(source); if (this.net.isFlow()) { this.getChannelManager().removeNode(source); @@ -159,14 +169,17 @@ public boolean splitNode(NodeG source) { if (targetGroup.size() != 0) { if (this.net.isFlow()) { // remove our owned nodes from their manager, and remove their nodes from our manager. + // also make sure to finish split from their perspective. new NetGroup<>(this.graph, this.net, targetGroup) - .setChannelManager(this.getChannelManager().subManager(this.nodes)); + .setChannelManager(this.getChannelManager().subManager(this.nodes)) + .finishSplit(); this.getChannelManager().removeNodes(targetGroup); } else { new NetGroup<>(this.graph, this.net, targetGroup); } } } + this.finishSplit(); return true; } return false; @@ -181,6 +194,7 @@ public boolean splitNode(NodeG source) { */ public boolean splitEdge(NodeG source, NodeG target) { if (graph.removeEdge(source, target) != null) { + this.prepSplit(); this.clearCaches(); Set> targetGroup = new ObjectOpenHashSet<>(); BreadthFirstIterator, NetEdge> i = new BreadthFirstIterator<>(graph, target); @@ -188,25 +202,43 @@ public boolean splitEdge(NodeG source, NodeG(this.graph, this.net, targetGroup) - .setChannelManager(this.getChannelManager().subManager(this.nodes)); + .setChannelManager(this.getChannelManager().subManager(this.nodes)) + .finishSplit(); this.getChannelManager().removeNodes(targetGroup); } else { new NetGroup<>(this.graph, this.net, targetGroup); } } + this.finishSplit(); return true; } return false; } + private void prepSplit() { + if (this.net.isFlow()) { + this.getChannelManager().disconnectSuperNodes(); + } + } + + private void finishSplit() { + if (this.net.isFlow()) { + this.getChannelManager().reconnectSuperNodes(); + } + } + /** * For memory considerations, returns the uncloned set. Do not modify this directly. */ @@ -235,8 +267,9 @@ public FlowChannel getChannel(Object key) { return this.getChannelManager().getChannel(key); } - private void setChannelManager(FlowChannelManager manager) { + private NetGroup setChannelManager(FlowChannelManager manager) { this.channelManager = manager; + return this; } private FlowChannelManager getChannelManager() { @@ -252,6 +285,10 @@ public NBTTagCompound serializeNBT() { int i = 0; for (NodeG node : this.nodes) { tag.setLong(String.valueOf(i), node.getLongPos()); + if (this.net.isFlow()) { + // should I do some weird, bit-based encoding with an adaptable number of longs instead of booleans? + tag.setBoolean("F" + i, node.hasConnecteds()); + } i++; } tag.setInteger("NodeCount", i); @@ -265,20 +302,41 @@ public NBTTagCompound serializeNBT() { @Deprecated public void deserializeNBT(NBTTagCompound nbt) {} + private void addSinks(Set> sinks) { + for (NodeG sink : sinks) { + this.getChannelManager().addSink(sink); + } + } + static final class NBTBuilder & IPipeType, - NodeDataType extends INodeData> { + NodeDataType extends INodeData> implements INBTBuilder { private final Set> nodes; + private final Set> sinks; - NBTBuilder(Map> longPosMap, NBTTagCompound tag) { + private final Graph, NetEdge> graph; + private final WorldPipeNetG net; + + NBTBuilder(Map> longPosMap, NBTTagCompound tag, boolean isFlow, + Graph, NetEdge> graph, WorldPipeNetG net) { nodes = new ObjectOpenHashSet<>(); + if (isFlow) sinks = new ObjectOpenHashSet<>(); + else sinks = null; for (int i = 0; i < tag.getInteger("NodeCount"); i++) { - nodes.add(longPosMap.get(tag.getLong(String.valueOf(i)))); + NodeG node = longPosMap.get(tag.getLong(String.valueOf(i))); + nodes.add(node); + if (isFlow && tag.getBoolean("F" + i)) { + sinks.add(node); + } } + this.graph = graph; + this.net = net; } - void build(Graph, NetEdge> graph, WorldPipeNetG net) { + @Override + public void build() { NetGroup g = new NetGroup<>(graph, net, nodes); + if (net.isFlow()) g.addSinks(sinks); } } } diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index edd9d9886eb..da00ac55aec 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -118,7 +118,6 @@ public NodeDataType getMinData() { public boolean checkPredicate(Object o) { for (NetEdge edge : this.edgeList) { - if (edge.getPredicate() == null) continue; if (!edge.getPredicate().test(o)) return false; } return true; diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 71e245d3e97..02c23529fc2 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -1,6 +1,7 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.flow.FlowChannel; import gregtech.api.pipenet.tile.IPipeTile; import net.minecraft.nbt.NBTTagCompound; @@ -143,7 +144,15 @@ public boolean hasConnecteds() { return false; } + /** + * Returns null if we cannot get a valid mte for our location; this happens during world load. + */ public Map getConnecteds() { + try { + getHeldMTE(); + } catch (Exception e) { + return null; + } Map map = new Object2ObjectOpenHashMap<>(6); for (EnumFacing facing : EnumFacing.VALUES) { if (!isConnected(facing)) continue; @@ -284,21 +293,22 @@ public void clearPathCache() { * @return {@code true} if the provided channel can be supported by the node. */ public boolean canSupportChannel(FlowChannel channel) { + if (this.data == null) return true; return this.channels.size() < this.data.getChannelMaxCount() || this.channels.contains(channel); } /** - * Adds a channel to a node's collection. Cannot go over the node's chnnael limit. + * Adds a channel to a node's collection. Cannot go over the node's channel limit. * * @param channel the channel to add. - * @return {@code true} if the channel was added. + * @return {@code true} if the channel was added or was already present. */ public boolean addChannel(FlowChannel channel) { if (this.channels.size() < this.data.getChannelMaxCount()) { this.channels.add(channel); return true; } - return false; + return this.channels.contains(channel); } /** @@ -335,7 +345,7 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; NodeG nodeG = (NodeG) o; - return Objects.equals(nodePos, nodeG.nodePos); + return nodePos != null && Objects.equals(nodePos, nodeG.nodePos); } @Override diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index a1a5bd3c881..d796d1357c3 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -5,6 +5,7 @@ import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; import gregtech.api.pipenet.alg.SinglePathAlgorithm; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.common.covers.CoverShutter; @@ -41,14 +42,16 @@ public abstract class WorldPipeNetG private final boolean isSinglePath; private final boolean isFlow; + private Set builders = null; + private WeakReference worldRef = new WeakReference<>(null); // TODO move graph & algorithm into NetGroup to reduce unnecessary algorithm cost - Graph, NetEdge> pipeGraph; + protected final Graph, NetEdge> pipeGraph; final Map> pipeMap = new Object2ObjectOpenHashMap<>(); final NetAlgorithm.NetAlgorithmWrapper netAlgorithm; - boolean validAlgorithmInstance = false; + private boolean validAlgorithmInstance = false; /** * @param isDirected Determines whether this net needs directed graph handling. @@ -69,13 +72,11 @@ public WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath) { } /** - * Override ONLY for use by {@link WorldPipeFlowNetG} + * Override only for use by {@link WorldPipeFlowNetG} */ - WorldPipeNetG(boolean isDirected, boolean isSinglePath, String name) { + protected WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath, Graph, NetEdge> graph) { super(name); - if (isDirected()) - this.pipeGraph = new SimpleDirectedWeightedGraph<>(NetEdge.class); - else this.pipeGraph = new SimpleWeightedGraph<>(NetEdge.class); + this.pipeGraph = graph; this.netAlgorithm = null; this.isDirected = isDirected; this.isSinglePath = isSinglePath; @@ -94,6 +95,18 @@ public final boolean isFlow() { return isFlow; } + protected void markAlgInvalid() { + this.validAlgorithmInstance = false; + } + + protected void markAlgValid() { + this.validAlgorithmInstance = true; + } + + protected boolean hasValidAlg() { + return this.validAlgorithmInstance; + } + public World getWorld() { return this.worldRef.get(); } @@ -102,6 +115,8 @@ protected void setWorldAndInit(World world) { if (world != this.worldRef.get()) { this.worldRef = new WeakReference<>(world); onWorldSet(); + // some builders have to wait for world set, so we wait until then to build them. + if (this.builders != null) this.builders.forEach(INBTBuilder::build); } } @@ -142,7 +157,7 @@ public List> getPaths(@Nullable NodeG> cache = node.getPathCache(); if (cache != null) { @@ -180,6 +195,8 @@ protected TileEntityPipeBase castTE(TileEntity te) { return null; } + public void markNodeAsOldData(NodeG node) {} + protected abstract Class> getBasePipeClass(); /** @@ -319,7 +336,7 @@ public void addUndirectedEdge(NodeG source, NodeG source, NodeG target, @Nullable AbstractEdgePredicate predicate) { addEdge(source, target, source.getData().getWeightFactor() + target.getData().getWeightFactor(), predicate); - this.validAlgorithmInstance = false; + this.markAlgInvalid(); } public void addUndirectedEdge(NodeG source, NodeG target, @@ -336,7 +353,7 @@ public void addEdge(NodeG source, NodeG source, NodeG source, NodeG target) { if (source.getGroupSafe() != null && source.getGroupSafe().splitEdge(source, target)) { - this.validAlgorithmInstance = false; + this.markAlgInvalid(); this.markDirty(); } } @@ -409,9 +426,9 @@ public void removeNode(BlockPos pos) { public void removeNode(@Nullable NodeG node) { if (node != null) { - if (this.pipeGraph.edgesOf(node).size() != 0) this.validAlgorithmInstance = false; - if (node.getGroupSafe() != null) { - node.getGroupSafe().splitNode(node); + if (this.pipeGraph.edgesOf(node).size() != 0) this.markAlgInvalid(); + if (node.getGroupUnsafe() != null) { + node.getGroupUnsafe().splitNode(node); } else this.pipeGraph.removeVertex(node); this.pipeMap.remove(node.getNodePos()); this.markDirty(); @@ -441,7 +458,7 @@ protected void rebuildNetAlgorithm() { } else { this.netAlgorithm.setAlg(new SinglePathAlgorithm<>(pipeGraph, isDirected())); } - this.validAlgorithmInstance = true; + this.markAlgValid(); } @Override @@ -449,6 +466,7 @@ public void readFromNBT(NBTTagCompound nbt) { if (!nbt.hasKey("NetEdges")) { return; } + this.builders = new ObjectOpenHashSet<>(); NBTTagList allPipeNodes = nbt.getTagList("PipeNodes", Constants.NBT.TAG_COMPOUND); Map> longPosMap = new Long2ObjectOpenHashMap<>(); for (int i = 0; i < allPipeNodes.tagCount(); i++) { @@ -460,12 +478,12 @@ public void readFromNBT(NBTTagCompound nbt) { NBTTagList allNetEdges = nbt.getTagList("NetEdges", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < allNetEdges.tagCount(); i++) { NBTTagCompound gEdgeTag = allNetEdges.getCompoundTagAt(i); - new NetEdge.NBTBuilder<>(longPosMap, gEdgeTag, this::addEdge).addIfBuildable(); + this.builders.add(new NetEdge.NBTBuilder<>(longPosMap, gEdgeTag, this::addEdge)); } NBTTagList allNetGroups = nbt.getTagList("NetGroups", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < allNetGroups.tagCount(); i++) { NBTTagCompound gTag = allNetGroups.getCompoundTagAt(i); - new NetGroup.NBTBuilder<>(longPosMap, gTag).build(this.pipeGraph, this); + this.builders.add(new NetGroup.NBTBuilder<>(longPosMap, gTag, this.isFlow(), this.pipeGraph, this)); } } diff --git a/src/main/java/gregtech/api/pipenet/FlowChannel.java b/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java similarity index 88% rename from src/main/java/gregtech/api/pipenet/FlowChannel.java rename to src/main/java/gregtech/api/pipenet/flow/FlowChannel.java index d38661fd1ee..b6855b01cf5 100644 --- a/src/main/java/gregtech/api/pipenet/FlowChannel.java +++ b/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java @@ -1,8 +1,11 @@ -package gregtech.api.pipenet; +package gregtech.api.pipenet.flow; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; import gregtech.api.cover.CoverHolder; +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetEdge; +import gregtech.api.pipenet.NodeG; import gregtech.api.pipenet.block.IPipeType; import net.minecraft.tileentity.TileEntity; @@ -35,6 +38,8 @@ FlowChannel setManager(FlowChannelManager manager) { return this; } + public abstract void clearAlg(); + public abstract void evaluate(); /** @@ -64,6 +69,18 @@ protected void deactivate() { } } + void disconnectSuperNodes() { + for (NodeG source : activeSources) { + network.removeEdge(this.manager.getSuperSource(), source); + } + } + + void reconnectSuperNodes() { + for (NodeG source : activeSources) { + network.addEdge(this.manager.getSuperSource(), source); + } + } + protected abstract double getSourceValue(NodeG source); protected abstract double getSinkValue(NodeG sink); @@ -122,6 +139,4 @@ protected void removeNode(NodeG node) { this.activeSources.remove(node); this.receiveSidesMap.remove(node); } - - protected abstract FlowChannel getNew(); } diff --git a/src/main/java/gregtech/api/pipenet/FlowChannelManager.java b/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java similarity index 66% rename from src/main/java/gregtech/api/pipenet/FlowChannelManager.java rename to src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java index c917646803e..d4faf1a3192 100644 --- a/src/main/java/gregtech/api/pipenet/FlowChannelManager.java +++ b/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java @@ -1,11 +1,15 @@ -package gregtech.api.pipenet; +package gregtech.api.pipenet.flow; +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NodeG; import gregtech.api.pipenet.block.IPipeType; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import org.jetbrains.annotations.Nullable; +import java.lang.ref.WeakReference; import java.util.Map; import java.util.Set; @@ -20,11 +24,23 @@ public class FlowChannelManager & IPipeType net) { this.net = net; - FlowChannelTicker.addManager(net.getWorld(), this); + WeakReference> ref = new WeakReference<>(this); + FlowChannelTicker.addManager(net.getWorld(), ref); + this.net.addManager(ref); + } + + void clearAlgs() { + this.channels.values().forEach(FlowChannel::clearAlg); } public void tick() { - channels.forEach((k, v) -> v.evaluate()); + if (this.activeSinks.size() == 0) return; + this.channels.forEach((k, v) -> v.evaluate()); + if (this.net.unhandledOldNodes.size() != 0) { + for (NodeG node : this.net.unhandledOldNodes) { + node.getGroupSafe().connectionChange(node); + } + } } /** @@ -81,10 +97,32 @@ public Set> getActiveSinks() { return activeSinks; } + public void addSink(NodeG sink) { + if (this.activeSinks.add(sink)) this.net.getPipeGraph().addEdge(sink, this.net.getSuperSink()); + } + + public void removeSink(NodeG sink) { + if (this.activeSinks.remove(sink)) this.net.getPipeGraph().removeEdge(sink, this.net.getSuperSink()); + } + public void setChannel(Object key, FlowChannel channel) { this.channels.put(key, channel.setManager(this)); } + public void disconnectSuperNodes() { + this.channels.forEach((key, value) -> value.disconnectSuperNodes()); + for (NodeG node : activeSinks) { + this.net.getPipeGraph().removeEdge(node, getSuperSink()); + } + } + + public void reconnectSuperNodes() { + this.channels.forEach((key, value) -> value.reconnectSuperNodes()); + for (NodeG node : activeSinks) { + this.net.getPipeGraph().addEdge(node, getSuperSink()); + } + } + @Nullable public FlowChannel getChannel(Object key) { return this.channels.get(key); diff --git a/src/main/java/gregtech/api/pipenet/FlowChannelTicker.java b/src/main/java/gregtech/api/pipenet/flow/FlowChannelTicker.java similarity index 72% rename from src/main/java/gregtech/api/pipenet/FlowChannelTicker.java rename to src/main/java/gregtech/api/pipenet/flow/FlowChannelTicker.java index 1318d4eff49..72a7609618a 100644 --- a/src/main/java/gregtech/api/pipenet/FlowChannelTicker.java +++ b/src/main/java/gregtech/api/pipenet/flow/FlowChannelTicker.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet; +package gregtech.api.pipenet.flow; import gregtech.api.GTValues; @@ -12,6 +12,7 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import java.lang.ref.WeakReference; +import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -20,6 +21,8 @@ @Mod.EventBusSubscriber(modid = GTValues.MODID) public final class FlowChannelTicker { + public static final int FLOWNET_TICKRATE = 10; + private final static Map>>> MANAGERS = new Object2ObjectOpenHashMap<>(); private final static Map TICK_COUNTS = new Object2ObjectOpenHashMap<>(); @@ -30,24 +33,26 @@ public static void onWorldTick(TickEvent.WorldTickEvent event) { if (event.world.isRemote) return; TICK_COUNTS.compute(event.world, (k, v) -> { if (v == null) v = 0; - return v % 10 + 1; + return (v % FLOWNET_TICKRATE) + 1; }); - if (TICK_COUNTS.get(event.world) != 10) return; + if (TICK_COUNTS.get(event.world) != FLOWNET_TICKRATE) return; - for (WeakReference> ref : MANAGERS.getOrDefault(event.world, EMPTY)) { + Iterator>> iter = MANAGERS.getOrDefault(event.world, EMPTY).iterator(); + while (iter.hasNext()) { + WeakReference> ref = iter.next(); FlowChannelManager manager = ref.get(); if (manager != null) { manager.tick(); } else { - MANAGERS.get(event.world).remove(ref); + iter.remove(); } } } - public static void addManager(World world, FlowChannelManager manager) { + public static void addManager(World world, WeakReference> ref) { if (!MANAGERS.containsKey(world)) { MANAGERS.put(world, new ObjectOpenHashSet<>()); } - MANAGERS.get(world).add(new WeakReference<>(manager)); + MANAGERS.get(world).add(ref); } } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java similarity index 72% rename from src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java rename to src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java index d801b595df5..a32f49a24ae 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeFlowNetG.java +++ b/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java @@ -1,5 +1,12 @@ -package gregtech.api.pipenet; - +package gregtech.api.pipenet.flow; + +import gregtech.api.pipenet.AbstractEdgePredicate; +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetEdge; +import gregtech.api.pipenet.NetGroup; +import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -7,11 +14,16 @@ import net.minecraft.nbt.NBTTagList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraftforge.common.capabilities.Capability; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; import org.jgrapht.graph.SimpleDirectedWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph; +import java.lang.ref.WeakReference; import java.util.List; import java.util.Set; @@ -21,20 +33,70 @@ public abstract class WorldPipeFlowNetG superSource = new NodeG<>(); private final NodeG superSink = new NodeG<>(); + protected final Set> unhandledOldNodes = new ObjectOpenHashSet<>(); + + protected final Set>> managers = new ObjectOpenHashSet<>(); + /** * @param isDirected Determines whether this net needs directed graph handling. * Used to respect filter directions in the item net and fluid net, for example. * If the graph is not directed, pipes should not support blocked connections. */ public WorldPipeFlowNetG(String name, boolean isDirected) { - super(isDirected, false, name); - if (isDirected()) - this.pipeGraph = new FlowDirected<>(); - else this.pipeGraph = new FlowUndirected<>(); + super(name, isDirected, false, isDirected ? new FlowDirected<>() : new FlowUndirected<>()); this.pipeGraph.addVertex(superSource); this.pipeGraph.addVertex(superSink); } + @Override + public void markNodeAsOldData(NodeG node) { + this.unhandledOldNodes.add(node); + } + + Graph, NetEdge> getPipeGraph() { + return this.pipeGraph; + } + + protected abstract Capability getSinkCapability(); + + @Override + public void addNodeSilent(NodeG node) { + super.addNodeSilent(node); + // Flow algorithms will throw an out of index if the number of nodes increases + this.markAlgInvalid(); + } + + @Override + public void removeNode(@Nullable NodeG node) { + super.removeNode(node); + // Flow algorithms will become mis-indexed if the number of nodes decreases + this.markAlgInvalid(); + } + + @Override + public void addEdge(NodeG source, NodeG target, + @Nullable AbstractEdgePredicate predicate) { + addEdge(source, target, Math.min(source.getData().getWeightFactor(), target.getData().getWeightFactor()) + * FlowChannelTicker.FLOWNET_TICKRATE, predicate); + this.markAlgInvalid(); + } + + @Override + protected void onWorldSet() {} + + @Override + protected void markAlgInvalid() { + for (WeakReference> ref : this.managers) { + FlowChannelManager manager = ref.get(); + if (manager != null) manager.clearAlgs(); + else this.managers.remove(ref); + } + } + + public void addManager(WeakReference> ref) { + this.managers.add(ref); + } + @Override public List> getPaths(@Nullable NodeG node, @Nullable TileEntityPipeBase tile) { diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 3fca0e612e1..8645a85eebf 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -10,6 +10,7 @@ import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import gregtech.api.unification.material.Material; import net.minecraft.block.Block; @@ -456,8 +457,9 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { } protected void doOldNetSetup() { + WorldPipeNetG net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); + net.markNodeAsOldData(this.getNode()); for (EnumFacing facing : EnumFacing.VALUES) { - WorldPipeNetG net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); NodeG nodeOffset = net.getNode(this.getPipePos().offset(facing)); if (nodeOffset == null) continue; if (net.isDirected()) { diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 885f4653748..444aee48365 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -6,6 +6,8 @@ import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.flow.FlowChannelTicker; + import it.unimi.dsi.fastutil.objects.Object2BooleanMap; import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; import org.jetbrains.annotations.NotNull; @@ -145,6 +147,11 @@ public int getChannelMaxCount() { return this.tanks; } + @Override + public double getWeightFactor() { + return this.getThroughput(); + } + @Override public FluidPipeProperties getMinData(Set datas) { return null; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java index c5f300765e1..d65100154f8 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -1,11 +1,11 @@ package gregtech.common.pipelike.fluidpipe.net; import gregtech.api.cover.Cover; -import gregtech.api.pipenet.FlowChannel; +import gregtech.api.pipenet.flow.FlowChannel; import gregtech.api.pipenet.NetEdge; import gregtech.api.pipenet.NetGroup; import gregtech.api.pipenet.NodeG; -import gregtech.api.pipenet.WorldPipeFlowNetG; +import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.covers.CoverPump; @@ -34,7 +34,7 @@ public class FluidChannel extends FlowChannel alg = null; - private Set> oldNodes = null; + private Set> oldNodes = new ObjectOpenHashSet<>(0); public FluidChannel(Graph, NetEdge> network, Fluid fluid) { super(network); @@ -45,10 +45,16 @@ public void setFluid(Fluid fluid) { this.fluid = new FluidStack(fluid, 1); } + @Override + public void clearAlg() { + this.alg = null; + } + @Override public void evaluate() { // Kill this channel if we have no more active sources if (this.activeSources.size() == 0) { + // should I put the channel in a 'recycling queue' to be reused instead? this.manager.removeChannel(this.fluid.getFluid()); return; } @@ -86,7 +92,7 @@ public void evaluate() { // destroyethify if (node.getHeldMTE() instanceof TileEntityFluidPipe f) { f.checkAndDestroy(fluid); - // TODO implement fluid leakage? + // TODO fix fluid leakage? } } } @@ -194,9 +200,4 @@ public static FluidChannel getChannelFromGroup(Fluid key, NetGroup getNew() { - return new FluidChannel(this.network, this.fluid.getFluid()); - } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index 300b15897bd..bb83b487eb8 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -1,6 +1,6 @@ package gregtech.common.pipelike.fluidpipe.net; -import gregtech.api.pipenet.WorldPipeFlowNetG; +import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.pipelike.fluidpipe.FluidPipeType; @@ -8,6 +8,8 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; public class WorldFluidPipeNet extends WorldPipeFlowNetG { @@ -33,6 +35,11 @@ protected Class> getBase return TileEntityFluidPipe.class; } + @Override + protected Capability getSinkCapability() { + return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; + } + @Override protected void writeNodeData(FluidPipeProperties nodeData, NBTTagCompound tagCompound) { tagCompound.setInteger("max_temperature", nodeData.getMaxFluidTemperature()); diff --git a/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java index 0944790e398..fb3b3173dc4 100644 --- a/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java @@ -273,17 +273,16 @@ public static void init() { .buildAndRegister(); ASSEMBLER_RECIPES.recipeBuilder().duration(100).EUt(VA[HV]) - .inputs(COVER_DIGITAL_INTERFACE.getStackForm()) - .inputs(WIRELESS.getStackForm()) + .inputs(MetaItems.COVER_SCREEN.getStackForm()) + .input(plate, Aluminium) + .input(circuit, MarkerMaterials.Tier.MV) + .input(screw, StainlessSteel, 4) .fluidInputs(Polyethylene.getFluid(L)) - .outputs(COVER_DIGITAL_INTERFACE_WIRELESS.getStackForm()) + .outputs(COVER_DIGITAL_INTERFACE.getStackForm()) .buildAndRegister(); ASSEMBLER_RECIPES.recipeBuilder().duration(100).EUt(VA[HV]) - .inputs(MetaItems.COVER_SCREEN.getStackForm()) - .input(plate, Aluminium) - .input(circuit, MarkerMaterials.Tier.MV) - .input(screw, StainlessSteel, 2) + .inputs(COVER_DIGITAL_INTERFACE.getStackForm()) .inputs(WIRELESS.getStackForm()) .fluidInputs(Polyethylene.getFluid(L)) .outputs(COVER_DIGITAL_INTERFACE_WIRELESS.getStackForm()) @@ -323,9 +322,9 @@ public static void init() { // terminal ASSEMBLER_RECIPES.recipeBuilder().duration(100).EUt(VA[MV]) - .input(circuit, MarkerMaterials.Tier.LV, 4) - .input(EMITTER_MV) - .input(SENSOR_MV) + .input(circuit, MarkerMaterials.Tier.MV, 4) + .input(EMITTER_MV, 2) + .input(SENSOR_MV, 2) .input(plate, StainlessSteel) .fluidInputs(Polyethylene.getFluid(L)) .outputs(WIRELESS.getStackForm()) From 4e15156743c560b57974c389a63abd2393c09ffe Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 10 Feb 2024 22:50:38 -0700 Subject: [PATCH 050/157] More fixes & improvements --- .../java/gregtech/api/pipenet/NetGroup.java | 2 - src/main/java/gregtech/api/pipenet/NodeG.java | 46 +++--- .../gregtech/api/pipenet/WorldPipeNetG.java | 3 +- .../api/pipenet/flow/FlowChannel.java | 13 +- .../api/pipenet/flow/FlowChannelManager.java | 1 - .../api/pipenet/flow/WorldPipeFlowNetG.java | 15 +- .../api/pipenet/tile/TileEntityPipeBase.java | 15 +- .../properties/FluidPipeProperties.java | 2 - .../pipelike/fluidpipe/net/FluidChannel.java | 31 ++-- .../fluidpipe/tile/TileEntityFluidPipe.java | 4 +- .../tile/TileEntityFluidPipeTickable.java | 135 ------------------ .../debug/DebugPipeNetInfoProvider.java | 2 +- 12 files changed, 70 insertions(+), 199 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 1379f556571..27acfefe927 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -1,10 +1,8 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; - import gregtech.api.pipenet.flow.FlowChannel; import gregtech.api.pipenet.flow.FlowChannelManager; - import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 02c23529fc2..5625c967515 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -32,11 +32,11 @@ public class NodeG & IPipeType, private NodeDataType data; /** - * Specifies bitmask of active connections. - * Active connections determine visual connections and graph edges. - * An active connection does not always mean an edge is present. + * Specifies bitmask of open connections. + * Open connections determine visual connections and graph edges. + * An open connection does not always mean an edge is present. */ - private int activeConnections; + private int openConnections; /** * Specifies bitmask of blocked connections. * Blocked connections allow flow out, but not flow in. @@ -67,7 +67,7 @@ public class NodeG & IPipeType, public NodeG(NodeDataType data, IPipeTile heldMTE, WorldPipeNetG net) { this.data = data; - this.activeConnections = 0; + this.openConnections = 0; this.blockedConnections = 0; this.mark = 0; this.isActive = false; @@ -86,7 +86,7 @@ public NodeG(IPipeTile heldMTE) { this.net = null; this.data = null; this.heldMTE = new WeakReference<>(heldMTE); - this.activeConnections = 0; + this.openConnections = 0; this.blockedConnections = 0; } @@ -99,7 +99,7 @@ public NodeG() { this.net = null; this.data = null; this.heldMTE = new WeakReference<>(null); - this.activeConnections = 0; + this.openConnections = 0; this.blockedConnections = 0; } @@ -167,28 +167,28 @@ public TileEntity getConnnected(EnumFacing facing) { } public boolean isConnected(EnumFacing facing) { - return (activeConnections & 1 << facing.getIndex()) != 0; + return (openConnections & 1 << facing.getIndex()) != 0; } /** * Should only be used with dummy nodes, otherwise go through the net. */ - public void setActiveConnections(int activeConnections) { - this.activeConnections = activeConnections; + public void setOpenConnections(int openConnections) { + this.openConnections = openConnections; } void setConnected(EnumFacing facing, boolean connect) { if (connect) { - this.activeConnections |= 1 << facing.getIndex(); + this.openConnections |= 1 << facing.getIndex(); } else { - this.activeConnections &= ~(1 << facing.getIndex()); + this.openConnections &= ~(1 << facing.getIndex()); } - this.getHeldMTE().onConnectionChange(); + this.getHeldMTESafe().onConnectionChange(); this.getGroupSafe().connectionChange(this); } - public int getActiveConnections() { - return activeConnections; + public int getOpenConnections() { + return openConnections; } public boolean isBlocked(EnumFacing facing) { @@ -208,7 +208,7 @@ void setBlocked(EnumFacing facing, boolean block) { } else { this.blockedConnections &= ~(1 << facing.getIndex()); } - this.getHeldMTE().onBlockedChange(); + this.getHeldMTESafe().onBlockedChange(); } public int getBlockedConnections() { @@ -249,15 +249,15 @@ public IPipeTile getHeldMTE() { } /** - * Ensures that the returned tile is not null nor invalid. + * Ensures that the returned tile is the correct one for this position. */ public IPipeTile getHeldMTESafe() { IPipeTile te = getHeldMTEUnsafe(); - if (te == null || !te.isValidTile()) { - te = net.castTE(net.getWorld().getTileEntity(this.nodePos)); - setHeldMTE(te); + IPipeTile properTE = net.castTE(net.getWorld().getTileEntity(this.nodePos)); + if (te != properTE) { + setHeldMTE(properTE); } - return te; + return properTE; } public void setData(NodeDataType data) { @@ -326,7 +326,7 @@ public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); tag.setLong("Pos", this.nodePos.toLong()); tag.setInteger("Mark", this.mark); - tag.setInteger("OpenConnections", this.activeConnections); + tag.setInteger("OpenConnections", this.openConnections); tag.setInteger("BlockedConnections", this.blockedConnections); tag.setBoolean("IsActive", this.isActive); return tag; @@ -335,7 +335,7 @@ public NBTTagCompound serializeNBT() { @Override public void deserializeNBT(NBTTagCompound nbt) { this.mark = nbt.getInteger("Mark"); - this.activeConnections = nbt.getInteger("OpenConnections"); + this.openConnections = nbt.getInteger("OpenConnections"); this.blockedConnections = nbt.getInteger("BlockedConnections"); this.isActive = nbt.getBoolean("IsActive"); } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index d796d1357c3..cc4e1524cd8 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -74,7 +74,8 @@ public WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath) { /** * Override only for use by {@link WorldPipeFlowNetG} */ - protected WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath, Graph, NetEdge> graph) { + protected WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath, + Graph, NetEdge> graph) { super(name); this.pipeGraph = graph; this.netAlgorithm = null; diff --git a/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java b/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java index b6855b01cf5..f9bf9ce024b 100644 --- a/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java +++ b/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java @@ -48,6 +48,7 @@ FlowChannel setManager(FlowChannelManager manager) { protected void activate() { for (NodeG source : activeSources) { double v = getSourceValue(source); + // TODO find source of random NPE crash where a source edge doesn't exist after world load (pls help) network.setEdgeWeight(this.manager.getSuperSource(), source, v); if (v == 0) removeSource(source); } @@ -85,11 +86,6 @@ void reconnectSuperNodes() { protected abstract double getSinkValue(NodeG sink); - public void addSource(NodeG source) { - this.activeSources.add(source); - this.network.addEdge(this.manager.getSuperSource(), source); - } - public void addReceiveSide(NodeG node, EnumFacing side) { this.receiveSidesMap.compute(node, (k, v) -> { if (v == null) { @@ -103,9 +99,12 @@ public void addReceiveSide(NodeG node, EnumFacing side) { }); } + public void addSource(NodeG source) { + if (this.activeSources.add(source)) this.network.addEdge(this.manager.getSuperSource(), source); + } + public void removeSource(NodeG source) { - this.activeSources.remove(source); - this.network.removeEdge(this.manager.getSuperSource(), source); + if (this.activeSources.remove(source)) this.network.removeEdge(this.manager.getSuperSource(), source); } @Nullable diff --git a/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java b/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java index d4faf1a3192..e78da938250 100644 --- a/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java +++ b/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java @@ -6,7 +6,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; diff --git a/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java index a32f49a24ae..232cf9aea8f 100644 --- a/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java +++ b/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java @@ -12,11 +12,9 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraftforge.common.capabilities.Capability; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; @@ -24,6 +22,7 @@ import org.jgrapht.graph.SimpleWeightedGraph; import java.lang.ref.WeakReference; +import java.util.Iterator; import java.util.List; import java.util.Set; @@ -76,8 +75,8 @@ public void removeNode(@Nullable NodeG node) { @Override public void addEdge(NodeG source, NodeG target, @Nullable AbstractEdgePredicate predicate) { - addEdge(source, target, Math.min(source.getData().getWeightFactor(), target.getData().getWeightFactor()) - * FlowChannelTicker.FLOWNET_TICKRATE, predicate); + addEdge(source, target, Math.min(source.getData().getWeightFactor(), target.getData().getWeightFactor()) * + FlowChannelTicker.FLOWNET_TICKRATE, predicate); this.markAlgInvalid(); } @@ -86,10 +85,12 @@ protected void onWorldSet() {} @Override protected void markAlgInvalid() { - for (WeakReference> ref : this.managers) { + Iterator>> iterator = this.managers.iterator(); + while (iterator.hasNext()) { + WeakReference> ref = iterator.next(); FlowChannelManager manager = ref.get(); if (manager != null) manager.clearAlgs(); - else this.managers.remove(ref); + else iterator.remove(); } } diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 8645a85eebf..3ba953fd119 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -10,7 +10,6 @@ import gregtech.api.pipenet.WorldPipeNetG; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import gregtech.api.unification.material.Material; import net.minecraft.block.Block; @@ -214,7 +213,7 @@ public IPipeTile setSupportsTicking() { @Override public int getConnections() { - return this.getNode().getActiveConnections(); + return this.getNode().getOpenConnections(); } @Override @@ -399,7 +398,7 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { } compound.setInteger("PipeNetVersion", 2); compound.setInteger("PipeType", pipeType.ordinal()); - compound.setInteger("Connections", getNode().getActiveConnections()); + compound.setInteger("Connections", getNode().getOpenConnections()); compound.setInteger("BlockedConnections", getNode().getBlockedConnections()); if (isPainted()) { compound.setInteger("InsulationColor", paintingColor); @@ -426,7 +425,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { this.nbtLoad = true; if (compound.hasKey("Connections")) { - this.getNode().setActiveConnections(compound.getInteger("Connections")); + this.getNode().setOpenConnections(compound.getInteger("Connections")); } else if (compound.hasKey("BlockedConnectionsMap")) { int connections = 0; NBTTagCompound blockedConnectionsTag = compound.getCompoundTag("BlockedConnectionsMap"); @@ -434,7 +433,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { int blockedConnections = blockedConnectionsTag.getInteger(attachmentTypeKey); connections |= blockedConnections; } - this.getNode().setActiveConnections(connections); + this.getNode().setOpenConnections(connections); } this.getNode().setBlockedConnections(compound.getInteger("BlockedConnections")); @@ -492,7 +491,7 @@ protected void readPipeProperties(PacketBuffer buf) { @Override public void writeInitialSyncData(PacketBuffer buf) { writePipeProperties(buf); - buf.writeVarInt(this.getNode().getActiveConnections()); + buf.writeVarInt(this.getNode().getOpenConnections()); buf.writeVarInt(this.getNode().getBlockedConnections()); buf.writeInt(paintingColor); buf.writeVarInt(frameMaterial == null ? -1 : frameMaterial.getRegistry().getNetworkId()); @@ -507,7 +506,7 @@ public void receiveInitialSyncData(PacketBuffer buf) { return; } readPipeProperties(buf); - this.getNode().setActiveConnections(buf.readVarInt()); + this.getNode().setOpenConnections(buf.readVarInt()); this.getNode().setBlockedConnections(buf.readVarInt()); this.paintingColor = buf.readInt(); int registryId = buf.readVarInt(); @@ -533,7 +532,7 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { if (discriminator == UPDATE_INSULATION_COLOR) { this.paintingColor = buf.readInt(); } else if (discriminator == UPDATE_CONNECTIONS) { - this.getNode().setActiveConnections(buf.readVarInt()); + this.getNode().setOpenConnections(buf.readVarInt()); } else if (discriminator == SYNC_COVER_IMPLEMENTATION) { this.coverableImplementation.readCustomData(buf.readVarInt(), buf); } else if (discriminator == UPDATE_PIPE_TYPE) { diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 444aee48365..92b05f52aa0 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -6,8 +6,6 @@ import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.flow.FlowChannelTicker; - import it.unimi.dsi.fastutil.objects.Object2BooleanMap; import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java index d65100154f8..401ef5a1dcd 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -1,12 +1,13 @@ package gregtech.common.pipelike.fluidpipe.net; import gregtech.api.cover.Cover; -import gregtech.api.pipenet.flow.FlowChannel; import gregtech.api.pipenet.NetEdge; import gregtech.api.pipenet.NetGroup; import gregtech.api.pipenet.NodeG; -import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; +import gregtech.api.pipenet.flow.FlowChannel; +import gregtech.api.pipenet.flow.FlowChannelTicker; +import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.covers.CoverPump; import gregtech.common.covers.CoverShutter; @@ -77,22 +78,28 @@ public void evaluate() { for (Map.Entry flow : flows.entrySet()) { if (flow.getValue() == 0) continue; - inMap.merge(flow.getKey().getTarget(), flow.getValue(), Double::sum); - outMap.merge(flow.getKey().getSource(), flow.getValue(), Double::sum); - nodes.add((NodeG) flow.getKey().getSource()); - nodes.add((NodeG) flow.getKey().getTarget()); + NetEdge edge = flow.getKey(); + // we only care about a flow if it involves a super node, and we only care about non-super node nodes. + if (edge.getSource() == this.manager.getSuperSource()) { + inMap.merge(edge.getTarget(), flow.getValue(), Double::sum); + nodes.add((NodeG) edge.getTarget()); + } else if (edge.getTarget() == this.manager.getSuperSink()) { + outMap.merge(flow.getKey().getSource(), flow.getValue(), Double::sum); + nodes.add((NodeG) edge.getSource()); + } else { + nodes.add((NodeG) edge.getSource()); + nodes.add((NodeG) edge.getTarget()); + } } for (NodeG node : nodes) { - // dataless nodes are only the superSource and superSink - if (node.getData() == null) continue; if (!node.addChannel(this)) throw new IllegalStateException("Node rejected channel despite approving it earlier!"); if (!node.getData().test(fluid)) { // destroyethify if (node.getHeldMTE() instanceof TileEntityFluidPipe f) { f.checkAndDestroy(fluid); - // TODO fix fluid leakage? + // TODO fix fluid leakage } } } @@ -141,7 +148,7 @@ protected double getSinkValue(NodeG sink) { return pushToNode(sink, Integer.MAX_VALUE, false); } - private double pushToNode(NodeG sink, int amount, boolean doFill) { + private int pushToNode(NodeG sink, int amount, boolean doFill) { int flow = 0; if (sink.getHeldMTE() instanceof TileEntityFluidPipe f) { int fill; @@ -160,7 +167,9 @@ private double pushToNode(NodeG sink, int am } Cover thisCover = f.getCoverableImplementation().getCoverAtSide(connected.getKey()); Cover themCover = getCoverOnNeighbour(sink, connected.getKey().getOpposite()); - int transferMax = evaluateCover(themCover, evaluateCover(thisCover, amount)); + int transferMax = Math.min(evaluateCover(themCover, evaluateCover(thisCover, amount)), + // max flow per side cannot exceed throughput + sink.getData().getThroughput() * FlowChannelTicker.FLOWNET_TICKRATE); IFluidHandler handler = connected.getValue().getCapability( CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, connected.getKey().getOpposite()); if (handler != null) { diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java index b769654753b..51a3fe48553 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java @@ -52,6 +52,7 @@ public class TileEntityFluidPipe extends TileEntityMaterialPipeBase tankLists = new EnumMap<>(EnumFacing.class); private FluidTank[] fluidTanks; private final int offset = GTValues.RNG.nextInt(20); + private long lastSoundTime = 0; public long getOffsetTimer() { return FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter() + offset; @@ -107,8 +108,9 @@ public void checkAndDestroy(@NotNull FluidStack stack) { public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, boolean isCorroding, boolean isShattering, boolean isMelting) { // prevent the sound from spamming when filled from anything not a pipe - if (getOffsetTimer() % 10 == 0) { + if (getOffsetTimer() >= lastSoundTime + 10) { world.playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); + lastSoundTime = getOffsetTimer() + 10; } if (isLeaking) { diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java index 773007be383..fbfedad51ba 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java @@ -6,146 +6,11 @@ public class TileEntityFluidPipeTickable extends TileEntityFluidPipe implements @Override public void update() { - // timer++; getCoverableImplementation().update(); - // if (!world.isRemote && getOffsetTimer() % FREQUENCY == 0) { - // lastReceivedFrom &= 63; - // if (lastReceivedFrom == 63) { - // lastReceivedFrom = 0; - // } - // - // boolean shouldDistribute = (oldLastReceivedFrom == lastReceivedFrom); - // int tanks = getNodeData().getTanks(); - // for (int i = 0, j = GTValues.RNG.nextInt(tanks); i < tanks; i++) { - // int index = (i + j) % tanks; - // FluidTank tank = getFluidTanks()[index]; - // FluidStack fluid = tank.getFluid(); - // if (fluid == null) - // continue; - // if (fluid.amount <= 0) { - // tank.setFluid(null); - // continue; - // } - // - // if (shouldDistribute) { - // distributeFluid(index, tank, fluid); - // lastReceivedFrom = 0; - // } - // } - // oldLastReceivedFrom = lastReceivedFrom; - // } } @Override public boolean supportsTicking() { return true; } - - // private void distributeFluid(int channel, FluidTank tank, FluidStack fluid) { - // // Tank, From, Amount to receive - // List tanks = new ArrayList<>(); - // int amount = fluid.amount; - // - // FluidStack maxFluid = fluid.copy(); - // double availableCapacity = 0; - // - // for (byte i = 0, j = (byte) GTValues.RNG.nextInt(6); i < 6; i++) { - // // Get a list of tanks accepting fluids, and what side they're on - // byte side = (byte) ((i + j) % 6); - // EnumFacing facing = EnumFacing.VALUES[side]; - // - // if (!isConnected(facing) || (lastReceivedFrom & (1 << side)) != 0) { - // continue; - // } - // - // TileEntity neighbor = getNeighbor(facing); - // if (neighbor == null) continue; - // IFluidHandler fluidHandler = neighbor.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - // facing.getOpposite()); - // if (fluidHandler == null) continue; - // - // IFluidHandler pipeTank = tank; - // Cover cover = getCoverableImplementation().getCoverAtSide(facing); - // - // // pipeTank should only be determined by the cover attached to the actual pipe - // if (cover != null) { - // pipeTank = cover.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, pipeTank); - // // Shutter covers return null capability when active, so check here to prevent NPE - // if (pipeTank == null || checkForPumpCover(cover)) continue; - // } else { - // CoverableView coverable = neighbor.getCapability(GregtechTileCapabilities.CAPABILITY_COVER_HOLDER, - // facing.getOpposite()); - // if (coverable != null) { - // cover = coverable.getCoverAtSide(facing.getOpposite()); - // if (checkForPumpCover(cover)) continue; - // } - // } - // - // FluidStack drainable = pipeTank.drain(maxFluid, false); - // if (drainable == null || drainable.amount <= 0) { - // continue; - // } - // - // int filled = Math.min(fluidHandler.fill(maxFluid, false), drainable.amount); - // - // if (filled > 0) { - // tanks.add(new FluidTransaction(fluidHandler, pipeTank, filled)); - // availableCapacity += filled; - // } - // maxFluid.amount = amount; // Because some mods do actually modify input fluid stack - // } - // - // if (availableCapacity <= 0) - // return; - // - // // How much of this fluid is available for distribution? - // final double maxAmount = Math.min(getCapacityPerTank() / 2, fluid.amount); - // - // // Now distribute - // for (FluidTransaction transaction : tanks) { - // if (availableCapacity > maxAmount) { - // transaction.amount = (int) Math.floor(transaction.amount * maxAmount / availableCapacity); // Distribute - // // fluids - // // based on - // // percentage - // // available - // // space at - // // destination - // } - // if (transaction.amount == 0) { - // if (tank.getFluidAmount() <= 0) break; // If there is no more stored fluid, stop transferring to prevent - // // dupes - // transaction.amount = 1; // If the percent is not enough to give at least 1L, try to give 1L - // } else if (transaction.amount < 0) { - // continue; - // } - // - // FluidStack toInsert = fluid.copy(); - // toInsert.amount = transaction.amount; - // - // int inserted = transaction.target.fill(toInsert, true); - // if (inserted > 0) { - // transaction.pipeTank.drain(inserted, true); - // } - // } - // } - - // private boolean checkForPumpCover(@Nullable Cover cover) { - // if (cover instanceof CoverPump coverPump) { - // int pipeThroughput = getNodeData().getThroughput() * 20; - // if (coverPump.getTransferRate() > pipeThroughput) { - // coverPump.setTransferRate(pipeThroughput); - // } - // return coverPump.getManualImportExportMode() == ManualImportExportMode.DISABLED; - // } - // return false; - // } - // - // private IFluidHandler getFluidHandlerAt(EnumFacing facing, EnumFacing oppositeSide) { - // TileEntity tile = world.getTileEntity(pos.offset(facing)); - // if (tile == null) { - // return null; - // } - // return tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, oppositeSide); - // } } diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java index 609435d8168..3c5b1071cc7 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java @@ -56,7 +56,7 @@ public void addProbeInfo(@NotNull ProbeMode mode, @NotNull IProbeInfo probeInfo, builder.append("{") .append("active: ").append(node.isActive) .append(", mark: ").append(node.mark) - .append(", open: ").append(node.getActiveConnections()) + .append(", open: ").append(node.getOpenConnections()) .append(", blocked: ").append(node.getBlockedConnections()) .append("}"); probeInfo.text(builder.toString()); From 52ee1007975d5cbf3b59105c543a8d377b22b198 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 12 Feb 2024 12:55:20 -0700 Subject: [PATCH 051/157] Fix nodes not deregistering killed channels --- .../gregtech/common/pipelike/fluidpipe/net/FluidChannel.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java index 401ef5a1dcd..76eac3cacaf 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -57,6 +57,7 @@ public void evaluate() { if (this.activeSources.size() == 0) { // should I put the channel in a 'recycling queue' to be reused instead? this.manager.removeChannel(this.fluid.getFluid()); + oldNodes.forEach(oldNode -> oldNode.removeChannel(this)); return; } @@ -105,9 +106,7 @@ public void evaluate() { } oldNodes.removeAll(nodes); - for (NodeG oldNode : oldNodes) { - oldNode.removeChannel(this); - } + oldNodes.forEach(oldNode -> oldNode.removeChannel(this)); oldNodes = nodes; // Everything should be properly balanced at this point due to earlier operations. From 46616d0f0d7ac61143ccaf5af3219c4a149db1a9 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 30 May 2024 21:44:07 -0600 Subject: [PATCH 052/157] Curse you Ghz --- .../common/covers/CoverItemFilter.java | 5 ++ .../pipelike/fluidpipe/net/FluidChannel.java | 8 +-- .../itempipe/net/ItemEdgePredicate.java | 60 ++++++++++--------- .../itempipe/net/WorldItemPipeNet.java | 8 +-- 4 files changed, 45 insertions(+), 36 deletions(-) diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 909fb09e481..4ce80925012 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -11,6 +11,7 @@ import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; import gregtech.client.utils.TooltipHelper; import gregtech.common.covers.filter.BaseFilter; +import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.ItemFilterContainer; import net.minecraft.entity.player.EntityPlayer; @@ -105,6 +106,10 @@ public ItemFilterMode getFilterMode() { return filterMode; } + public @NotNull BaseFilterContainer getFilterContainer() { + return this.itemFilterContainer; + } + @SuppressWarnings("DataFlowIssue") // this cover should always have a filter public @NotNull BaseFilter getFilter() { return this.itemFilterContainer.hasFilter() ? diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java index 76eac3cacaf..3e9920b5f05 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -9,9 +9,9 @@ import gregtech.api.pipenet.flow.FlowChannelTicker; import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.common.covers.CoverFluidFilter; import gregtech.common.covers.CoverPump; import gregtech.common.covers.CoverShutter; -import gregtech.common.covers.filter.FluidFilter; import gregtech.common.pipelike.fluidpipe.FluidPipeType; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; @@ -188,13 +188,13 @@ private int evaluateCover(Cover cover, int transferMax) { return 0; } case FILTERED -> { - if (!p.getFluidFilterContainer().testFluidStack(this.fluid)) return 0; + if (!p.getFluidFilterContainer().test(this.fluid)) return 0; } } return Math.min(transferMax, p.getTransferRate()); } - if (cover instanceof FluidFilter f) { - return f.testFluid(this.fluid) ? transferMax : 0; + if (cover instanceof CoverFluidFilter f) { + return f.getFilter().testFluid(this.fluid) ? transferMax : 0; } if (cover instanceof CoverShutter) return 0; return transferMax; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java index 8101c607e03..78ebcc88025 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java @@ -3,8 +3,10 @@ import gregtech.api.pipenet.AbstractEdgePredicate; import gregtech.api.pipenet.IShutteredEdgePredicate; import gregtech.api.util.IDirtyNotifiable; -import gregtech.common.covers.filter.FilterTypeRegistry; -import gregtech.common.covers.filter.ItemFilterWrapper; + +import gregtech.common.covers.filter.BaseFilterContainer; + +import gregtech.common.covers.filter.ItemFilterContainer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -22,8 +24,8 @@ public class ItemEdgePredicate extends AbstractEdgePredicate protected boolean shutteredSource; protected boolean shutteredTarget; - ItemFilterWrapper sourceFilter = new ItemFilterWrapper(DECOY); - ItemFilterWrapper targetFilter = new ItemFilterWrapper(DECOY); + @NotNull BaseFilterContainer sourceFilter = new DecoyContainer(); + @NotNull BaseFilterContainer targetFilter = new DecoyContainer(); @Override public void setShutteredSource(boolean shutteredSource) { @@ -35,11 +37,11 @@ public void setShutteredTarget(boolean shutteredTarget) { this.shutteredTarget = shutteredTarget; } - public void setSourceFilter(ItemFilterWrapper sourceFilter) { + public void setSourceFilter(@NotNull BaseFilterContainer sourceFilter) { this.sourceFilter = sourceFilter; } - public void setTargetFilter(ItemFilterWrapper targetFilter) { + public void setTargetFilter(@NotNull BaseFilterContainer targetFilter) { this.targetFilter = targetFilter; } @@ -47,7 +49,7 @@ public void setTargetFilter(ItemFilterWrapper targetFilter) { public boolean test(Object o) { if (shutteredSource || shutteredTarget) return false; if (!(o instanceof ItemStack stack)) return false; - return sourceFilter.testItemStack(stack) && targetFilter.testItemStack(stack); + return sourceFilter.test(stack) && targetFilter.test(stack); } @Override @@ -55,22 +57,13 @@ public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); if (shutteredSource) tag.setBoolean("ShutteredSource", true); if (shutteredTarget) tag.setBoolean("ShutteredTarget", true); - NBTTagCompound filterComponent; tag.setBoolean("SourceBlacklist", this.sourceFilter.isBlacklistFilter()); - if (this.sourceFilter.getItemFilter() != null) { - filterComponent = new NBTTagCompound(); - tag.setInteger("SourceFilterType", - FilterTypeRegistry.getIdForItemFilter(this.sourceFilter.getItemFilter())); - this.sourceFilter.getItemFilter().writeToNBT(filterComponent); - tag.setTag("SourceFilter", filterComponent); + if (this.sourceFilter.getFilter() != null) { + tag.setTag("SourceFilter", this.sourceFilter.serializeNBT()); } tag.setBoolean("TargetBlacklist", this.targetFilter.isBlacklistFilter()); - if (this.targetFilter.getItemFilter() != null) { - filterComponent = new NBTTagCompound(); - tag.setInteger("TargetFilterType", - FilterTypeRegistry.getIdForItemFilter(this.targetFilter.getItemFilter())); - this.targetFilter.getItemFilter().writeToNBT(filterComponent); - tag.setTag("TargetFilter", filterComponent); + if (this.targetFilter.getFilter() != null) { + tag.setTag("TargetFilter", this.targetFilter.serializeNBT()); } return tag; } @@ -80,16 +73,10 @@ public void deserializeNBT(NBTTagCompound nbt) { shutteredSource = nbt.getBoolean("ShutteredSource"); shutteredTarget = nbt.getBoolean("ShutteredTarget"); if (nbt.hasKey("SourceFilter")) { - this.sourceFilter - .setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("SourceFilterType"))); - this.sourceFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("SourceFilter")); - this.sourceFilter.setBlacklistFilter(nbt.getBoolean("SourceBlacklist")); + this.sourceFilter.deserializeNBT(nbt.getCompoundTag("SourceFilter")); } if (nbt.hasKey("TargetFilter")) { - this.targetFilter - .setItemFilter(FilterTypeRegistry.createItemFilterById(nbt.getInteger("TargetFilterType"))); - this.targetFilter.getItemFilter().readFromNBT(nbt.getCompoundTag("TargetFilter")); - this.targetFilter.setBlacklistFilter(nbt.getBoolean("TargetBlacklist")); + this.targetFilter.deserializeNBT(nbt.getCompoundTag("TargetFilter")); } } @@ -103,6 +90,23 @@ protected String predicateType() { return "Item"; } + private static class DecoyContainer extends ItemFilterContainer { + + protected DecoyContainer() { + super(DECOY); + } + + @Override + protected boolean isItemValid(ItemStack stack) { + return false; + } + + @Override + protected String getFilterName() { + return "INVALID"; + } + } + private static class Decoy implements IDirtyNotifiable { @Override diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index 39668db849b..26c23575134 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -43,24 +43,24 @@ protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbour ItemEdgePredicate predicate = new ItemEdgePredicate(); if (thisCover instanceof CoverItemFilter filter && filter.getFilterMode() != ItemFilterMode.FILTER_INSERT) { - predicate.setSourceFilter(filter.getItemFilter()); + predicate.setSourceFilter(filter.getFilterContainer()); } if (neighbourCover instanceof CoverItemFilter filter && filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT) { - predicate.setTargetFilter(filter.getItemFilter()); + predicate.setTargetFilter(filter.getFilterContainer()); } if (thisCover instanceof CoverConveyor conveyor) { if (conveyor.getManualImportExportMode() == ManualImportExportMode.DISABLED) { predicate.setShutteredSource(true); } else if (conveyor.getManualImportExportMode() == ManualImportExportMode.FILTERED) { - predicate.setSourceFilter(conveyor.getItemFilterContainer().getFilterWrapper()); + predicate.setSourceFilter(conveyor.getItemFilterContainer()); } } if (neighbourCover instanceof CoverConveyor conveyor) { if (conveyor.getManualImportExportMode() == ManualImportExportMode.DISABLED) { predicate.setShutteredTarget(true); } else if (conveyor.getManualImportExportMode() == ManualImportExportMode.FILTERED) { - predicate.setTargetFilter(conveyor.getItemFilterContainer().getFilterWrapper()); + predicate.setTargetFilter(conveyor.getItemFilterContainer()); } } // TODO should robot arms apply rate limits to edge predicates? From feb830a85d333bf36b091af2318566ac7cdf24fb Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 30 May 2024 22:12:12 -0600 Subject: [PATCH 053/157] Fluid predicates --- .../api/pipenet/AbstractEdgePredicate.java | 4 +- .../api/pipenet/BasicEdgePredicate.java | 2 +- .../api/pipenet/StandardEdgePredicate.java | 75 ++++++++++++++++ .../common/covers/CoverFluidFilter.java | 5 ++ .../fluidpipe/net/FluidEdgePredicate.java | 47 ++++++++++ .../fluidpipe/net/WorldFluidPipeNet.java | 38 ++++++++ .../itempipe/net/ItemEdgePredicate.java | 90 ++----------------- 7 files changed, 177 insertions(+), 84 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/StandardEdgePredicate.java create mode 100644 src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java diff --git a/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java b/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java index d903b2e6e40..daefc7e2d04 100644 --- a/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java @@ -27,7 +27,7 @@ public void setPosInfo(BlockPos sourcePos, BlockPos targetPos) { @NotNull protected abstract T createPredicate(); - protected abstract String predicateType(); + protected abstract String predicateName(); public static AbstractEdgePredicate newPredicate(String identifier) { AbstractEdgePredicate predicate = PREDICATES.get(identifier); @@ -50,7 +50,7 @@ public static AbstractEdgePredicate nbtPredicate(NBTTagCompound nbt) { public static NBTTagCompound toNBT(AbstractEdgePredicate predicate) { NBTTagCompound tag = new NBTTagCompound(); - tag.setString("Type", predicate.predicateType()); + tag.setString("Type", predicate.predicateName()); tag.setTag("Data", predicate.serializeNBT()); return tag; } diff --git a/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java b/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java index c1e012b9efc..c739dd85434 100644 --- a/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java @@ -48,7 +48,7 @@ public void deserializeNBT(NBTTagCompound nbt) { } @Override - protected String predicateType() { + protected String predicateName() { return "Basic"; } } diff --git a/src/main/java/gregtech/api/pipenet/StandardEdgePredicate.java b/src/main/java/gregtech/api/pipenet/StandardEdgePredicate.java new file mode 100644 index 00000000000..1cc4a2799fa --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/StandardEdgePredicate.java @@ -0,0 +1,75 @@ +package gregtech.api.pipenet; + +import gregtech.api.util.IDirtyNotifiable; +import gregtech.common.covers.filter.BaseFilterContainer; +import gregtech.common.covers.filter.ItemFilterContainer; + +import net.minecraft.nbt.NBTTagCompound; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +public abstract class StandardEdgePredicate> extends AbstractEdgePredicate + implements IShutteredEdgePredicate { + + + protected static final IDirtyNotifiable DECOY = () -> {}; + + protected boolean shutteredSource; + protected boolean shutteredTarget; + + protected @NotNull BaseFilterContainer sourceFilter; + protected @NotNull BaseFilterContainer targetFilter; + + public StandardEdgePredicate() { + sourceFilter = ((StandardEdgePredicate) PREDICATES.get(predicateName())).getDefaultFilterContainer(); + targetFilter = ((StandardEdgePredicate) PREDICATES.get(predicateName())).getDefaultFilterContainer(); + } + + @Override + public void setShutteredSource(boolean shutteredSource) { + this.shutteredSource = shutteredSource; + } + + @Override + public void setShutteredTarget(boolean shutteredTarget) { + this.shutteredTarget = shutteredTarget; + } + + public void setSourceFilter(@NotNull BaseFilterContainer sourceFilter) { + this.sourceFilter = sourceFilter; + } + + public void setTargetFilter(@NotNull BaseFilterContainer targetFilter) { + this.targetFilter = targetFilter; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + if (shutteredSource) tag.setBoolean("ShutteredSource", true); + if (shutteredTarget) tag.setBoolean("ShutteredTarget", true); + if (this.sourceFilter.getFilter() != null) { + tag.setTag("SourceFilter", this.sourceFilter.serializeNBT()); + } + if (this.targetFilter.getFilter() != null) { + tag.setTag("TargetFilter", this.targetFilter.serializeNBT()); + } + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + shutteredSource = nbt.getBoolean("ShutteredSource"); + shutteredTarget = nbt.getBoolean("ShutteredTarget"); + if (nbt.hasKey("SourceFilter")) { + this.sourceFilter.deserializeNBT(nbt.getCompoundTag("SourceFilter")); + } + if (nbt.hasKey("TargetFilter")) { + this.targetFilter.deserializeNBT(nbt.getCompoundTag("TargetFilter")); + } + } + + @Contract("-> new") + protected abstract BaseFilterContainer getDefaultFilterContainer(); +} diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index 648968c90dc..ee751436bc8 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -11,6 +11,7 @@ import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; import gregtech.client.utils.TooltipHelper; import gregtech.common.covers.filter.BaseFilter; +import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.FluidFilterContainer; import net.minecraft.entity.player.EntityPlayer; @@ -107,6 +108,10 @@ public FluidFilterMode getFilterMode() { return filterMode; } + public @NotNull BaseFilterContainer getFilterContainer() { + return this.fluidFilterContainer; + } + @SuppressWarnings("DataFlowIssue") // this cover always has a filter public @NotNull BaseFilter getFilter() { return this.fluidFilterContainer.hasFilter() ? diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java new file mode 100644 index 00000000000..9febb367d66 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java @@ -0,0 +1,47 @@ +package gregtech.common.pipelike.fluidpipe.net; + +import gregtech.api.pipenet.AbstractEdgePredicate; +import gregtech.api.pipenet.IShutteredEdgePredicate; +import gregtech.api.pipenet.StandardEdgePredicate; +import gregtech.api.util.IDirtyNotifiable; +import gregtech.common.covers.filter.BaseFilterContainer; +import gregtech.common.covers.filter.FluidFilterContainer; +import gregtech.common.covers.filter.ItemFilterContainer; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import net.minecraftforge.fluids.FluidStack; + +import org.jetbrains.annotations.NotNull; + +public class FluidEdgePredicate extends StandardEdgePredicate { + + private final static String KEY = "Fluid"; + + static { + PREDICATES.put(KEY, new FluidEdgePredicate()); + } + + @Override + public boolean test(Object o) { + if (shutteredSource || shutteredTarget) return false; + if (!(o instanceof FluidStack stack)) return false; + return sourceFilter.test(stack) && targetFilter.test(stack); + } + + @Override + public @NotNull FluidEdgePredicate createPredicate() { + return new FluidEdgePredicate(); + } + + @Override + protected String predicateName() { + return KEY; + } + + @Override + protected BaseFilterContainer getDefaultFilterContainer() { + return new FluidFilterContainer(DECOY); + } +} diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index bb83b487eb8..b01db87386a 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -1,8 +1,17 @@ package gregtech.common.pipelike.fluidpipe.net; +import gregtech.api.cover.Cover; +import gregtech.api.pipenet.AbstractEdgePredicate; import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.common.covers.CoverConveyor; +import gregtech.common.covers.CoverFluidFilter; +import gregtech.common.covers.CoverItemFilter; +import gregtech.common.covers.CoverPump; +import gregtech.common.covers.FluidFilterMode; +import gregtech.common.covers.ItemFilterMode; +import gregtech.common.covers.ManualImportExportMode; import gregtech.common.pipelike.fluidpipe.FluidPipeType; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; @@ -35,6 +44,35 @@ protected Class> getBase return TileEntityFluidPipe.class; } + @Override + protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbourCover) { + FluidEdgePredicate predicate = new FluidEdgePredicate(); + if (thisCover instanceof CoverFluidFilter filter && + filter.getFilterMode() != FluidFilterMode.FILTER_FILL) { + predicate.setSourceFilter(filter.getFilterContainer()); + } + if (neighbourCover instanceof CoverFluidFilter filter && + filter.getFilterMode() != FluidFilterMode.FILTER_DRAIN) { + predicate.setTargetFilter(filter.getFilterContainer()); + } + if (thisCover instanceof CoverPump pump) { + if (pump.getManualImportExportMode() == ManualImportExportMode.DISABLED) { + predicate.setShutteredSource(true); + } else if (pump.getManualImportExportMode() == ManualImportExportMode.FILTERED) { + predicate.setSourceFilter(pump.getFluidFilterContainer()); + } + } + if (neighbourCover instanceof CoverPump pump) { + if (pump.getManualImportExportMode() == ManualImportExportMode.DISABLED) { + predicate.setShutteredTarget(true); + } else if (pump.getManualImportExportMode() == ManualImportExportMode.FILTERED) { + predicate.setTargetFilter(pump.getFluidFilterContainer()); + } + } + // TODO should fluid regulators apply rate limits to edge predicates? + return shutterify(predicate, thisCover, neighbourCover); + } + @Override protected Capability getSinkCapability() { return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java index 78ebcc88025..78facd202c7 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java @@ -1,48 +1,22 @@ package gregtech.common.pipelike.itempipe.net; -import gregtech.api.pipenet.AbstractEdgePredicate; import gregtech.api.pipenet.IShutteredEdgePredicate; -import gregtech.api.util.IDirtyNotifiable; +import gregtech.api.pipenet.StandardEdgePredicate; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.ItemFilterContainer; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import org.jetbrains.annotations.NotNull; -public class ItemEdgePredicate extends AbstractEdgePredicate implements IShutteredEdgePredicate { +public class ItemEdgePredicate extends StandardEdgePredicate { - private final static Decoy DECOY = new Decoy(); + private final static String KEY = "Item"; static { - PREDICATES.put("Item", new ItemEdgePredicate()); - } - - protected boolean shutteredSource; - protected boolean shutteredTarget; - - @NotNull BaseFilterContainer sourceFilter = new DecoyContainer(); - @NotNull BaseFilterContainer targetFilter = new DecoyContainer(); - - @Override - public void setShutteredSource(boolean shutteredSource) { - this.shutteredSource = shutteredSource; - } - - @Override - public void setShutteredTarget(boolean shutteredTarget) { - this.shutteredTarget = shutteredTarget; - } - - public void setSourceFilter(@NotNull BaseFilterContainer sourceFilter) { - this.sourceFilter = sourceFilter; - } - - public void setTargetFilter(@NotNull BaseFilterContainer targetFilter) { - this.targetFilter = targetFilter; + PREDICATES.put(KEY, new ItemEdgePredicate()); } @Override @@ -52,64 +26,18 @@ public boolean test(Object o) { return sourceFilter.test(stack) && targetFilter.test(stack); } - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tag = new NBTTagCompound(); - if (shutteredSource) tag.setBoolean("ShutteredSource", true); - if (shutteredTarget) tag.setBoolean("ShutteredTarget", true); - tag.setBoolean("SourceBlacklist", this.sourceFilter.isBlacklistFilter()); - if (this.sourceFilter.getFilter() != null) { - tag.setTag("SourceFilter", this.sourceFilter.serializeNBT()); - } - tag.setBoolean("TargetBlacklist", this.targetFilter.isBlacklistFilter()); - if (this.targetFilter.getFilter() != null) { - tag.setTag("TargetFilter", this.targetFilter.serializeNBT()); - } - return tag; - } - - @Override - public void deserializeNBT(NBTTagCompound nbt) { - shutteredSource = nbt.getBoolean("ShutteredSource"); - shutteredTarget = nbt.getBoolean("ShutteredTarget"); - if (nbt.hasKey("SourceFilter")) { - this.sourceFilter.deserializeNBT(nbt.getCompoundTag("SourceFilter")); - } - if (nbt.hasKey("TargetFilter")) { - this.targetFilter.deserializeNBT(nbt.getCompoundTag("TargetFilter")); - } - } - @Override public @NotNull ItemEdgePredicate createPredicate() { return new ItemEdgePredicate(); } @Override - protected String predicateType() { - return "Item"; - } - - private static class DecoyContainer extends ItemFilterContainer { - - protected DecoyContainer() { - super(DECOY); - } - - @Override - protected boolean isItemValid(ItemStack stack) { - return false; - } - - @Override - protected String getFilterName() { - return "INVALID"; - } + protected String predicateName() { + return KEY; } - private static class Decoy implements IDirtyNotifiable { - - @Override - public void markAsDirty() {} + @Override + protected BaseFilterContainer getDefaultFilterContainer() { + return new ItemFilterContainer(DECOY); } } From 1b63dfd25b69198e747ad7aaf21182af436f1111 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 30 May 2024 22:13:07 -0600 Subject: [PATCH 054/157] Fix a potential issue with predication --- src/main/java/gregtech/api/pipenet/WorldPipeNetG.java | 3 ++- src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java | 3 ++- .../java/gregtech/api/pipenet/tile/TileEntityPipeBase.java | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java index cc4e1524cd8..549c363895c 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java @@ -56,7 +56,8 @@ public abstract class WorldPipeNetG /** * @param isDirected Determines whether this net needs directed graph handling. * Used to respect filter directions in the item net and fluid net, for example. - * If the graph is not directed, pipes should not support blocked connections. + * If the graph is not directed, pipes should not support blocked connections + * or unidirectional covers. * @param isSinglePath Determines whether this net allows only one source and one destination per group. * Allows for optimizations in path lookup and cache invalidation. */ diff --git a/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java index 232cf9aea8f..c95292547fe 100644 --- a/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java +++ b/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java @@ -39,7 +39,8 @@ public abstract class WorldPipeFlowNetG() : new FlowUndirected<>()); diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 3c306d913be..0737b8878e2 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -576,7 +576,7 @@ public void markAsDirty() { if (getWorld().isRemote || this.nbtLoad) return; for (EnumFacing facing : EnumFacing.VALUES) { if (!isConnected(facing)) continue; - this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()).predicateEdge(this.getPipePos(), facing); + this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()).predicateUndirectedEdge(this.getPipePos(), facing); } } From 1e93ca036cd460f162fe1e1eda3b711eda042e44 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 31 May 2024 16:05:17 -0600 Subject: [PATCH 055/157] Spotless --- .../java/gregtech/api/pipenet/StandardEdgePredicate.java | 4 +--- .../common/pipelike/fluidpipe/net/FluidEdgePredicate.java | 7 ------- .../common/pipelike/fluidpipe/net/WorldFluidPipeNet.java | 3 --- .../common/pipelike/itempipe/net/ItemEdgePredicate.java | 3 --- .../common/pipelike/itempipe/net/ItemNetHandler.java | 2 +- 5 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/StandardEdgePredicate.java b/src/main/java/gregtech/api/pipenet/StandardEdgePredicate.java index 1cc4a2799fa..fe6a7457296 100644 --- a/src/main/java/gregtech/api/pipenet/StandardEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/StandardEdgePredicate.java @@ -2,7 +2,6 @@ import gregtech.api.util.IDirtyNotifiable; import gregtech.common.covers.filter.BaseFilterContainer; -import gregtech.common.covers.filter.ItemFilterContainer; import net.minecraft.nbt.NBTTagCompound; @@ -10,8 +9,7 @@ import org.jetbrains.annotations.NotNull; public abstract class StandardEdgePredicate> extends AbstractEdgePredicate - implements IShutteredEdgePredicate { - + implements IShutteredEdgePredicate { protected static final IDirtyNotifiable DECOY = () -> {}; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java index 9febb367d66..4795bdf8472 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java @@ -1,15 +1,8 @@ package gregtech.common.pipelike.fluidpipe.net; -import gregtech.api.pipenet.AbstractEdgePredicate; -import gregtech.api.pipenet.IShutteredEdgePredicate; import gregtech.api.pipenet.StandardEdgePredicate; -import gregtech.api.util.IDirtyNotifiable; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.FluidFilterContainer; -import gregtech.common.covers.filter.ItemFilterContainer; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.FluidStack; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index b01db87386a..70b1b163ba7 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -5,12 +5,9 @@ import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; -import gregtech.common.covers.CoverConveyor; import gregtech.common.covers.CoverFluidFilter; -import gregtech.common.covers.CoverItemFilter; import gregtech.common.covers.CoverPump; import gregtech.common.covers.FluidFilterMode; -import gregtech.common.covers.ItemFilterMode; import gregtech.common.covers.ManualImportExportMode; import gregtech.common.pipelike.fluidpipe.FluidPipeType; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java index 78facd202c7..d11f45f6d0e 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java @@ -1,10 +1,7 @@ package gregtech.common.pipelike.itempipe.net; -import gregtech.api.pipenet.IShutteredEdgePredicate; import gregtech.api.pipenet.StandardEdgePredicate; - import gregtech.common.covers.filter.BaseFilterContainer; - import gregtech.common.covers.filter.ItemFilterContainer; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index 63182298d55..2e199c09b96 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -9,12 +9,12 @@ import gregtech.api.util.GTTransferUtils; import gregtech.api.util.ItemStackHashStrategy; import gregtech.common.covers.*; -import gregtech.common.pipelike.itempipe.ItemPipeType; import gregtech.common.covers.CoverConveyor; import gregtech.common.covers.CoverItemFilter; import gregtech.common.covers.CoverRoboticArm; import gregtech.common.covers.DistributionMode; import gregtech.common.covers.ItemFilterMode; +import gregtech.common.pipelike.itempipe.ItemPipeType; import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; import net.minecraft.item.ItemStack; From 7e4a281a279c83d5595b5ed365f04489df75730f Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 4 Jun 2024 10:39:47 -0600 Subject: [PATCH 056/157] Fix issue with initialization of predicates --- .../api/pipenet/AbstractEdgePredicate.java | 24 +++++++++---------- .../api/pipenet/BasicEdgePredicate.java | 13 ++++------ ...dicate.java => FilteredEdgePredicate.java} | 13 +++++----- .../fluidpipe/net/FluidEdgePredicate.java | 13 ++++------ .../itempipe/net/ItemEdgePredicate.java | 13 ++++------ 5 files changed, 31 insertions(+), 45 deletions(-) rename src/main/java/gregtech/api/pipenet/{StandardEdgePredicate.java => FilteredEdgePredicate.java} (82%) diff --git a/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java b/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java index daefc7e2d04..5cc781d36cf 100644 --- a/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java @@ -10,11 +10,12 @@ import java.util.Map; import java.util.function.Predicate; +import java.util.function.Supplier; public abstract class AbstractEdgePredicate> implements Predicate, INBTSerializable { - protected static final Map> PREDICATES = new Object2ObjectOpenHashMap<>(); + protected static final Map>> PREDICATE_SUPPLIERS = new Object2ObjectOpenHashMap<>(); protected BlockPos sourcePos; protected BlockPos targetPos; @@ -24,31 +25,28 @@ public void setPosInfo(BlockPos sourcePos, BlockPos targetPos) { this.targetPos = targetPos; } - @NotNull - protected abstract T createPredicate(); - protected abstract String predicateName(); + private static Supplier> getSupplier(String identifier) { + return PREDICATE_SUPPLIERS.getOrDefault(identifier, () -> null); + } + + @Nullable public static AbstractEdgePredicate newPredicate(String identifier) { - AbstractEdgePredicate predicate = PREDICATES.get(identifier); - if (predicate != null) { - return predicate.createPredicate(); - } - return null; + return getSupplier(identifier).get(); } @Nullable - public static AbstractEdgePredicate nbtPredicate(NBTTagCompound nbt) { - AbstractEdgePredicate predicate = PREDICATES.get(nbt.getString("Type")); + public static AbstractEdgePredicate nbtPredicate(@NotNull NBTTagCompound nbt) { + AbstractEdgePredicate predicate = getSupplier(nbt.getString("Type")).get(); if (predicate != null) { - predicate = predicate.createPredicate(); predicate.deserializeNBT(nbt.getCompoundTag("Data")); return predicate; } return null; } - public static NBTTagCompound toNBT(AbstractEdgePredicate predicate) { + public static @NotNull NBTTagCompound toNBT(@NotNull AbstractEdgePredicate predicate) { NBTTagCompound tag = new NBTTagCompound(); tag.setString("Type", predicate.predicateName()); tag.setTag("Data", predicate.serializeNBT()); diff --git a/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java b/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java index c739dd85434..32776ca3534 100644 --- a/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java @@ -6,8 +6,10 @@ public class BasicEdgePredicate extends AbstractEdgePredicate implements IShutteredEdgePredicate { + private final static String KEY = "Basic"; + static { - PREDICATES.put("Basic", new BasicEdgePredicate()); + PREDICATE_SUPPLIERS.put(KEY, BasicEdgePredicate::new); } protected boolean shutteredSource; @@ -37,18 +39,13 @@ public NBTTagCompound serializeNBT() { } @Override - public void deserializeNBT(NBTTagCompound nbt) { + public void deserializeNBT(@NotNull NBTTagCompound nbt) { shutteredSource = nbt.getBoolean("ShutteredSource"); shutteredTarget = nbt.getBoolean("ShutteredTarget"); } - @Override - public @NotNull BasicEdgePredicate createPredicate() { - return new BasicEdgePredicate(); - } - @Override protected String predicateName() { - return "Basic"; + return KEY; } } diff --git a/src/main/java/gregtech/api/pipenet/StandardEdgePredicate.java b/src/main/java/gregtech/api/pipenet/FilteredEdgePredicate.java similarity index 82% rename from src/main/java/gregtech/api/pipenet/StandardEdgePredicate.java rename to src/main/java/gregtech/api/pipenet/FilteredEdgePredicate.java index fe6a7457296..1981c19aa29 100644 --- a/src/main/java/gregtech/api/pipenet/StandardEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/FilteredEdgePredicate.java @@ -3,12 +3,13 @@ import gregtech.api.util.IDirtyNotifiable; import gregtech.common.covers.filter.BaseFilterContainer; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -public abstract class StandardEdgePredicate> extends AbstractEdgePredicate +public abstract class FilteredEdgePredicate> extends AbstractEdgePredicate implements IShutteredEdgePredicate { protected static final IDirtyNotifiable DECOY = () -> {}; @@ -19,9 +20,9 @@ public abstract class StandardEdgePredicate> protected @NotNull BaseFilterContainer sourceFilter; protected @NotNull BaseFilterContainer targetFilter; - public StandardEdgePredicate() { - sourceFilter = ((StandardEdgePredicate) PREDICATES.get(predicateName())).getDefaultFilterContainer(); - targetFilter = ((StandardEdgePredicate) PREDICATES.get(predicateName())).getDefaultFilterContainer(); + public FilteredEdgePredicate() { + sourceFilter = this.getDefaultFilterContainer(); + targetFilter = this.getDefaultFilterContainer(); } @Override @@ -57,7 +58,7 @@ public NBTTagCompound serializeNBT() { } @Override - public void deserializeNBT(NBTTagCompound nbt) { + public void deserializeNBT(@NotNull NBTTagCompound nbt) { shutteredSource = nbt.getBoolean("ShutteredSource"); shutteredTarget = nbt.getBoolean("ShutteredTarget"); if (nbt.hasKey("SourceFilter")) { @@ -69,5 +70,5 @@ public void deserializeNBT(NBTTagCompound nbt) { } @Contract("-> new") - protected abstract BaseFilterContainer getDefaultFilterContainer(); + protected abstract @NotNull BaseFilterContainer getDefaultFilterContainer(); } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java index 4795bdf8472..b1ade12d8bf 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java @@ -1,6 +1,6 @@ package gregtech.common.pipelike.fluidpipe.net; -import gregtech.api.pipenet.StandardEdgePredicate; +import gregtech.api.pipenet.FilteredEdgePredicate; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.FluidFilterContainer; @@ -8,12 +8,12 @@ import org.jetbrains.annotations.NotNull; -public class FluidEdgePredicate extends StandardEdgePredicate { +public class FluidEdgePredicate extends FilteredEdgePredicate { private final static String KEY = "Fluid"; static { - PREDICATES.put(KEY, new FluidEdgePredicate()); + PREDICATE_SUPPLIERS.put(KEY, FluidEdgePredicate::new); } @Override @@ -23,18 +23,13 @@ public boolean test(Object o) { return sourceFilter.test(stack) && targetFilter.test(stack); } - @Override - public @NotNull FluidEdgePredicate createPredicate() { - return new FluidEdgePredicate(); - } - @Override protected String predicateName() { return KEY; } @Override - protected BaseFilterContainer getDefaultFilterContainer() { + protected @NotNull BaseFilterContainer getDefaultFilterContainer() { return new FluidFilterContainer(DECOY); } } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java index d11f45f6d0e..805d3a76a37 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java @@ -1,6 +1,6 @@ package gregtech.common.pipelike.itempipe.net; -import gregtech.api.pipenet.StandardEdgePredicate; +import gregtech.api.pipenet.FilteredEdgePredicate; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.ItemFilterContainer; @@ -8,12 +8,12 @@ import org.jetbrains.annotations.NotNull; -public class ItemEdgePredicate extends StandardEdgePredicate { +public class ItemEdgePredicate extends FilteredEdgePredicate { private final static String KEY = "Item"; static { - PREDICATES.put(KEY, new ItemEdgePredicate()); + PREDICATE_SUPPLIERS.put(KEY, ItemEdgePredicate::new); } @Override @@ -23,18 +23,13 @@ public boolean test(Object o) { return sourceFilter.test(stack) && targetFilter.test(stack); } - @Override - public @NotNull ItemEdgePredicate createPredicate() { - return new ItemEdgePredicate(); - } - @Override protected String predicateName() { return KEY; } @Override - protected BaseFilterContainer getDefaultFilterContainer() { + protected @NotNull BaseFilterContainer getDefaultFilterContainer() { return new ItemFilterContainer(DECOY); } } From 8cbb9726c16dde8b1f37005015796ec5e8435422 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 4 Jun 2024 15:20:17 -0600 Subject: [PATCH 057/157] flow improvements --- .../api/pipenet/flow/FlowChannel.java | 12 ++++-- .../api/pipenet/flow/FlowChannelManager.java | 3 +- .../api/pipenet/flow/WorldPipeFlowNetG.java | 28 ++++++------- .../pipelike/fluidpipe/net/FluidChannel.java | 42 ++++++++++++------- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java b/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java index f9bf9ce024b..46889b1629e 100644 --- a/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java +++ b/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java @@ -16,6 +16,7 @@ import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; +import java.util.ArrayList; import java.util.Map; import java.util.Set; @@ -34,6 +35,7 @@ public FlowChannel(Graph, NetEdge> network) { } FlowChannel setManager(FlowChannelManager manager) { + if (this.manager != null) this.manager.removeChannel(this.getKey()); this.manager = manager; return this; } @@ -46,13 +48,13 @@ FlowChannel setManager(FlowChannelManager manager) { * Prime the edges to the super nodes to prepare for calculations. */ protected void activate() { - for (NodeG source : activeSources) { + for (NodeG source : new ArrayList<>(activeSources)) { double v = getSourceValue(source); // TODO find source of random NPE crash where a source edge doesn't exist after world load (pls help) network.setEdgeWeight(this.manager.getSuperSource(), source, v); if (v == 0) removeSource(source); } - for (NodeG sink : this.manager.getActiveSinks()) { + for (NodeG sink : new ArrayList<>(this.manager.getActiveSinks())) { double v = getSinkValue(sink); network.setEdgeWeight(sink, this.manager.getSuperSink(), v); } @@ -62,10 +64,10 @@ protected void activate() { * Zero out the edges to the super nodes to prevent other calculations from using them. */ protected void deactivate() { - for (NodeG source : activeSources) { + for (NodeG source : new ArrayList<>(activeSources)) { network.setEdgeWeight(this.manager.getSuperSource(), source, 0); } - for (NodeG sink : this.manager.getActiveSinks()) { + for (NodeG sink : new ArrayList<>(this.manager.getActiveSinks())) { network.setEdgeWeight(sink, this.manager.getSuperSink(), 0); } } @@ -138,4 +140,6 @@ protected void removeNode(NodeG node) { this.activeSources.remove(node); this.receiveSidesMap.remove(node); } + + protected abstract Object getKey(); } diff --git a/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java b/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java index e78da938250..89225716b8f 100644 --- a/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java +++ b/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java @@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; @@ -104,7 +105,7 @@ public void removeSink(NodeG sink) { if (this.activeSinks.remove(sink)) this.net.getPipeGraph().removeEdge(sink, this.net.getSuperSink()); } - public void setChannel(Object key, FlowChannel channel) { + public void setChannel(Object key, @NotNull FlowChannel channel) { this.channels.put(key, channel.setManager(this)); } diff --git a/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java index c95292547fe..b3c95077c10 100644 --- a/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java +++ b/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java @@ -160,8 +160,8 @@ protected static class FlowUndirected, PT extends Enu extends SimpleWeightedGraph, NetEdge> implements IFlowGraph { - Object testObject; - FlowChannel queryingChannel; + final ThreadLocal testObject = new ThreadLocal<>(); + final ThreadLocal> queryingChannel = new ThreadLocal<>(); public FlowUndirected() { super(NetEdge.class); @@ -171,19 +171,19 @@ public FlowUndirected() { @Override public double getEdgeWeight(NetEdge netEdge) { // Both source and target must support the channel, and the netEdge predicate must allow our object. - return ((NodeG) netEdge.getSource()).canSupportChannel(queryingChannel) && - ((NodeG) netEdge.getTarget()).canSupportChannel(queryingChannel) && - netEdge.getPredicate().test(testObject) ? super.getEdgeWeight(netEdge) : 0; + return ((NodeG) netEdge.getSource()).canSupportChannel(queryingChannel.get()) && + ((NodeG) netEdge.getTarget()).canSupportChannel(queryingChannel.get()) && + netEdge.getPredicate().test(testObject.get()) ? super.getEdgeWeight(netEdge) : 0; } @Override public void setTestObject(Object object) { - this.testObject = object; + this.testObject.set(object); } @Override public void setQueryingChannel(FlowChannel channel) { - this.queryingChannel = channel; + this.queryingChannel.set(channel); } } @@ -191,8 +191,8 @@ protected static class FlowDirected, PT extends Enum< extends SimpleDirectedWeightedGraph, NetEdge> implements IFlowGraph { - Object testObject; - FlowChannel queryingChannel; + final ThreadLocal testObject = new ThreadLocal<>(); + final ThreadLocal> queryingChannel = new ThreadLocal<>(); public FlowDirected() { super(NetEdge.class); @@ -202,19 +202,19 @@ public FlowDirected() { @Override public double getEdgeWeight(NetEdge netEdge) { // Both source and target must support the channel, and the netEdge predicate must allow our object. - return ((NodeG) netEdge.getSource()).canSupportChannel(queryingChannel) && - ((NodeG) netEdge.getTarget()).canSupportChannel(queryingChannel) && - netEdge.getPredicate().test(testObject) ? super.getEdgeWeight(netEdge) : 0; + return ((NodeG) netEdge.getSource()).canSupportChannel(queryingChannel.get()) && + ((NodeG) netEdge.getTarget()).canSupportChannel(queryingChannel.get()) && + netEdge.getPredicate().test(testObject.get()) ? super.getEdgeWeight(netEdge) : 0; } @Override public void setTestObject(Object object) { - this.testObject = object; + this.testObject.set(object); } @Override public void setQueryingChannel(FlowChannel channel) { - this.queryingChannel = channel; + this.queryingChannel.set(channel); } } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java index 3e9920b5f05..7e19aa51528 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java @@ -43,9 +43,15 @@ public FluidChannel(Graph, NetEdge> ne } public void setFluid(Fluid fluid) { + if (this.manager != null) return; this.fluid = new FluidStack(fluid, 1); } + @Override + protected Object getKey() { + return fluid.getFluid(); + } + @Override public void clearAlg() { this.alg = null; @@ -56,7 +62,7 @@ public void evaluate() { // Kill this channel if we have no more active sources if (this.activeSources.size() == 0) { // should I put the channel in a 'recycling queue' to be reused instead? - this.manager.removeChannel(this.fluid.getFluid()); + this.manager.removeChannel(this.getKey()); oldNodes.forEach(oldNode -> oldNode.removeChannel(this)); return; } @@ -64,50 +70,55 @@ public void evaluate() { activate(); if (network instanceof WorldPipeFlowNetG.IFlowGraphgraph) { - graph.setTestObject(fluid.getFluid()); + graph.setTestObject(fluid); ((WorldPipeFlowNetG.IFlowGraph) graph) .setQueryingChannel(this); } else throw new IllegalStateException("Attempted to do flow calculations on a non-flow graph!"); if (alg == null) alg = new MaximumFlowAlgorithm<>(network); - alg.calculateMaximumFlow(this.manager.getSuperSource(), this.manager.getSuperSink()); - Map flows = alg.getFlowMap(); + Map flows = alg.getMaximumFlow(manager.getSuperSource(), manager.getSuperSink()).getFlowMap(); Map, Double> inMap = new Object2DoubleOpenHashMap<>(); Map, Double> outMap = new Object2DoubleOpenHashMap<>(); - Set> nodes = new ObjectOpenHashSet<>(); + Map, Double> interMap = new Object2DoubleOpenHashMap<>(); for (Map.Entry flow : flows.entrySet()) { if (flow.getValue() == 0) continue; NetEdge edge = flow.getKey(); - // we only care about a flow if it involves a super node, and we only care about non-super node nodes. + // the interflows receive values from both inflow and outflow, which are equivalent, thus divide by two. if (edge.getSource() == this.manager.getSuperSource()) { inMap.merge(edge.getTarget(), flow.getValue(), Double::sum); - nodes.add((NodeG) edge.getTarget()); + interMap.merge((NodeG) edge.getTarget(), + flow.getValue() / 2, Double::sum); } else if (edge.getTarget() == this.manager.getSuperSink()) { - outMap.merge(flow.getKey().getSource(), flow.getValue(), Double::sum); - nodes.add((NodeG) edge.getSource()); + outMap.merge(edge.getSource(), flow.getValue(), Double::sum); + interMap.merge((NodeG) edge.getSource(), + flow.getValue() / 2, Double::sum); } else { - nodes.add((NodeG) edge.getSource()); - nodes.add((NodeG) edge.getTarget()); + interMap.merge((NodeG) edge.getSource(), + flow.getValue() / 2, Double::sum); + interMap.merge((NodeG) edge.getTarget(), + flow.getValue() / 2, Double::sum); } } - for (NodeG node : nodes) { + for (var flow : interMap.entrySet()) { + NodeG node = flow.getKey(); if (!node.addChannel(this)) throw new IllegalStateException("Node rejected channel despite approving it earlier!"); if (!node.getData().test(fluid)) { // destroyethify if (node.getHeldMTE() instanceof TileEntityFluidPipe f) { - f.checkAndDestroy(fluid); + FluidStack flowStack = new FluidStack(fluid, (int) (double) flow.getValue()); + f.checkAndDestroy(flowStack); // TODO fix fluid leakage } } } - oldNodes.removeAll(nodes); + oldNodes.removeAll(interMap.keySet()); oldNodes.forEach(oldNode -> oldNode.removeChannel(this)); - oldNodes = nodes; + oldNodes = interMap.keySet(); // Everything should be properly balanced at this point due to earlier operations. // If something is off, it's too late to fix. @@ -153,6 +164,7 @@ private int pushToNode(NodeG sink, int amoun int fill; Byte receiveSides = this.receiveSidesMap.get(sink); for (Map.Entry connected : sink.getConnecteds().entrySet()) { + if (amount == 0) break; if (receiveSides != null) { int facing = (1 << connected.getKey().getIndex()); if ((receiveSides & facing) != 0) { From 0886a4c095cc09c4dce4cc8ab34e9b9a943116d4 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 18 Jun 2024 19:51:08 -0600 Subject: [PATCH 058/157] Truly Tickless fluid piping (pain) --- .../java/gregtech/api/pipenet/INodeData.java | 9 + .../gregtech/api/pipenet/IPipeNetHandler.java | 30 ++ .../java/gregtech/api/pipenet/NetEdge.java | 166 +++++++++++ .../java/gregtech/api/pipenet/NetGroup.java | 122 +------- .../java/gregtech/api/pipenet/NetPath.java | 17 +- src/main/java/gregtech/api/pipenet/NodeG.java | 65 +---- .../api/pipenet/WorldPipeNetComplex.java | 126 +++++++++ ...dPipeNetG.java => WorldPipeNetSimple.java} | 49 ++-- .../{NetAlgorithm.java => INetAlgorithm.java} | 8 +- .../api/pipenet/alg/MaximumFlowAlgorithm.java | 20 -- .../pipenet/alg/ShortestPathsAlgorithm.java | 2 +- .../api/pipenet/alg/SinglePathAlgorithm.java | 4 +- .../gregtech/api/pipenet/block/BlockPipe.java | 6 +- .../block/material/BlockMaterialPipe.java | 4 +- .../material/TileEntityMaterialPipeBase.java | 2 +- .../pipenet/block/simple/BlockSimplePipe.java | 4 +- .../api/pipenet/flow/FlowChannel.java | 145 ---------- .../api/pipenet/flow/FlowChannelManager.java | 134 --------- .../api/pipenet/flow/FlowChannelTicker.java | 58 ---- .../api/pipenet/flow/WorldPipeFlowNetG.java | 220 --------------- .../pipenet/longdist/LongDistanceNetwork.java | 4 +- .../api/pipenet/tile/TileEntityPipeBase.java | 14 +- .../properties/FluidPipeProperties.java | 21 +- .../properties/ItemPipeProperties.java | 2 +- .../material/properties/WireProperties.java | 2 +- .../pipelike/cable/net/EnergyNetHandler.java | 11 +- .../pipelike/cable/net/WorldEnergyNet.java | 12 +- .../pipelike/fluidpipe/net/FluidChannel.java | 223 --------------- .../fluidpipe/net/FluidNetHandler.java | 260 ++++++++++++++++++ .../pipelike/fluidpipe/net/PipeTankList.java | 3 +- .../fluidpipe/net/WorldFluidPipeNet.java | 23 +- .../fluidpipe/tile/TileEntityFluidPipe.java | 150 +++++----- .../pipelike/itempipe/net/ItemNetHandler.java | 34 +-- .../itempipe/net/WorldItemPipeNet.java | 13 +- .../itempipe/tile/TileEntityItemPipe.java | 1 - .../pipelike/laser/net/LaserNetHandler.java | 19 +- .../pipelike/laser/net/WorldLaserPipeNet.java | 12 +- .../optical/net/OpticalNetHandler.java | 13 +- .../optical/net/WorldOpticalPipeNet.java | 13 +- .../debug/DebugPipeNetInfoProvider.java | 4 +- 40 files changed, 888 insertions(+), 1137 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/IPipeNetHandler.java create mode 100644 src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java rename src/main/java/gregtech/api/pipenet/{WorldPipeNetG.java => WorldPipeNetSimple.java} (92%) rename src/main/java/gregtech/api/pipenet/alg/{NetAlgorithm.java => INetAlgorithm.java} (72%) delete mode 100644 src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java delete mode 100644 src/main/java/gregtech/api/pipenet/flow/FlowChannel.java delete mode 100644 src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java delete mode 100644 src/main/java/gregtech/api/pipenet/flow/FlowChannelTicker.java delete mode 100644 src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java delete mode 100644 src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java create mode 100644 src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java diff --git a/src/main/java/gregtech/api/pipenet/INodeData.java b/src/main/java/gregtech/api/pipenet/INodeData.java index 4515f84c54a..235bfd3938d 100644 --- a/src/main/java/gregtech/api/pipenet/INodeData.java +++ b/src/main/java/gregtech/api/pipenet/INodeData.java @@ -1,5 +1,6 @@ package gregtech.api.pipenet; +import java.util.Collections; import java.util.Set; public interface INodeData> { @@ -12,8 +13,16 @@ default double getWeightFactor() { return 1; } + default int getThroughput() { + return 1; + } + /** * Note - since datas is a set, no summative operations are allowed. */ T getMinData(Set datas); + + default T getMinData(Object data) { + return getMinData(Collections.singleton((T) data)); + } } diff --git a/src/main/java/gregtech/api/pipenet/IPipeNetHandler.java b/src/main/java/gregtech/api/pipenet/IPipeNetHandler.java new file mode 100644 index 00000000000..7fd8c5a7b0f --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/IPipeNetHandler.java @@ -0,0 +1,30 @@ +package gregtech.api.pipenet; + +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.cover.Cover; +import gregtech.api.cover.CoverHolder; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +public interface IPipeNetHandler { + + WorldPipeNetSimple getNet(); + + EnumFacing getFacing(); + + default Cover getCoverOnNeighbour(BlockPos pos, EnumFacing facing) { + NodeG node = getNet().getNode(pos); + if (node != null) { + TileEntity tile = node.getConnnected(facing); + if (tile != null) { + CoverHolder coverHolder = tile.getCapability(GregtechTileCapabilities.CAPABILITY_COVER_HOLDER, + facing.getOpposite()); + if (coverHolder == null) return null; + return coverHolder.getCoverAtSide(facing.getOpposite()); + } + } + return null; + } +} diff --git a/src/main/java/gregtech/api/pipenet/NetEdge.java b/src/main/java/gregtech/api/pipenet/NetEdge.java index b992a519e48..2f25cc2a343 100644 --- a/src/main/java/gregtech/api/pipenet/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/NetEdge.java @@ -3,12 +3,20 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.util.function.QuadConsumer; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.INBTSerializable; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; import org.jgrapht.graph.DefaultWeightedEdge; +import java.util.List; import java.util.Map; +import java.util.WeakHashMap; import java.util.function.Predicate; public final class NetEdge extends DefaultWeightedEdge implements INBTSerializable { @@ -16,6 +24,8 @@ public final class NetEdge extends DefaultWeightedEdge implements INBTSerializab private AbstractEdgePredicate predicate; private boolean invertedPredicate; + public NetEdge() {} + public void setPredicate(AbstractEdgePredicate predicate) { this.predicate = predicate; this.invertedPredicate = predicate.sourcePos != this.getSource().getNodePos(); @@ -41,6 +51,16 @@ public boolean isPredicateInverted() { return (NodeG) super.getTarget(); } + @SuppressWarnings("unchecked") + public & IPipeType, NDT extends INodeData> NodeG getCastSource() { + return (NodeG) getSource(); + } + + @SuppressWarnings("unchecked") + public & IPipeType, NDT extends INodeData> NodeG getCastTarget() { + return (NodeG) getTarget(); + } + @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); @@ -92,4 +112,150 @@ public void build() { } } } + + /// Complex graph related code /// + + private int flowBufferTicks; + private ChannelsHolder channels; + private WeakHashMap simulatedChannels; + + private INodeData> minData; + + public NetEdge(int flowBufferTicks) { + this.flowBufferTicks = flowBufferTicks; + this.channels = new ChannelsHolder(); + this.simulatedChannels = new WeakHashMap<>(9); + } + + /** + * Claims a new, unique simulator instance for properly simulating flow edge limits without actually changing them. + *
+ * This simulator must be discarded after use so that the garbage collector can clean up. + */ + public static ChannelSimulator getNewSimulatorInstance() { + return new ChannelSimulator(); + } + + private ChannelsHolder getChannels(@Nullable ChannelSimulator simulator) { + if (simulator == null) return this.channels; + else { + ChannelsHolder channels = simulatedChannels.get(simulator); + if (channels == null) { + channels = new ChannelsHolder(this.channels); + simulatedChannels.put(simulator, channels); + } + return channels; + } + } + + private INodeData> getMinData() { + if (this.minData == null) this.minData = this.getCastSource().getData().getMinData(this.getCastTarget().getData()); + return this.minData; + } + + private int getAdjustedThroughput() { + return getMinData().getThroughput() * flowBufferTicks; + } + + private boolean cannotSupportChannel(Object channel, long queryTick, @Nullable ChannelSimulator simulator) { + var channels = getChannels(simulator); + channels.recalculateFlowLimits(queryTick); + return channels.map.size() >= getMinData().getChannelMaxCount() && !channels.map.containsKey(channel); + } + + public & IPipeType, NDT extends INodeData> int getFlowLimit( + Object channel, Graph, NetEdge> graph, long queryTick, @Nullable ChannelSimulator simulator) { + if (this.cannotSupportChannel(channel, queryTick, simulator)) { + return 0; + } + int limit = getChannels(simulator).map.getOrDefault(channel, getAdjustedThroughput()); + + NetEdge inverse = graph.getEdge(this.getCastTarget(), this.getCastSource()); + if (inverse != null && inverse != this) { + if (inverse.cannotSupportChannel(channel, queryTick, simulator)) return 0; + limit += inverse.getConsumedLimit(channel, queryTick, simulator); + } + + return limit; + } + + public & IPipeType, NDT extends INodeData> int getConsumedLimit( + Object channel, long queryTick, @Nullable ChannelSimulator simulator) { + var channels = getChannels(simulator); + channels.recalculateFlowLimits(queryTick); + int limit = getAdjustedThroughput(); + return limit - channels.map.getOrDefault(channel, limit); + } + + public & IPipeType, NDT extends INodeData> void consumeFlowLimit( + Object channel, Graph, NetEdge> graph, int amount, long queryTick, @Nullable ChannelSimulator simulator) { + if (amount == 0) return; + var channels = getChannels(simulator); + channels.recalculateFlowLimits(queryTick); + + // check against reverse edge + NetEdge inverse = graph.getEdge(this.getCastTarget(), this.getCastSource()); + if (inverse != null && inverse != this) { + int inverseConsumed = inverse.getConsumedLimit(channel, queryTick, simulator); + if (inverseConsumed != 0) { + int toFreeUp = Math.min(inverseConsumed, amount); + inverse.consumeFlowLimit(channel, graph, -toFreeUp, queryTick, simulator); + if (toFreeUp == amount) return; + amount -= toFreeUp; + } + } + + int finalAmount = amount; + channels.map.compute(channel, (k, v) -> { + int d = getAdjustedThroughput(); + if (v == null) v = d; + v -= finalAmount; + if (v >= d) return null; + return v; + }); + } + + private final class ChannelsHolder { + public final Object2IntOpenHashMap map; + public long lastQueryTick; + + public ChannelsHolder() { + this.map = new Object2IntOpenHashMap<>(9); + } + + public ChannelsHolder(ChannelsHolder prototype) { + this.map = prototype.map.clone(); + this.lastQueryTick = prototype.lastQueryTick; + } + + public void recalculateFlowLimits(long queryTick) { + int time = (int) (queryTick - this.lastQueryTick); + if (time < 0) { + this.map.clear(); + } else { + List toRemove = new ObjectArrayList<>(); + this.map.replaceAll((k, v) -> { + v += time * getMinData().getThroughput(); + if (v >= getAdjustedThroughput()) toRemove.add(k); + return v; + }); + toRemove.forEach(this.map::removeInt); + } + this.lastQueryTick = queryTick; + } + } + + public static final class ChannelSimulator { + private static int ID; + private final int id; + private ChannelSimulator() { + this.id = ID++; + } + + @Override + public int hashCode() { + // enforcing hash uniqueness improves weak map performance + return id; + } + } } diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 27acfefe927..d7407c45517 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -1,17 +1,11 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.flow.FlowChannel; -import gregtech.api.pipenet.flow.FlowChannelManager; -import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; import net.minecraftforge.common.util.INBTSerializable; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; import org.jgrapht.traverse.BreadthFirstIterator; @@ -23,25 +17,22 @@ public class NetGroup & IPipeType, NodeDataType extends INodeData> implements INBTSerializable { - public final WorldPipeNetG net; + public final WorldPipeNetSimple net; private final Graph, NetEdge> graph; private final Set> nodes; - @Nullable - private FlowChannelManager channelManager = null; - private final AbstractGroupData data; - public NetGroup(Graph, NetEdge> graph, WorldPipeNetG net) { + public NetGroup(Graph, NetEdge> graph, WorldPipeNetSimple net) { this.graph = graph; this.nodes = new ObjectOpenHashSet<>(); this.net = net; this.data = net.getBlankGroupData(); } - public NetGroup(Graph, NetEdge> graph, WorldPipeNetG net, + public NetGroup(Graph, NetEdge> graph, WorldPipeNetSimple net, Set> nodes) { this.graph = graph; this.nodes = nodes; @@ -52,7 +43,6 @@ public NetGroup(Graph, NetEdge> graph, WorldPipeNe private void clear() { this.nodes.clear(); - this.channelManager = null; } protected void addNode(NodeG node) { @@ -78,15 +68,8 @@ protected final void addNodes(NodeG... nodes) { } public void connectionChange(NodeG node) { - if (!this.net.isFlow()) return; - Map map = node.getConnecteds(); - // if map is null, then we're in world data load phase - do nothing - if (map == null) return; - if (map.size() != 0) { - this.getChannelManager().addSink(node); - } else { - this.getChannelManager().removeSink(node); - } + // TODO simplify path search by only checking nodes that have connections + // use net's connection capabilities } /** @@ -119,9 +102,6 @@ protected void mergeNode(NodeG node) { NetGroup group = cast.getGroupUnsafe(); if (group != null) { this.addNodes(group.getNodes()); - if (this.net.isFlow()) { - this.getChannelManager().merge(group.getChannelManager()); - } group.clear(); } else addNode(cast); this.clearCaches(); @@ -135,7 +115,6 @@ protected void mergeNode(NodeG node) { */ public boolean splitNode(NodeG source) { if (this.graph.containsVertex(source)) { - this.prepSplit(); this.clearCaches(); List> targets = graph.outgoingEdgesOf(source).stream().map(a -> { // handling so undirected graphs don't throw an error @@ -145,11 +124,9 @@ public boolean splitNode(NodeG source) { }).collect(Collectors.toList()); this.graph.removeVertex(source); this.nodes.remove(source); - if (this.net.isFlow()) { - this.getChannelManager().removeNode(source); - } while (!targets.isEmpty()) { // get the lastmost target; if this throws a cast exception, something is very wrong with the graph. + @SuppressWarnings("unchecked") NodeG target = (NodeG) targets .remove(targets.size() - 1); @@ -165,19 +142,9 @@ public boolean splitNode(NodeG source) { } this.nodes.removeAll(targetGroup); if (targetGroup.size() != 0) { - if (this.net.isFlow()) { - // remove our owned nodes from their manager, and remove their nodes from our manager. - // also make sure to finish split from their perspective. - new NetGroup<>(this.graph, this.net, targetGroup) - .setChannelManager(this.getChannelManager().subManager(this.nodes)) - .finishSplit(); - this.getChannelManager().removeNodes(targetGroup); - } else { - new NetGroup<>(this.graph, this.net, targetGroup); - } + new NetGroup<>(this.graph, this.net, targetGroup); } } - this.finishSplit(); return true; } return false; @@ -192,7 +159,6 @@ public boolean splitNode(NodeG source) { */ public boolean splitEdge(NodeG source, NodeG target) { if (graph.removeEdge(source, target) != null) { - this.prepSplit(); this.clearCaches(); Set> targetGroup = new ObjectOpenHashSet<>(); BreadthFirstIterator, NetEdge> i = new BreadthFirstIterator<>(graph, target); @@ -200,43 +166,18 @@ public boolean splitEdge(NodeG source, NodeG(this.graph, this.net, targetGroup) - .setChannelManager(this.getChannelManager().subManager(this.nodes)) - .finishSplit(); - this.getChannelManager().removeNodes(targetGroup); - } else { - new NetGroup<>(this.graph, this.net, targetGroup); - } + new NetGroup<>(this.graph, this.net, targetGroup); } - this.finishSplit(); return true; } return false; } - private void prepSplit() { - if (this.net.isFlow()) { - this.getChannelManager().disconnectSuperNodes(); - } - } - - private void finishSplit() { - if (this.net.isFlow()) { - this.getChannelManager().reconnectSuperNodes(); - } - } - /** * For memory considerations, returns the uncloned set. Do not modify this directly. */ @@ -256,37 +197,12 @@ public AbstractGroupData getData() { return this.data; } - public void setChannel(Object key, FlowChannel channel) { - this.getChannelManager().setChannel(key, channel); - } - - @Nullable - public FlowChannel getChannel(Object key) { - return this.getChannelManager().getChannel(key); - } - - private NetGroup setChannelManager(FlowChannelManager manager) { - this.channelManager = manager; - return this; - } - - private FlowChannelManager getChannelManager() { - if (this.channelManager == null) { - this.channelManager = new FlowChannelManager<>((WorldPipeFlowNetG) this.net); - } - return this.channelManager; - } - @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); int i = 0; for (NodeG node : this.nodes) { tag.setLong(String.valueOf(i), node.getLongPos()); - if (this.net.isFlow()) { - // should I do some weird, bit-based encoding with an adaptable number of longs instead of booleans? - tag.setBoolean("F" + i, node.hasConnecteds()); - } i++; } tag.setInteger("NodeCount", i); @@ -300,32 +216,19 @@ public NBTTagCompound serializeNBT() { @Deprecated public void deserializeNBT(NBTTagCompound nbt) {} - private void addSinks(Set> sinks) { - for (NodeG sink : sinks) { - this.getChannelManager().addSink(sink); - } - } - static final class NBTBuilder & IPipeType, NodeDataType extends INodeData> implements INBTBuilder { private final Set> nodes; - private final Set> sinks; - private final Graph, NetEdge> graph; - private final WorldPipeNetG net; + private final WorldPipeNetSimple net; - NBTBuilder(Map> longPosMap, NBTTagCompound tag, boolean isFlow, - Graph, NetEdge> graph, WorldPipeNetG net) { + NBTBuilder(Map> longPosMap, NBTTagCompound tag, + Graph, NetEdge> graph, WorldPipeNetSimple net) { nodes = new ObjectOpenHashSet<>(); - if (isFlow) sinks = new ObjectOpenHashSet<>(); - else sinks = null; for (int i = 0; i < tag.getInteger("NodeCount"); i++) { NodeG node = longPosMap.get(tag.getLong(String.valueOf(i))); nodes.add(node); - if (isFlow && tag.getBoolean("F" + i)) { - sinks.add(node); - } } this.graph = graph; this.net = net; @@ -334,7 +237,6 @@ static final class NBTBuilder & IPipeType g = new NetGroup<>(graph, net, nodes); - if (net.isFlow()) g.addSinks(sinks); } } } diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index da00ac55aec..dba48a1be90 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.GraphPath; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -36,10 +37,10 @@ public class NetPath & IPipeType, public NetPath(NodeG node) { this.sourceNode = node; this.targetNode = node; - this.nodeList = new ObjectArrayList<>(1); - this.nodeList.add(node); + this.nodeList = Collections.singletonList(node); this.weight = node.getData().getWeightFactor(); this.edgeList = new ObjectArrayList<>(0); + assert this.nodeList.size() == this.edgeList.size() + 1; } /** @@ -56,6 +57,7 @@ public NetPath(List> nodes, List edges, d this.nodeList = nodes; this.weight = weight; this.edgeList = edges; + assert this.nodeList.size() == this.edgeList.size() + 1; } /** @@ -71,6 +73,7 @@ public NetPath(GraphPath, NetEdge> path) { this.weight = (path.getWeight() + sourceNode.getData().getWeightFactor() + targetNode.getData().getWeightFactor()) / 2; this.edgeList = path.getEdgeList(); + assert this.nodeList.size() == this.edgeList.size() + 1; } protected NetPath() {} @@ -79,6 +82,10 @@ public List> getNodeList() { return nodeList; } + public List getEdgeList() { + return edgeList; + } + public NodeG getSourceNode() { return sourceNode; } @@ -142,6 +149,10 @@ public List> getNodeList() { return path.getNodeList(); } + public List getEdgeList() { + return path.getEdgeList(); + } + public NodeG getSourceNode() { return path.getSourceNode(); } @@ -158,7 +169,7 @@ public double getWeight() { return path.getWeight(); } - public NDT getData() { + public NDT getMinData() { return path.getMinData(); } diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NodeG.java index 5625c967515..5cc7fdf177a 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NodeG.java @@ -1,9 +1,10 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.flow.FlowChannel; import gregtech.api.pipenet.tile.IPipeTile; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; @@ -13,22 +14,20 @@ import net.minecraftforge.fml.relauncher.SideOnly; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; -public class NodeG & IPipeType, +public final class NodeG & IPipeType, NodeDataType extends INodeData> implements INBTSerializable { public static final int DEFAULT_MARK = 0; - private final WorldPipeNetG net; + private final WorldPipeNetSimple net; private NodeDataType data; /** @@ -57,15 +56,11 @@ public class NodeG & IPipeType, private NetGroup group = null; - /** - * Stores the channels that this node is involved with. Used exclusively for flow graphs. - */ - private final Set> channels = new ObjectOpenHashSet<>(); - private List> pathCache = null; + public NodeG(NodeDataType data, IPipeTile heldMTE, - WorldPipeNetG net) { + WorldPipeNetSimple net) { this.data = data; this.openConnections = 0; this.blockedConnections = 0; @@ -90,23 +85,10 @@ public NodeG(IPipeTile heldMTE) { this.blockedConnections = 0; } - /** - * Creates a dummy node for flow network calculations. - * Should never be required to reference its net, data, mte, or position. - */ - public NodeG() { - this.nodePos = null; - this.net = null; - this.data = null; - this.heldMTE = new WeakReference<>(null); - this.openConnections = 0; - this.blockedConnections = 0; - } - /** * For construction during NBT reading only */ - public NodeG(NBTTagCompound tag, WorldPipeNetG net) { + public NodeG(NBTTagCompound tag, WorldPipeNetSimple net) { this.nodePos = BlockPos.fromLong(tag.getLong("Pos")); deserializeNBT(tag); this.data = net.readNodeData(tag.getCompoundTag("Data")); @@ -288,39 +270,6 @@ public void clearPathCache() { this.pathCache = null; } - /** - * @param channel The channel to test. Can be null to check only if there is space for another channel. - * @return {@code true} if the provided channel can be supported by the node. - */ - public boolean canSupportChannel(FlowChannel channel) { - if (this.data == null) return true; - return this.channels.size() < this.data.getChannelMaxCount() || this.channels.contains(channel); - } - - /** - * Adds a channel to a node's collection. Cannot go over the node's channel limit. - * - * @param channel the channel to add. - * @return {@code true} if the channel was added or was already present. - */ - public boolean addChannel(FlowChannel channel) { - if (this.channels.size() < this.data.getChannelMaxCount()) { - this.channels.add(channel); - return true; - } - return this.channels.contains(channel); - } - - /** - * Removes a channel from a node's collection. - * - * @param channel the channel to remove. - * @return {@code true} if the channel was in the node's collection. - */ - public boolean removeChannel(FlowChannel channel) { - return this.channels.remove(channel); - } - @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java new file mode 100644 index 00000000000..42b8dfe400e --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java @@ -0,0 +1,126 @@ +package gregtech.api.pipenet; + +import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.tile.TileEntityPipeBase; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; +import org.jgrapht.graph.SimpleDirectedWeightedGraph; +import org.jgrapht.graph.SimpleWeightedGraph; + +import java.util.List; +import java.util.function.Supplier; + +public abstract class WorldPipeNetComplex, + PipeType extends Enum & IPipeType> extends WorldPipeNetSimple { + + /** + * Alternate pipenet representation. + * Supports pipenet-level limits on flow per tick and nodes with multiple channels, but cannot cache paths. + *

+ * Note - undirected versions of this pipenet will treat flow in either direction along an edge towards its capacity, + * while directed versions will cancel out reverse flow for improved behavior. + * + * @param isDirected Determines whether this net needs directed graph handling. + * Used to respect filter directions in the item net and fluid net, for example. + * If the graph is not directed, pipes should not support blocked connections + * or unidirectional covers. + * @param isSinglePath Determines whether this net allows only one source and one destination per group. + * Allows for optimizations in path lookup and cache invalidation. + * @param flowBufferTicks Determines how many ticks of 'buffer' flow capacity can be built up along edges. + * Allows for once-an-interval push/pull operations instead of needing them every tick for + * maximum throughput. + */ + public WorldPipeNetComplex(String name, boolean isDirected, boolean isSinglePath, int flowBufferTicks) { + super(name, isDirected, isSinglePath, + isDirected ? new DirectedLimitedGraph<>(() -> new NetEdge(flowBufferTicks)) : + new UndirectedLimitedGraph<>(() -> new NetEdge(flowBufferTicks))); + } + +// @Override +// public void addNodeSilent(NodeG node) { +// super.addNodeSilent(node); +// // Flow algorithms will throw an out of index if the number of nodes increases +// this.markAlgInvalid(); +// } +// +// @Override +// public void removeNode(@Nullable NodeG node) { +// super.removeNode(node); +// // Flow algorithms will become mis-indexed if the number of nodes decreases +// this.markAlgInvalid(); +// } + + @Override + public List> getPaths(@Nullable NodeG node, + @Nullable TileEntityPipeBase tile, + Object testObject) { + if (node == null) return new ObjectArrayList<>(); + + node.setHeldMTE(tile); + + if (!this.hasValidAlg()) this.rebuildNetAlgorithm(); + + ((IComplexGraph) this.pipeGraph).setTestObject(testObject); + List> list = this.netAlgorithm.getPathsList(node); + ((IComplexGraph) this.pipeGraph).setTestObject(null); + return verifyList(list, node); + } + + + public interface IComplexGraph, PT extends Enum & IPipeType> extends Graph, NetEdge> { + + void setTestObject(Object object); + } + + protected static class UndirectedLimitedGraph, PT extends Enum & IPipeType> + extends SimpleWeightedGraph, NetEdge> + implements IComplexGraph { + + final ThreadLocal testObject = new ThreadLocal<>(); + + public UndirectedLimitedGraph(Supplier supplier) { + super(null, supplier); + } + + @Override + public double getEdgeWeight(NetEdge netEdge) { + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + int limit = netEdge.getFlowLimit(testObject.get(), this, tick, null); + return limit > 0 && netEdge.getPredicate().test(testObject.get()) ? this.getEdgeWeight(netEdge) : Double.POSITIVE_INFINITY; + } + + @Override + public void setTestObject(Object object) { + this.testObject.set(object); + } + } + + protected static class DirectedLimitedGraph, PT extends Enum & IPipeType> + extends SimpleDirectedWeightedGraph, NetEdge> + implements IComplexGraph { + + final ThreadLocal testObject = new ThreadLocal<>(); + + + public DirectedLimitedGraph(Supplier supplier) { + super(null, supplier); + } + + @Override + public double getEdgeWeight(NetEdge netEdge) { + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + int limit = netEdge.getFlowLimit(testObject.get(), this, tick, null); + return limit > 0 && netEdge.getPredicate().test(testObject.get()) ? super.getEdgeWeight(netEdge) : Double.POSITIVE_INFINITY; + } + + @Override + public void setTestObject(Object object) { + this.testObject.set(object); + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java similarity index 92% rename from src/main/java/gregtech/api/pipenet/WorldPipeNetG.java rename to src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java index 549c363895c..caae19dead0 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetG.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java @@ -1,11 +1,10 @@ package gregtech.api.pipenet; import gregtech.api.cover.Cover; -import gregtech.api.pipenet.alg.NetAlgorithm; +import gregtech.api.pipenet.alg.INetAlgorithm; import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; import gregtech.api.pipenet.alg.SinglePathAlgorithm; import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.flow.WorldPipeFlowNetG; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.common.covers.CoverShutter; @@ -17,6 +16,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.storage.WorldSavedData; +import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.Constants; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; @@ -35,7 +35,7 @@ import java.util.Set; import java.util.stream.Collectors; -public abstract class WorldPipeNetG, +public abstract class WorldPipeNetSimple, PipeType extends Enum & IPipeType> extends WorldSavedData { private final boolean isDirected; @@ -45,15 +45,16 @@ public abstract class WorldPipeNetG private Set builders = null; private WeakReference worldRef = new WeakReference<>(null); - // TODO move graph & algorithm into NetGroup to reduce unnecessary algorithm cost protected final Graph, NetEdge> pipeGraph; final Map> pipeMap = new Object2ObjectOpenHashMap<>(); - final NetAlgorithm.NetAlgorithmWrapper netAlgorithm; + final INetAlgorithm.NetAlgorithmWrapper netAlgorithm; private boolean validAlgorithmInstance = false; /** + * Standard pipenet representation. Provides the base form of the pipenet abstraction. + * * @param isDirected Determines whether this net needs directed graph handling. * Used to respect filter directions in the item net and fluid net, for example. * If the graph is not directed, pipes should not support blocked connections @@ -61,30 +62,31 @@ public abstract class WorldPipeNetG * @param isSinglePath Determines whether this net allows only one source and one destination per group. * Allows for optimizations in path lookup and cache invalidation. */ - public WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath) { + public WorldPipeNetSimple(String name, boolean isDirected, boolean isSinglePath) { super(name); if (isDirected()) this.pipeGraph = new SimpleDirectedWeightedGraph<>(NetEdge.class); else this.pipeGraph = new SimpleWeightedGraph<>(NetEdge.class); - this.netAlgorithm = new NetAlgorithm.NetAlgorithmWrapper<>(); + this.netAlgorithm = new INetAlgorithm.NetAlgorithmWrapper<>(); this.isDirected = isDirected; this.isSinglePath = isSinglePath; this.isFlow = false; } - /** - * Override only for use by {@link WorldPipeFlowNetG} - */ - protected WorldPipeNetG(String name, boolean isDirected, boolean isSinglePath, - Graph, NetEdge> graph) { + protected WorldPipeNetSimple(String name, boolean isDirected, boolean isSinglePath, + Graph, NetEdge> graph) { super(name); this.pipeGraph = graph; - this.netAlgorithm = null; + this.netAlgorithm = new INetAlgorithm.NetAlgorithmWrapper<>(); this.isDirected = isDirected; this.isSinglePath = isSinglePath; this.isFlow = true; } + public final Graph, NetEdge> getGraph() { + return this.pipeGraph; + } + public final boolean isDirected() { return isDirected; } @@ -124,7 +126,7 @@ protected void setWorldAndInit(World world) { public static String getDataID(final String baseID, final World world) { if (world == null || world.isRemote) - throw new RuntimeException("WorldPipeNetG should only be created on the server!"); + throw new RuntimeException("WorldPipeNetSimple should only be created on the server!"); int dimension = world.provider.getDimension(); return dimension == 0 ? baseID : baseID + '.' + dimension; } @@ -137,24 +139,28 @@ protected void onWorldSet() { * Preferred override. Only collects a fresh TE from the server if the provided TE is invalid. * * @param tile The {@link TileEntityPipeBase} that paths are being requested for + * @param testObject Can be null for simple nets. Complex nets need this for their behavior. * @return the ordered list of paths associated with the {@link TileEntityPipeBase} */ - public List> getPaths(TileEntityPipeBase tile) { - return getPaths(this.pipeMap.get(tile.getPipePos()), tile); + public List> getPaths(TileEntityPipeBase tile, + Object testObject) { + return getPaths(this.pipeMap.get(tile.getPipePos()), tile, testObject); } /** * Special-case override. Forces the collection of a fresh TE from the server. * * @param pos The {@link BlockPos} that paths are being requested for + * @param testObject Can be null for simple nets. Complex nets need this for their behavior. * @return the ordered list of paths associated with the {@link BlockPos} */ - public List> getPaths(BlockPos pos) { - return getPaths(this.pipeMap.get(pos), null); + public List> getPaths(BlockPos pos, Object testObject) { + return getPaths(this.pipeMap.get(pos), null, testObject); } public List> getPaths(@Nullable NodeG node, - @Nullable TileEntityPipeBase tile) { + @Nullable TileEntityPipeBase tile, + Object testObject) { if (node == null) return new ObjectArrayList<>(); node.setHeldMTE(tile); @@ -310,6 +316,8 @@ public void updateMark(BlockPos nodePos, int newMark) { } } + protected abstract Capability[] getConnectionCapabilities(); + public boolean hasNode(BlockPos pos) { return pipeMap.containsKey(pos); } @@ -338,7 +346,6 @@ public void addUndirectedEdge(NodeG source, NodeG source, NodeG target, @Nullable AbstractEdgePredicate predicate) { addEdge(source, target, source.getData().getWeightFactor() + target.getData().getWeightFactor(), predicate); - this.markAlgInvalid(); } public void addUndirectedEdge(NodeG source, NodeG target, @@ -485,7 +492,7 @@ public void readFromNBT(NBTTagCompound nbt) { NBTTagList allNetGroups = nbt.getTagList("NetGroups", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < allNetGroups.tagCount(); i++) { NBTTagCompound gTag = allNetGroups.getCompoundTagAt(i); - this.builders.add(new NetGroup.NBTBuilder<>(longPosMap, gTag, this.isFlow(), this.pipeGraph, this)); + this.builders.add(new NetGroup.NBTBuilder<>(longPosMap, gTag, this.pipeGraph, this)); } } diff --git a/src/main/java/gregtech/api/pipenet/alg/NetAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java similarity index 72% rename from src/main/java/gregtech/api/pipenet/alg/NetAlgorithm.java rename to src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java index 90f589ad849..fa314bd8478 100644 --- a/src/main/java/gregtech/api/pipenet/alg/NetAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java @@ -8,20 +8,20 @@ import java.util.List; @FunctionalInterface -public interface NetAlgorithm & IPipeType, NDT extends INodeData> { +public interface INetAlgorithm & IPipeType, NDT extends INodeData> { List> getPathsList(NodeG source); class NetAlgorithmWrapper & IPipeType, NodeDataType extends INodeData> { - NetAlgorithm alg; + INetAlgorithm alg; - public void setAlg(NetAlgorithm alg) { + public void setAlg(INetAlgorithm alg) { this.alg = alg; } - public NetAlgorithm getAlg() { + public INetAlgorithm getAlg() { return alg; } diff --git a/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java deleted file mode 100644 index e5db0ca773f..00000000000 --- a/src/main/java/gregtech/api/pipenet/alg/MaximumFlowAlgorithm.java +++ /dev/null @@ -1,20 +0,0 @@ -package gregtech.api.pipenet.alg; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetEdge; -import gregtech.api.pipenet.NodeG; -import gregtech.api.pipenet.block.IPipeType; - -import org.jgrapht.Graph; -import org.jgrapht.alg.flow.PushRelabelMFImpl; - -/** - * Secretly just {@link PushRelabelMFImpl}, but may be modified in the future. - */ -public final class MaximumFlowAlgorithm & IPipeType, NDT extends INodeData> - extends PushRelabelMFImpl, NetEdge> { - - public MaximumFlowAlgorithm(Graph, NetEdge> network) { - super(network); - } -} diff --git a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java index d9805d8e033..36f260dfb9a 100644 --- a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java @@ -17,7 +17,7 @@ public final class ShortestPathsAlgorithm & IPipeType, NDT extends INodeData> extends CHManyToManyShortestPaths, NetEdge> - implements NetAlgorithm { + implements INetAlgorithm { public ShortestPathsAlgorithm(Graph, NetEdge> graph) { super(graph); diff --git a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java index 62299dfb40d..c5f85c9c3a7 100644 --- a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java @@ -13,7 +13,7 @@ import java.util.List; public final class SinglePathAlgorithm & IPipeType, NDT extends INodeData> - implements NetAlgorithm { + implements INetAlgorithm { private final Graph, NetEdge> graph; private final boolean isDirected; @@ -50,7 +50,7 @@ public List> getPathsList(NodeG source) { } else if (i.hasNext()) i.next(); if (i.hasNext()) valid = false; // third edge detected - that's an invalid group lastNode = node; - node = (NodeG) (reversedEdge ? edge.getSource() : edge.getTarget()); + node = reversedEdge ? edge.getCastSource() : edge.getCastTarget(); edges.add(edge); nodes.add(node); sumWeight += node.getData().getWeightFactor(); diff --git a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java index 3b6f83da2df..63bd02fbe6d 100644 --- a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java @@ -9,7 +9,7 @@ import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.pipenet.IBlockAppearance; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.WorldPipeNetSimple; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.PipeCoverableImplementation; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -66,7 +66,7 @@ @SuppressWarnings("deprecation") public abstract class BlockPipe & IPipeType, NodeDataType extends INodeData, - WorldPipeNetType extends WorldPipeNetG> extends BuiltInRenderBlock + WorldPipeNetType extends WorldPipeNetSimple> extends BuiltInRenderBlock implements ITileEntityProvider, IFacadeWrapper, IBlockAppearance { protected final ThreadLocal> tileEntities = new ThreadLocal<>(); @@ -239,7 +239,7 @@ public void updateActiveNodeStatus(@NotNull World worldIn, BlockPos pos, IPipeTile pipeTile) { if (worldIn.isRemote) return; - WorldPipeNetG pipeNet = getWorldPipeNet(worldIn); + WorldPipeNetSimple pipeNet = getWorldPipeNet(worldIn); if (pipeNet != null && pipeTile != null) { int activeConnections = pipeTile.getConnections(); // remove blocked connections boolean isActiveNodeNow = activeConnections != 0; diff --git a/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java b/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java index 67223f8c64a..17f93eafbba 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java @@ -2,7 +2,7 @@ import gregtech.api.GTValues; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.WorldPipeNetSimple; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; @@ -29,7 +29,7 @@ public abstract class BlockMaterialPipe< PipeType extends Enum & IPipeType & IMaterialPipeType, NodeDataType extends INodeData, - WorldPipeNetType extends WorldPipeNetG> + WorldPipeNetType extends WorldPipeNetSimple> extends BlockPipe { protected final PipeType pipeType; diff --git a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java index a2aa9197546..90101a6e5e1 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java @@ -72,7 +72,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { this.pipeMaterial = registry.getFallbackMaterial(); } this.getNode().setData(getPipeBlock().createProperties(this)); - if (!compound.hasKey("PipeNetVersion")) doOldNetSetup(); + if (!compound.hasKey("PipeNetVersion")) markAsNeedingOldNetSetup(); } private void writePipeMaterial(@NotNull PacketBuffer buf) { diff --git a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java index 7f921023050..7bfa18461ff 100644 --- a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java +++ b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java @@ -1,7 +1,7 @@ package gregtech.api.pipenet.block.simple; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.WorldPipeNetSimple; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.tile.IPipeTile; @@ -11,7 +11,7 @@ public abstract class BlockSimplePipe & IPipeType, NodeDataType extends INodeData, - WorldPipeNetType extends WorldPipeNetG> + WorldPipeNetType extends WorldPipeNetSimple> extends BlockPipe { @Override diff --git a/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java b/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java deleted file mode 100644 index 46889b1629e..00000000000 --- a/src/main/java/gregtech/api/pipenet/flow/FlowChannel.java +++ /dev/null @@ -1,145 +0,0 @@ -package gregtech.api.pipenet.flow; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.cover.Cover; -import gregtech.api.cover.CoverHolder; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetEdge; -import gregtech.api.pipenet.NodeG; -import gregtech.api.pipenet.block.IPipeType; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; - -import java.util.ArrayList; -import java.util.Map; -import java.util.Set; - -public abstract class FlowChannel & IPipeType, NDT extends INodeData> { - - protected final Graph, NetEdge> network; - - protected final Set> activeSources = new ObjectOpenHashSet<>(); - - protected final Map, Byte> receiveSidesMap = new Object2ObjectOpenHashMap<>(); - - protected FlowChannelManager manager; - - public FlowChannel(Graph, NetEdge> network) { - this.network = network; - } - - FlowChannel setManager(FlowChannelManager manager) { - if (this.manager != null) this.manager.removeChannel(this.getKey()); - this.manager = manager; - return this; - } - - public abstract void clearAlg(); - - public abstract void evaluate(); - - /** - * Prime the edges to the super nodes to prepare for calculations. - */ - protected void activate() { - for (NodeG source : new ArrayList<>(activeSources)) { - double v = getSourceValue(source); - // TODO find source of random NPE crash where a source edge doesn't exist after world load (pls help) - network.setEdgeWeight(this.manager.getSuperSource(), source, v); - if (v == 0) removeSource(source); - } - for (NodeG sink : new ArrayList<>(this.manager.getActiveSinks())) { - double v = getSinkValue(sink); - network.setEdgeWeight(sink, this.manager.getSuperSink(), v); - } - } - - /** - * Zero out the edges to the super nodes to prevent other calculations from using them. - */ - protected void deactivate() { - for (NodeG source : new ArrayList<>(activeSources)) { - network.setEdgeWeight(this.manager.getSuperSource(), source, 0); - } - for (NodeG sink : new ArrayList<>(this.manager.getActiveSinks())) { - network.setEdgeWeight(sink, this.manager.getSuperSink(), 0); - } - } - - void disconnectSuperNodes() { - for (NodeG source : activeSources) { - network.removeEdge(this.manager.getSuperSource(), source); - } - } - - void reconnectSuperNodes() { - for (NodeG source : activeSources) { - network.addEdge(this.manager.getSuperSource(), source); - } - } - - protected abstract double getSourceValue(NodeG source); - - protected abstract double getSinkValue(NodeG sink); - - public void addReceiveSide(NodeG node, EnumFacing side) { - this.receiveSidesMap.compute(node, (k, v) -> { - if (v == null) { - byte a = 0; - a |= (1 << side.getIndex()); - return a; - } - byte a = v; - a |= (1 << side.getIndex()); - return a; - }); - } - - public void addSource(NodeG source) { - if (this.activeSources.add(source)) this.network.addEdge(this.manager.getSuperSource(), source); - } - - public void removeSource(NodeG source) { - if (this.activeSources.remove(source)) this.network.removeEdge(this.manager.getSuperSource(), source); - } - - @Nullable - protected static Cover getCoverOnNeighbour(NodeG node, EnumFacing facing) { - TileEntity tile = node.getConnnected(facing); - if (tile != null) { - CoverHolder coverHolder = tile.getCapability(GregtechTileCapabilities.CAPABILITY_COVER_HOLDER, - facing.getOpposite()); - if (coverHolder == null) return null; - return coverHolder.getCoverAtSide(facing.getOpposite()); - } - return null; - } - - protected FlowChannel merge(FlowChannel otherChannel) { - this.activeSources.addAll(otherChannel.activeSources); - for (Map.Entry, Byte> entry : otherChannel.receiveSidesMap.entrySet()) { - this.receiveSidesMap.merge(entry.getKey(), entry.getValue(), (a, b) -> (byte) (a | b)); - } - return this; - } - - protected void removeNodes(Set> nodes) { - this.activeSources.removeAll(nodes); - for (NodeG node : nodes) { - this.receiveSidesMap.remove(node); - } - } - - protected void removeNode(NodeG node) { - this.activeSources.remove(node); - this.receiveSidesMap.remove(node); - } - - protected abstract Object getKey(); -} diff --git a/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java b/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java deleted file mode 100644 index 89225716b8f..00000000000 --- a/src/main/java/gregtech/api/pipenet/flow/FlowChannelManager.java +++ /dev/null @@ -1,134 +0,0 @@ -package gregtech.api.pipenet.flow; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NodeG; -import gregtech.api.pipenet.block.IPipeType; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.ref.WeakReference; -import java.util.Map; -import java.util.Set; - -public class FlowChannelManager & IPipeType, - NodeDataType extends INodeData> { - - private final WorldPipeFlowNetG net; - - protected final Set> activeSinks = new ObjectOpenHashSet<>(); - - private final Map> channels = new Object2ObjectOpenHashMap<>(); - - public FlowChannelManager(WorldPipeFlowNetG net) { - this.net = net; - WeakReference> ref = new WeakReference<>(this); - FlowChannelTicker.addManager(net.getWorld(), ref); - this.net.addManager(ref); - } - - void clearAlgs() { - this.channels.values().forEach(FlowChannel::clearAlg); - } - - public void tick() { - if (this.activeSinks.size() == 0) return; - this.channels.forEach((k, v) -> v.evaluate()); - if (this.net.unhandledOldNodes.size() != 0) { - for (NodeG node : this.net.unhandledOldNodes) { - node.getGroupSafe().connectionChange(node); - } - } - } - - /** - * Updates active nodes based on the active nodes of another manager. - */ - public FlowChannelManager merge(FlowChannelManager otherManager) { - this.activeSinks.addAll(otherManager.activeSinks); - for (Map.Entry> entry : otherManager.channels.entrySet()) { - this.channels.merge(entry.getKey(), entry.getValue(), FlowChannel::merge); - } - return this; - } - - /** - * Generates a new manager that filters this manager's active nodes by removing the provided nodes. - */ - public FlowChannelManager subManager(Set> nodes) { - FlowChannelManager newManager = new FlowChannelManager<>(this.net); - newManager.channels.putAll(this.channels); - newManager.channels.forEach((key, value) -> { - value.setManager(newManager); - value.activeSources.removeAll(nodes); - for (NodeG node : nodes) { - value.receiveSidesMap.remove(node); - } - }); - newManager.activeSinks.addAll(this.activeSinks); - newManager.activeSinks.removeAll(nodes); - return newManager; - } - - /** - * Filters this manager's active nodes by removing the provided nodes. - */ - public void removeNodes(Set> nodes) { - this.activeSinks.removeAll(nodes); - this.channels.forEach((key, value) -> value.removeNodes(nodes)); - } - - public void removeNode(NodeG node) { - this.activeSinks.remove(node); - this.channels.forEach((key, value) -> value.removeNode(node)); - } - - public NodeG getSuperSource() { - return this.net.getSuperSource(); - } - - public NodeG getSuperSink() { - return this.net.getSuperSink(); - } - - public Set> getActiveSinks() { - return activeSinks; - } - - public void addSink(NodeG sink) { - if (this.activeSinks.add(sink)) this.net.getPipeGraph().addEdge(sink, this.net.getSuperSink()); - } - - public void removeSink(NodeG sink) { - if (this.activeSinks.remove(sink)) this.net.getPipeGraph().removeEdge(sink, this.net.getSuperSink()); - } - - public void setChannel(Object key, @NotNull FlowChannel channel) { - this.channels.put(key, channel.setManager(this)); - } - - public void disconnectSuperNodes() { - this.channels.forEach((key, value) -> value.disconnectSuperNodes()); - for (NodeG node : activeSinks) { - this.net.getPipeGraph().removeEdge(node, getSuperSink()); - } - } - - public void reconnectSuperNodes() { - this.channels.forEach((key, value) -> value.reconnectSuperNodes()); - for (NodeG node : activeSinks) { - this.net.getPipeGraph().addEdge(node, getSuperSink()); - } - } - - @Nullable - public FlowChannel getChannel(Object key) { - return this.channels.get(key); - } - - public void removeChannel(Object key) { - this.channels.remove(key); - } -} diff --git a/src/main/java/gregtech/api/pipenet/flow/FlowChannelTicker.java b/src/main/java/gregtech/api/pipenet/flow/FlowChannelTicker.java deleted file mode 100644 index 72a7609618a..00000000000 --- a/src/main/java/gregtech/api/pipenet/flow/FlowChannelTicker.java +++ /dev/null @@ -1,58 +0,0 @@ -package gregtech.api.pipenet.flow; - -import gregtech.api.GTValues; - -import net.minecraft.world.World; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArraySet; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - -import java.lang.ref.WeakReference; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -// Ok, I admit, truly tickless fluidpipes would mean sacrificing behavior. I'd have to make them act like itempipes. -// To get true 'flow' behavior, all sources and all destinations must be defined, then a single evaluation performed. -@Mod.EventBusSubscriber(modid = GTValues.MODID) -public final class FlowChannelTicker { - - public static final int FLOWNET_TICKRATE = 10; - - private final static Map>>> MANAGERS = new Object2ObjectOpenHashMap<>(); - private final static Map TICK_COUNTS = new Object2ObjectOpenHashMap<>(); - - private final static Set>> EMPTY = new ObjectArraySet<>(0); - - @SubscribeEvent - public static void onWorldTick(TickEvent.WorldTickEvent event) { - if (event.world.isRemote) return; - TICK_COUNTS.compute(event.world, (k, v) -> { - if (v == null) v = 0; - return (v % FLOWNET_TICKRATE) + 1; - }); - if (TICK_COUNTS.get(event.world) != FLOWNET_TICKRATE) return; - - Iterator>> iter = MANAGERS.getOrDefault(event.world, EMPTY).iterator(); - while (iter.hasNext()) { - WeakReference> ref = iter.next(); - FlowChannelManager manager = ref.get(); - if (manager != null) { - manager.tick(); - } else { - iter.remove(); - } - } - } - - public static void addManager(World world, WeakReference> ref) { - if (!MANAGERS.containsKey(world)) { - MANAGERS.put(world, new ObjectOpenHashSet<>()); - } - MANAGERS.get(world).add(ref); - } -} diff --git a/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java b/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java deleted file mode 100644 index b3c95077c10..00000000000 --- a/src/main/java/gregtech/api/pipenet/flow/WorldPipeFlowNetG.java +++ /dev/null @@ -1,220 +0,0 @@ -package gregtech.api.pipenet.flow; - -import gregtech.api.pipenet.AbstractEdgePredicate; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetEdge; -import gregtech.api.pipenet.NetGroup; -import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.NodeG; -import gregtech.api.pipenet.WorldPipeNetG; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.tile.TileEntityPipeBase; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraftforge.common.capabilities.Capability; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; -import org.jgrapht.graph.SimpleDirectedWeightedGraph; -import org.jgrapht.graph.SimpleWeightedGraph; - -import java.lang.ref.WeakReference; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -public abstract class WorldPipeFlowNetG, - PipeType extends Enum & IPipeType> extends WorldPipeNetG { - - private final NodeG superSource = new NodeG<>(); - private final NodeG superSink = new NodeG<>(); - - protected final Set> unhandledOldNodes = new ObjectOpenHashSet<>(); - - protected final Set>> managers = new ObjectOpenHashSet<>(); - - /** - * @param isDirected Determines whether this net needs directed graph handling. - * Used to respect filter directions in the item net and fluid net, for example. - * If the graph is not directed, pipes should not support blocked connections - * or unidirectional covers. - */ - public WorldPipeFlowNetG(String name, boolean isDirected) { - super(name, isDirected, false, isDirected ? new FlowDirected<>() : new FlowUndirected<>()); - this.pipeGraph.addVertex(superSource); - this.pipeGraph.addVertex(superSink); - } - - @Override - public void markNodeAsOldData(NodeG node) { - this.unhandledOldNodes.add(node); - } - - Graph, NetEdge> getPipeGraph() { - return this.pipeGraph; - } - - protected abstract Capability getSinkCapability(); - - @Override - public void addNodeSilent(NodeG node) { - super.addNodeSilent(node); - // Flow algorithms will throw an out of index if the number of nodes increases - this.markAlgInvalid(); - } - - @Override - public void removeNode(@Nullable NodeG node) { - super.removeNode(node); - // Flow algorithms will become mis-indexed if the number of nodes decreases - this.markAlgInvalid(); - } - - @Override - public void addEdge(NodeG source, NodeG target, - @Nullable AbstractEdgePredicate predicate) { - addEdge(source, target, Math.min(source.getData().getWeightFactor(), target.getData().getWeightFactor()) * - FlowChannelTicker.FLOWNET_TICKRATE, predicate); - this.markAlgInvalid(); - } - - @Override - protected void onWorldSet() {} - - @Override - protected void markAlgInvalid() { - Iterator>> iterator = this.managers.iterator(); - while (iterator.hasNext()) { - WeakReference> ref = iterator.next(); - FlowChannelManager manager = ref.get(); - if (manager != null) manager.clearAlgs(); - else iterator.remove(); - } - } - - public void addManager(WeakReference> ref) { - this.managers.add(ref); - } - - @Override - public List> getPaths(@Nullable NodeG node, - @Nullable TileEntityPipeBase tile) { - throw new IllegalStateException("Cannot get paths from a flow network. " + - "Must locally instantiate algorithm and evaluate; look at the FluidChannel class as an example."); - } - - @Override - public @NotNull NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { - NBTTagList allPipeNodes = new NBTTagList(); - Set> groups = new ObjectOpenHashSet<>(); - for (NodeG node : pipeGraph.vertexSet()) { - // prevent contamination by our supernodes - if (node == superSource || node == superSink) continue; - if (node.getGroupUnsafe() != null) groups.add(node.getGroupUnsafe()); - NBTTagCompound nodeTag = node.serializeNBT(); - NBTTagCompound dataTag = new NBTTagCompound(); - writeNodeData(node.getData(), dataTag); - nodeTag.setTag("Data", dataTag); - allPipeNodes.appendTag(nodeTag); - } - compound.setTag("PipeNodes", allPipeNodes); - - NBTTagList allNetEdges = new NBTTagList(); - for (NetEdge edge : pipeGraph.edgeSet()) { - // prevent contamination by our manager edges - if (edge.getSource() == superSource || edge.getTarget() == superSource || - edge.getSource() == superSink || edge.getTarget() == superSink) - continue; - allNetEdges.appendTag(edge.serializeNBT()); - } - compound.setTag("NetEdges", allNetEdges); - - NBTTagList allNetGroups = new NBTTagList(); - for (NetGroup group : groups) { - allNetGroups.appendTag(group.serializeNBT()); - } - compound.setTag("NetGroups", allNetGroups); - - return compound; - } - - public NodeG getSuperSource() { - return superSource; - } - - public NodeG getSuperSink() { - return superSink; - } - - public interface IFlowGraph, PT extends Enum & IPipeType> { - - void setTestObject(Object object); - - void setQueryingChannel(FlowChannel channel); - } - - protected static class FlowUndirected, PT extends Enum & IPipeType> - extends SimpleWeightedGraph, NetEdge> - implements IFlowGraph { - - final ThreadLocal testObject = new ThreadLocal<>(); - final ThreadLocal> queryingChannel = new ThreadLocal<>(); - - public FlowUndirected() { - super(NetEdge.class); - } - - // this overcomplicated workaround is due to not enough protected/public visibilities. - @Override - public double getEdgeWeight(NetEdge netEdge) { - // Both source and target must support the channel, and the netEdge predicate must allow our object. - return ((NodeG) netEdge.getSource()).canSupportChannel(queryingChannel.get()) && - ((NodeG) netEdge.getTarget()).canSupportChannel(queryingChannel.get()) && - netEdge.getPredicate().test(testObject.get()) ? super.getEdgeWeight(netEdge) : 0; - } - - @Override - public void setTestObject(Object object) { - this.testObject.set(object); - } - - @Override - public void setQueryingChannel(FlowChannel channel) { - this.queryingChannel.set(channel); - } - } - - protected static class FlowDirected, PT extends Enum & IPipeType> - extends SimpleDirectedWeightedGraph, NetEdge> - implements IFlowGraph { - - final ThreadLocal testObject = new ThreadLocal<>(); - final ThreadLocal> queryingChannel = new ThreadLocal<>(); - - public FlowDirected() { - super(NetEdge.class); - } - - // this overcomplicated workaround is due to not enough protected/public visibilities. - @Override - public double getEdgeWeight(NetEdge netEdge) { - // Both source and target must support the channel, and the netEdge predicate must allow our object. - return ((NodeG) netEdge.getSource()).canSupportChannel(queryingChannel.get()) && - ((NodeG) netEdge.getTarget()).canSupportChannel(queryingChannel.get()) && - netEdge.getPredicate().test(testObject.get()) ? super.getEdgeWeight(netEdge) : 0; - } - - @Override - public void setTestObject(Object object) { - this.testObject.set(object); - } - - @Override - public void setQueryingChannel(FlowChannel channel) { - this.queryingChannel.set(channel); - } - } -} diff --git a/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java b/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java index 6ae366e6bb6..b0511ed7668 100644 --- a/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java +++ b/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java @@ -1,6 +1,6 @@ package gregtech.api.pipenet.longdist; -import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.WorldPipeNetSimple; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; @@ -331,7 +331,7 @@ public static WorldData get(World world) { if (worldData != null) { return worldData; } - String DATA_ID = WorldPipeNetG.getDataID("long_dist_pipe", world); + String DATA_ID = WorldPipeNetSimple.getDataID("long_dist_pipe", world); WorldData netWorldData = (WorldData) world.loadData(WorldData.class, DATA_ID); if (netWorldData == null) { netWorldData = new WorldData(DATA_ID); diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 0737b8878e2..903467ae2a6 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -7,7 +7,7 @@ import gregtech.api.metatileentity.SyncedTileEntityBase; import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.NodeG; -import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.WorldPipeNetSimple; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.unification.material.Material; @@ -60,6 +60,7 @@ public abstract class TileEntityPipeBase & IPipe private TileEntityPipeBase tickingPipe; private boolean nbtLoad = false; + private boolean needsOldNetSetup = false; public TileEntityPipeBase() { super(false); @@ -456,11 +457,17 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { } this.nbtLoad = false; - if (!compound.hasKey("PipeNetVersion") && !compound.hasKey("PipeMaterial")) doOldNetSetup(); + if (!compound.hasKey("PipeNetVersion") && !compound.hasKey("PipeMaterial")) markAsNeedingOldNetSetup(); + } + + protected void markAsNeedingOldNetSetup() { + this.needsOldNetSetup = true; } protected void doOldNetSetup() { - WorldPipeNetG net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); + // TODO inexplicable crash during world load when old net setup required + // something to do with removing the tile entities that the chunk is iterating over to load + WorldPipeNetSimple net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); net.markNodeAsOldData(this.getNode()); for (EnumFacing facing : EnumFacing.VALUES) { NodeG nodeOffset = net.getNode(this.getPipePos().offset(facing)); @@ -482,6 +489,7 @@ protected void doOldNetSetup() { @Override public void onLoad() { super.onLoad(); + if (this.needsOldNetSetup) doOldNetSetup(); } protected void writePipeProperties(PacketBuffer buf) { diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 92b05f52aa0..3595e0bc93b 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -145,14 +145,23 @@ public int getChannelMaxCount() { return this.tanks; } - @Override - public double getWeightFactor() { - return this.getThroughput(); - } - @Override public FluidPipeProperties getMinData(Set datas) { - return null; + int maxFluidTemperature = this.getMaxFluidTemperature(); + int throughput = this.getThroughput(); + boolean gasProof = this.isGasProof(); + boolean acidProof = this.isAcidProof(); + boolean cryoProof = this.isCryoProof(); + boolean plasmaProof = this.isPlasmaProof(); + for (FluidPipeProperties data : datas) { + maxFluidTemperature = Math.min(maxFluidTemperature, data.getMaxFluidTemperature()); + throughput = Math.min(throughput, data.getThroughput()); + gasProof &= data.isGasProof(); + acidProof &= data.isAcidProof(); + cryoProof &= data.isCryoProof(); + plasmaProof &= data.isPlasmaProof(); + } + return new FluidPipeProperties(maxFluidTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof); } @Override diff --git a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java index f60d5c33bed..341c8b1b131 100644 --- a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java @@ -84,7 +84,7 @@ public double getWeightFactor() { @Override public ItemPipeProperties getMinData(Set datas) { - float transferRate = Integer.MAX_VALUE; + float transferRate = this.getTransferRate(); for (ItemPipeProperties data : datas) { transferRate = Math.min(transferRate, data.getTransferRate()); } diff --git a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java index 195e9a8d93e..1976ba2a364 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java @@ -152,7 +152,7 @@ public double getWeightFactor() { @Override public WireProperties getMinData(Set datas) { - int amperage = Integer.MAX_VALUE; + int amperage = this.getAmperage(); for (WireProperties data : datas) { amperage = Math.min(amperage, data.getAmperage()); } diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java index 3982a768bad..05b0fe11838 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -3,6 +3,7 @@ import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IEnergyContainer; import gregtech.api.pipenet.AbstractGroupData; +import gregtech.api.pipenet.IPipeNetHandler; import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.NodeG; import gregtech.api.unification.material.properties.WireProperties; @@ -20,7 +21,7 @@ import java.util.Iterator; -public class EnergyNetHandler implements IEnergyContainer { +public class EnergyNetHandler implements IEnergyContainer, IPipeNetHandler { private final WorldEnergyNet net; private boolean transfer; @@ -33,10 +34,16 @@ public EnergyNetHandler(WorldEnergyNet net, TileEntityCable cable, EnumFacing fa this.facing = facing; } + @Override public WorldEnergyNet getNet() { return net; } + @Override + public EnumFacing getFacing() { + return facing; + } + @Override public long getInputPerSec() { AbstractGroupData data = net.getGroup(cable.getPipePos()).getData(); @@ -66,7 +73,7 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage long amperesUsed = 0L; mainloop: - for (NetPath routePath : net.getPaths(cable)) { + for (NetPath routePath : net.getPaths(cable, null)) { Iterator iterator = routePath.getFacingIterator(); // weight = loss if (routePath.getWeight() >= voltage) { diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java index 5c24c460441..73195e5bdcd 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -1,7 +1,7 @@ package gregtech.common.pipelike.cable.net; import gregtech.api.pipenet.AbstractGroupData; -import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.WorldPipeNetSimple; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.WireProperties; import gregtech.common.pipelike.cable.Insulation; @@ -9,8 +9,11 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.energy.CapabilityEnergy; -public class WorldEnergyNet extends WorldPipeNetG { +// TODO move onto complex net +public class WorldEnergyNet extends WorldPipeNetSimple { private static final String DATA_ID_BASE = "gregtech.e_net"; @@ -29,6 +32,11 @@ public WorldEnergyNet(String name) { super(name, false, false); } + @Override + protected Capability[] getConnectionCapabilities() { + return new Capability[] { CapabilityEnergy.ENERGY }; + } + @Override protected Class> getBasePipeClass() { return TileEntityCable.class; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java deleted file mode 100644 index 7e19aa51528..00000000000 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidChannel.java +++ /dev/null @@ -1,223 +0,0 @@ -package gregtech.common.pipelike.fluidpipe.net; - -import gregtech.api.cover.Cover; -import gregtech.api.pipenet.NetEdge; -import gregtech.api.pipenet.NetGroup; -import gregtech.api.pipenet.NodeG; -import gregtech.api.pipenet.alg.MaximumFlowAlgorithm; -import gregtech.api.pipenet.flow.FlowChannel; -import gregtech.api.pipenet.flow.FlowChannelTicker; -import gregtech.api.pipenet.flow.WorldPipeFlowNetG; -import gregtech.api.unification.material.properties.FluidPipeProperties; -import gregtech.common.covers.CoverFluidFilter; -import gregtech.common.covers.CoverPump; -import gregtech.common.covers.CoverShutter; -import gregtech.common.pipelike.fluidpipe.FluidPipeType; -import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; - -import it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jgrapht.Graph; - -import java.util.Map; -import java.util.Set; - -public class FluidChannel extends FlowChannel { - - private FluidStack fluid; - - private MaximumFlowAlgorithm alg = null; - - private Set> oldNodes = new ObjectOpenHashSet<>(0); - - public FluidChannel(Graph, NetEdge> network, Fluid fluid) { - super(network); - this.fluid = new FluidStack(fluid, 1); - } - - public void setFluid(Fluid fluid) { - if (this.manager != null) return; - this.fluid = new FluidStack(fluid, 1); - } - - @Override - protected Object getKey() { - return fluid.getFluid(); - } - - @Override - public void clearAlg() { - this.alg = null; - } - - @Override - public void evaluate() { - // Kill this channel if we have no more active sources - if (this.activeSources.size() == 0) { - // should I put the channel in a 'recycling queue' to be reused instead? - this.manager.removeChannel(this.getKey()); - oldNodes.forEach(oldNode -> oldNode.removeChannel(this)); - return; - } - - activate(); - - if (network instanceof WorldPipeFlowNetG.IFlowGraphgraph) { - graph.setTestObject(fluid); - ((WorldPipeFlowNetG.IFlowGraph) graph) - .setQueryingChannel(this); - } else throw new IllegalStateException("Attempted to do flow calculations on a non-flow graph!"); - - if (alg == null) alg = new MaximumFlowAlgorithm<>(network); - - Map flows = alg.getMaximumFlow(manager.getSuperSource(), manager.getSuperSink()).getFlowMap(); - Map, Double> inMap = new Object2DoubleOpenHashMap<>(); - Map, Double> outMap = new Object2DoubleOpenHashMap<>(); - Map, Double> interMap = new Object2DoubleOpenHashMap<>(); - - for (Map.Entry flow : flows.entrySet()) { - if (flow.getValue() == 0) continue; - NetEdge edge = flow.getKey(); - // the interflows receive values from both inflow and outflow, which are equivalent, thus divide by two. - if (edge.getSource() == this.manager.getSuperSource()) { - inMap.merge(edge.getTarget(), flow.getValue(), Double::sum); - interMap.merge((NodeG) edge.getTarget(), - flow.getValue() / 2, Double::sum); - } else if (edge.getTarget() == this.manager.getSuperSink()) { - outMap.merge(edge.getSource(), flow.getValue(), Double::sum); - interMap.merge((NodeG) edge.getSource(), - flow.getValue() / 2, Double::sum); - } else { - interMap.merge((NodeG) edge.getSource(), - flow.getValue() / 2, Double::sum); - interMap.merge((NodeG) edge.getTarget(), - flow.getValue() / 2, Double::sum); - } - } - - for (var flow : interMap.entrySet()) { - NodeG node = flow.getKey(); - if (!node.addChannel(this)) - throw new IllegalStateException("Node rejected channel despite approving it earlier!"); - if (!node.getData().test(fluid)) { - // destroyethify - if (node.getHeldMTE() instanceof TileEntityFluidPipe f) { - FluidStack flowStack = new FluidStack(fluid, (int) (double) flow.getValue()); - f.checkAndDestroy(flowStack); - // TODO fix fluid leakage - } - } - } - - oldNodes.removeAll(interMap.keySet()); - oldNodes.forEach(oldNode -> oldNode.removeChannel(this)); - oldNodes = interMap.keySet(); - - // Everything should be properly balanced at this point due to earlier operations. - // If something is off, it's too late to fix. - for (NodeG source : activeSources) { - double flow = inMap.getOrDefault(source, 0d); - if (flow != 0) - pullFromNode(source, (int) flow, true); - } - for (NodeG sink : this.manager.getActiveSinks()) { - double flow = outMap.getOrDefault(sink, 0d); - if (flow != 0) - pushToNode(sink, (int) flow, true); - } - - deactivate(); - } - - @Override - protected double getSourceValue(NodeG source) { - return pullFromNode(source, Integer.MAX_VALUE, false); - } - - private double pullFromNode(NodeG source, int amount, boolean doDrain) { - FluidStack stack = null; - if (source.getHeldMTE() instanceof TileEntityFluidPipe f) { - IFluidHandler handler = f.getCapability( - CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); - if (handler != null) { - stack = handler.drain(new FluidStack(this.fluid.getFluid(), amount), doDrain); - } - } - return stack != null ? stack.amount : 0; - } - - @Override - protected double getSinkValue(NodeG sink) { - return pushToNode(sink, Integer.MAX_VALUE, false); - } - - private int pushToNode(NodeG sink, int amount, boolean doFill) { - int flow = 0; - if (sink.getHeldMTE() instanceof TileEntityFluidPipe f) { - int fill; - Byte receiveSides = this.receiveSidesMap.get(sink); - for (Map.Entry connected : sink.getConnecteds().entrySet()) { - if (amount == 0) break; - if (receiveSides != null) { - int facing = (1 << connected.getKey().getIndex()); - if ((receiveSides & facing) != 0) { - if (doFill) this.receiveSidesMap.compute(sink, (k, v) -> { - assert v != null; - // bitwise XOR to remove this side from the map - return (byte) (v ^ facing); - }); - continue; - } - } - Cover thisCover = f.getCoverableImplementation().getCoverAtSide(connected.getKey()); - Cover themCover = getCoverOnNeighbour(sink, connected.getKey().getOpposite()); - int transferMax = Math.min(evaluateCover(themCover, evaluateCover(thisCover, amount)), - // max flow per side cannot exceed throughput - sink.getData().getThroughput() * FlowChannelTicker.FLOWNET_TICKRATE); - IFluidHandler handler = connected.getValue().getCapability( - CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, connected.getKey().getOpposite()); - if (handler != null) { - fill = handler.fill(new FluidStack(this.fluid.getFluid(), transferMax), doFill); - flow += fill; - amount -= fill; - } - } - } - return flow; - } - - private int evaluateCover(Cover cover, int transferMax) { - if (cover instanceof CoverPump p) { - switch (p.getManualImportExportMode()) { - case DISABLED -> { - return 0; - } - case FILTERED -> { - if (!p.getFluidFilterContainer().test(this.fluid)) return 0; - } - } - return Math.min(transferMax, p.getTransferRate()); - } - if (cover instanceof CoverFluidFilter f) { - return f.getFilter().testFluid(this.fluid) ? transferMax : 0; - } - if (cover instanceof CoverShutter) return 0; - return transferMax; - } - - public static FluidChannel getChannelFromGroup(Fluid key, NetGroup group) { - FluidChannel channel = (FluidChannel) group.getChannel(key); - if (channel == null) { - channel = new FluidChannel(group.getGraph(), key); - group.setChannel(key, channel); - } - return channel; - } -} diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java new file mode 100644 index 00000000000..ebed465fd71 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java @@ -0,0 +1,260 @@ +package gregtech.common.pipelike.fluidpipe.net; + +import gregtech.api.cover.Cover; +import gregtech.api.pipenet.IPipeNetHandler; +import gregtech.api.pipenet.NetEdge; +import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.NodeG; +import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.common.covers.CoverFluidRegulator; +import gregtech.common.covers.CoverPump; +import gregtech.common.pipelike.fluidpipe.FluidPipeType; +import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; +import net.minecraftforge.fml.common.FMLCommonHandler; + +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; + +public class FluidNetHandler implements IFluidHandler, IPipeNetHandler { + + private static final IFluidTankProperties[] EMPTY = new IFluidTankProperties[0]; + + private final WorldFluidPipeNet net; + private TileEntityFluidPipe pipe; + private final EnumFacing facing; + + private final IFluidHandler testHandler = new FluidTank(Integer.MAX_VALUE); + + private NetEdge.ChannelSimulator simulator; + + public FluidNetHandler(WorldFluidPipeNet net, TileEntityFluidPipe pipe, EnumFacing facing) { + this.net = net; + this.pipe = pipe; + this.facing = facing; + } + + public void updatePipe(TileEntityFluidPipe pipe) { + this.pipe = pipe; + } + + @Override + public WorldFluidPipeNet getNet() { + return net; + } + + @Override + public EnumFacing getFacing() { + return facing; + } + + @Override + public IFluidTankProperties[] getTankProperties() { + // TODO instead collect a list of all connected tanks? + return EMPTY; + } + + @Override + public int fill(FluidStack resource, boolean doFill) { + if (net == null || pipe == null || pipe.isInvalid() || pipe.isFaceBlocked(facing)) return 0; + + FluidTestObject testObject = new FluidTestObject(resource); + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + // push flow through net + List> paths = + this.getNet().getPaths(pipe, testObject); + FluidStack helper = resource.copy(); + if (!doFill) this.simulator = NetEdge.getNewSimulatorInstance(); + else this.simulator = null; + mainloop: + for (NetPath path : paths) { + for (Iterator it = path.getFacingIterator(); it.hasNext(); ) { + EnumFacing facing = it.next(); + NetPath.FacedNetPath routePath = path.withFacing(facing); + helper.amount -= this.fill(routePath, testObject, tick, helper, doFill); + if (helper.amount <= 0) break mainloop; + } + } + if (!doFill) this.simulator = null; + return resource.amount - helper.amount; + } + + public int fill(NetPath.FacedNetPath routePath, + FluidTestObject testObject, long tick, FluidStack resource, boolean doFill) { + if (routePath.getTargetNode().getNodePos().equals(this.pipe.getPos()) && routePath.facing == this.facing) { + return 0; + } + int allowed = resource.amount; + Cover pipeCover = routePath.getTargetNode().getHeldMTE().getCoverableImplementation() + .getCoverAtSide(routePath.facing); + Cover tileCover = getCoverOnNeighbour(routePath.getTargetNode().getNodePos(), + routePath.facing.getOpposite()); + + if (pipeCover != null) { + FluidStack helper; + testHandler.fill(resource, true); + IFluidHandler fluidHandler = pipeCover.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + testHandler); + if (fluidHandler == null || (fluidHandler != testHandler && + ((helper = fluidHandler.drain(resource, false)) == null || + (allowed = helper.amount) <= 0))) { + testHandler.drain(Integer.MAX_VALUE, true); + return 0; + } + testHandler.drain(Integer.MAX_VALUE, true); + } + IFluidHandler neighbourHandler = routePath.getTargetTE() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, routePath.facing.getOpposite()); + if (neighbourHandler == null) return 0; + + if (pipeCover instanceof CoverFluidRegulator && + ((CoverFluidRegulator) pipeCover).getPumpMode() == CoverPump.PumpMode.EXPORT) { + return fillOverRegulator(routePath, neighbourHandler, testObject, tick, (CoverFluidRegulator) pipeCover, + resource, allowed, doFill); + } else if (tileCover instanceof CoverFluidRegulator && + ((CoverFluidRegulator) tileCover).getPumpMode() == CoverPump.PumpMode.IMPORT) { + return fillOverRegulator(routePath, neighbourHandler, testObject, tick, (CoverFluidRegulator) tileCover, + resource, allowed, doFill); + } else { + return fill(routePath, neighbourHandler, testObject, tick, resource, allowed, doFill); + } + } + + public int fillOverRegulator(NetPath.FacedNetPath routePath, + IFluidHandler handler, FluidTestObject testObject, long tick, + CoverFluidRegulator regulator, FluidStack resource, int allowed, boolean doFill) { + var matched = regulator.getFluidFilterContainer().match(resource); + boolean isStackSpecific = false; + int rate, count; + + if (matched.isMatched()) { + int index = matched.getFilterIndex(); + rate = regulator.getFluidFilterContainer().getTransferLimit(index); + isStackSpecific = true; + } else { + rate = regulator.getFluidFilterContainer().getTransferSize(); + } + + switch (regulator.getTransferMode()) { + case TRANSFER_ANY -> { + return fill(routePath, handler, testObject, tick, resource, allowed, doFill); + } + case KEEP_EXACT -> { + count = rate - countStack(handler, resource, regulator, isStackSpecific); + if (count <= 0) return 0; + count = Math.min(allowed, Math.min(resource.amount, count)); + return fill(routePath, handler, testObject, tick, resource, count, doFill); + } + case TRANSFER_EXACT -> { + // TODO can regulators have the equivalent of robot arm buffering? + count = Math.min(allowed, Math.min(rate, resource.amount)); + if (count < rate) { + return 0; + } + if (fill(routePath, handler, testObject, tick, resource, count, false) != count) { + return 0; + } + return fill(routePath, handler, testObject, tick, resource, count, true); + } + } + return 0; + } + + private int fill(NetPath.FacedNetPath routePath, IFluidHandler handler, + FluidTestObject testObject, long tick, FluidStack resource, int allowed, boolean doFill) { + FluidStack helper = new FluidStack(resource, allowed); + allowed = handler.fill(helper, false); + + // iterate through path + List> nodeList = routePath.getNodeList(); + List edgeList = routePath.getEdgeList(); + List> flowLimitConsumers = new ObjectArrayList<>(); + int inputAmount = resource.amount; + int outputAmount = resource.amount; + // always 1 less edge than nodes + for (int i = 0; i < edgeList.size(); i++) { + NodeG source = nodeList.get(i); + NodeG target = nodeList.get(i + 1); + NetEdge edge = edgeList.get(i); + int flow = Math.min(edge.getFlowLimit(testObject, getNet().getGraph(), tick, simulator), outputAmount); + double ratio = (double) flow / outputAmount; + inputAmount *= ratio; + flowLimitConsumers.add(finalRatio -> + edge.consumeFlowLimit(testObject, getNet().getGraph(), (int) (finalRatio * flow), tick, simulator)); + double loss = 1; // TODO fluid loss & pipe damage + outputAmount = (int) (flow * loss); + } + // outputAmount is currently the maximum flow to the endpoint, and inputAmount is the requisite flow into the net + allowed = Math.min(allowed, outputAmount); + + helper.amount = allowed; + allowed = handler.fill(helper, doFill); + double ratio = (double) allowed / outputAmount; + flowLimitConsumers.forEach(a -> a.accept(ratio)); + + return (int) (inputAmount * ratio); + + } + + public static int countStack(IFluidHandler handler, FluidStack stack, CoverFluidRegulator regulator, boolean isStackSpecific) { + if (regulator == null) return 0; + int count = 0; + for (int i = 0; i < handler.getTankProperties().length; i++) { + FluidStack slot = handler.getTankProperties()[i].getContents(); + if (slot == null) continue; + if (isStackSpecific ? slot.isFluidEqual(stack) : + regulator.getFluidFilterContainer().test(slot)) { + count += slot.amount; + } + } + return count; + } + + @Override + public FluidStack drain(FluidStack resource, boolean doDrain) { + // TODO support pulling from net? + return null; + } + + @Override + public FluidStack drain(int maxDrain, boolean doDrain) { + // TODO support pulling from net? + return null; + } + + protected static class FluidTestObject { + + public final Fluid fluid; + public final NBTTagCompound tag; + + public FluidTestObject(FluidStack stack) { + this.fluid = stack.getFluid(); + this.tag = stack.tag; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + FluidTestObject that = (FluidTestObject) o; + return Objects.equals(fluid, that.fluid) && Objects.equals(tag, that.tag); + } + + @Override + public int hashCode() { + return Objects.hash(fluid, tag); + } + } +} diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java index cd609d54fba..b97d64e8144 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java @@ -15,6 +15,7 @@ import java.util.Arrays; import java.util.Iterator; +// TODO implement old fluid handling for pipes public class PipeTankList implements IFluidHandler, Iterable { private final TileEntityFluidPipe pipe; @@ -77,7 +78,6 @@ private int fill(FluidStack resource, boolean doFill, int channel) { newFluid.amount = Math.min(pipe.getCapacityPerTank(), newFluid.amount); if (doFill) { tank.setFluid(newFluid); - pipe.receivedFrom(newFluid.getFluid(), facing); pipe.checkAndDestroy(newFluid); } return newFluid.amount; @@ -87,7 +87,6 @@ private int fill(FluidStack resource, boolean doFill, int channel) { if (toAdd > 0) { if (doFill) { currentFluid.amount += toAdd; - pipe.receivedFrom(currentFluid.getFluid(), facing); pipe.checkAndDestroy(currentFluid); } return toAdd; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index 70b1b163ba7..06e158ceccf 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -2,7 +2,8 @@ import gregtech.api.cover.Cover; import gregtech.api.pipenet.AbstractEdgePredicate; -import gregtech.api.pipenet.flow.WorldPipeFlowNetG; +import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.WorldPipeNetComplex; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.covers.CoverFluidFilter; @@ -12,12 +13,18 @@ import gregtech.common.pipelike.fluidpipe.FluidPipeType; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -public class WorldFluidPipeNet extends WorldPipeFlowNetG { +import java.util.Set; + +public class WorldFluidPipeNet extends WorldPipeNetComplex { + + // TODO handle fluids in old fluid pipes private static final String DATA_ID_BASE = "gregtech.fluid_pipe_net"; @@ -33,7 +40,12 @@ public static WorldFluidPipeNet getWorldPipeNet(World world) { } public WorldFluidPipeNet(String name) { - super(name, true); + super(name, true, false, 20); + } + + @Override + protected Capability[] getConnectionCapabilities() { + return new Capability[] { CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY }; } @Override @@ -70,11 +82,6 @@ protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbour return shutterify(predicate, thisCover, neighbourCover); } - @Override - protected Capability getSinkCapability() { - return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY; - } - @Override protected void writeNodeData(FluidPipeProperties nodeData, NBTTagCompound tagCompound) { tagCompound.setInteger("max_temperature", nodeData.getMaxFluidTemperature()); diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java index 51a3fe48553..b44c36fd78e 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java @@ -7,22 +7,32 @@ import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.metatileentity.IDataInfoProvider; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; +import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.util.EntityDamageUtil; import gregtech.api.util.TextFormattingUtil; import gregtech.common.pipelike.fluidpipe.FluidPipeType; -import gregtech.common.pipelike.fluidpipe.net.FluidChannel; +import gregtech.common.pipelike.fluidpipe.net.FluidNetHandler; import gregtech.common.pipelike.fluidpipe.net.PipeTankList; +import gregtech.common.pipelike.fluidpipe.net.WorldFluidPipeNet; +import gregtech.common.pipelike.itempipe.net.ItemNetHandler; + +import gregtech.common.pipelike.itempipe.net.WorldItemPipeNet; + +import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; + import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.Blocks; import net.minecraft.init.SoundEvents; +import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.SoundCategory; +import net.minecraft.util.Tuple; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.ITextComponent; @@ -36,8 +46,13 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemStackHandler; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,12 +60,18 @@ import java.util.EnumMap; import java.util.List; -public class TileEntityFluidPipe extends TileEntityMaterialPipeBase - implements IDataInfoProvider { +public class TileEntityFluidPipe extends TileEntityMaterialPipeBase { + // old code to maintain compat with old worlds // private PipeTankList pipeTankList; private final EnumMap tankLists = new EnumMap<>(EnumFacing.class); private FluidTank[] fluidTanks; + // ------------------------------------------- // + + private final EnumMap handlers = new EnumMap<>(EnumFacing.class); + private FluidNetHandler defaultHandler; + // the FluidNetHandler can only be created on the server so we have a empty placeholder for the client + private final IFluidHandler clientCapability = new FluidTank(0); private final int offset = GTValues.RNG.nextInt(20); private long lastSoundTime = 0; @@ -62,15 +83,49 @@ public long getOffsetTimer() { @Override public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { - PipeTankList tankList = getTankList(facing); - if (tankList == null) - return null; - return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(tankList); + if (world.isRemote) + return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(clientCapability); + + if (handlers.size() == 0) + initHandlers(); + return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(handlers.getOrDefault(facing, defaultHandler)); } return super.getCapabilityInternal(capability, facing); } + private void initHandlers() { + WorldFluidPipeNet net = WorldFluidPipeNet.getWorldPipeNet(getPipeWorld()); + for (EnumFacing facing : EnumFacing.values()) { + handlers.put(facing, new FluidNetHandler(net, this, facing)); + } + defaultHandler = new FluidNetHandler(net, this, null); + } + + @Override + public void transferDataFrom(IPipeTile tileEntity) { + super.transferDataFrom(tileEntity); + TileEntityFluidPipe fluidPipe = (TileEntityFluidPipe) tileEntity; + // take handlers from old pipe + if (!fluidPipe.handlers.isEmpty()) { + this.handlers.clear(); + for (FluidNetHandler handler : fluidPipe.handlers.values()) { + handler.updatePipe(this); + this.handlers.put(handler.getFacing(), handler); + } + } + if (fluidPipe.defaultHandler != null) { + fluidPipe.defaultHandler.updatePipe(this); + this.defaultHandler = fluidPipe.defaultHandler; + } + } + public void checkAndDestroy(@NotNull FluidStack stack) { + var result = determineFluidPassthroughResult(stack.copy(), world, pos); + stack.amount *= result.getSecond(); + result.getFirst().run(); + } + + public Tuple determineFluidPassthroughResult(@NotNull FluidStack stack, World world, BlockPos pos) { Fluid fluid = stack.getFluid(); FluidPipeProperties prop = getNodeData(); @@ -101,12 +156,22 @@ public void checkAndDestroy(@NotNull FluidStack stack) { } if (burning || leaking || corroding || shattering || melting) { - destroyPipe(stack, burning, leaking, corroding, shattering, melting); - } + return determineDestroyPipeResults(stack, burning, leaking, corroding, shattering, melting, world, pos); + } else return new Tuple<>(() -> {}, 1d); } public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, boolean isCorroding, boolean isShattering, boolean isMelting) { + var result = determineDestroyPipeResults(stack, isBurning, isLeaking, isCorroding, isShattering, isMelting, world, pos); + stack.amount *= result.getSecond(); + result.getFirst().run(); + } + + public Tuple determineDestroyPipeResults(FluidStack stack, boolean isBurning, boolean isLeaking, + boolean isCorroding, boolean isShattering, + boolean isMelting, World world, BlockPos pos) { + Runnable postAction = () -> {}; + double mult = 1; // prevent the sound from spamming when filled from anything not a pipe if (getOffsetTimer() >= lastSoundTime + 10) { world.playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); @@ -118,7 +183,7 @@ public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, 7 + GTValues.RNG.nextInt(2)); // voids 10% - stack.amount = Math.max(0, stack.amount * 9 / 10); + mult *= 0.9; // apply heat damage in area surrounding the pipe if (getOffsetTimer() % 20 == 0) { @@ -141,7 +206,7 @@ public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, 3 + GTValues.RNG.nextInt(2)); // voids 25% - stack.amount = Math.max(0, stack.amount * 3 / 4); + mult *= 0.75; // apply chemical damage in area surrounding the pipe if (getOffsetTimer() % 20 == 0) { @@ -154,8 +219,8 @@ public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, // 1/10 chance to void everything and destroy the pipe if (GTValues.RNG.nextInt(10) == 0) { - stack.amount = 0; - world.setBlockToAir(pos); + mult = 0; + postAction = () -> world.setBlockToAir(pos); } } @@ -164,7 +229,7 @@ public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, (isMelting ? 7 : 3) + GTValues.RNG.nextInt(2)); // voids 75% - stack.amount = Math.max(0, stack.amount / 4); + mult *= 0.25; // 1/4 chance to burn everything around it if (GTValues.RNG.nextInt(4) == 0) { @@ -183,8 +248,8 @@ public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, // 1/10 chance to void everything and burn the pipe if (GTValues.RNG.nextInt(10) == 0) { - stack.amount = 0; - world.setBlockState(pos, Blocks.FIRE.getDefaultState()); + mult = 0; + postAction = () -> world.setBlockState(pos, Blocks.FIRE.getDefaultState()); } } @@ -193,7 +258,7 @@ public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, 3 + GTValues.RNG.nextInt(2)); // voids 75% - stack.amount = Math.max(0, stack.amount / 4); + mult *= 0.75; // apply frost damage in area surrounding the pipe if (getOffsetTimer() % 20 == 0) { @@ -207,19 +272,11 @@ public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, // 1/10 chance to void everything and freeze the pipe if (GTValues.RNG.nextInt(10) == 0) { - stack.amount = 0; - world.setBlockToAir(pos); + mult = 0; + postAction = () -> world.setBlockToAir(pos); } } - } - - public void receivedFrom(Fluid fluid, EnumFacing facing) { - // on fluid received, add us as a source to the proper channel - FluidChannel channel = FluidChannel.getChannelFromGroup(fluid, this.getNode().getGroupSafe()); - channel.addSource(this.getNode()); - if (facing != null) { - channel.addReceiveSide(this.getNode(), facing); - } + return new Tuple<>(postAction, mult); } public FluidStack getContainedFluid(int channel) { @@ -329,6 +386,7 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound nbt) { @Override public void readFromNBT(@NotNull NBTTagCompound nbt) { super.readFromNBT(nbt); + if (!nbt.hasKey("Fluids")) return; NBTTagList list = (NBTTagList) nbt.getTag("Fluids"); createTanksList(); for (int i = 0; i < list.tagCount(); i++) { @@ -336,42 +394,8 @@ public void readFromNBT(@NotNull NBTTagCompound nbt) { if (!tag.getBoolean("isNull")) { FluidStack stack = FluidStack.loadFluidStackFromNBT(tag); if (stack == null) continue; - fluidTanks[i].setFluid(stack); - // the best part is that this naturally gives us backwards compatibility. - FluidChannel channel = FluidChannel.getChannelFromGroup(stack.getFluid(), - this.getNode().getGroupSafe()); - channel.addSource(this.getNode()); + // TODO old fluid in pipes handling } } } - - @NotNull - @Override - public List getDataInfo() { - List list = new ArrayList<>(); - - FluidStack[] fluids = this.getContainedFluids(); - if (fluids != null) { - boolean allTanksEmpty = true; - for (int i = 0; i < fluids.length; i++) { - if (fluids[i] != null) { - if (fluids[i].getFluid() == null) - continue; - - allTanksEmpty = false; - list.add(new TextComponentTranslation("behavior.tricorder.tank", i, - new TextComponentTranslation(TextFormattingUtil.formatNumbers(fluids[i].amount)) - .setStyle(new Style().setColor(TextFormatting.GREEN)), - new TextComponentTranslation(TextFormattingUtil.formatNumbers(this.getCapacityPerTank())) - .setStyle(new Style().setColor(TextFormatting.YELLOW)), - new TextComponentTranslation(fluids[i].getFluid().getLocalizedName(fluids[i])) - .setStyle(new Style().setColor(TextFormatting.GOLD)))); - } - } - - if (allTanksEmpty) - list.add(new TextComponentTranslation("behavior.tricorder.tanks_empty")); - } - return list; - } } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index 2e199c09b96..465979ce077 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -1,14 +1,12 @@ package gregtech.common.pipelike.itempipe.net; -import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; -import gregtech.api.cover.CoverHolder; +import gregtech.api.pipenet.IPipeNetHandler; import gregtech.api.pipenet.NetPath; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.util.FacingPos; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.ItemStackHashStrategy; -import gregtech.common.covers.*; import gregtech.common.covers.CoverConveyor; import gregtech.common.covers.CoverItemFilter; import gregtech.common.covers.CoverRoboticArm; @@ -18,9 +16,7 @@ import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemStackHandler; @@ -36,7 +32,7 @@ import java.util.Iterator; import java.util.List; -public class ItemNetHandler implements IItemHandler { +public class ItemNetHandler implements IItemHandler, IPipeNetHandler { private final WorldItemPipeNet net; private TileEntityItemPipe pipe; @@ -55,10 +51,12 @@ public void updatePipe(TileEntityItemPipe pipe) { this.pipe = pipe; } + @Override public WorldItemPipeNet getNet() { return net; } + @Override public EnumFacing getFacing() { return facing; } @@ -114,7 +112,7 @@ public static boolean checkImportCover(Cover cover, boolean onPipe, ItemStack st } public ItemStack insertFirst(ItemStack stack, boolean simulate) { - for (NetPath inv : net.getPaths(pipe)) { + for (NetPath inv : net.getPaths(pipe, null)) { stack = insert(inv.firstFacing(), stack, simulate); if (stack.isEmpty()) return ItemStack.EMPTY; @@ -123,7 +121,7 @@ public ItemStack insertFirst(ItemStack stack, boolean simulate) { } public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean global) { - List> routePaths = net.getPaths(pipe); + List> routePaths = net.getPaths(pipe, null); if (routePaths.isEmpty()) return stack; if (routePaths.size() == 1 && routePaths.get(0).getTargetTEs().size() == 1) { @@ -132,7 +130,7 @@ public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean glo List> routePathsCopy = new ArrayList<>(routePaths); if (global) { - stack = insertToHandlersEnhanced(routePathsCopy, stack, routePaths.size(), simulate); + stack = insertToHandlersEnhanced(routePathsCopy, stack, simulate); } else { stack = insertToHandlers(routePathsCopy, stack, simulate); if (!stack.isEmpty() && !routePathsCopy.isEmpty()) @@ -193,7 +191,7 @@ private ItemStack insertToHandlers(List> copy, ItemStack stack, - int dest, boolean simulate) { + boolean simulate) { List transferred = new ArrayList<>(); IntList steps = new IntArrayList(); int min = Integer.MAX_VALUE; @@ -317,8 +315,11 @@ public ItemStack insert(NetPath.FacedNetPath r public ItemStack insert(NetPath.FacedNetPath routePath, ItemStack stack, boolean simulate, boolean ignoreLimit) { + if (routePath.getTargetNode().getNodePos() == this.pipe.getPos() && routePath.facing == this.facing) { + return stack; + } int allowed = ignoreLimit ? stack.getCount() : - checkTransferable(routePath.getData().getTransferRate(), stack.getCount(), simulate); + checkTransferable(routePath.getMinData().getTransferRate(), stack.getCount(), simulate); if (allowed == 0 || !routePath.checkPredicate(stack)) { return stack; } @@ -371,17 +372,6 @@ private ItemStack insert(IItemHandler handler, ItemStack stack, boolean simulate return remainder; } - public Cover getCoverOnNeighbour(BlockPos pos, EnumFacing facing) { - TileEntity tile = net.getNode(pos).getConnnected(facing); - if (tile != null) { - CoverHolder coverHolder = tile.getCapability(GregtechTileCapabilities.CAPABILITY_COVER_HOLDER, - facing.getOpposite()); - if (coverHolder == null) return null; - return coverHolder.getCoverAtSide(facing.getOpposite()); - } - return null; - } - public ItemStack insertOverRobotArm(IItemHandler handler, CoverRoboticArm arm, ItemStack stack, boolean simulate, int allowed, boolean ignoreLimit) { var matched = arm.getItemFilterContainer().match(stack); diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index 26c23575134..02cc922d56f 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -2,7 +2,7 @@ import gregtech.api.cover.Cover; import gregtech.api.pipenet.AbstractEdgePredicate; -import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.WorldPipeNetSimple; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.common.covers.CoverConveyor; @@ -14,8 +14,12 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; -public class WorldItemPipeNet extends WorldPipeNetG { +import net.minecraftforge.items.CapabilityItemHandler; + +// TODO move onto complex net +public class WorldItemPipeNet extends WorldPipeNetSimple { private static final String DATA_ID = "gregtech.item_pipe_net"; @@ -33,6 +37,11 @@ public WorldItemPipeNet(String name) { super(name, true, false); } + @Override + protected Capability[] getConnectionCapabilities() { + return new Capability[] { CapabilityItemHandler.ITEM_HANDLER_CAPABILITY }; + } + @Override protected Class> getBasePipeClass() { return TileEntityItemPipe.class; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java index 53eac210e24..cc0d78f4868 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java @@ -57,7 +57,6 @@ private void initHandlers() { @Override public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { - if (world.isRemote) return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(clientCapability); diff --git a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java index a7102854c04..4cb90b94e03 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java @@ -2,6 +2,7 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserContainer; +import gregtech.api.pipenet.IPipeNetHandler; import gregtech.api.pipenet.NetGroup; import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.NodeG; @@ -18,7 +19,7 @@ import java.util.List; import java.util.Map; -public class LaserNetHandler implements ILaserContainer { +public class LaserNetHandler implements ILaserContainer, IPipeNetHandler { private final WorldLaserPipeNet net; private final TileEntityLaserPipe pipe; @@ -30,6 +31,16 @@ public LaserNetHandler(WorldLaserPipeNet net, @NotNull TileEntityLaserPipe pipe, this.facing = facing; } + @Override + public WorldLaserPipeNet getNet() { + return net; + } + + @Override + public EnumFacing getFacing() { + return facing; + } + private void setPipesActive() { NetGroup group = getNet().getNode(this.pipe.getPipePos()).getGroupSafe(); if (group != null) { @@ -47,7 +58,7 @@ private ILaserContainer getInnerContainer() { return null; } - List> data = net.getPaths(this.pipe); + List> data = net.getPaths(this.pipe, null); if (data == null || data.size() != 1) return null; Map connecteds = data.get(0).getTargetTEs(); if (connecteds.size() != 1) return null; @@ -110,10 +121,6 @@ public long getInputVoltage() { return 0; } - public WorldLaserPipeNet getNet() { - return net; - } - @Override public boolean isOneProbeHidden() { return true; diff --git a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java b/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java index 5299262521e..0bde1623b2c 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java @@ -1,6 +1,7 @@ package gregtech.common.pipelike.laser.net; -import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.pipenet.WorldPipeNetSimple; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.common.pipelike.laser.LaserPipeProperties; import gregtech.common.pipelike.laser.LaserPipeType; @@ -9,9 +10,11 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; + import org.jetbrains.annotations.NotNull; -public class WorldLaserPipeNet extends WorldPipeNetG { +public class WorldLaserPipeNet extends WorldPipeNetSimple { private static final String DATA_ID = "gregtech.laser_pipe_net"; @@ -19,6 +22,11 @@ public WorldLaserPipeNet(String name) { super(name, false, true); } + @Override + protected Capability[] getConnectionCapabilities() { + return new Capability[] { GregtechTileCapabilities.CAPABILITY_LASER }; + } + @Override protected Class> getBasePipeClass() { return TileEntityLaserPipe.class; diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java index ab788d4b036..8d31e474637 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java @@ -4,6 +4,7 @@ import gregtech.api.capability.IDataAccessHatch; import gregtech.api.capability.IOpticalComputationProvider; import gregtech.api.capability.IOpticalDataAccessHatch; +import gregtech.api.pipenet.IPipeNetHandler; import gregtech.api.pipenet.NetGroup; import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.NodeG; @@ -22,7 +23,7 @@ import java.util.List; import java.util.Map; -public class OpticalNetHandler implements IDataAccessHatch, IOpticalComputationProvider { +public class OpticalNetHandler implements IDataAccessHatch, IOpticalComputationProvider, IPipeNetHandler { private final TileEntityOpticalPipe pipe; private final EnumFacing facing; @@ -36,10 +37,16 @@ public OpticalNetHandler(WorldOpticalPipeNet net, @NotNull TileEntityOpticalPipe this.facing = facing; } + @Override public WorldOpticalPipeNet getNet() { return net; } + @Override + public EnumFacing getFacing() { + return facing; + } + @Override public boolean isRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { boolean isAvailable = traverseRecipeAvailable(recipe, seen); @@ -88,7 +95,7 @@ private boolean isNetInvalidForTraversal() { private boolean traverseRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { if (isNetInvalidForTraversal()) return false; - List> inv = net.getPaths(this.pipe); + List> inv = net.getPaths(this.pipe, null); if (inv == null || inv.size() != 1) return false; Map connecteds = inv.get(0).getTargetTEs(); if (connecteds.size() != 1) return false; @@ -126,7 +133,7 @@ private boolean traverseCanBridge(@NotNull Collection seen) { if (isNetInvalidForTraversal()) return null; - List> inv = net.getPaths(this.pipe); + List> inv = net.getPaths(this.pipe, null); if (inv == null || inv.size() != 1) return null; Map connecteds = inv.get(0).getTargetTEs(); if (connecteds.size() != 1) return null; diff --git a/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java b/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java index 00e0f032ab1..8f85f99e485 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java @@ -1,6 +1,7 @@ package gregtech.common.pipelike.optical.net; -import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.pipenet.WorldPipeNetSimple; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.common.pipelike.optical.OpticalPipeProperties; import gregtech.common.pipelike.optical.OpticalPipeType; @@ -9,9 +10,11 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; + import org.jetbrains.annotations.NotNull; -public class WorldOpticalPipeNet extends WorldPipeNetG { +public class WorldOpticalPipeNet extends WorldPipeNetSimple { private static final String DATA_ID = "gregtech.optical_pipe_net"; @@ -19,6 +22,12 @@ public WorldOpticalPipeNet(String name) { super(name, false, true); } + @Override + protected Capability[] getConnectionCapabilities() { + return new Capability[] { GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, + GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER }; + } + @Override protected Class> getBasePipeClass() { return TileEntityOpticalPipe.class; diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java index 3c5b1071cc7..6bd63b109cf 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java @@ -3,7 +3,7 @@ import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.pipenet.NodeG; -import gregtech.api.pipenet.WorldPipeNetG; +import gregtech.api.pipenet.WorldPipeNetSimple; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -47,7 +47,7 @@ public void addProbeInfo(@NotNull ProbeMode mode, @NotNull IProbeInfo probeInfo, if (tileEntity instanceof TileEntityPipeBase) { IPipeTile pipeTile = (IPipeTile) tileEntity; BlockPipe blockPipe = pipeTile.getPipeBlock(); - WorldPipeNetG pipeNet = blockPipe.getWorldPipeNet(world); + WorldPipeNetSimple pipeNet = blockPipe.getWorldPipeNet(world); if (pipeNet != null) { probeInfo.text("Net: " + pipeNet.hashCode()); probeInfo.text("Node Info: "); From 6e69da57517dd4ce32c769fb92e6001f939a348d Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 18 Jun 2024 23:27:25 -0600 Subject: [PATCH 059/157] Fixes --- .../java/gregtech/api/pipenet/NetEdge.java | 23 ++- .../api/pipenet/WorldPipeNetComplex.java | 76 +------ .../api/pipenet/WorldPipeNetSimple.java | 3 +- .../api/pipenet/tile/TileEntityPipeBase.java | 3 +- .../properties/FluidPipeProperties.java | 168 +++++++++++++++ .../pipelike/fluidpipe/BlockFluidPipe.java | 1 + .../fluidpipe/net/FluidNetHandler.java | 77 +++++-- .../fluidpipe/tile/TileEntityFluidPipe.java | 195 ++---------------- 8 files changed, 275 insertions(+), 271 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/NetEdge.java b/src/main/java/gregtech/api/pipenet/NetEdge.java index 2f25cc2a343..cecfa5152ee 100644 --- a/src/main/java/gregtech/api/pipenet/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/NetEdge.java @@ -24,6 +24,7 @@ public final class NetEdge extends DefaultWeightedEdge implements INBTSerializab private AbstractEdgePredicate predicate; private boolean invertedPredicate; + @SuppressWarnings("unused") // used via reflection public NetEdge() {} public void setPredicate(AbstractEdgePredicate predicate) { @@ -113,11 +114,11 @@ public void build() { } } - /// Complex graph related code /// + /// Flow behavior related code /// private int flowBufferTicks; private ChannelsHolder channels; - private WeakHashMap simulatedChannels; + private WeakHashMap simulatedChannels; private INodeData> minData; @@ -132,11 +133,11 @@ public NetEdge(int flowBufferTicks) { *
* This simulator must be discarded after use so that the garbage collector can clean up. */ - public static ChannelSimulator getNewSimulatorInstance() { - return new ChannelSimulator(); + public static ChannelSimulatorKey getNewSimulatorInstance() { + return new ChannelSimulatorKey(); } - private ChannelsHolder getChannels(@Nullable ChannelSimulator simulator) { + private ChannelsHolder getChannels(@Nullable NetEdge.ChannelSimulatorKey simulator) { if (simulator == null) return this.channels; else { ChannelsHolder channels = simulatedChannels.get(simulator); @@ -157,14 +158,14 @@ private int getAdjustedThroughput() { return getMinData().getThroughput() * flowBufferTicks; } - private boolean cannotSupportChannel(Object channel, long queryTick, @Nullable ChannelSimulator simulator) { + private boolean cannotSupportChannel(Object channel, long queryTick, @Nullable NetEdge.ChannelSimulatorKey simulator) { var channels = getChannels(simulator); channels.recalculateFlowLimits(queryTick); return channels.map.size() >= getMinData().getChannelMaxCount() && !channels.map.containsKey(channel); } public & IPipeType, NDT extends INodeData> int getFlowLimit( - Object channel, Graph, NetEdge> graph, long queryTick, @Nullable ChannelSimulator simulator) { + Object channel, Graph, NetEdge> graph, long queryTick, @Nullable NetEdge.ChannelSimulatorKey simulator) { if (this.cannotSupportChannel(channel, queryTick, simulator)) { return 0; } @@ -180,7 +181,7 @@ public & IPipeType, NDT extends INodeData> int ge } public & IPipeType, NDT extends INodeData> int getConsumedLimit( - Object channel, long queryTick, @Nullable ChannelSimulator simulator) { + Object channel, long queryTick, @Nullable NetEdge.ChannelSimulatorKey simulator) { var channels = getChannels(simulator); channels.recalculateFlowLimits(queryTick); int limit = getAdjustedThroughput(); @@ -188,7 +189,7 @@ public & IPipeType, NDT extends INodeData> int ge } public & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, Graph, NetEdge> graph, int amount, long queryTick, @Nullable ChannelSimulator simulator) { + Object channel, Graph, NetEdge> graph, int amount, long queryTick, @Nullable NetEdge.ChannelSimulatorKey simulator) { if (amount == 0) return; var channels = getChannels(simulator); channels.recalculateFlowLimits(queryTick); @@ -245,10 +246,10 @@ public void recalculateFlowLimits(long queryTick) { } } - public static final class ChannelSimulator { + public static final class ChannelSimulatorKey { private static int ID; private final int id; - private ChannelSimulator() { + private ChannelSimulatorKey() { this.id = ID++; } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java index 42b8dfe400e..7069bf1d242 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java @@ -19,8 +19,7 @@ public abstract class WorldPipeNetComplex & IPipeType> extends WorldPipeNetSimple { /** - * Alternate pipenet representation. - * Supports pipenet-level limits on flow per tick and nodes with multiple channels, but cannot cache paths. + * Alternate pipenet representation. Disables node path caching and activates {@link NetEdge} flow behavior. *

* Note - undirected versions of this pipenet will treat flow in either direction along an edge towards its capacity, * while directed versions will cancel out reverse flow for improved behavior. @@ -37,24 +36,10 @@ public abstract class WorldPipeNetComplex(() -> new NetEdge(flowBufferTicks)) : - new UndirectedLimitedGraph<>(() -> new NetEdge(flowBufferTicks))); + isDirected ? new SimpleDirectedWeightedGraph<>(null, () -> new NetEdge(flowBufferTicks)) : + new SimpleWeightedGraph<>(null, () -> new NetEdge(flowBufferTicks))); } -// @Override -// public void addNodeSilent(NodeG node) { -// super.addNodeSilent(node); -// // Flow algorithms will throw an out of index if the number of nodes increases -// this.markAlgInvalid(); -// } -// -// @Override -// public void removeNode(@Nullable NodeG node) { -// super.removeNode(node); -// // Flow algorithms will become mis-indexed if the number of nodes decreases -// this.markAlgInvalid(); -// } - @Override public List> getPaths(@Nullable NodeG node, @Nullable TileEntityPipeBase tile, @@ -65,62 +50,7 @@ public List> getPaths(@Nullable NodeG) this.pipeGraph).setTestObject(testObject); List> list = this.netAlgorithm.getPathsList(node); - ((IComplexGraph) this.pipeGraph).setTestObject(null); return verifyList(list, node); } - - - public interface IComplexGraph, PT extends Enum & IPipeType> extends Graph, NetEdge> { - - void setTestObject(Object object); - } - - protected static class UndirectedLimitedGraph, PT extends Enum & IPipeType> - extends SimpleWeightedGraph, NetEdge> - implements IComplexGraph { - - final ThreadLocal testObject = new ThreadLocal<>(); - - public UndirectedLimitedGraph(Supplier supplier) { - super(null, supplier); - } - - @Override - public double getEdgeWeight(NetEdge netEdge) { - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - int limit = netEdge.getFlowLimit(testObject.get(), this, tick, null); - return limit > 0 && netEdge.getPredicate().test(testObject.get()) ? this.getEdgeWeight(netEdge) : Double.POSITIVE_INFINITY; - } - - @Override - public void setTestObject(Object object) { - this.testObject.set(object); - } - } - - protected static class DirectedLimitedGraph, PT extends Enum & IPipeType> - extends SimpleDirectedWeightedGraph, NetEdge> - implements IComplexGraph { - - final ThreadLocal testObject = new ThreadLocal<>(); - - - public DirectedLimitedGraph(Supplier supplier) { - super(null, supplier); - } - - @Override - public double getEdgeWeight(NetEdge netEdge) { - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - int limit = netEdge.getFlowLimit(testObject.get(), this, tick, null); - return limit > 0 && netEdge.getPredicate().test(testObject.get()) ? super.getEdgeWeight(netEdge) : Double.POSITIVE_INFINITY; - } - - @Override - public void setTestObject(Object object) { - this.testObject.set(object); - } - } } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java index caae19dead0..f0c8ef58c26 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java @@ -184,7 +184,8 @@ public List> getPaths(@Nullable NodeG> verifyList(List> list, NodeG source) { if (!verifyNode(source)) return new ObjectArrayList<>(); - return list.stream().filter(a -> verifyNode(a.getTargetNode())).collect(Collectors.toList()); + return list.stream().filter(a -> verifyNode(a.getTargetNode()) && a.getWeight() != Double.POSITIVE_INFINITY) + .collect(Collectors.toList()); } protected boolean verifyNode(NodeG node) { diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 903467ae2a6..fb3a914fd68 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -98,7 +98,7 @@ public NodeG getNode() { } @Override - protected void setWorldCreate(World worldIn) { + protected void setWorldCreate(@NotNull World worldIn) { this.setWorld(worldIn); } @@ -600,6 +600,7 @@ public boolean shouldRefresh(@NotNull World world, @NotNull BlockPos pos, @NotNu return true; } + @Deprecated public void doExplosion(float explosionPower) { getWorld().setBlockToAir(getPos()); if (!getWorld().isRemote) { diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 3595e0bc93b..ba5fb88027e 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -1,19 +1,43 @@ package gregtech.api.unification.material.properties; +import gregtech.api.GTValues; import gregtech.api.capability.IPropertyFluidFilter; +import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; +import gregtech.api.fluids.attribute.AttributedFluid; import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.util.EntityDamageUtil; +import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; + import it.unimi.dsi.fastutil.objects.Object2BooleanMap; import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraft.init.Blocks; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.Tuple; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.UnmodifiableView; import java.util.Collection; +import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.function.Consumer; public class FluidPipeProperties implements IMaterialProperty, IPropertyFluidFilter, INodeData { @@ -145,6 +169,135 @@ public int getChannelMaxCount() { return this.tanks; } + public PipeLossResult determineFluidPassthroughResult(@NotNull FluidStack stack, World world, BlockPos pos) { + Fluid fluid = stack.getFluid(); + + boolean burning = this.getMaxFluidTemperature() < fluid.getTemperature(stack); + boolean leaking = !this.isGasProof() && fluid.isGaseous(stack); + boolean shattering = !this.isCryoProof() && fluid.getTemperature() < FluidConstants.CRYOGENIC_FLUID_THRESHOLD; + boolean corroding = false; + boolean melting = false; + + if (fluid instanceof AttributedFluid attributedFluid) { + FluidState state = attributedFluid.getState(); + if (!this.canContain(state)) { + leaking = state == FluidState.GAS; + melting = state == FluidState.PLASMA; + } + + // carrying plasmas which are too hot when plasma proof does not burn pipes + if (burning && state == FluidState.PLASMA && this.canContain(FluidState.PLASMA)) { + burning = false; + } + + for (FluidAttribute attribute : attributedFluid.getAttributes()) { + if (!this.canContain(attribute)) { + // corrodes if the pipe can't handle the attribute, even if it's not an acid + corroding = true; + } + } + } + + if (burning || leaking || corroding || shattering || melting) { + return determineDestroyPipeResults(stack, burning, leaking, corroding, shattering, melting, world, pos); + } else return new PipeLossResult(n -> {}, 1d); + } + + public PipeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBurning, boolean isLeaking, + boolean isCorroding, boolean isShattering, + boolean isMelting, World world, BlockPos pos) { + List particleActions = new ObjectArrayList<>(); + Consumer damageAction = tile -> {}; + Runnable destructionAction = () -> {}; + double mult = 1; + + if (isLeaking) { + particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.SMOKE_NORMAL, 7 + GTValues.RNG.nextInt(2))); + + // voids 10% + mult *= 0.9; + + // apply heat damage in area surrounding the pipe + damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, stack.getFluid().getTemperature(stack), 2.0F, 10)); + + // chance to do a small explosion + if (GTValues.RNG.nextInt(isBurning ? 3 : 7) == 0) { + destructionAction = () -> world.setBlockToAir(pos); + if (!world.isRemote) { + particleActions.add(() -> ((WorldServer) world).spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.2, 0.2, 0.2, 0.0)); + } + particleActions.add(() -> world.createExplosion(null, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, + 1.0f + GTValues.RNG.nextFloat(), false)); + } + } + + if (isCorroding) { + particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.CRIT_MAGIC, 3 + GTValues.RNG.nextInt(2))); + + // voids 25% + mult *= 0.75; + + // apply chemical damage in area surrounding the pipe + damageAction = tile -> tile.dealDamage(1, entity -> EntityDamageUtil.applyChemicalDamage(entity, 2)); + + // 1/10 chance to void everything and destroy the pipe + if (GTValues.RNG.nextInt(10) == 0) { + mult = 0; + destructionAction = () -> world.setBlockToAir(pos); + } + } + + if (isBurning || isMelting) { + particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.FLAME, (isMelting ? 7 : 3) + GTValues.RNG.nextInt(2))); + + // voids 75% + mult *= 0.25; + + // 1/4 chance to burn everything around it + if (GTValues.RNG.nextInt(4) == 0) { + TileEntityFluidPipe.setNeighboursToFire(world, pos); + } + + // apply heat damage in area surrounding the pipe + damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, stack.getFluid().getTemperature(stack), 2.0F, 10)); + + // 1/10 chance to void everything and burn the pipe + if (GTValues.RNG.nextInt(10) == 0) { + mult = 0; + destructionAction = () -> world.setBlockState(pos, Blocks.FIRE.getDefaultState()); + } + } + + if (isShattering) { + particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2))); + + // voids 75% + mult *= 0.75; + + // apply frost damage in area surrounding the pipe + damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, stack.getFluid().getTemperature(stack), 2.0F, 10)); + + // 1/10 chance to void everything and freeze the pipe + if (GTValues.RNG.nextInt(10) == 0) { + mult = 0; + destructionAction = () -> world.setBlockState(pos, Blocks.ICE.getDefaultState()); + } + } + Runnable finalDestructionAction = destructionAction; + Consumer finalDamageAction = damageAction; + return new PipeLossResult(nodeG -> { + // only do 'extra' actions if the node already holds its MTE. + // don't go fetch it from the world as this 9 times out of 10 means loading a chunk unnecessarily. + IPipeTile tile = nodeG.getHeldMTEUnsafe(); + if (tile instanceof TileEntityFluidPipe pipe) { + pipe.playDamageSound(); + particleActions.forEach(Runnable::run); + finalDamageAction.accept(pipe); + } + finalDestructionAction.run(); + }, mult); + } + @Override public FluidPipeProperties getMinData(Set datas) { int maxFluidTemperature = this.getMaxFluidTemperature(); @@ -195,4 +348,19 @@ public String toString() { ", containmentPredicate=" + containmentPredicate + '}'; } + + public static class PipeLossResult extends Tuple>, Double> { + + public PipeLossResult(Consumer> postAction, Double lossFunction) { + super(postAction, lossFunction); + } + + public Consumer> getPostAction() { + return this.getFirst(); + } + + public Double getLossFunction() { + return this.getSecond(); + } + } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java index c0fcec54f7a..c192d8a134a 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java @@ -134,6 +134,7 @@ public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @No TileEntityFluidPipe pipe = (TileEntityFluidPipe) getPipeTileEntity(worldIn, pos); if (pipe.getFrameMaterial() == null && pipe.getOffsetTimer() % 10 == 0) { if (entityIn instanceof EntityLivingBase) { + // TODO detection for what fluids have flowed through a pipe recently if (pipe.getFluidTanks().length > 1) { // apply temperature damage for the hottest and coldest pipe (multi fluid pipes) int maxTemperature = Integer.MIN_VALUE; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java index ebed465fd71..cff06562b02 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java @@ -11,6 +11,7 @@ import gregtech.common.pipelike.fluidpipe.FluidPipeType; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.nbt.NBTTagCompound; @@ -25,6 +26,7 @@ import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.function.Consumer; @@ -38,7 +40,9 @@ public class FluidNetHandler implements IFluidHandler, IPipeNetHandler { private final IFluidHandler testHandler = new FluidTank(Integer.MAX_VALUE); - private NetEdge.ChannelSimulator simulator; + private NetEdge.ChannelSimulatorKey simulatorKey; + private FluidStack lastFillResource; + private final Map, FluidPipeProperties.PipeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); public FluidNetHandler(WorldFluidPipeNet net, TileEntityFluidPipe pipe, EnumFacing facing) { this.net = net; @@ -70,14 +74,21 @@ public IFluidTankProperties[] getTankProperties() { public int fill(FluidStack resource, boolean doFill) { if (net == null || pipe == null || pipe.isInvalid() || pipe.isFaceBlocked(facing)) return 0; + if (!resource.isFluidStackIdentical(this.lastFillResource)) { + // cache needs to persist through the entire 'try with doFill false then try with doFill true' process, + // but should not persist into a new fill attempt. + this.lossResultCache.clear(); + this.lastFillResource = resource.copy(); + } + FluidTestObject testObject = new FluidTestObject(resource); long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); // push flow through net List> paths = this.getNet().getPaths(pipe, testObject); FluidStack helper = resource.copy(); - if (!doFill) this.simulator = NetEdge.getNewSimulatorInstance(); - else this.simulator = null; + if (!doFill) this.simulatorKey = NetEdge.getNewSimulatorInstance(); + else this.simulatorKey = null; mainloop: for (NetPath path : paths) { for (Iterator it = path.getFacingIterator(); it.hasNext(); ) { @@ -87,7 +98,11 @@ public int fill(FluidStack resource, boolean doFill) { if (helper.amount <= 0) break mainloop; } } - if (!doFill) this.simulator = null; + if (!doFill) this.simulatorKey = null; + if (doFill && !this.lossResultCache.isEmpty()) { + this.lossResultCache.forEach((k, v) -> v.getPostAction().accept(k)); + this.lossResultCache.clear(); + } return resource.amount - helper.amount; } @@ -180,20 +195,22 @@ private int fill(NetPath.FacedNetPath routeP // iterate through path List> nodeList = routePath.getNodeList(); List edgeList = routePath.getEdgeList(); - List> flowLimitConsumers = new ObjectArrayList<>(); + List flowLimitConsumers = new ObjectArrayList<>(); int inputAmount = resource.amount; int outputAmount = resource.amount; // always 1 less edge than nodes for (int i = 0; i < edgeList.size(); i++) { - NodeG source = nodeList.get(i); - NodeG target = nodeList.get(i + 1); NetEdge edge = edgeList.get(i); - int flow = Math.min(edge.getFlowLimit(testObject, getNet().getGraph(), tick, simulator), outputAmount); + if (!edge.getPredicate().test(resource)) return 0; + int flow = Math.min(edge.getFlowLimit(testObject, getNet().getGraph(), tick, simulatorKey), outputAmount); double ratio = (double) flow / outputAmount; inputAmount *= ratio; - flowLimitConsumers.add(finalRatio -> - edge.consumeFlowLimit(testObject, getNet().getGraph(), (int) (finalRatio * flow), tick, simulator)); - double loss = 1; // TODO fluid loss & pipe damage + flowLimitConsumers.forEach(c -> c.modifyRatio(ratio)); + flowLimitConsumers.add(new FlowConsumer(edge, testObject, flow, tick)); + // TODO undo loss when backflowing +// var sourceResult = getOrGenerateLossResult(nodeList.get(i), resource); + var targetResult = getOrGenerateLossResult(nodeList.get(i + 1), resource); + double loss = targetResult.getLossFunction(); outputAmount = (int) (flow * loss); } // outputAmount is currently the maximum flow to the endpoint, and inputAmount is the requisite flow into the net @@ -234,7 +251,43 @@ public FluidStack drain(int maxDrain, boolean doDrain) { return null; } - protected static class FluidTestObject { + protected FluidPipeProperties.PipeLossResult getOrGenerateLossResult(NodeG node, + FluidStack resource) { + var cachedResult = this.lossResultCache.get(node); + if (cachedResult == null) { + cachedResult = node.getData().determineFluidPassthroughResult(resource, net.getWorld(), node.getNodePos()); + this.lossResultCache.put(node, cachedResult); + } + return cachedResult; + } + + protected final class FlowConsumer implements Consumer { + + private final NetEdge edge; + private final FluidTestObject testObject; + private final int flow; + private final long tick; + + private double ratio = 1; + + public FlowConsumer(NetEdge edge, FluidTestObject testObject, int flow, long tick) { + this.edge = edge; + this.testObject = testObject; + this.flow = flow; + this.tick = tick; + } + + public void modifyRatio(Double ratio) { + this.ratio *= ratio; + } + + @Override + public void accept(Double finalRatio) { + edge.consumeFlowLimit(testObject, getNet().getGraph(), (int) (finalRatio * ratio * flow), tick, simulatorKey); + } + } + + public static final class FluidTestObject { public final Fluid fluid; public final NBTTagCompound tag; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java index b44c36fd78e..e31573c1373 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java @@ -1,64 +1,41 @@ package gregtech.common.pipelike.fluidpipe.tile; import gregtech.api.GTValues; -import gregtech.api.fluids.FluidConstants; -import gregtech.api.fluids.FluidState; -import gregtech.api.fluids.attribute.AttributedFluid; -import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.metatileentity.IDataInfoProvider; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; -import gregtech.api.util.EntityDamageUtil; -import gregtech.api.util.TextFormattingUtil; import gregtech.common.pipelike.fluidpipe.FluidPipeType; import gregtech.common.pipelike.fluidpipe.net.FluidNetHandler; import gregtech.common.pipelike.fluidpipe.net.PipeTankList; import gregtech.common.pipelike.fluidpipe.net.WorldFluidPipeNet; -import gregtech.common.pipelike.itempipe.net.ItemNetHandler; - -import gregtech.common.pipelike.itempipe.net.WorldItemPipeNet; - -import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.init.Blocks; import net.minecraft.init.SoundEvents; -import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.SoundCategory; -import net.minecraft.util.Tuple; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.Style; -import net.minecraft.util.text.TextComponentTranslation; -import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fml.common.FMLCommonHandler; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemStackHandler; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.EnumMap; import java.util.List; +import java.util.function.Consumer; public class TileEntityFluidPipe extends TileEntityMaterialPipeBase { @@ -73,7 +50,8 @@ public class TileEntityFluidPipe extends TileEntityMaterialPipeBase tileE } public void checkAndDestroy(@NotNull FluidStack stack) { - var result = determineFluidPassthroughResult(stack.copy(), world, pos); - stack.amount *= result.getSecond(); - result.getFirst().run(); - } - - public Tuple determineFluidPassthroughResult(@NotNull FluidStack stack, World world, BlockPos pos) { - Fluid fluid = stack.getFluid(); - FluidPipeProperties prop = getNodeData(); - - boolean burning = prop.getMaxFluidTemperature() < fluid.getTemperature(stack); - boolean leaking = !prop.isGasProof() && fluid.isGaseous(stack); - boolean shattering = !prop.isCryoProof() && fluid.getTemperature() < FluidConstants.CRYOGENIC_FLUID_THRESHOLD; - boolean corroding = false; - boolean melting = false; - - if (fluid instanceof AttributedFluid attributedFluid) { - FluidState state = attributedFluid.getState(); - if (!prop.canContain(state)) { - leaking = state == FluidState.GAS; - melting = state == FluidState.PLASMA; - } - - // carrying plasmas which are too hot when plasma proof does not burn pipes - if (burning && state == FluidState.PLASMA && prop.canContain(FluidState.PLASMA)) { - burning = false; - } - - for (FluidAttribute attribute : attributedFluid.getAttributes()) { - if (!prop.canContain(attribute)) { - // corrodes if the pipe can't handle the attribute, even if it's not an acid - corroding = true; - } - } - } - - if (burning || leaking || corroding || shattering || melting) { - return determineDestroyPipeResults(stack, burning, leaking, corroding, shattering, melting, world, pos); - } else return new Tuple<>(() -> {}, 1d); + var result = getNodeData().determineFluidPassthroughResult(stack.copy(), world, pos); + stack.amount *= result.getLossFunction(); + result.getPostAction().accept(this.getNode()); } public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, boolean isCorroding, boolean isShattering, boolean isMelting) { - var result = determineDestroyPipeResults(stack, isBurning, isLeaking, isCorroding, isShattering, isMelting, world, pos); - stack.amount *= result.getSecond(); - result.getFirst().run(); + var result = getNodeData().determineDestroyPipeResults(stack, isBurning, isLeaking, isCorroding, isShattering, isMelting, world, pos); + stack.amount *= result.getLossFunction(); + result.getPostAction().accept(this.getNode()); } - public Tuple determineDestroyPipeResults(FluidStack stack, boolean isBurning, boolean isLeaking, - boolean isCorroding, boolean isShattering, - boolean isMelting, World world, BlockPos pos) { - Runnable postAction = () -> {}; - double mult = 1; - // prevent the sound from spamming when filled from anything not a pipe - if (getOffsetTimer() >= lastSoundTime + 10) { - world.playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); - lastSoundTime = getOffsetTimer() + 10; + public void playDamageSound() { + long timer = getOffsetTimer(); + if (timer >= this.nextSoundTime) { + getPipeWorld().playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); + this.nextSoundTime = timer + 20; } + } - if (isLeaking) { - TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.SMOKE_NORMAL, - 7 + GTValues.RNG.nextInt(2)); - - // voids 10% - mult *= 0.9; - - // apply heat damage in area surrounding the pipe - if (getOffsetTimer() % 20 == 0) { - List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, - new AxisAlignedBB(getPipePos()).grow(2)); - for (EntityLivingBase entityLivingBase : entities) { - EntityDamageUtil.applyTemperatureDamage(entityLivingBase, stack.getFluid().getTemperature(stack), - 2.0F, 10); - } - } - - // chance to do a small explosion - if (GTValues.RNG.nextInt(isBurning ? 3 : 7) == 0) { - this.doExplosion(1.0f + GTValues.RNG.nextFloat()); - } - } - - if (isCorroding) { - TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.CRIT_MAGIC, - 3 + GTValues.RNG.nextInt(2)); - - // voids 25% - mult *= 0.75; - - // apply chemical damage in area surrounding the pipe - if (getOffsetTimer() % 20 == 0) { - List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, - new AxisAlignedBB(getPipePos()).grow(1)); - for (EntityLivingBase entityLivingBase : entities) { - EntityDamageUtil.applyChemicalDamage(entityLivingBase, 2); - } - } - - // 1/10 chance to void everything and destroy the pipe - if (GTValues.RNG.nextInt(10) == 0) { - mult = 0; - postAction = () -> world.setBlockToAir(pos); - } - } - - if (isBurning || isMelting) { - TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.FLAME, - (isMelting ? 7 : 3) + GTValues.RNG.nextInt(2)); - - // voids 75% - mult *= 0.25; - - // 1/4 chance to burn everything around it - if (GTValues.RNG.nextInt(4) == 0) { - TileEntityFluidPipe.setNeighboursToFire(world, pos); - } - - // apply heat damage in area surrounding the pipe - if (isMelting && getOffsetTimer() % 20 == 0) { - List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, - new AxisAlignedBB(getPipePos()).grow(2)); - for (EntityLivingBase entityLivingBase : entities) { - EntityDamageUtil.applyTemperatureDamage(entityLivingBase, stack.getFluid().getTemperature(stack), - 2.0F, 10); - } - } - - // 1/10 chance to void everything and burn the pipe - if (GTValues.RNG.nextInt(10) == 0) { - mult = 0; - postAction = () -> world.setBlockState(pos, Blocks.FIRE.getDefaultState()); - } - } - - if (isShattering) { - TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.CLOUD, - 3 + GTValues.RNG.nextInt(2)); - - // voids 75% - mult *= 0.75; - - // apply frost damage in area surrounding the pipe - if (getOffsetTimer() % 20 == 0) { - List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, - new AxisAlignedBB(getPipePos()).grow(2)); - for (EntityLivingBase entityLivingBase : entities) { - EntityDamageUtil.applyTemperatureDamage(entityLivingBase, stack.getFluid().getTemperature(stack), - 2.0F, 10); - } - } - - // 1/10 chance to void everything and freeze the pipe - if (GTValues.RNG.nextInt(10) == 0) { - mult = 0; - postAction = () -> world.setBlockToAir(pos); - } + public void dealDamage(int size, Consumer damageFunction) { + long timer = getOffsetTimer(); + if (timer >= this.nextDamageTime) { + List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(getPipePos()).grow(size)); + entities.forEach(damageFunction); + this.nextDamageTime = timer + 20; } - return new Tuple<>(postAction, mult); } public FluidStack getContainedFluid(int channel) { From f9e18d75e0276fa48636181864e5c63d73357c98 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 19 Jun 2024 12:33:03 -0600 Subject: [PATCH 060/157] The Great Generification (and spotless) --- .../api/block/machines/MachineItemBlock.java | 9 +- .../gregtech/api/cover/CoverRayTracer.java | 2 +- .../multiblock/MultiblockControllerBase.java | 3 +- .../api/pipenet/AbstractEdgePredicate.java | 8 + .../api/pipenet/AbstractGroupData.java | 4 +- .../api/pipenet/FilteredEdgePredicate.java | 1 - .../gregtech/api/pipenet/IPipeNetHandler.java | 4 +- .../java/gregtech/api/pipenet/IRoutePath.java | 41 -- .../java/gregtech/api/pipenet/NetEdge.java | 262 --------- .../java/gregtech/api/pipenet/NetGroup.java | 94 ++-- .../api/pipenet/{NodeG.java => NetNode.java} | 54 +- .../java/gregtech/api/pipenet/NetPath.java | 46 +- src/main/java/gregtech/api/pipenet/Node.java | 42 -- .../java/gregtech/api/pipenet/PipeNet.java | 481 ---------------- .../gregtech/api/pipenet/PipeNetWalker.java | 256 --------- .../gregtech/api/pipenet/WorldPipeNet.java | 177 ------ .../api/pipenet/WorldPipeNetBase.java | 529 ++++++++++++++++++ .../api/pipenet/WorldPipeNetComplex.java | 41 +- .../api/pipenet/WorldPipeNetSimple.java | 525 +---------------- .../api/pipenet/alg/INetAlgorithm.java | 17 +- .../pipenet/alg/ShortestPathsAlgorithm.java | 20 +- .../api/pipenet/alg/SinglePathAlgorithm.java | 28 +- .../gregtech/api/pipenet/block/BlockPipe.java | 101 ++-- .../api/pipenet/block/ItemBlockPipe.java | 4 +- .../block/material/BlockMaterialPipe.java | 21 +- .../block/material/IMaterialPipeTile.java | 5 +- .../block/material/ItemBlockMaterialPipe.java | 4 +- .../material/TileEntityMaterialPipeBase.java | 19 +- .../pipenet/block/simple/BlockSimplePipe.java | 15 +- .../pipenet/block/simple/EmptyNodeData.java | 13 - .../api/pipenet/edge/INetFlowEdge.java | 42 ++ .../gregtech/api/pipenet/edge/NetEdge.java | 114 ++++ .../api/pipenet/edge/NetFlowEdge.java | 157 ++++++ .../api/pipenet/edge/util/FlowConsumer.java | 44 ++ .../pipenet/longdist/LongDistanceNetwork.java | 4 +- .../tickable/TickableWorldPipeNet.java | 145 ----- .../TickableWorldPipeNetEventHandler.java | 56 -- .../gregtech/api/pipenet/tile/IPipeTile.java | 13 +- .../tile/PipeCoverableImplementation.java | 6 +- .../api/pipenet/tile/TileEntityPipeBase.java | 49 +- .../properties/FluidPipeProperties.java | 53 +- .../gregtech/api/util/FluidTestObject.java | 31 + .../client/renderer/pipe/CableRenderer.java | 7 +- .../renderer/pipe/FluidPipeRenderer.java | 4 +- .../renderer/pipe/ItemPipeRenderer.java | 4 +- .../renderer/pipe/LaserPipeRenderer.java | 5 +- .../renderer/pipe/OpticalPipeRenderer.java | 5 +- .../client/renderer/pipe/PipeRenderer.java | 25 +- .../java/gregtech/common/EventHandlers.java | 2 +- .../gregtech/common/ToolEventHandlers.java | 7 +- .../gregtech/common/blocks/BlockFrame.java | 18 +- .../common/command/CommandRecipeCheck.java | 2 +- .../filter/oreglob/impl/NodeInterpreter.java | 2 +- .../filter/oreglob/impl/NodeOreGlob.java | 2 +- .../items/behaviors/ColorSprayBehaviour.java | 9 +- .../items/behaviors/TricorderBehavior.java | 6 +- .../MetaTileEntityMonitorScreen.java | 2 +- .../common/pipelike/cable/BlockCable.java | 11 +- .../common/pipelike/cable/ItemBlockCable.java | 2 +- .../pipelike/cable/net/EnergyNetHandler.java | 11 +- .../pipelike/cable/net/WorldEnergyNet.java | 3 +- .../pipelike/cable/tile/TileEntityCable.java | 3 +- .../pipelike/fluidpipe/BlockFluidPipe.java | 15 +- .../fluidpipe/ItemBlockFluidPipe.java | 2 +- .../fluidpipe/net/FluidNetHandler.java | 127 ++--- .../fluidpipe/net/WorldFluidPipeNet.java | 12 +- .../fluidpipe/tile/TileEntityFluidPipe.java | 9 +- .../pipelike/itempipe/BlockItemPipe.java | 11 +- .../pipelike/itempipe/ItemBlockItemPipe.java | 2 +- .../pipelike/itempipe/net/ItemNetHandler.java | 40 +- .../itempipe/net/WorldItemPipeNet.java | 4 +- .../itempipe/tile/TileEntityItemPipe.java | 5 +- .../common/pipelike/laser/BlockLaserPipe.java | 19 +- .../pipelike/laser/ItemBlockLaserPipe.java | 3 +- .../pipelike/laser/net/LaserNetHandler.java | 10 +- .../pipelike/laser/net/WorldLaserPipeNet.java | 4 +- .../laser/tile/TileEntityLaserPipe.java | 7 +- .../pipelike/optical/BlockOpticalPipe.java | 19 +- .../optical/net/OpticalNetHandler.java | 11 +- .../optical/net/WorldOpticalPipeNet.java | 4 +- .../optical/tile/TileEntityOpticalPipe.java | 7 +- .../debug/DebugPipeNetInfoProvider.java | 28 +- 82 files changed, 1461 insertions(+), 2548 deletions(-) delete mode 100644 src/main/java/gregtech/api/pipenet/IRoutePath.java delete mode 100644 src/main/java/gregtech/api/pipenet/NetEdge.java rename src/main/java/gregtech/api/pipenet/{NodeG.java => NetNode.java} (79%) delete mode 100644 src/main/java/gregtech/api/pipenet/Node.java delete mode 100644 src/main/java/gregtech/api/pipenet/PipeNet.java delete mode 100644 src/main/java/gregtech/api/pipenet/PipeNetWalker.java delete mode 100644 src/main/java/gregtech/api/pipenet/WorldPipeNet.java create mode 100644 src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java delete mode 100644 src/main/java/gregtech/api/pipenet/block/simple/EmptyNodeData.java create mode 100644 src/main/java/gregtech/api/pipenet/edge/INetFlowEdge.java create mode 100644 src/main/java/gregtech/api/pipenet/edge/NetEdge.java create mode 100644 src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java create mode 100644 src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java delete mode 100644 src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java delete mode 100644 src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java create mode 100644 src/main/java/gregtech/api/util/FluidTestObject.java diff --git a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java index d8fb09dcc19..80bb7c71331 100644 --- a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java +++ b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java @@ -5,7 +5,6 @@ import gregtech.api.metatileentity.ITieredMetaTileEntity; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.util.GTUtility; import gregtech.api.util.LocalizationUtils; import gregtech.client.utils.TooltipHelper; @@ -96,11 +95,9 @@ public boolean placeBlockAt(@NotNull ItemStack stack, @NotNull EntityPlayer play if (superVal && !world.isRemote) { BlockPos possiblePipe = pos.offset(side.getOpposite()); Block block = world.getBlockState(possiblePipe).getBlock(); - if (block instanceof BlockPipe) { - IPipeTile pipeTile = ((BlockPipe) block).getPipeTileEntity(world, possiblePipe); - if (pipeTile != null && ((BlockPipe) block).canPipeConnectToBlock(pipeTile, side.getOpposite(), - world.getTileEntity(pos))) { - pipeTile.setConnection(side, true, false); + if (block instanceof BlockPipepipe) { + if (pipe.canPipeConnectToBlock(world, possiblePipe, side.getOpposite(), world.getTileEntity(pos))) { + pipe.getPipeTileEntity(world, possiblePipe).setConnection(side, true, false); } } } diff --git a/src/main/java/gregtech/api/cover/CoverRayTracer.java b/src/main/java/gregtech/api/cover/CoverRayTracer.java index e44588d4dc3..e8507cb7665 100644 --- a/src/main/java/gregtech/api/cover/CoverRayTracer.java +++ b/src/main/java/gregtech/api/cover/CoverRayTracer.java @@ -20,7 +20,7 @@ private CoverRayTracer() {} @NotNull EntityPlayer player) { // if the coverable view is from a blockpipe, use the proper raytrace method RayTraceResult result = coverableView.getWorld().getBlockState(coverableView.getPos()) - .getBlock() instanceof BlockPipepipe ? + .getBlock() instanceof BlockPipepipe ? pipe.getServerCollisionRayTrace(player, coverableView.getPos(), coverableView.getWorld()) : RayTracer.retraceBlock(coverableView.getWorld(), player, coverableView.getPos()); if (result == null || result.typeOfHit != RayTraceResult.Type.BLOCK) { diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java index 54b5bd45b5c..c24c471ae58 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java @@ -240,10 +240,9 @@ public static TraceabilityPredicate frames(Material... frameMaterials) { .toArray(IBlockState[]::new)) .or(new TraceabilityPredicate(blockWorldState -> { TileEntity tileEntity = blockWorldState.getTileEntity(); - if (!(tileEntity instanceof IPipeTile)) { + if (!(tileEntity instanceof IPipeTilepipeTile)) { return false; } - IPipeTile pipeTile = (IPipeTile) tileEntity; return ArrayUtils.contains(frameMaterials, pipeTile.getFrameMaterial()); })); } diff --git a/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java b/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java index 5cc781d36cf..921e7d298d3 100644 --- a/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java @@ -27,6 +27,14 @@ public void setPosInfo(BlockPos sourcePos, BlockPos targetPos) { protected abstract String predicateName(); + public BlockPos getSourcePos() { + return sourcePos; + } + + public BlockPos getTargetPos() { + return targetPos; + } + private static Supplier> getSupplier(String identifier) { return PREDICATE_SUPPLIERS.getOrDefault(identifier, () -> null); } diff --git a/src/main/java/gregtech/api/pipenet/AbstractGroupData.java b/src/main/java/gregtech/api/pipenet/AbstractGroupData.java index 20201723882..b3ba32072f2 100644 --- a/src/main/java/gregtech/api/pipenet/AbstractGroupData.java +++ b/src/main/java/gregtech/api/pipenet/AbstractGroupData.java @@ -5,9 +5,9 @@ public abstract class AbstractGroupData & IPipeType, NodeDataType extends INodeData> { - protected NetGroup group; + protected NetGroup group; - public AbstractGroupData withGroup(NetGroup group) { + public AbstractGroupData withGroup(NetGroup group) { this.group = group; return this; } diff --git a/src/main/java/gregtech/api/pipenet/FilteredEdgePredicate.java b/src/main/java/gregtech/api/pipenet/FilteredEdgePredicate.java index 1981c19aa29..d485253a1bb 100644 --- a/src/main/java/gregtech/api/pipenet/FilteredEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/FilteredEdgePredicate.java @@ -3,7 +3,6 @@ import gregtech.api.util.IDirtyNotifiable; import gregtech.common.covers.filter.BaseFilterContainer; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import org.jetbrains.annotations.Contract; diff --git a/src/main/java/gregtech/api/pipenet/IPipeNetHandler.java b/src/main/java/gregtech/api/pipenet/IPipeNetHandler.java index 7fd8c5a7b0f..ef9400c3f62 100644 --- a/src/main/java/gregtech/api/pipenet/IPipeNetHandler.java +++ b/src/main/java/gregtech/api/pipenet/IPipeNetHandler.java @@ -10,12 +10,12 @@ public interface IPipeNetHandler { - WorldPipeNetSimple getNet(); + WorldPipeNetBase getNet(); EnumFacing getFacing(); default Cover getCoverOnNeighbour(BlockPos pos, EnumFacing facing) { - NodeG node = getNet().getNode(pos); + NetNode node = getNet().getNode(pos); if (node != null) { TileEntity tile = node.getConnnected(facing); if (tile != null) { diff --git a/src/main/java/gregtech/api/pipenet/IRoutePath.java b/src/main/java/gregtech/api/pipenet/IRoutePath.java deleted file mode 100644 index 166e5b8f39a..00000000000 --- a/src/main/java/gregtech/api/pipenet/IRoutePath.java +++ /dev/null @@ -1,41 +0,0 @@ -package gregtech.api.pipenet; - -import gregtech.api.pipenet.tile.IPipeTile; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraftforge.common.capabilities.Capability; - -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -@Deprecated -@ApiStatus.ScheduledForRemoval(inVersion = "2.9") -public interface IRoutePath> { - - @NotNull - T getTargetPipe(); - - @NotNull - default BlockPos getTargetPipePos() { - return getTargetPipe().getPipePos(); - } - - @NotNull - EnumFacing getTargetFacing(); - - int getDistance(); - - @Nullable - default TileEntity getTargetTileEntity() { - return getTargetPipe().getNeighbor(getTargetFacing()); - } - - @Nullable - default I getTargetCapability(Capability capability) { - TileEntity tile = getTargetTileEntity(); - return tile == null ? null : tile.getCapability(capability, getTargetFacing().getOpposite()); - } -} diff --git a/src/main/java/gregtech/api/pipenet/NetEdge.java b/src/main/java/gregtech/api/pipenet/NetEdge.java deleted file mode 100644 index cecfa5152ee..00000000000 --- a/src/main/java/gregtech/api/pipenet/NetEdge.java +++ /dev/null @@ -1,262 +0,0 @@ -package gregtech.api.pipenet; - -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.util.function.QuadConsumer; - -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.common.util.INBTSerializable; - -import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; -import org.jgrapht.graph.DefaultWeightedEdge; - -import java.util.List; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.function.Predicate; - -public final class NetEdge extends DefaultWeightedEdge implements INBTSerializable { - - private AbstractEdgePredicate predicate; - private boolean invertedPredicate; - - @SuppressWarnings("unused") // used via reflection - public NetEdge() {} - - public void setPredicate(AbstractEdgePredicate predicate) { - this.predicate = predicate; - this.invertedPredicate = predicate.sourcePos != this.getSource().getNodePos(); - } - - public Predicate getPredicate() { - // if we don't have a predicate, just assume that we're good. - if (predicate == null) return (a) -> true; - return predicate; - } - - public boolean isPredicateInverted() { - return invertedPredicate; - } - - @Override - public NodeG getSource() { - return (NodeG) super.getSource(); - } - - @Override - public NodeG getTarget() { - return (NodeG) super.getTarget(); - } - - @SuppressWarnings("unchecked") - public & IPipeType, NDT extends INodeData> NodeG getCastSource() { - return (NodeG) getSource(); - } - - @SuppressWarnings("unchecked") - public & IPipeType, NDT extends INodeData> NodeG getCastTarget() { - return (NodeG) getTarget(); - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tag = new NBTTagCompound(); - tag.setLong("SourceLongPos", getSource().getLongPos()); - tag.setLong("TargetLongPos", getTarget().getLongPos()); - tag.setDouble("Weight", getWeight()); - if (predicate != null) tag.setTag("Predicate", AbstractEdgePredicate.toNBT(predicate)); - tag.setBoolean("InvertedPredicate", isPredicateInverted()); - return tag; - } - - /** - * Use {@link NBTBuilder} instead, this does nothing. - */ - @Override - @Deprecated - public void deserializeNBT(NBTTagCompound nbt) {} - - static final class NBTBuilder & IPipeType, - NodeDataType extends INodeData> implements INBTBuilder { - - private final NodeG node1; - private final NodeG node2; - private final AbstractEdgePredicate predicate; - private final double weight; - private final boolean buildable; - - private final QuadConsumer, NodeG, Double, AbstractEdgePredicate> edgeProducer; - - NBTBuilder(Map> longPosMap, NBTTagCompound tag, - QuadConsumer, NodeG, Double, AbstractEdgePredicate> edgeProducer) { - this.node1 = longPosMap.get(tag.getLong("SourceLongPos")); - this.node2 = longPosMap.get(tag.getLong("TargetLongPos")); - this.weight = tag.getDouble("Weight"); - this.predicate = AbstractEdgePredicate.nbtPredicate(tag.getCompoundTag("Predicate")); - if (predicate != null) { - if (tag.getBoolean("InvertedPredicate")) - this.predicate.setPosInfo(this.node2.getNodePos(), this.node1.getNodePos()); - else this.predicate.setPosInfo(this.node1.getNodePos(), this.node2.getNodePos()); - } - this.edgeProducer = edgeProducer; - this.buildable = node1 != null && node2 != null; - } - - @Override - public void build() { - if (buildable) { - edgeProducer.accept(node1, node2, weight, predicate); - } - } - } - - /// Flow behavior related code /// - - private int flowBufferTicks; - private ChannelsHolder channels; - private WeakHashMap simulatedChannels; - - private INodeData> minData; - - public NetEdge(int flowBufferTicks) { - this.flowBufferTicks = flowBufferTicks; - this.channels = new ChannelsHolder(); - this.simulatedChannels = new WeakHashMap<>(9); - } - - /** - * Claims a new, unique simulator instance for properly simulating flow edge limits without actually changing them. - *
- * This simulator must be discarded after use so that the garbage collector can clean up. - */ - public static ChannelSimulatorKey getNewSimulatorInstance() { - return new ChannelSimulatorKey(); - } - - private ChannelsHolder getChannels(@Nullable NetEdge.ChannelSimulatorKey simulator) { - if (simulator == null) return this.channels; - else { - ChannelsHolder channels = simulatedChannels.get(simulator); - if (channels == null) { - channels = new ChannelsHolder(this.channels); - simulatedChannels.put(simulator, channels); - } - return channels; - } - } - - private INodeData> getMinData() { - if (this.minData == null) this.minData = this.getCastSource().getData().getMinData(this.getCastTarget().getData()); - return this.minData; - } - - private int getAdjustedThroughput() { - return getMinData().getThroughput() * flowBufferTicks; - } - - private boolean cannotSupportChannel(Object channel, long queryTick, @Nullable NetEdge.ChannelSimulatorKey simulator) { - var channels = getChannels(simulator); - channels.recalculateFlowLimits(queryTick); - return channels.map.size() >= getMinData().getChannelMaxCount() && !channels.map.containsKey(channel); - } - - public & IPipeType, NDT extends INodeData> int getFlowLimit( - Object channel, Graph, NetEdge> graph, long queryTick, @Nullable NetEdge.ChannelSimulatorKey simulator) { - if (this.cannotSupportChannel(channel, queryTick, simulator)) { - return 0; - } - int limit = getChannels(simulator).map.getOrDefault(channel, getAdjustedThroughput()); - - NetEdge inverse = graph.getEdge(this.getCastTarget(), this.getCastSource()); - if (inverse != null && inverse != this) { - if (inverse.cannotSupportChannel(channel, queryTick, simulator)) return 0; - limit += inverse.getConsumedLimit(channel, queryTick, simulator); - } - - return limit; - } - - public & IPipeType, NDT extends INodeData> int getConsumedLimit( - Object channel, long queryTick, @Nullable NetEdge.ChannelSimulatorKey simulator) { - var channels = getChannels(simulator); - channels.recalculateFlowLimits(queryTick); - int limit = getAdjustedThroughput(); - return limit - channels.map.getOrDefault(channel, limit); - } - - public & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, Graph, NetEdge> graph, int amount, long queryTick, @Nullable NetEdge.ChannelSimulatorKey simulator) { - if (amount == 0) return; - var channels = getChannels(simulator); - channels.recalculateFlowLimits(queryTick); - - // check against reverse edge - NetEdge inverse = graph.getEdge(this.getCastTarget(), this.getCastSource()); - if (inverse != null && inverse != this) { - int inverseConsumed = inverse.getConsumedLimit(channel, queryTick, simulator); - if (inverseConsumed != 0) { - int toFreeUp = Math.min(inverseConsumed, amount); - inverse.consumeFlowLimit(channel, graph, -toFreeUp, queryTick, simulator); - if (toFreeUp == amount) return; - amount -= toFreeUp; - } - } - - int finalAmount = amount; - channels.map.compute(channel, (k, v) -> { - int d = getAdjustedThroughput(); - if (v == null) v = d; - v -= finalAmount; - if (v >= d) return null; - return v; - }); - } - - private final class ChannelsHolder { - public final Object2IntOpenHashMap map; - public long lastQueryTick; - - public ChannelsHolder() { - this.map = new Object2IntOpenHashMap<>(9); - } - - public ChannelsHolder(ChannelsHolder prototype) { - this.map = prototype.map.clone(); - this.lastQueryTick = prototype.lastQueryTick; - } - - public void recalculateFlowLimits(long queryTick) { - int time = (int) (queryTick - this.lastQueryTick); - if (time < 0) { - this.map.clear(); - } else { - List toRemove = new ObjectArrayList<>(); - this.map.replaceAll((k, v) -> { - v += time * getMinData().getThroughput(); - if (v >= getAdjustedThroughput()) toRemove.add(k); - return v; - }); - toRemove.forEach(this.map::removeInt); - } - this.lastQueryTick = queryTick; - } - } - - public static final class ChannelSimulatorKey { - private static int ID; - private final int id; - private ChannelSimulatorKey() { - this.id = ID++; - } - - @Override - public int hashCode() { - // enforcing hash uniqueness improves weak map performance - return id; - } - } -} diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index d7407c45517..55b44ab7c2a 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -1,6 +1,7 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.INBTSerializable; @@ -15,25 +16,26 @@ import java.util.stream.Collectors; public class NetGroup & IPipeType, - NodeDataType extends INodeData> implements INBTSerializable { + NodeDataType extends INodeData, E extends NetEdge> implements INBTSerializable { - public final WorldPipeNetSimple net; + public final WorldPipeNetBase net; - private final Graph, NetEdge> graph; + private final Graph, E> graph; - private final Set> nodes; + private final Set> nodes; private final AbstractGroupData data; - public NetGroup(Graph, NetEdge> graph, WorldPipeNetSimple net) { + public NetGroup(Graph, E> graph, + WorldPipeNetBase net) { this.graph = graph; this.nodes = new ObjectOpenHashSet<>(); this.net = net; this.data = net.getBlankGroupData(); } - public NetGroup(Graph, NetEdge> graph, WorldPipeNetSimple net, - Set> nodes) { + public NetGroup(Graph, E> graph, WorldPipeNetBase net, + Set> nodes) { this.graph = graph; this.nodes = nodes; this.net = net; @@ -45,13 +47,13 @@ private void clear() { this.nodes.clear(); } - protected void addNode(NodeG node) { + protected void addNode(NetNode node) { this.nodes.add(node); node.setGroup(this); this.connectionChange(node); } - protected void addNodes(Set> nodes) { + protected void addNodes(Set> nodes) { this.nodes.addAll(nodes); nodes.forEach(a -> { a.setGroup(this); @@ -60,14 +62,14 @@ protected void addNodes(Set> nodes) { } @SafeVarargs - protected final void addNodes(NodeG... nodes) { - for (NodeG node : nodes) { + protected final void addNodes(NetNode... nodes) { + for (NetNode node : nodes) { this.addNode(node); this.connectionChange(node); } } - public void connectionChange(NodeG node) { + public void connectionChange(NetNode node) { // TODO simplify path search by only checking nodes that have connections // use net's connection capabilities } @@ -78,9 +80,12 @@ public void connectionChange(NodeG node) { * @param source the source node of the edge * @param target the target node of the edge */ - public static void mergeEdge(NodeG source, NodeG target) { - NetGroup sourceGroup = source.getGroupUnsafe(); - NetGroup targetGroup = target.getGroupUnsafe(); + public static & IPipeType, + NDT extends INodeData, E extends NetEdge> void mergeEdge( + NetNode source, + NetNode target) { + NetGroup sourceGroup = source.getGroupUnsafe(); + NetGroup targetGroup = target.getGroupUnsafe(); if (sourceGroup == targetGroup) { if (sourceGroup == null) { sourceGroup = source.getGroupSafe(); @@ -97,13 +102,12 @@ public static void mergeEdge(NodeG source, NodeG target) { } } - protected void mergeNode(NodeG node) { - NodeG cast = (NodeG) node; - NetGroup group = cast.getGroupUnsafe(); + protected void mergeNode(NetNode node) { + NetGroup group = node.getGroupUnsafe(); if (group != null) { this.addNodes(group.getNodes()); group.clear(); - } else addNode(cast); + } else addNode(node); this.clearCaches(); } @@ -113,27 +117,26 @@ protected void mergeNode(NodeG node) { * @param source node to remove * @return Whether the node existed in the graph */ - public boolean splitNode(NodeG source) { + public boolean splitNode(NetNode source) { if (this.graph.containsVertex(source)) { this.clearCaches(); - List> targets = graph.outgoingEdgesOf(source).stream().map(a -> { + List> targets = graph.outgoingEdgesOf(source).stream().map(a -> { // handling so undirected graphs don't throw an error - if (net.isDirected()) return a.getTarget(); - if (a.getTarget().getNodePos() != source.getNodePos()) return a.getTarget(); + if (net.isDirected() || a.getTarget().getNodePos() != source.getNodePos()) return a.getTarget(); return a.getSource(); }).collect(Collectors.toList()); this.graph.removeVertex(source); this.nodes.remove(source); while (!targets.isEmpty()) { - // get the lastmost target; if this throws a cast exception, something is very wrong with the graph. + // get the last target; if this throws a cast exception, something is very wrong with the graph. @SuppressWarnings("unchecked") - NodeG target = (NodeG) targets + NetNode target = (NetNode) targets .remove(targets.size() - 1); - Set> targetGroup = new ObjectOpenHashSet<>(); - BreadthFirstIterator, NetEdge> i = new BreadthFirstIterator<>(graph, + Set> targetGroup = new ObjectOpenHashSet<>(); + BreadthFirstIterator, E> i = new BreadthFirstIterator<>(graph, target); - NodeG temp; + NetNode temp; while (i.hasNext()) { temp = i.next(); targetGroup.add(temp); @@ -157,12 +160,12 @@ public boolean splitNode(NodeG source) { * @param target target of the edge * @return Whether the edge existed in the graph */ - public boolean splitEdge(NodeG source, NodeG target) { + public boolean splitEdge(NetNode source, NetNode target) { if (graph.removeEdge(source, target) != null) { this.clearCaches(); - Set> targetGroup = new ObjectOpenHashSet<>(); - BreadthFirstIterator, NetEdge> i = new BreadthFirstIterator<>(graph, target); - NodeG temp; + Set> targetGroup = new ObjectOpenHashSet<>(); + BreadthFirstIterator, E> i = new BreadthFirstIterator<>(graph, target); + NetNode temp; while (i.hasNext()) { temp = i.next(); // if there's a another complete path to the source node from the target node, there's no need to split @@ -181,15 +184,15 @@ public boolean splitEdge(NodeG source, NodeG> getNodes() { + public Set> getNodes() { return nodes; } protected void clearCaches() { - this.nodes.forEach(NodeG::clearPathCache); + this.nodes.forEach(NetNode::clearPathCache); } - public Graph, NetEdge> getGraph() { + public Graph, E> getGraph() { return graph; } @@ -201,7 +204,7 @@ public AbstractGroupData getData() { public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); int i = 0; - for (NodeG node : this.nodes) { + for (NetNode node : this.nodes) { tag.setLong(String.valueOf(i), node.getLongPos()); i++; } @@ -216,18 +219,19 @@ public NBTTagCompound serializeNBT() { @Deprecated public void deserializeNBT(NBTTagCompound nbt) {} - static final class NBTBuilder & IPipeType, - NodeDataType extends INodeData> implements INBTBuilder { + public static final class NBTBuilder & IPipeType, + NodeDataType extends INodeData, E extends NetEdge> implements INBTBuilder { - private final Set> nodes; - private final Graph, NetEdge> graph; - private final WorldPipeNetSimple net; + private final Set> nodes; + private final Graph, E> graph; + private final WorldPipeNetBase net; - NBTBuilder(Map> longPosMap, NBTTagCompound tag, - Graph, NetEdge> graph, WorldPipeNetSimple net) { + public NBTBuilder(Map> longPosMap, NBTTagCompound tag, + Graph, E> graph, + WorldPipeNetBase net) { nodes = new ObjectOpenHashSet<>(); for (int i = 0; i < tag.getInteger("NodeCount"); i++) { - NodeG node = longPosMap.get(tag.getLong(String.valueOf(i))); + NetNode node = longPosMap.get(tag.getLong(String.valueOf(i))); nodes.add(node); } this.graph = graph; @@ -236,7 +240,7 @@ static final class NBTBuilder & IPipeType g = new NetGroup<>(graph, net, nodes); + NetGroup g = new NetGroup<>(graph, net, nodes); } } } diff --git a/src/main/java/gregtech/api/pipenet/NodeG.java b/src/main/java/gregtech/api/pipenet/NetNode.java similarity index 79% rename from src/main/java/gregtech/api/pipenet/NodeG.java rename to src/main/java/gregtech/api/pipenet/NetNode.java index 5cc7fdf177a..e85ca44a64f 100644 --- a/src/main/java/gregtech/api/pipenet/NodeG.java +++ b/src/main/java/gregtech/api/pipenet/NetNode.java @@ -1,10 +1,9 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; @@ -21,13 +20,13 @@ import java.util.Map; import java.util.Objects; -public final class NodeG & IPipeType, - NodeDataType extends INodeData> - implements INBTSerializable { +public final class NetNode & IPipeType, + NodeDataType extends INodeData, Edge extends NetEdge> + implements INBTSerializable { public static final int DEFAULT_MARK = 0; - private final WorldPipeNetSimple net; + private final WorldPipeNetBase net; private NodeDataType data; /** @@ -50,17 +49,16 @@ public final class NodeG & IPipeType> heldMTE; + private WeakReference> heldMTE; private final BlockPos nodePos; - private NetGroup group = null; - - private List> pathCache = null; + private NetGroup group = null; + private List> pathCache = null; - public NodeG(NodeDataType data, IPipeTile heldMTE, - WorldPipeNetSimple net) { + public NetNode(NodeDataType data, IPipeTile heldMTE, + WorldPipeNetBase net) { this.data = data; this.openConnections = 0; this.blockedConnections = 0; @@ -76,7 +74,7 @@ public NodeG(NodeDataType data, IPipeTile heldMTE, * Should never be required to reference its net, data, or position. */ @SideOnly(Side.CLIENT) - public NodeG(IPipeTile heldMTE) { + public NetNode(IPipeTile heldMTE) { this.nodePos = null; this.net = null; this.data = null; @@ -88,7 +86,7 @@ public NodeG(IPipeTile heldMTE) { /** * For construction during NBT reading only */ - public NodeG(NBTTagCompound tag, WorldPipeNetSimple net) { + public NetNode(NBTTagCompound tag, WorldPipeNetBase net) { this.nodePos = BlockPos.fromLong(tag.getLong("Pos")); deserializeNBT(tag); this.data = net.readNodeData(tag.getCompoundTag("Data")); @@ -96,7 +94,7 @@ public NodeG(NBTTagCompound tag, WorldPipeNetSimple net) this.heldMTE = new WeakReference<>(null); } - public NetGroup getGroupSafe() { + public NetGroup getGroupSafe() { if (this.group == null) { new NetGroup<>(this.net.pipeGraph, this.net).addNodes(this); // addNodes automatically sets our group to the new group @@ -105,11 +103,11 @@ public NetGroup getGroupSafe() { } @Nullable - public NetGroup getGroupUnsafe() { + public NetGroup getGroupUnsafe() { return this.group; } - NetGroup setGroup(NetGroup group) { + NetGroup setGroup(NetGroup group) { this.group = group; return group; } @@ -205,7 +203,7 @@ public long getLongPos() { return nodePos.toLong(); } - public void setHeldMTE(IPipeTile heldMTE) { + public void setHeldMTE(IPipeTile heldMTE) { if (this.heldMTE.get() != heldMTE) this.heldMTE = new WeakReference<>(heldMTE); } @@ -214,15 +212,15 @@ public void setHeldMTE(IPipeTile heldMTE) { * Performs no safety checks. */ @Nullable - public IPipeTile getHeldMTEUnsafe() { + public IPipeTile getHeldMTEUnsafe() { return heldMTE.get(); } /** * Ensures that the returned tile is not null. */ - public IPipeTile getHeldMTE() { - IPipeTile te = getHeldMTEUnsafe(); + public IPipeTile getHeldMTE() { + IPipeTile te = getHeldMTEUnsafe(); if (te == null) { te = net.castTE(net.getWorld().getTileEntity(this.nodePos)); setHeldMTE(te); @@ -233,9 +231,9 @@ public IPipeTile getHeldMTE() { /** * Ensures that the returned tile is the correct one for this position. */ - public IPipeTile getHeldMTESafe() { - IPipeTile te = getHeldMTEUnsafe(); - IPipeTile properTE = net.castTE(net.getWorld().getTileEntity(this.nodePos)); + public IPipeTile getHeldMTESafe() { + IPipeTile te = getHeldMTEUnsafe(); + IPipeTile properTE = net.castTE(net.getWorld().getTileEntity(this.nodePos)); if (te != properTE) { setHeldMTE(properTE); } @@ -251,7 +249,7 @@ public NodeDataType getData() { } @Nullable - public List> getPathCache() { + public List> getPathCache() { return pathCache; } @@ -261,7 +259,7 @@ public List> getPathCache() { * @param pathCache The new cache. * @return The new cache. */ - public List> setPathCache(List> pathCache) { + public List> setPathCache(List> pathCache) { this.pathCache = pathCache; return pathCache; } @@ -293,8 +291,8 @@ public void deserializeNBT(NBTTagCompound nbt) { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - NodeG nodeG = (NodeG) o; - return nodePos != null && Objects.equals(nodePos, nodeG.nodePos); + NetNode node = (NetNode) o; + return nodePos != null && Objects.equals(nodePos, node.nodePos); } @Override diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index dba48a1be90..0713a3260d2 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -1,6 +1,7 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.util.FacingPos; import net.minecraft.tileentity.TileEntity; @@ -16,14 +17,14 @@ import java.util.stream.Collectors; public class NetPath & IPipeType, - NodeDataType extends INodeData> { + NodeDataType extends INodeData, E extends NetEdge> { - private List> nodeList; - private List edgeList; + private List> nodeList; + private List edgeList; - private NodeG sourceNode; + private NetNode sourceNode; - private NodeG targetNode; + private NetNode targetNode; private double weight; @@ -34,7 +35,7 @@ public class NetPath & IPipeType, * * @param node the node to */ - public NetPath(NodeG node) { + public NetPath(NetNode node) { this.sourceNode = node; this.targetNode = node; this.nodeList = Collections.singletonList(node); @@ -51,7 +52,7 @@ public NetPath(NodeG node) { * @param edges List of edges. * @param weight Sum weight of the path. */ - public NetPath(List> nodes, List edges, double weight) { + public NetPath(List> nodes, List edges, double weight) { this.sourceNode = nodes.get(0); this.targetNode = nodes.get(nodes.size() - 1); this.nodeList = nodes; @@ -65,7 +66,7 @@ public NetPath(List> nodes, List edges, d * * @param path the GraphPath */ - public NetPath(GraphPath, NetEdge> path) { + public NetPath(GraphPath, E> path) { this.sourceNode = path.getStartVertex(); this.targetNode = path.getEndVertex(); this.nodeList = path.getVertexList(); @@ -78,19 +79,19 @@ public NetPath(GraphPath, NetEdge> path) { protected NetPath() {} - public List> getNodeList() { + public List> getNodeList() { return nodeList; } - public List getEdgeList() { + public List getEdgeList() { return edgeList; } - public NodeG getSourceNode() { + public NetNode getSourceNode() { return sourceNode; } - public NodeG getTargetNode() { + public NetNode getTargetNode() { return targetNode; } @@ -98,11 +99,11 @@ public Iterator getFacingIterator() { return this.getTargetTEs().keySet().iterator(); } - public FacedNetPath firstFacing() { + public FacedNetPath firstFacing() { return this.withFacing(this.getFacingIterator().next()); } - public FacedNetPath withFacing(EnumFacing facing) { + public FacedNetPath withFacing(EnumFacing facing) { return new FacedNetPath<>(this, facing); } @@ -118,7 +119,7 @@ public NodeDataType getMinData() { // generate min data on-demand and cache it, rather than generating for every path always if (this.data == null) { this.data = sourceNode.getData() - .getMinData(this.nodeList.stream().map(NodeG::getData).collect(Collectors.toSet())); + .getMinData(this.nodeList.stream().map(NetNode::getData).collect(Collectors.toSet())); } return data; } @@ -130,13 +131,14 @@ public boolean checkPredicate(Object o) { return true; } - public static class FacedNetPath & IPipeType, NDT extends INodeData> { + public static class FacedNetPath & IPipeType, NDT extends INodeData, + E extends NetEdge> { - public NetPath path; + public NetPath path; public EnumFacing facing; - public FacedNetPath(NetPath path, EnumFacing facing) { + public FacedNetPath(NetPath path, EnumFacing facing) { this.path = path; this.facing = facing; } @@ -145,19 +147,19 @@ public TileEntity getTargetTE() { return path.getTargetTEs().get(facing); } - public List> getNodeList() { + public List> getNodeList() { return path.getNodeList(); } - public List getEdgeList() { + public List getEdgeList() { return path.getEdgeList(); } - public NodeG getSourceNode() { + public NetNode getSourceNode() { return path.getSourceNode(); } - public NodeG getTargetNode() { + public NetNode getTargetNode() { return path.getTargetNode(); } diff --git a/src/main/java/gregtech/api/pipenet/Node.java b/src/main/java/gregtech/api/pipenet/Node.java deleted file mode 100644 index 2fb139d779e..00000000000 --- a/src/main/java/gregtech/api/pipenet/Node.java +++ /dev/null @@ -1,42 +0,0 @@ -package gregtech.api.pipenet; - -import net.minecraft.util.EnumFacing; - -import org.jetbrains.annotations.ApiStatus; - -/** - * Represents a single node in network of pipes - * It can have blocked connections and be active or not - */ -@Deprecated -@ApiStatus.ScheduledForRemoval(inVersion = "2.9") -public final class Node { - - public static final int DEFAULT_MARK = 0; - - public final NodeDataType data; - /** - * Specifies bitmask of blocked connections - * Node will not connect in blocked direction in any case, - * even if neighbour node mark matches - */ - public int openConnections; - /** - * Specifies mark of this node - * Nodes can connect only if their marks are equal, or if - * one of marks is default one - */ - public int mark; - public boolean isActive; - - public Node(NodeDataType data, int openConnections, int mark, boolean isActive) { - this.data = data; - this.openConnections = openConnections; - this.mark = mark; - this.isActive = isActive; - } - - public boolean isBlocked(EnumFacing facing) { - return (openConnections & 1 << facing.getIndex()) == 0; - } -} diff --git a/src/main/java/gregtech/api/pipenet/PipeNet.java b/src/main/java/gregtech/api/pipenet/PipeNet.java deleted file mode 100644 index 8beea2d4193..00000000000 --- a/src/main/java/gregtech/api/pipenet/PipeNet.java +++ /dev/null @@ -1,481 +0,0 @@ -package gregtech.api.pipenet; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockPos.MutableBlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.World; -import net.minecraftforge.common.util.Constants.NBT; -import net.minecraftforge.common.util.INBTSerializable; - -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import org.jetbrains.annotations.ApiStatus; - -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.Deque; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -@Deprecated -@ApiStatus.ScheduledForRemoval(inVersion = "2.9") -public abstract class PipeNet implements INBTSerializable { - - protected final WorldPipeNet> worldData; - private final Map> nodeByBlockPos = new HashMap<>(); - private final Map> unmodifiableNodeByBlockPos = Collections - .unmodifiableMap(nodeByBlockPos); - private final Map ownedChunks = new HashMap<>(); - private long lastUpdate; - boolean isValid = false; - - public PipeNet(WorldPipeNet> world) { - // noinspection unchecked - this.worldData = (WorldPipeNet>) world; - } - - public Set getContainedChunks() { - return Collections.unmodifiableSet(ownedChunks.keySet()); - } - - public World getWorldData() { - return worldData.getWorld(); - } - - public long getLastUpdate() { - return lastUpdate; - } - - public boolean isValid() { - return isValid; - } - - /** - * Is only called when connections changed of nodes. Nodes can ONLY connect to other nodes. - */ - protected void onNodeConnectionsUpdate() { - this.lastUpdate = System.currentTimeMillis(); - } - - /** - * Is called when any connection of any pipe in the net changes - */ - public void onPipeConnectionsUpdate() {} - - public void onNeighbourUpdate(BlockPos fromPos) {} - - /** - * Is called when any Pipe TE in the PipeNet is unloaded - */ - public void onChunkUnload() {} - - public Map> getAllNodes() { - return unmodifiableNodeByBlockPos; - } - - public Node getNodeAt(BlockPos blockPos) { - return nodeByBlockPos.get(blockPos); - } - - public boolean containsNode(BlockPos blockPos) { - return nodeByBlockPos.containsKey(blockPos); - } - - protected void addNodeSilently(BlockPos nodePos, Node node) { - this.nodeByBlockPos.put(nodePos, node); - checkAddedInChunk(nodePos); - } - - protected void addNode(BlockPos nodePos, Node node) { - addNodeSilently(nodePos, node); - onNodeConnectionsUpdate(); - worldData.markDirty(); - } - - protected Node removeNodeWithoutRebuilding(BlockPos nodePos) { - Node removedNode = this.nodeByBlockPos.remove(nodePos); - ensureRemovedFromChunk(nodePos); - worldData.markDirty(); - return removedNode; - } - - protected void removeNode(BlockPos nodePos) { - if (nodeByBlockPos.containsKey(nodePos)) { - Node selfNode = removeNodeWithoutRebuilding(nodePos); - rebuildNetworkOnNodeRemoval(nodePos, selfNode); - } - } - - protected void checkAddedInChunk(BlockPos nodePos) { - ChunkPos chunkPos = new ChunkPos(nodePos); - int newValue = this.ownedChunks.compute(chunkPos, (pos, old) -> (old == null ? 0 : old) + 1); - if (newValue == 1 && isValid()) { - this.worldData.addPipeNetToChunk(chunkPos, this); - } - } - - protected void ensureRemovedFromChunk(BlockPos nodePos) { - ChunkPos chunkPos = new ChunkPos(nodePos); - int newValue = this.ownedChunks.compute(chunkPos, (pos, old) -> old == null ? 0 : old - 1); - if (newValue == 0) { - this.ownedChunks.remove(chunkPos); - if (isValid()) { - this.worldData.removePipeNetFromChunk(chunkPos, this); - } - } - } - - protected void updateBlockedConnections(BlockPos nodePos, EnumFacing facing, boolean isBlocked) { - if (!containsNode(nodePos)) { - return; - } - Node selfNode = getNodeAt(nodePos); - if (selfNode.isBlocked(facing) == isBlocked) - return; - - setBlocked(selfNode, facing, isBlocked); - BlockPos offsetPos = nodePos.offset(facing); - PipeNet pipeNetAtOffset = worldData.getNetFromPos(offsetPos); - if (pipeNetAtOffset == null) { - // if there is no any pipe net at this side, - // updating blocked status of it won't change anything in any net - return; - } - // if we are on that side of node too - // and it is blocked now - if (pipeNetAtOffset == this) { - // if side was unblocked, well, there is really nothing changed in this e-net - // if it is blocked now, but was able to connect with neighbour node before, try split networks - if (isBlocked) { - // need to unblock node before doing canNodesConnectCheck - setBlocked(selfNode, facing, false); - if (canNodesConnect(selfNode, facing, getNodeAt(offsetPos), this)) { - // now block again to call findAllConnectedBlocks - setBlocked(selfNode, facing, true); - HashMap> thisENet = findAllConnectedBlocks(nodePos); - if (!getAllNodes().equals(thisENet)) { - // node visibility has changed, split network into 2 - // node that code below is similar to removeNodeInternal, but only for 2 networks, and without - // node removal - PipeNet newPipeNet = worldData.createNetInstance(); - thisENet.keySet().forEach(this::removeNodeWithoutRebuilding); - newPipeNet.transferNodeData(thisENet, this); - worldData.addPipeNet(newPipeNet); - } - } - } - // there is another network on that side - // if this is an unblock, and we can connect with their node, merge them - - } else if (!isBlocked) { - Node neighbourNode = pipeNetAtOffset.getNodeAt(offsetPos); - // check connection availability from both networks - if (canNodesConnect(selfNode, facing, neighbourNode, pipeNetAtOffset) && - pipeNetAtOffset.canNodesConnect(neighbourNode, facing.getOpposite(), selfNode, this)) { - // so, side is unblocked now, and nodes can connect, merge two networks - // our network consumes other one - uniteNetworks(pipeNetAtOffset); - } - } - onNodeConnectionsUpdate(); - worldData.markDirty(); - } - - protected void updateMark(BlockPos nodePos, int newMark) { - if (!containsNode(nodePos)) { - return; - } - HashMap> selfConnectedBlocks = null; - Node selfNode = getNodeAt(nodePos); - int oldMark = selfNode.mark; - selfNode.mark = newMark; - for (EnumFacing facing : EnumFacing.VALUES) { - BlockPos offsetPos = nodePos.offset(facing); - PipeNet otherPipeNet = worldData.getNetFromPos(offsetPos); - Node secondNode = otherPipeNet == null ? null : otherPipeNet.getNodeAt(offsetPos); - if (secondNode == null) - continue; // there is noting here - if (!areNodeBlockedConnectionsCompatible(selfNode, facing, secondNode) || - !areNodesCustomContactable(selfNode.data, secondNode.data, otherPipeNet)) - continue; // if connections aren't compatible, skip them - if (areMarksCompatible(oldMark, secondNode.mark) == areMarksCompatible(newMark, secondNode.mark)) - continue; // if compatibility didn't change, skip it - if (areMarksCompatible(newMark, secondNode.mark)) { - // if marks are compatible now, and offset network is different network, merge them - // if it is same network, just update mask and paths - if (otherPipeNet != this) { - uniteNetworks(otherPipeNet); - } - // marks are incompatible now, and this net is connected with it - } else if (otherPipeNet == this) { - // search connected nodes from newly marked node - // populate self connected blocks lazily only once - if (selfConnectedBlocks == null) { - selfConnectedBlocks = findAllConnectedBlocks(nodePos); - } - if (getAllNodes().equals(selfConnectedBlocks)) { - continue; // if this node is still connected to this network, just continue - } - // otherwise, it is not connected - HashMap> offsetConnectedBlocks = findAllConnectedBlocks(offsetPos); - // if in the result of remarking offset node has separated from main network, - // and it is also separated from current cable too, form new network for it - if (!offsetConnectedBlocks.equals(selfConnectedBlocks)) { - offsetConnectedBlocks.keySet().forEach(this::removeNodeWithoutRebuilding); - PipeNet offsetPipeNet = worldData.createNetInstance(); - offsetPipeNet.transferNodeData(offsetConnectedBlocks, this); - worldData.addPipeNet(offsetPipeNet); - } - } - } - onNodeConnectionsUpdate(); - worldData.markDirty(); - } - - private void setBlocked(Node selfNode, EnumFacing facing, boolean isBlocked) { - if (!isBlocked) { - selfNode.openConnections |= 1 << facing.getIndex(); - } else { - selfNode.openConnections &= ~(1 << facing.getIndex()); - } - } - - public boolean markNodeAsActive(BlockPos nodePos, boolean isActive) { - if (containsNode(nodePos) && getNodeAt(nodePos).isActive != isActive) { - getNodeAt(nodePos).isActive = isActive; - worldData.markDirty(); - onNodeConnectionsUpdate(); - return true; - } - return false; - } - - protected final void uniteNetworks(PipeNet unitedPipeNet) { - Map> allNodes = new HashMap<>(unitedPipeNet.getAllNodes()); - worldData.removePipeNet(unitedPipeNet); - allNodes.keySet().forEach(unitedPipeNet::removeNodeWithoutRebuilding); - transferNodeData(allNodes, unitedPipeNet); - } - - private boolean areNodeBlockedConnectionsCompatible(Node first, EnumFacing firstFacing, - Node second) { - return !first.isBlocked(firstFacing) && !second.isBlocked(firstFacing.getOpposite()); - } - - private static boolean areMarksCompatible(int mark1, int mark2) { - return mark1 == mark2 || mark1 == Node.DEFAULT_MARK || mark2 == Node.DEFAULT_MARK; - } - - /** - * Checks if given nodes can connect - * Note that this logic should equal with block connection logic - * for proper work of network - */ - protected final boolean canNodesConnect(Node first, EnumFacing firstFacing, Node second, - PipeNet secondPipeNet) { - return areNodeBlockedConnectionsCompatible(first, firstFacing, second) && - areMarksCompatible(first.mark, second.mark) && - areNodesCustomContactable(first.data, second.data, secondPipeNet); - } - - // we need to search only this network - protected HashMap> findAllConnectedBlocks(BlockPos startPos) { - HashMap> observedSet = new HashMap<>(); - observedSet.put(startPos, getNodeAt(startPos)); - Node firstNode = getNodeAt(startPos); - MutableBlockPos currentPos = new MutableBlockPos(startPos); - Deque moveStack = new ArrayDeque<>(); - main: - while (true) { - for (EnumFacing facing : EnumFacing.VALUES) { - currentPos.move(facing); - Node secondNode = getNodeAt(currentPos); - // if there is node, and it can connect with previous node, add it to list, and set previous node as - // current - if (secondNode != null && canNodesConnect(firstNode, facing, secondNode, this) && - !observedSet.containsKey(currentPos)) { - observedSet.put(currentPos.toImmutable(), getNodeAt(currentPos)); - firstNode = secondNode; - moveStack.push(facing.getOpposite()); - continue main; - } else currentPos.move(facing.getOpposite()); - } - if (!moveStack.isEmpty()) { - currentPos.move(moveStack.pop()); - firstNode = getNodeAt(currentPos); - } else break; - } - return observedSet; - } - - // called when node is removed to rebuild network - protected void rebuildNetworkOnNodeRemoval(BlockPos nodePos, Node selfNode) { - int amountOfConnectedSides = 0; - for (EnumFacing facing : EnumFacing.values()) { - BlockPos offsetPos = nodePos.offset(facing); - if (containsNode(offsetPos)) - amountOfConnectedSides++; - } - // if we are connected only on one side or not connected at all, we don't need to find connected blocks - // because they are only on on side or doesn't exist at all - // this saves a lot of performance in big networks, which are quite big to depth-first them fastly - if (amountOfConnectedSides >= 2) { - for (EnumFacing facing : EnumFacing.VALUES) { - BlockPos offsetPos = nodePos.offset(facing); - Node secondNode = getNodeAt(offsetPos); - if (secondNode == null || !canNodesConnect(selfNode, facing, secondNode, this)) { - // if there isn't any neighbour node, or it wasn't connected with us, just skip it - continue; - } - HashMap> thisENet = findAllConnectedBlocks(offsetPos); - if (getAllNodes().equals(thisENet)) { - // if cable on some direction contains all nodes of this network - // the network didn't change so keep it as is - break; - } else { - // and use them to create new network with caching active nodes set - PipeNet energyNet = worldData.createNetInstance(); - // remove blocks that aren't connected with this network - thisENet.keySet().forEach(this::removeNodeWithoutRebuilding); - energyNet.transferNodeData(thisENet, this); - worldData.addPipeNet(energyNet); - } - } - } - if (getAllNodes().isEmpty()) { - // if this energy net is empty now, remove it - worldData.removePipeNet(this); - } - onNodeConnectionsUpdate(); - worldData.markDirty(); - } - - protected boolean areNodesCustomContactable(NodeDataType first, NodeDataType second, - PipeNet secondNodePipeNet) { - return true; - } - - protected boolean canAttachNode(NodeDataType nodeData) { - return true; - } - - /** - * Called during network split when one net needs to transfer some of it's nodes to another one - * Use this for diving old net contents according to node amount of new network - * For example, for fluid pipes it would remove amount of fluid contained in old nodes - * from parent network and add it to it's own tank, keeping network contents when old network is split - * Note that it should be called when parent net doesn't have transferredNodes in allNodes already - */ - protected void transferNodeData(Map> transferredNodes, - PipeNet parentNet) { - transferredNodes.forEach(this::addNodeSilently); - onNodeConnectionsUpdate(); - worldData.markDirty(); - } - - /** - * Serializes node data into specified tag compound - * Used for writing persistent node data - */ - protected abstract void writeNodeData(NodeDataType nodeData, NBTTagCompound tagCompound); - - /** - * Deserializes node data from specified tag compound - * Used for reading persistent node data - */ - protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound compound = new NBTTagCompound(); - compound.setTag("Nodes", serializeAllNodeList(nodeByBlockPos)); - return compound; - } - - @Override - public void deserializeNBT(NBTTagCompound nbt) { - this.nodeByBlockPos.clear(); - this.ownedChunks.clear(); - deserializeAllNodeList(nbt.getCompoundTag("Nodes")); - } - - protected void deserializeAllNodeList(NBTTagCompound compound) { - NBTTagList allNodesList = compound.getTagList("NodeIndexes", NBT.TAG_COMPOUND); - NBTTagList wirePropertiesList = compound.getTagList("WireProperties", NBT.TAG_COMPOUND); - Int2ObjectMap readProperties = new Int2ObjectOpenHashMap<>(); - - for (int i = 0; i < wirePropertiesList.tagCount(); i++) { - NBTTagCompound propertiesTag = wirePropertiesList.getCompoundTagAt(i); - int wirePropertiesIndex = propertiesTag.getInteger("index"); - NodeDataType nodeData = readNodeData(propertiesTag); - readProperties.put(wirePropertiesIndex, nodeData); - } - - for (int i = 0; i < allNodesList.tagCount(); i++) { - NBTTagCompound nodeTag = allNodesList.getCompoundTagAt(i); - int x = nodeTag.getInteger("x"); - int y = nodeTag.getInteger("y"); - int z = nodeTag.getInteger("z"); - int wirePropertiesIndex = nodeTag.getInteger("index"); - BlockPos blockPos = new BlockPos(x, y, z); - NodeDataType nodeData = readProperties.get(wirePropertiesIndex); - int openConnections = nodeTag.getInteger("open"); - int mark = nodeTag.getInteger("mark"); - boolean isNodeActive = nodeTag.getBoolean("active"); - addNodeSilently(blockPos, new Node<>(nodeData, openConnections, mark, isNodeActive)); - } - } - - protected NBTTagCompound serializeAllNodeList(Map> allNodes) { - NBTTagCompound compound = new NBTTagCompound(); - NBTTagList allNodesList = new NBTTagList(); - NBTTagList wirePropertiesList = new NBTTagList(); - Object2IntMap alreadyWritten = new Object2IntOpenHashMap<>(10, 0.5f); - alreadyWritten.defaultReturnValue(-1); - int currentIndex = 0; - - for (Entry> entry : allNodes.entrySet()) { - BlockPos nodePos = entry.getKey(); - Node node = entry.getValue(); - NBTTagCompound nodeTag = new NBTTagCompound(); - nodeTag.setInteger("x", nodePos.getX()); - nodeTag.setInteger("y", nodePos.getY()); - nodeTag.setInteger("z", nodePos.getZ()); - int wirePropertiesIndex = alreadyWritten.getInt(node.data); - if (wirePropertiesIndex == -1) { - wirePropertiesIndex = currentIndex; - alreadyWritten.put(node.data, wirePropertiesIndex); - currentIndex++; - } - nodeTag.setInteger("index", wirePropertiesIndex); - if (node.mark != Node.DEFAULT_MARK) { - nodeTag.setInteger("mark", node.mark); - } - if (node.openConnections > 0) { - nodeTag.setInteger("open", node.openConnections); - } - if (node.isActive) { - nodeTag.setBoolean("active", true); - } - allNodesList.appendTag(nodeTag); - } - - for (Object2IntMap.Entry entry : alreadyWritten.object2IntEntrySet()) { - NBTTagCompound propertiesTag = new NBTTagCompound(); - propertiesTag.setInteger("index", entry.getIntValue()); - writeNodeData(entry.getKey(), propertiesTag); - wirePropertiesList.appendTag(propertiesTag); - } - - compound.setTag("NodeIndexes", allNodesList); - compound.setTag("WireProperties", wirePropertiesList); - return compound; - } -} diff --git a/src/main/java/gregtech/api/pipenet/PipeNetWalker.java b/src/main/java/gregtech/api/pipenet/PipeNetWalker.java deleted file mode 100644 index 56a76e1ee7d..00000000000 --- a/src/main/java/gregtech/api/pipenet/PipeNetWalker.java +++ /dev/null @@ -1,256 +0,0 @@ -package gregtech.api.pipenet; - -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.util.GTLog; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; - -import java.util.*; - -/** - * This is a helper class to get information about a pipe net - *

- * The walker is written that it will always find the shortest path to any destination - *

- * On the way it can collect information about the pipes and it's neighbours - *

- * After creating a walker simply call {@link #traversePipeNet()} to start walking, then you can just collect the data - *

- * Do not walk a walker more than once - *

- */ -@Deprecated -@ApiStatus.ScheduledForRemoval(inVersion = "2.9") -public abstract class PipeNetWalker> { - - protected PipeNetWalker root; - private final World world; - private Set walked; - private final List nextPipeFacings = new ArrayList<>(5); - private final List nextPipes = new ArrayList<>(5); - private List> walkers; - private final BlockPos.MutableBlockPos currentPos; - private T currentPipe; - private EnumFacing from = null; - private int walkedBlocks; - private boolean invalid; - private boolean running; - private boolean failed = false; - - protected PipeNetWalker(World world, BlockPos sourcePipe, int walkedBlocks) { - this.world = Objects.requireNonNull(world); - this.walkedBlocks = walkedBlocks; - this.currentPos = new BlockPos.MutableBlockPos(Objects.requireNonNull(sourcePipe)); - this.root = this; - } - - /** - * Creates a sub walker - * Will be called when a pipe has multiple valid pipes - * - * @param world world - * @param nextPos next pos to check - * @param walkedBlocks distance from source in blocks - * @return new sub walker - */ - protected abstract PipeNetWalker createSubWalker(World world, EnumFacing facingToNextPos, BlockPos nextPos, - int walkedBlocks); - - /** - * You can increase walking stats here. for example - * - * @param pipeTile current checking pipe - * @param pos current pipe pos - */ - protected abstract void checkPipe(T pipeTile, BlockPos pos); - - /** - * Checks the neighbour of the current pos - * - * @param pipePos current pos - * @param faceToNeighbour face to neighbour - * @param neighbourTile neighbour tile - */ - protected abstract void checkNeighbour(T pipeTile, BlockPos pipePos, EnumFacing faceToNeighbour, - @Nullable TileEntity neighbourTile); - - /** - * If the pipe is valid to perform a walk on - * - * @param currentPipe current pipe - * @param neighbourPipe neighbour pipe to check - * @param pipePos current pos (tile.getPipePos() != pipePos) - * @param faceToNeighbour face to pipeTile - * @return if the pipe is valid - */ - protected boolean isValidPipe(T currentPipe, T neighbourPipe, BlockPos pipePos, EnumFacing faceToNeighbour) { - return true; - } - - protected abstract Class getBasePipeClass(); - - /** - * The directions that this net can traverse from this pipe - * - * @return the array of valid EnumFacings - */ - protected EnumFacing[] getSurroundingPipeSides() { - return EnumFacing.VALUES; - } - - /** - * Called when a sub walker is done walking - * - * @param subWalker the finished sub walker - */ - protected void onRemoveSubWalker(PipeNetWalker subWalker) {} - - public void traversePipeNet() { - traversePipeNet(32768); - } - - /** - * Starts walking the pipe net and gathers information. - * - * @param maxWalks max walks to prevent possible stack overflow - * @throws IllegalStateException if the walker already walked - */ - public void traversePipeNet(int maxWalks) { - if (invalid) - throw new IllegalStateException("This walker already walked. Create a new one if you want to walk again"); - root = this; - walked = new ObjectOpenHashSet<>(); - int i = 0; - running = true; - while (running && !walk() && i++ < maxWalks); - running = false; - walked = null; - if (i >= maxWalks) - GTLog.logger.fatal("The walker reached the maximum amount of walks {}", i); - invalid = true; - } - - private boolean walk() { - if (walkers == null) { - if (!checkPos()) { - this.root.failed = true; - return true; - } - - if (nextPipeFacings.isEmpty()) - return true; - if (nextPipeFacings.size() == 1) { - currentPos.setPos(nextPipes.get(0).getPipePos()); - currentPipe = nextPipes.get(0); - from = nextPipeFacings.get(0).getOpposite(); - walkedBlocks++; - return !isRunning(); - } - - walkers = new ArrayList<>(); - for (int i = 0; i < nextPipeFacings.size(); i++) { - EnumFacing side = nextPipeFacings.get(i); - PipeNetWalker walker = Objects.requireNonNull( - createSubWalker(world, side, currentPos.offset(side), walkedBlocks + 1), - "Walker can't be null"); - walker.root = root; - walker.currentPipe = nextPipes.get(i); - walker.from = side.getOpposite(); - walkers.add(walker); - } - } - Iterator> iterator = walkers.iterator(); - while (iterator.hasNext()) { - PipeNetWalker walker = iterator.next(); - if (walker.walk()) { - onRemoveSubWalker(walker); - iterator.remove(); - } - } - - return !isRunning() || walkers.isEmpty(); - } - - private boolean checkPos() { - nextPipeFacings.clear(); - nextPipes.clear(); - if (currentPipe == null) { - TileEntity thisPipe = world.getTileEntity(currentPos); - if (!(thisPipe instanceof IPipeTile)) { - GTLog.logger.fatal("PipeWalker expected a pipe, but found {} at {}", thisPipe, currentPos); - return false; - } - if (!getBasePipeClass().isAssignableFrom(thisPipe.getClass())) { - return false; - } - currentPipe = (T) thisPipe; - } - T pipeTile = currentPipe; - checkPipe(pipeTile, currentPos); - root.walked.add(pipeTile); - - // check for surrounding pipes and item handlers - for (EnumFacing accessSide : getSurroundingPipeSides()) { - // skip sides reported as blocked by pipe network - if (accessSide == from || !pipeTile.isConnected(accessSide)) - continue; - - TileEntity tile = pipeTile.getNeighbor(accessSide); - if (tile != null && getBasePipeClass().isAssignableFrom(tile.getClass())) { - T otherPipe = (T) tile; - if (!otherPipe.isConnected(accessSide.getOpposite()) || - otherPipe.isFaceBlocked(accessSide.getOpposite()) || isWalked(otherPipe)) - continue; - if (isValidPipe(pipeTile, otherPipe, currentPos, accessSide)) { - nextPipeFacings.add(accessSide); - nextPipes.add(otherPipe); - continue; - } - } - checkNeighbour(pipeTile, currentPos, accessSide, tile); - } - return true; - } - - protected boolean isWalked(T pipe) { - return root.walked.contains(pipe); - } - - /** - * Will cause the root walker to stop after the next walk - */ - public void stop() { - root.running = false; - } - - public boolean isRunning() { - return root.running; - } - - public World getWorld() { - return world; - } - - public BlockPos getCurrentPos() { - return currentPos; - } - - public int getWalkedBlocks() { - return walkedBlocks; - } - - public boolean isRoot() { - return this.root == this; - } - - public boolean isFailed() { - return failed; - } -} diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/pipenet/WorldPipeNet.java deleted file mode 100644 index fc9f8467a63..00000000000 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNet.java +++ /dev/null @@ -1,177 +0,0 @@ -package gregtech.api.pipenet; - -import gregtech.api.util.GTLog; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.World; -import net.minecraft.world.storage.WorldSavedData; -import net.minecraftforge.common.util.Constants.NBT; - -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Deprecated -@ApiStatus.ScheduledForRemoval(inVersion = "2.9") -public abstract class WorldPipeNet> extends WorldSavedData { - - private WeakReference worldRef = new WeakReference<>(null); - protected List pipeNets = new ArrayList<>(); - protected final Map> pipeNetsByChunk = new HashMap<>(); - - public WorldPipeNet(String name) { - super(name); - } - - public World getWorld() { - return this.worldRef.get(); - } - - protected void setWorldAndInit(World world) { - if (world != this.worldRef.get()) { - this.worldRef = new WeakReference<>(world); - onWorldSet(); - } - } - - public static @NotNull String getDataID(@NotNull final String baseID, @NotNull final World world) { - // noinspection ConstantValue - if (world == null || world.isRemote) { - GTLog.logger.error("WorldPipeNet should only be created on the server!", new Throwable()); - // noinspection ConstantValue - if (world == null) { - return baseID; - } - } - - int dimension = world.provider.getDimension(); - return dimension == 0 ? baseID : baseID + '.' + dimension; - } - - protected void onWorldSet() { - this.pipeNets.forEach(PipeNet::onNodeConnectionsUpdate); - } - - public void addNode(BlockPos nodePos, NodeDataType nodeData, int mark, int openConnections, boolean isActive) { - T myPipeNet = null; - Node node = new Node<>(nodeData, openConnections, mark, isActive); - for (EnumFacing facing : EnumFacing.VALUES) { - BlockPos offsetPos = nodePos.offset(facing); - T pipeNet = getNetFromPos(offsetPos); - Node secondNode = pipeNet == null ? null : pipeNet.getAllNodes().get(offsetPos); - if (pipeNet != null && pipeNet.canAttachNode(nodeData) && - pipeNet.canNodesConnect(secondNode, facing.getOpposite(), node, null)) { - if (myPipeNet == null) { - myPipeNet = pipeNet; - myPipeNet.addNode(nodePos, node); - } else if (myPipeNet != pipeNet) { - myPipeNet.uniteNetworks(pipeNet); - } - } - - } - if (myPipeNet == null) { - myPipeNet = createNetInstance(); - myPipeNet.addNode(nodePos, node); - addPipeNet(myPipeNet); - markDirty(); - } - } - - protected void addPipeNetToChunk(ChunkPos chunkPos, T pipeNet) { - this.pipeNetsByChunk.computeIfAbsent(chunkPos, any -> new ArrayList<>()).add(pipeNet); - } - - protected void removePipeNetFromChunk(ChunkPos chunkPos, T pipeNet) { - List list = this.pipeNetsByChunk.get(chunkPos); - if (list != null) { - list.remove(pipeNet); - if (list.isEmpty()) { - this.pipeNetsByChunk.remove(chunkPos); - } - } - } - - public void removeNode(BlockPos nodePos) { - T pipeNet = getNetFromPos(nodePos); - if (pipeNet != null) { - pipeNet.removeNode(nodePos); - } - } - - public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean isBlocked) { - T pipeNet = getNetFromPos(nodePos); - if (pipeNet != null) { - pipeNet.updateBlockedConnections(nodePos, side, isBlocked); - pipeNet.onPipeConnectionsUpdate(); - } - } - - public void updateMark(BlockPos nodePos, int newMark) { - T pipeNet = getNetFromPos(nodePos); - if (pipeNet != null) { - pipeNet.updateMark(nodePos, newMark); - } - } - - public T getNetFromPos(BlockPos blockPos) { - List pipeNetsInChunk = pipeNetsByChunk.getOrDefault(new ChunkPos(blockPos), Collections.emptyList()); - for (T pipeNet : pipeNetsInChunk) { - if (pipeNet.containsNode(blockPos)) - return pipeNet; - } - return null; - } - - protected void addPipeNet(T pipeNet) { - addPipeNetSilently(pipeNet); - } - - protected void addPipeNetSilently(T pipeNet) { - this.pipeNets.add(pipeNet); - pipeNet.getContainedChunks().forEach(chunkPos -> addPipeNetToChunk(chunkPos, pipeNet)); - pipeNet.isValid = true; - } - - protected void removePipeNet(T pipeNet) { - this.pipeNets.remove(pipeNet); - pipeNet.getContainedChunks().forEach(chunkPos -> removePipeNetFromChunk(chunkPos, pipeNet)); - pipeNet.isValid = false; - } - - protected abstract T createNetInstance(); - - @Override - public void readFromNBT(NBTTagCompound nbt) { - this.pipeNets = new ArrayList<>(); - NBTTagList allEnergyNets = nbt.getTagList("PipeNets", NBT.TAG_COMPOUND); - for (int i = 0; i < allEnergyNets.tagCount(); i++) { - NBTTagCompound pNetTag = allEnergyNets.getCompoundTagAt(i); - T pipeNet = createNetInstance(); - pipeNet.deserializeNBT(pNetTag); - addPipeNetSilently(pipeNet); - } - } - - @NotNull - @Override - public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { - NBTTagList allPipeNets = new NBTTagList(); - for (T pipeNet : pipeNets) { - NBTTagCompound pNetTag = pipeNet.serializeNBT(); - allPipeNets.appendTag(pNetTag); - } - compound.setTag("PipeNets", allPipeNets); - return compound; - } -} diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java new file mode 100644 index 00000000000..8d1378e0492 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java @@ -0,0 +1,529 @@ +package gregtech.api.pipenet; + +import gregtech.api.cover.Cover; +import gregtech.api.pipenet.alg.INetAlgorithm; +import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; +import gregtech.api.pipenet.alg.SinglePathAlgorithm; +import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.common.covers.CoverShutter; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.storage.WorldSavedData; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.util.Constants; + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; + +import java.lang.ref.WeakReference; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +@ApiStatus.Internal +public abstract class WorldPipeNetBase, + PipeType extends Enum & IPipeType, Edge extends NetEdge> extends WorldSavedData { + + private final boolean isDirected; + private final boolean isSinglePath; + private final boolean isFlow; + + private Set builders = null; + + private WeakReference worldRef = new WeakReference<>(null); + protected final Graph, Edge> pipeGraph; + final Map> pipeMap = new Object2ObjectOpenHashMap<>(); + + final INetAlgorithm.NetAlgorithmWrapper netAlgorithm; + + private boolean validAlgorithmInstance = false; + + protected WorldPipeNetBase(String name, boolean isDirected, boolean isSinglePath, + Graph, Edge> graph) { + super(name); + this.pipeGraph = graph; + this.netAlgorithm = new INetAlgorithm.NetAlgorithmWrapper<>(); + this.isDirected = isDirected; + this.isSinglePath = isSinglePath; + this.isFlow = true; + } + + public Graph, Edge> getGraph() { + return this.pipeGraph; + } + + public final boolean isDirected() { + return isDirected; + } + + public final boolean isSinglePath() { + return isSinglePath; + } + + public final boolean isFlow() { + return isFlow; + } + + protected void markAlgInvalid() { + this.validAlgorithmInstance = false; + } + + protected void markAlgValid() { + this.validAlgorithmInstance = true; + } + + protected boolean hasValidAlg() { + return this.validAlgorithmInstance; + } + + public World getWorld() { + return this.worldRef.get(); + } + + protected void setWorldAndInit(World world) { + if (world != this.worldRef.get()) { + this.worldRef = new WeakReference<>(world); + onWorldSet(); + // some builders have to wait for world set, so we wait until then to build them. + if (this.builders != null) this.builders.forEach(INBTBuilder::build); + } + } + + public static String getDataID(final String baseID, final World world) { + if (world == null || world.isRemote) + throw new RuntimeException("WorldPipeNetBase should only be created on the server!"); + int dimension = world.provider.getDimension(); + return dimension == 0 ? baseID : baseID + '.' + dimension; + } + + protected void onWorldSet() { + this.rebuildNetAlgorithm(); + } + + /** + * Preferred override. Only collects a fresh TE from the server if the provided TE is invalid. + * + * @param tile The {@link TileEntityPipeBase} that paths are being requested for + * @param testObject Can be null for simple nets. Complex nets need this for their behavior. + * @return the ordered list of paths associated with the {@link TileEntityPipeBase} + */ + public List> getPaths(TileEntityPipeBase tile, + Object testObject) { + return getPaths(this.pipeMap.get(tile.getPipePos()), tile, testObject); + } + + /** + * Special-case override. Forces the collection of a fresh TE from the server. + * + * @param pos The {@link BlockPos} that paths are being requested for + * @param testObject Can be null for simple nets. Complex nets need this for their behavior. + * @return the ordered list of paths associated with the {@link BlockPos} + */ + public List> getPaths(BlockPos pos, Object testObject) { + return getPaths(this.pipeMap.get(pos), null, testObject); + } + + public List> getPaths(@Nullable NetNode node, + @Nullable TileEntityPipeBase tile, + Object testObject) { + if (node == null) return new ObjectArrayList<>(); + + node.setHeldMTE(tile); + + if (!this.hasValidAlg()) this.rebuildNetAlgorithm(); + + List> cache = node.getPathCache(); + if (cache != null) { + return verifyList(cache, node); + } + + List> list = this.netAlgorithm.getPathsList(node); + return verifyList(node.setPathCache(list), node); + } + + /** + * Verification removes paths ending in unloaded TEs, + * paths that don't connect to anything, + * and all paths if the source TE is unloaded. + */ + protected List> verifyList(List> list, + NetNode source) { + if (!verifyNode(source)) return new ObjectArrayList<>(); + return list.stream().filter(a -> verifyNode(a.getTargetNode()) && a.getWeight() != Double.POSITIVE_INFINITY) + .collect(Collectors.toList()); + } + + protected boolean verifyNode(NetNode node) { + node.getHeldMTESafe(); + return node.hasConnecteds(); + } + + @Nullable + protected TileEntityPipeBase castTE(TileEntity te) { + if (te instanceof TileEntityPipeBasepipe) { + if (!getBasePipeClass().isAssignableFrom(pipe.getClass())) { + return null; + } + // noinspection unchecked + return (TileEntityPipeBase) pipe; + } + return null; + } + + public void markNodeAsOldData(NetNode node) {} + + protected abstract Class> getBasePipeClass(); + + /** + * Make sure to override this if your NetGroups use data. + * + * @return The correct data variant + */ + protected AbstractGroupData getBlankGroupData() { + return null; + } + + public NetNode getOrCreateNode(@NotNull IPipeTile mte) { + NetNode node = this.pipeMap.get(mte.getPipePos()); + if (node != null) return node; + if (!canAttachNode(mte.getNodeData())) return null; + node = new NetNode<>(mte.getNodeData(), mte, this); + this.addNode(node); + return node; + } + + protected final boolean canNodesConnect(NetNode source, EnumFacing nodeFacing, + NetNode target) { + return areNodeBlockedConnectionsCompatible(source, nodeFacing, target) && + areMarksCompatible(source.mark, target.mark) && + areNodesCustomContactable(source.getData(), target.getData()); + } + + private static boolean areMarksCompatible(int mark1, int mark2) { + return mark1 == mark2 || mark1 == NetNode.DEFAULT_MARK || mark2 == NetNode.DEFAULT_MARK; + } + + private boolean areNodeBlockedConnectionsCompatible(NetNode source, + EnumFacing nodeFacing, + NetNode target) { + return !source.isConnected(nodeFacing) && !target.isConnected(nodeFacing.getOpposite()); + } + + protected boolean areNodesCustomContactable(NodeDataType source, NodeDataType target) { + return true; + } + + protected boolean canAttachNode(NodeDataType nodeData) { + return true; + } + + public void updateActiveConnections(BlockPos nodePos, EnumFacing side, boolean connect) { + NetNode node = pipeMap.get(nodePos); + if (node == null || node.isConnected(side) == connect) return; + + node.setConnected(side, connect); + + NetNode nodeOffset = pipeMap.get(nodePos.offset(side)); + if (nodeOffset == null) return; + + nodeOffset.setConnected(side.getOpposite(), connect); + + if (connect) { + if (!node.isBlocked(side)) { + addEdge(nodeOffset, node, null); + this.predicateEdge(nodeOffset, node, side.getOpposite()); + if (!this.isDirected()) return; + } + if (!nodeOffset.isBlocked(side.getOpposite())) { + addEdge(node, nodeOffset, null); + this.predicateEdge(node, nodeOffset, side); + } + } else { + removeUndirectedEdge(node, nodeOffset); + } + } + + public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean blocked) { + if (!isDirected()) return; // no such thing as blocked connections on undirected graphs. + NetNode node = pipeMap.get(nodePos); + if (node == null || node.isBlocked(side) == blocked) return; + + node.setBlocked(side, blocked); + + NetNode nodeOffset = pipeMap.get(nodePos.offset(side)); + if (nodeOffset == null) return; + + if (!blocked) { + addEdge(nodeOffset, node, null); + this.predicateEdge(nodeOffset, node, side); + } else { + removeEdge(nodeOffset, node); + } + } + + public void updateMark(BlockPos nodePos, int newMark) { + NetNode node = pipeMap.get(nodePos); + + int oldMark = node.mark; + node.mark = newMark; + + for (EnumFacing side : EnumFacing.VALUES) { + NetNode nodeOffset = pipeMap.get(nodePos.offset(side)); + if (nodeOffset == null) continue; + if (!areNodeBlockedConnectionsCompatible(node, side, nodeOffset) || + !areNodesCustomContactable(node.getData(), nodeOffset.getData())) + continue; + if (areMarksCompatible(oldMark, nodeOffset.mark) == areMarksCompatible(newMark, nodeOffset.mark)) continue; + + if (areMarksCompatible(newMark, nodeOffset.mark)) { + addEdge(node, nodeOffset, null); + this.predicateEdge(node, nodeOffset, side); + } else { + removeEdge(node, nodeOffset); + } + } + } + + protected abstract Capability[] getConnectionCapabilities(); + + public boolean hasNode(BlockPos pos) { + return pipeMap.containsKey(pos); + } + + public void addNodeSilent(NetNode node) { + pipeGraph.addVertex(node); + this.pipeMap.put(node.getNodePos(), node); + // we do not need to invalidate the cache, because just adding a node means it's not connected to anything. + } + + public void addNode(NetNode node) { + addNodeSilent(node); + this.markDirty(); + } + + @Nullable + public NetNode getNode(BlockPos pos) { + return this.pipeMap.get(pos); + } + + public void addUndirectedEdge(NetNode source, + NetNode target) { + this.addEdge(source, target, null); + if (this.isDirected()) this.addEdge(target, source, null); + } + + public void addEdge(NetNode source, NetNode target, + @Nullable AbstractEdgePredicate predicate) { + addEdge(source, target, source.getData().getWeightFactor() + target.getData().getWeightFactor(), predicate); + } + + public void addUndirectedEdge(NetNode source, + NetNode target, + double weight) { + this.addEdge(source, target, weight, null); + if (this.isDirected()) this.addEdge(target, source, weight, null); + } + + public void addEdge(NetNode source, NetNode target, + double weight, + @Nullable AbstractEdgePredicate predicate) { + if (pipeGraph.addEdge(source, target) != null) { + NetGroup.mergeEdge(source, target); + pipeGraph.setEdgeWeight(source, target, weight); + if (predicate != null) { + pipeGraph.getEdge(source, target).setPredicate(predicate); + } + this.markAlgInvalid(); + this.markDirty(); + } + } + + public void predicateUndirectedEdge(BlockPos pos, EnumFacing faceToNeighbour) { + NetNode source = this.pipeMap.get(pos); + NetNode target = this.pipeMap.get(pos.offset(faceToNeighbour)); + if (source != null && target != null) { + this.predicateUndirectedEdge(source, target, faceToNeighbour); + } + } + + public void predicateEdge(BlockPos pos, EnumFacing faceToNeighbour) { + NetNode source = this.pipeMap.get(pos); + NetNode target = this.pipeMap.get(pos.offset(faceToNeighbour)); + if (source != null && target != null) + this.predicateEdge(source, target, faceToNeighbour); + } + + public void predicateUndirectedEdge(NetNode source, + NetNode target, + EnumFacing faceToNeighbour) { + this.predicateEdge(source, target, faceToNeighbour); + if (this.isDirected()) this.predicateEdge(target, source, faceToNeighbour.getOpposite()); + } + + public void predicateEdge(NetNode source, + NetNode target, + EnumFacing faceToNeighbour) { + if (!this.pipeGraph.containsEdge(source, target)) return; + Cover thisCover = source.getHeldMTESafe().getCoverableImplementation().getCoverAtSide(faceToNeighbour); + Cover neighbourCover = target.getHeldMTESafe().getCoverableImplementation() + .getCoverAtSide(faceToNeighbour.getOpposite()); + AbstractEdgePredicate predicate = getPredicate(thisCover, neighbourCover); + predicate.setPosInfo(source.getNodePos(), target.getNodePos()); + Edge edge = this.pipeGraph.getEdge(source, target); + edge.setPredicate(predicate); + } + + protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbourCover) { + return shutterify(new BasicEdgePredicate(), thisCover, neighbourCover); + } + + protected final AbstractEdgePredicate shutterify(AbstractEdgePredicate predicate, @Nullable Cover thisCover, + @Nullable Cover neighbourCover) { + if (predicate instanceof IShutteredEdgePredicate shutteredEdgePredicate) { + if (thisCover instanceof CoverShutter shutter) { + shutteredEdgePredicate.setShutteredSource(shutter.isWorkingEnabled()); + } + if (neighbourCover instanceof CoverShutter shutter) { + shutteredEdgePredicate.setShutteredTarget(shutter.isWorkingEnabled()); + } + } + return predicate; + } + + public void removeUndirectedEdge(NetNode source, + NetNode target) { + this.removeEdge(source, target); + if (isDirected()) this.removeEdge(target, source); + } + + public void removeEdge(NetNode source, NetNode target) { + if (source.getGroupSafe() != null && source.getGroupSafe().splitEdge(source, target)) { + this.markAlgInvalid(); + this.markDirty(); + } + } + + public void removeNode(BlockPos pos) { + this.removeNode(this.pipeMap.get(pos)); + } + + public void removeNode(@Nullable NetNode node) { + if (node != null) { + if (this.pipeGraph.edgesOf(node).size() != 0) this.markAlgInvalid(); + if (node.getGroupUnsafe() != null) { + node.getGroupUnsafe().splitNode(node); + } else this.pipeGraph.removeVertex(node); + this.pipeMap.remove(node.getNodePos()); + this.markDirty(); + } + } + + public NetGroup getGroup(BlockPos pos) { + NetNode node = this.getNode(pos); + if (node == null) return null; + if (node.getGroupSafe() != null) return node.getGroupSafe(); + return node.setGroup(new NetGroup<>(this.pipeGraph, this)); + } + + public boolean markNodeAsActive(BlockPos nodePos, boolean isActive) { + NetNode node = this.pipeMap.get(nodePos); + if (node != null && node.isActive != isActive) { + node.isActive = isActive; + this.markDirty(); + return true; + } + return false; + } + + protected void rebuildNetAlgorithm() { + if (!this.isSinglePath()) { + this.netAlgorithm.setAlg(new ShortestPathsAlgorithm<>(pipeGraph)); + } else { + this.netAlgorithm.setAlg(new SinglePathAlgorithm<>(pipeGraph, isDirected())); + } + this.markAlgValid(); + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + if (!nbt.hasKey("NetEdges")) { + return; + } + this.builders = new ObjectOpenHashSet<>(); + NBTTagList allPipeNodes = nbt.getTagList("PipeNodes", Constants.NBT.TAG_COMPOUND); + Map> longPosMap = new Long2ObjectOpenHashMap<>(); + for (int i = 0; i < allPipeNodes.tagCount(); i++) { + NBTTagCompound pNodeTag = allPipeNodes.getCompoundTagAt(i); + NetNode node = new NetNode<>(pNodeTag, this); + longPosMap.put(node.getLongPos(), node); + this.addNodeSilent(node); + } + NBTTagList allNetEdges = nbt.getTagList("NetEdges", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < allNetEdges.tagCount(); i++) { + NBTTagCompound gEdgeTag = allNetEdges.getCompoundTagAt(i); + this.builders.add(new NetEdge.NBTBuilder<>(longPosMap, gEdgeTag, this::addEdge)); + } + NBTTagList allNetGroups = nbt.getTagList("NetGroups", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < allNetGroups.tagCount(); i++) { + NBTTagCompound gTag = allNetGroups.getCompoundTagAt(i); + this.builders.add(new NetGroup.NBTBuilder<>(longPosMap, gTag, this.pipeGraph, this)); + } + } + + @NotNull + @Override + public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { + NBTTagList allPipeNodes = new NBTTagList(); + Set> groups = new ObjectOpenHashSet<>(); + for (NetNode node : pipeGraph.vertexSet()) { + if (node.getGroupUnsafe() != null) groups.add(node.getGroupUnsafe()); + NBTTagCompound nodeTag = node.serializeNBT(); + NBTTagCompound dataTag = new NBTTagCompound(); + writeNodeData(node.getData(), dataTag); + nodeTag.setTag("Data", dataTag); + allPipeNodes.appendTag(nodeTag); + } + compound.setTag("PipeNodes", allPipeNodes); + + NBTTagList allNetEdges = new NBTTagList(); + for (Edge edge : pipeGraph.edgeSet()) { + allNetEdges.appendTag(edge.serializeNBT()); + } + compound.setTag("NetEdges", allNetEdges); + + NBTTagList allNetGroups = new NBTTagList(); + for (NetGroup group : groups) { + allNetGroups.appendTag(group.serializeNBT()); + } + compound.setTag("NetGroups", allNetGroups); + + return compound; + } + + /** + * Serializes node data into specified tag compound + * Used for writing persistent node data + */ + protected abstract void writeNodeData(NodeDataType nodeData, NBTTagCompound tagCompound); + + /** + * Deserializes node data from specified tag compound + * Used for reading persistent node data + */ + protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); +} diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java index 7069bf1d242..0acbb4ff256 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java @@ -1,27 +1,22 @@ package gregtech.api.pipenet; import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.pipenet.edge.NetEdge; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import net.minecraftforge.fml.common.FMLCommonHandler; - -import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; import org.jgrapht.graph.SimpleDirectedWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph; -import java.util.List; import java.util.function.Supplier; public abstract class WorldPipeNetComplex, - PipeType extends Enum & IPipeType> extends WorldPipeNetSimple { + PipeType extends Enum & IPipeType, + E extends NetEdge> extends WorldPipeNetBase { /** - * Alternate pipenet representation. Disables node path caching and activates {@link NetEdge} flow behavior. + * Alternate pipenet representation. Allows for using children of the {@link NetEdge} class as edges. *

- * Note - undirected versions of this pipenet will treat flow in either direction along an edge towards its capacity, + * Note - undirected versions of this pipenet will treat flow in either direction along an edge towards its + * capacity, * while directed versions will cancel out reverse flow for improved behavior. * * @param isDirected Determines whether this net needs directed graph handling. @@ -30,27 +25,11 @@ public abstract class WorldPipeNetComplex edgeSupplier) { super(name, isDirected, isSinglePath, - isDirected ? new SimpleDirectedWeightedGraph<>(null, () -> new NetEdge(flowBufferTicks)) : - new SimpleWeightedGraph<>(null, () -> new NetEdge(flowBufferTicks))); - } - - @Override - public List> getPaths(@Nullable NodeG node, - @Nullable TileEntityPipeBase tile, - Object testObject) { - if (node == null) return new ObjectArrayList<>(); - - node.setHeldMTE(tile); - - if (!this.hasValidAlg()) this.rebuildNetAlgorithm(); - - List> list = this.netAlgorithm.getPathsList(node); - return verifyList(list, node); + isDirected ? new SimpleDirectedWeightedGraph<>(null, edgeSupplier) : + new SimpleWeightedGraph<>(null, edgeSupplier)); } } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java index f0c8ef58c26..01e6a3f78a7 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java @@ -1,56 +1,14 @@ package gregtech.api.pipenet; -import gregtech.api.cover.Cover; -import gregtech.api.pipenet.alg.INetAlgorithm; -import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; -import gregtech.api.pipenet.alg.SinglePathAlgorithm; import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; -import gregtech.common.covers.CoverShutter; +import gregtech.api.pipenet.edge.NetEdge; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.storage.WorldSavedData; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.Constants; - -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; import org.jgrapht.graph.SimpleDirectedWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph; -import java.lang.ref.WeakReference; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - public abstract class WorldPipeNetSimple, - PipeType extends Enum & IPipeType> extends WorldSavedData { - - private final boolean isDirected; - private final boolean isSinglePath; - private final boolean isFlow; - - private Set builders = null; - - private WeakReference worldRef = new WeakReference<>(null); - protected final Graph, NetEdge> pipeGraph; - final Map> pipeMap = new Object2ObjectOpenHashMap<>(); - - final INetAlgorithm.NetAlgorithmWrapper netAlgorithm; - - private boolean validAlgorithmInstance = false; + PipeType extends Enum & IPipeType> + extends WorldPipeNetBase { /** * Standard pipenet representation. Provides the base form of the pipenet abstraction. @@ -63,479 +21,8 @@ public abstract class WorldPipeNetSimple(NetEdge.class); - else this.pipeGraph = new SimpleWeightedGraph<>(NetEdge.class); - this.netAlgorithm = new INetAlgorithm.NetAlgorithmWrapper<>(); - this.isDirected = isDirected; - this.isSinglePath = isSinglePath; - this.isFlow = false; - } - - protected WorldPipeNetSimple(String name, boolean isDirected, boolean isSinglePath, - Graph, NetEdge> graph) { - super(name); - this.pipeGraph = graph; - this.netAlgorithm = new INetAlgorithm.NetAlgorithmWrapper<>(); - this.isDirected = isDirected; - this.isSinglePath = isSinglePath; - this.isFlow = true; - } - - public final Graph, NetEdge> getGraph() { - return this.pipeGraph; - } - - public final boolean isDirected() { - return isDirected; - } - - public final boolean isSinglePath() { - return isSinglePath; - } - - public final boolean isFlow() { - return isFlow; - } - - protected void markAlgInvalid() { - this.validAlgorithmInstance = false; - } - - protected void markAlgValid() { - this.validAlgorithmInstance = true; - } - - protected boolean hasValidAlg() { - return this.validAlgorithmInstance; - } - - public World getWorld() { - return this.worldRef.get(); - } - - protected void setWorldAndInit(World world) { - if (world != this.worldRef.get()) { - this.worldRef = new WeakReference<>(world); - onWorldSet(); - // some builders have to wait for world set, so we wait until then to build them. - if (this.builders != null) this.builders.forEach(INBTBuilder::build); - } - } - - public static String getDataID(final String baseID, final World world) { - if (world == null || world.isRemote) - throw new RuntimeException("WorldPipeNetSimple should only be created on the server!"); - int dimension = world.provider.getDimension(); - return dimension == 0 ? baseID : baseID + '.' + dimension; - } - - protected void onWorldSet() { - this.rebuildNetAlgorithm(); - } - - /** - * Preferred override. Only collects a fresh TE from the server if the provided TE is invalid. - * - * @param tile The {@link TileEntityPipeBase} that paths are being requested for - * @param testObject Can be null for simple nets. Complex nets need this for their behavior. - * @return the ordered list of paths associated with the {@link TileEntityPipeBase} - */ - public List> getPaths(TileEntityPipeBase tile, - Object testObject) { - return getPaths(this.pipeMap.get(tile.getPipePos()), tile, testObject); - } - - /** - * Special-case override. Forces the collection of a fresh TE from the server. - * - * @param pos The {@link BlockPos} that paths are being requested for - * @param testObject Can be null for simple nets. Complex nets need this for their behavior. - * @return the ordered list of paths associated with the {@link BlockPos} - */ - public List> getPaths(BlockPos pos, Object testObject) { - return getPaths(this.pipeMap.get(pos), null, testObject); - } - - public List> getPaths(@Nullable NodeG node, - @Nullable TileEntityPipeBase tile, - Object testObject) { - if (node == null) return new ObjectArrayList<>(); - - node.setHeldMTE(tile); - - if (!this.hasValidAlg()) this.rebuildNetAlgorithm(); - - List> cache = node.getPathCache(); - if (cache != null) { - return verifyList(cache, node); - } - - List> list = this.netAlgorithm.getPathsList(node); - return verifyList(node.setPathCache(list), node); - } - - /** - * Verification removes paths ending in unloaded TEs, - * paths that don't connect to anything, - * and all paths if the source TE is unloaded. - */ - protected List> verifyList(List> list, - NodeG source) { - if (!verifyNode(source)) return new ObjectArrayList<>(); - return list.stream().filter(a -> verifyNode(a.getTargetNode()) && a.getWeight() != Double.POSITIVE_INFINITY) - .collect(Collectors.toList()); - } - - protected boolean verifyNode(NodeG node) { - node.getHeldMTESafe(); - return node.hasConnecteds(); - } - - @Nullable - protected TileEntityPipeBase castTE(TileEntity te) { - if (te instanceof TileEntityPipeBasepipe) { - if (!getBasePipeClass().isAssignableFrom(pipe.getClass())) { - return null; - } - return (TileEntityPipeBase) pipe; - } - return null; - } - - public void markNodeAsOldData(NodeG node) {} - - protected abstract Class> getBasePipeClass(); - - /** - * Make sure to override this if your NetGroups use data. - * - * @return The correct data variant - */ - protected AbstractGroupData getBlankGroupData() { - return null; - } - - public NodeG getOrCreateNode(@NotNull IPipeTile mte) { - NodeG node = this.pipeMap.get(mte.getPipePos()); - if (node != null) return node; - if (!canAttachNode(mte.getNodeData())) return null; - node = new NodeG<>(mte.getNodeData(), mte, this); - this.addNode(node); - return node; - } - - protected final boolean canNodesConnect(NodeG source, EnumFacing nodeFacing, - NodeG target) { - return areNodeBlockedConnectionsCompatible(source, nodeFacing, target) && - areMarksCompatible(source.mark, target.mark) && - areNodesCustomContactable(source.getData(), target.getData()); + super(name, isDirected, isSinglePath, + isDirected ? new SimpleDirectedWeightedGraph<>(NetEdge.class) : + new SimpleWeightedGraph<>(NetEdge.class)); } - - private static boolean areMarksCompatible(int mark1, int mark2) { - return mark1 == mark2 || mark1 == NodeG.DEFAULT_MARK || mark2 == NodeG.DEFAULT_MARK; - } - - private boolean areNodeBlockedConnectionsCompatible(NodeG source, EnumFacing nodeFacing, - NodeG target) { - return !source.isConnected(nodeFacing) && !target.isConnected(nodeFacing.getOpposite()); - } - - protected boolean areNodesCustomContactable(NodeDataType source, NodeDataType target) { - return true; - } - - protected boolean canAttachNode(NodeDataType nodeData) { - return true; - } - - public void updateActiveConnections(BlockPos nodePos, EnumFacing side, boolean connect) { - NodeG node = pipeMap.get(nodePos); - if (node == null || node.isConnected(side) == connect) return; - - node.setConnected(side, connect); - - NodeG nodeOffset = pipeMap.get(nodePos.offset(side)); - if (nodeOffset == null) return; - - nodeOffset.setConnected(side.getOpposite(), connect); - - if (connect) { - if (!node.isBlocked(side)) { - addEdge(nodeOffset, node, null); - this.predicateEdge(nodeOffset, node, side.getOpposite()); - if (!this.isDirected()) return; - } - if (!nodeOffset.isBlocked(side.getOpposite())) { - addEdge(node, nodeOffset, null); - this.predicateEdge(node, nodeOffset, side); - } - } else { - removeUndirectedEdge(node, nodeOffset); - } - } - - public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean blocked) { - if (!isDirected()) return; // no such thing as blocked connections on undirected graphs. - NodeG node = pipeMap.get(nodePos); - if (node == null || node.isBlocked(side) == blocked) return; - - node.setBlocked(side, blocked); - - NodeG nodeOffset = pipeMap.get(nodePos.offset(side)); - if (nodeOffset == null) return; - - if (!blocked) { - addEdge(nodeOffset, node, null); - this.predicateEdge(nodeOffset, node, side); - } else { - removeEdge(nodeOffset, node); - } - } - - public void updateMark(BlockPos nodePos, int newMark) { - NodeG node = pipeMap.get(nodePos); - - int oldMark = node.mark; - node.mark = newMark; - - for (EnumFacing side : EnumFacing.VALUES) { - NodeG nodeOffset = pipeMap.get(nodePos.offset(side)); - if (nodeOffset == null) continue; - if (!areNodeBlockedConnectionsCompatible(node, side, nodeOffset) || - !areNodesCustomContactable(node.getData(), nodeOffset.getData())) - continue; - if (areMarksCompatible(oldMark, nodeOffset.mark) == areMarksCompatible(newMark, nodeOffset.mark)) continue; - - if (areMarksCompatible(newMark, nodeOffset.mark)) { - addEdge(node, nodeOffset, null); - this.predicateEdge(node, nodeOffset, side); - } else { - removeEdge(node, nodeOffset); - } - } - } - - protected abstract Capability[] getConnectionCapabilities(); - - public boolean hasNode(BlockPos pos) { - return pipeMap.containsKey(pos); - } - - public void addNodeSilent(NodeG node) { - pipeGraph.addVertex(node); - this.pipeMap.put(node.getNodePos(), node); - // we do not need to invalidate the cache, because just adding a node means it's not connected to anything. - } - - public void addNode(NodeG node) { - addNodeSilent(node); - this.markDirty(); - } - - @Nullable - public NodeG getNode(BlockPos pos) { - return this.pipeMap.get(pos); - } - - public void addUndirectedEdge(NodeG source, NodeG target) { - this.addEdge(source, target, null); - if (this.isDirected()) this.addEdge(target, source, null); - } - - public void addEdge(NodeG source, NodeG target, - @Nullable AbstractEdgePredicate predicate) { - addEdge(source, target, source.getData().getWeightFactor() + target.getData().getWeightFactor(), predicate); - } - - public void addUndirectedEdge(NodeG source, NodeG target, - double weight) { - this.addEdge(source, target, weight, null); - if (this.isDirected()) this.addEdge(target, source, weight, null); - } - - public void addEdge(NodeG source, NodeG target, double weight, - @Nullable AbstractEdgePredicate predicate) { - if (pipeGraph.addEdge(source, target) != null) { - NetGroup.mergeEdge(source, target); - pipeGraph.setEdgeWeight(source, target, weight); - if (predicate != null) { - pipeGraph.getEdge(source, target).setPredicate(predicate); - } - this.markAlgInvalid(); - this.markDirty(); - } - } - - public void predicateUndirectedEdge(BlockPos pos, EnumFacing faceToNeighbour) { - NodeG source = this.pipeMap.get(pos); - NodeG target = this.pipeMap.get(pos.offset(faceToNeighbour)); - if (source != null && target != null) { - this.predicateUndirectedEdge(source, target, faceToNeighbour); - } - } - - public void predicateEdge(BlockPos pos, EnumFacing faceToNeighbour) { - NodeG source = this.pipeMap.get(pos); - NodeG target = this.pipeMap.get(pos.offset(faceToNeighbour)); - if (source != null && target != null) - this.predicateEdge(source, target, faceToNeighbour); - } - - public void predicateUndirectedEdge(NodeG source, NodeG target, - EnumFacing faceToNeighbour) { - this.predicateEdge(source, target, faceToNeighbour); - if (this.isDirected()) this.predicateEdge(target, source, faceToNeighbour.getOpposite()); - } - - public void predicateEdge(NodeG source, NodeG target, - EnumFacing faceToNeighbour) { - if (!this.pipeGraph.containsEdge(source, target)) return; - Cover thisCover = source.getHeldMTESafe().getCoverableImplementation().getCoverAtSide(faceToNeighbour); - Cover neighbourCover = target.getHeldMTESafe().getCoverableImplementation() - .getCoverAtSide(faceToNeighbour.getOpposite()); - AbstractEdgePredicate predicate = getPredicate(thisCover, neighbourCover); - predicate.setPosInfo(source.getNodePos(), target.getNodePos()); - NetEdge edge = this.pipeGraph.getEdge(source, target); - edge.setPredicate(predicate); - } - - protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbourCover) { - return shutterify(new BasicEdgePredicate(), thisCover, neighbourCover); - } - - protected final AbstractEdgePredicate shutterify(AbstractEdgePredicate predicate, @Nullable Cover thisCover, - @Nullable Cover neighbourCover) { - if (predicate instanceof IShutteredEdgePredicate shutteredEdgePredicate) { - if (thisCover instanceof CoverShutter shutter) { - shutteredEdgePredicate.setShutteredSource(shutter.isWorkingEnabled()); - } - if (neighbourCover instanceof CoverShutter shutter) { - shutteredEdgePredicate.setShutteredTarget(shutter.isWorkingEnabled()); - } - } - return predicate; - } - - public void removeUndirectedEdge(NodeG source, NodeG target) { - this.removeEdge(source, target); - if (isDirected()) this.removeEdge(target, source); - } - - public void removeEdge(NodeG source, NodeG target) { - if (source.getGroupSafe() != null && source.getGroupSafe().splitEdge(source, target)) { - this.markAlgInvalid(); - this.markDirty(); - } - } - - public void removeNode(BlockPos pos) { - this.removeNode(this.pipeMap.get(pos)); - } - - public void removeNode(@Nullable NodeG node) { - if (node != null) { - if (this.pipeGraph.edgesOf(node).size() != 0) this.markAlgInvalid(); - if (node.getGroupUnsafe() != null) { - node.getGroupUnsafe().splitNode(node); - } else this.pipeGraph.removeVertex(node); - this.pipeMap.remove(node.getNodePos()); - this.markDirty(); - } - } - - public NetGroup getGroup(BlockPos pos) { - NodeG node = this.getNode(pos); - if (node == null) return null; - if (node.getGroupSafe() != null) return node.getGroupSafe(); - return node.setGroup(new NetGroup<>(this.pipeGraph, this)); - } - - public boolean markNodeAsActive(BlockPos nodePos, boolean isActive) { - NodeG node = this.pipeMap.get(nodePos); - if (node != null && node.isActive != isActive) { - node.isActive = isActive; - this.markDirty(); - return true; - } - return false; - } - - protected void rebuildNetAlgorithm() { - if (!this.isSinglePath()) { - this.netAlgorithm.setAlg(new ShortestPathsAlgorithm<>(pipeGraph)); - } else { - this.netAlgorithm.setAlg(new SinglePathAlgorithm<>(pipeGraph, isDirected())); - } - this.markAlgValid(); - } - - @Override - public void readFromNBT(NBTTagCompound nbt) { - if (!nbt.hasKey("NetEdges")) { - return; - } - this.builders = new ObjectOpenHashSet<>(); - NBTTagList allPipeNodes = nbt.getTagList("PipeNodes", Constants.NBT.TAG_COMPOUND); - Map> longPosMap = new Long2ObjectOpenHashMap<>(); - for (int i = 0; i < allPipeNodes.tagCount(); i++) { - NBTTagCompound pNodeTag = allPipeNodes.getCompoundTagAt(i); - NodeG node = new NodeG<>(pNodeTag, this); - longPosMap.put(node.getLongPos(), node); - this.addNodeSilent(node); - } - NBTTagList allNetEdges = nbt.getTagList("NetEdges", Constants.NBT.TAG_COMPOUND); - for (int i = 0; i < allNetEdges.tagCount(); i++) { - NBTTagCompound gEdgeTag = allNetEdges.getCompoundTagAt(i); - this.builders.add(new NetEdge.NBTBuilder<>(longPosMap, gEdgeTag, this::addEdge)); - } - NBTTagList allNetGroups = nbt.getTagList("NetGroups", Constants.NBT.TAG_COMPOUND); - for (int i = 0; i < allNetGroups.tagCount(); i++) { - NBTTagCompound gTag = allNetGroups.getCompoundTagAt(i); - this.builders.add(new NetGroup.NBTBuilder<>(longPosMap, gTag, this.pipeGraph, this)); - } - } - - @NotNull - @Override - public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { - NBTTagList allPipeNodes = new NBTTagList(); - Set> groups = new ObjectOpenHashSet<>(); - for (NodeG node : pipeGraph.vertexSet()) { - if (node.getGroupUnsafe() != null) groups.add(node.getGroupUnsafe()); - NBTTagCompound nodeTag = node.serializeNBT(); - NBTTagCompound dataTag = new NBTTagCompound(); - writeNodeData(node.getData(), dataTag); - nodeTag.setTag("Data", dataTag); - allPipeNodes.appendTag(nodeTag); - } - compound.setTag("PipeNodes", allPipeNodes); - - NBTTagList allNetEdges = new NBTTagList(); - for (NetEdge edge : pipeGraph.edgeSet()) { - allNetEdges.appendTag(edge.serializeNBT()); - } - compound.setTag("NetEdges", allNetEdges); - - NBTTagList allNetGroups = new NBTTagList(); - for (NetGroup group : groups) { - allNetGroups.appendTag(group.serializeNBT()); - } - compound.setTag("NetGroups", allNetGroups); - - return compound; - } - - /** - * Serializes node data into specified tag compound - * Used for writing persistent node data - */ - protected abstract void writeNodeData(NodeDataType nodeData, NBTTagCompound tagCompound); - - /** - * Deserializes node data from specified tag compound - * Used for reading persistent node data - */ - protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); } diff --git a/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java index fa314bd8478..daa72eb288f 100644 --- a/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java @@ -1,31 +1,32 @@ package gregtech.api.pipenet.alg; import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.NodeG; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; import java.util.List; @FunctionalInterface -public interface INetAlgorithm & IPipeType, NDT extends INodeData> { +public interface INetAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> { - List> getPathsList(NodeG source); + List> getPathsList(NetNode source); class NetAlgorithmWrapper & IPipeType, - NodeDataType extends INodeData> { + NodeDataType extends INodeData, E extends NetEdge> { - INetAlgorithm alg; + INetAlgorithm alg; - public void setAlg(INetAlgorithm alg) { + public void setAlg(INetAlgorithm alg) { this.alg = alg; } - public INetAlgorithm getAlg() { + public INetAlgorithm getAlg() { return alg; } - public List> getPathsList(NodeG source) { + public List> getPathsList(NetNode source) { if (alg == null) return null; return alg.getPathsList(source); } diff --git a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java index 36f260dfb9a..17aac266f6e 100644 --- a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java @@ -1,10 +1,10 @@ package gregtech.api.pipenet.alg; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetEdge; +import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.NodeG; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.Graph; @@ -16,27 +16,27 @@ import java.util.List; public final class ShortestPathsAlgorithm & IPipeType, - NDT extends INodeData> extends CHManyToManyShortestPaths, NetEdge> - implements INetAlgorithm { + NDT extends INodeData, E extends NetEdge> extends CHManyToManyShortestPaths, E> + implements INetAlgorithm { - public ShortestPathsAlgorithm(Graph, NetEdge> graph) { + public ShortestPathsAlgorithm(Graph, E> graph) { super(graph); } @Override - public List> getPathsList(NodeG source) { + public List> getPathsList(NetNode source) { if (!graph.containsVertex(source)) { throw new IllegalArgumentException("Graph must contain the source vertex"); } - List> paths = new ObjectArrayList<>(); + List> paths = new ObjectArrayList<>(); paths.add(new NetPath<>(source)); // if the source has no group, it has no paths other than the path to itself. if (source.getGroupUnsafe() == null) return paths; - ManyToManyShortestPaths, NetEdge> manyToManyPaths = getManyToManyPaths( + ManyToManyShortestPaths, E> manyToManyPaths = getManyToManyPaths( Collections.singleton(source), source.getGroupSafe().getNodes()); - for (NodeG v : source.getGroupSafe().getNodes()) { + for (NetNode v : source.getGroupSafe().getNodes()) { if (v == source) continue; - GraphPath, NetEdge> path = manyToManyPaths.getPath(source, v); + GraphPath, E> path = manyToManyPaths.getPath(source, v); if (path != null) { paths.add(new NetPath<>(path)); } diff --git a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java index c5f85c9c3a7..86918e9f7ef 100644 --- a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java @@ -1,10 +1,10 @@ package gregtech.api.pipenet.alg; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetEdge; +import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.NodeG; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.Graph; @@ -12,33 +12,33 @@ import java.util.Iterator; import java.util.List; -public final class SinglePathAlgorithm & IPipeType, NDT extends INodeData> - implements INetAlgorithm { +public final class SinglePathAlgorithm & IPipeType, NDT extends INodeData, + E extends NetEdge> implements INetAlgorithm { - private final Graph, NetEdge> graph; + private final Graph, E> graph; private final boolean isDirected; - public SinglePathAlgorithm(Graph, NetEdge> graph, boolean isDirected) { + public SinglePathAlgorithm(Graph, E> graph, boolean isDirected) { this.graph = graph; this.isDirected = isDirected; } @Override - public List> getPathsList(NodeG source) { + public List> getPathsList(NetNode source) { if (!this.graph.containsVertex(source)) { throw new IllegalArgumentException("Graph must contain the source vertex"); } - List> paths = new ObjectArrayList<>(); - List edges = new ObjectArrayList<>(); - List> nodes = new ObjectArrayList<>(); + List> paths = new ObjectArrayList<>(); + List edges = new ObjectArrayList<>(); + List> nodes = new ObjectArrayList<>(); nodes.add(source); - NodeG lastNode = null; - NodeG node = source; - NetEdge edge; + NetNode lastNode = null; + NetNode node = source; + E edge; double sumWeight = source.getData().getWeightFactor(); boolean valid = true; while (valid) { - Iterator i = this.graph.outgoingEdgesOf(node).iterator(); + Iterator i = this.graph.outgoingEdgesOf(node).iterator(); if (!i.hasNext()) break; // we've reached the end, exit the loop while still valid edge = i.next(); // if we are directed, we know that the target is the target. diff --git a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java index 63bd02fbe6d..7cbc1d1a1f3 100644 --- a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java @@ -9,7 +9,8 @@ import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.pipenet.IBlockAppearance; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.WorldPipeNetSimple; +import gregtech.api.pipenet.WorldPipeNetBase; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.PipeCoverableImplementation; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -65,11 +66,11 @@ @SuppressWarnings("deprecation") public abstract class BlockPipe & IPipeType, - NodeDataType extends INodeData, - WorldPipeNetType extends WorldPipeNetSimple> extends BuiltInRenderBlock + NodeDataType extends INodeData, Edge extends NetEdge, + WorldPipeNetType extends WorldPipeNetBase> extends BuiltInRenderBlock implements ITileEntityProvider, IFacadeWrapper, IBlockAppearance { - protected final ThreadLocal> tileEntities = new ThreadLocal<>(); + protected final ThreadLocal> tileEntities = new ThreadLocal<>(); public BlockPipe() { super(net.minecraft.block.material.Material.IRON); @@ -111,27 +112,28 @@ public static Cuboid6 getCoverSideBox(EnumFacing side, float thickness) { public abstract WorldPipeNetType getWorldPipeNet(World world); - public abstract TileEntityPipeBase createNewTileEntity(boolean supportsTicking); + public abstract TileEntityPipeBase createNewTileEntity(boolean supportsTicking); - public abstract NodeDataType createProperties(IPipeTile pipeTile); + public abstract NodeDataType createProperties(IPipeTile pipeTile); public abstract NodeDataType createItemProperties(ItemStack itemStack); - public abstract ItemStack getDropItem(IPipeTile pipeTile); + public abstract ItemStack getDropItem(IPipeTile pipeTile); protected abstract NodeDataType getFallbackType(); // TODO this has no reason to need an ItemStack parameter public abstract PipeType getItemPipeType(ItemStack itemStack); - public abstract void setTileEntityData(TileEntityPipeBase pipeTile, ItemStack itemStack); + public abstract void setTileEntityData(TileEntityPipeBase pipeTile, + ItemStack itemStack); @Override public abstract void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList items); @Override public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); + IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); if (pipeTile != null) { pipeTile.getCoverableImplementation().dropAllCovers(); tileEntities.set(pipeTile); @@ -148,7 +150,7 @@ public void onBlockAdded(World worldIn, @NotNull BlockPos pos, @NotNull IBlockSt @Override public void updateTick(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, @NotNull Random rand) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); + IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); if (pipeTile != null) { if (worldIn.isRemote) return; int activeConnections = pipeTile.getConnections(); @@ -160,9 +162,9 @@ public void updateTick(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull I @Override public void onBlockPlacedBy(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, @NotNull EntityLivingBase placer, @NotNull ItemStack stack) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); + IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); if (pipeTile != null) { - setTileEntityData((TileEntityPipeBase) pipeTile, stack); + setTileEntityData((TileEntityPipeBase) pipeTile, stack); // Color pipes/cables on place if holding spray can in off-hand if (placer instanceof EntityPlayer) { @@ -183,7 +185,7 @@ public void onBlockPlacedBy(@NotNull World worldIn, @NotNull BlockPos pos, @NotN public void neighborChanged(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos, @NotNull Block blockIn, @NotNull BlockPos fromPos) { if (worldIn.isRemote) return; - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); + IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); if (pipeTile != null) { pipeTile.getCoverableImplementation().updateInputRedstoneSignals(); EnumFacing facing = GTUtility.getFacingToNeighbor(pos, fromPos); @@ -204,7 +206,7 @@ public void neighborChanged(@NotNull IBlockState state, @NotNull World worldIn, @Override public void onNeighborChange(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull BlockPos neighbor) { - IPipeTile pipeTile = getPipeTileEntity(world, pos); + IPipeTile pipeTile = getPipeTileEntity(world, pos); if (pipeTile != null) { EnumFacing facing = GTUtility.getFacingToNeighbor(pos, neighbor); if (facing != null) { @@ -216,7 +218,7 @@ public void onNeighborChange(@NotNull IBlockAccess world, @NotNull BlockPos pos, @Override public boolean canConnectRedstone(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, @Nullable EnumFacing side) { - IPipeTile pipeTile = getPipeTileEntity(world, pos); + IPipeTile pipeTile = getPipeTileEntity(world, pos); return pipeTile != null && pipeTile.getCoverableImplementation().canConnectRedstone(side); } @@ -231,15 +233,15 @@ public boolean shouldCheckWeakPower(@NotNull IBlockState state, @NotNull IBlockA @Override public int getWeakPower(@NotNull IBlockState blockState, @NotNull IBlockAccess blockAccess, @NotNull BlockPos pos, @NotNull EnumFacing side) { - IPipeTile pipeTile = getPipeTileEntity(blockAccess, pos); + IPipeTile pipeTile = getPipeTileEntity(blockAccess, pos); return pipeTile == null ? 0 : pipeTile.getCoverableImplementation().getOutputRedstoneSignal(side.getOpposite()); } public void updateActiveNodeStatus(@NotNull World worldIn, BlockPos pos, - IPipeTile pipeTile) { + IPipeTile pipeTile) { if (worldIn.isRemote) return; - WorldPipeNetSimple pipeNet = getWorldPipeNet(worldIn); + WorldPipeNetBase pipeNet = getWorldPipeNet(worldIn); if (pipeNet != null && pipeTile != null) { int activeConnections = pipeTile.getConnections(); // remove blocked connections boolean isActiveNodeNow = activeConnections != 0; @@ -266,7 +268,7 @@ protected void onActiveModeChange(World world, BlockPos pos, boolean isActiveNow @Override public ItemStack getPickBlock(@NotNull IBlockState state, @NotNull RayTraceResult target, @NotNull World world, @NotNull BlockPos pos, @NotNull EntityPlayer player) { - IPipeTile pipeTile = getPipeTileEntity(world, pos); + IPipeTile pipeTile = getPipeTileEntity(world, pos); if (pipeTile == null) { return ItemStack.EMPTY; } @@ -284,7 +286,7 @@ public ItemStack getPickBlock(@NotNull IBlockState state, @NotNull RayTraceResul public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, @NotNull EntityPlayer playerIn, @NotNull EnumHand hand, @NotNull EnumFacing facing, float hitX, float hitY, float hitZ) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); + IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); CuboidRayTraceResult rayTraceResult = getServerCollisionRayTrace(playerIn, pos, worldIn); if (rayTraceResult == null || pipeTile == null) { @@ -295,7 +297,7 @@ public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @ public boolean onPipeActivated(World world, IBlockState state, BlockPos pos, EntityPlayer entityPlayer, EnumHand hand, EnumFacing side, CuboidRayTraceResult hit, - IPipeTile pipeTile) { + IPipeTile pipeTile) { ItemStack itemStack = entityPlayer.getHeldItem(hand); if (pipeTile.getFrameMaterial() == null && @@ -303,7 +305,7 @@ public boolean onPipeActivated(World world, IBlockState state, BlockPos pos, Ent pipeTile.getPipeType().getThickness() < 1) { BlockFrame frameBlock = BlockFrame.getFrameBlockFromItem(itemStack); if (frameBlock != null) { - ((TileEntityPipeBase) pipeTile) + ((TileEntityPipeBase) pipeTile) .setFrameMaterial(frameBlock.getGtMaterial(itemStack)); SoundType type = frameBlock.getSoundType(itemStack); world.playSound(entityPlayer, pos, type.getPlaceSound(), SoundCategory.BLOCKS, @@ -392,7 +394,8 @@ public boolean onPipeActivated(World world, IBlockState state, BlockPos pos, Ent } private boolean activateFrame(World world, IBlockState state, BlockPos pos, EntityPlayer entityPlayer, - EnumHand hand, CuboidRayTraceResult hit, IPipeTile pipeTile) { + EnumHand hand, CuboidRayTraceResult hit, + IPipeTile pipeTile) { if (pipeTile.getFrameMaterial() != null && !(entityPlayer.getHeldItem(hand).getItem() instanceof ItemBlockPipe)) { BlockFrame blockFrame = MetaBlocks.FRAMES.get(pipeTile.getFrameMaterial()); @@ -407,7 +410,7 @@ private boolean activateFrame(World world, IBlockState state, BlockPos pos, Enti * -1 if ItemStack failed the capability check (no action done, continue checks). */ public EnumActionResult onPipeToolUsed(World world, BlockPos pos, ItemStack stack, EnumFacing coverSide, - IPipeTile pipeTile, EntityPlayer entityPlayer, + IPipeTile pipeTile, EntityPlayer entityPlayer, EnumHand hand) { if (isPipeTool(stack)) { if (!entityPlayer.world.isRemote) { @@ -438,7 +441,7 @@ protected boolean isPipeTool(@NotNull ItemStack stack) { @Override public void onBlockClicked(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull EntityPlayer playerIn) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); + IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); CuboidRayTraceResult rayTraceResult = (CuboidRayTraceResult) RayTracer.retraceBlock(worldIn, playerIn, pos); if (pipeTile == null || rayTraceResult == null) { return; @@ -452,8 +455,9 @@ public void onBlockClicked(@NotNull World worldIn, @NotNull BlockPos pos, @NotNu } @Override - public void onEntityCollision(World worldIn, BlockPos pos, IBlockState state, Entity entityIn) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); + public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, + @NotNull Entity entityIn) { + IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); if (pipeTile != null && pipeTile.getFrameMaterial() != null) { // make pipe with frame climbable BlockFrame blockFrame = MetaBlocks.FRAMES.get(pipeTile.getFrameMaterial()); @@ -465,7 +469,7 @@ public void onEntityCollision(World worldIn, BlockPos pos, IBlockState state, En @Override public void harvestBlock(@NotNull World worldIn, @NotNull EntityPlayer player, @NotNull BlockPos pos, @NotNull IBlockState state, @Nullable TileEntity te, @NotNull ItemStack stack) { - tileEntities.set(te == null ? tileEntities.get() : (IPipeTile) te); + tileEntities.set(te == null ? tileEntities.get() : (IPipeTile) te); super.harvestBlock(worldIn, player, pos, state, te, stack); tileEntities.remove(); } @@ -473,7 +477,7 @@ public void harvestBlock(@NotNull World worldIn, @NotNull EntityPlayer player, @ @Override public void getDrops(@NotNull NonNullList drops, @NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull IBlockState state, int fortune) { - IPipeTile pipeTile = tileEntities.get() == null ? getPipeTileEntity(world, pos) : + IPipeTile pipeTile = tileEntities.get() == null ? getPipeTileEntity(world, pos) : tileEntities.get(); if (pipeTile == null) return; if (pipeTile.getFrameMaterial() != null) { @@ -488,7 +492,7 @@ public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World wor @NotNull AxisAlignedBB entityBox, @NotNull List collidingBoxes, @Nullable Entity entityIn, boolean isActualState) { // This iterator causes some heap memory overhead - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); + IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); if (pipeTile != null && pipeTile.getFrameMaterial() != null) { AxisAlignedBB box = BlockFrame.COLLISION_BOX.offset(pos); if (box.intersects(entityBox)) { @@ -533,7 +537,7 @@ public CuboidRayTraceResult getServerCollisionRayTrace(EntityPlayer playerIn, Bl @Override public BlockFaceShape getBlockFaceShape(@NotNull IBlockAccess worldIn, @NotNull IBlockState state, @NotNull BlockPos pos, @NotNull EnumFacing face) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); + IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); if (pipeTile != null && pipeTile.getCoverableImplementation().getCoverAtSide(face) != null) { return BlockFaceShape.SOLID; } @@ -543,7 +547,8 @@ public BlockFaceShape getBlockFaceShape(@NotNull IBlockAccess worldIn, @NotNull @Override public boolean recolorBlock(World world, @NotNull BlockPos pos, @NotNull EnumFacing side, @NotNull EnumDyeColor color) { - IPipeTile tileEntityPipe = (IPipeTile) world.getTileEntity(pos); + IPipeTile tileEntityPipe = (IPipeTile) world + .getTileEntity(pos); if (tileEntityPipe != null && tileEntityPipe.getPipeType() != null && tileEntityPipe.getPipeType().isPaintable() && tileEntityPipe.getPaintingColor() != color.colorValue) { @@ -560,20 +565,20 @@ protected boolean isThisPipeBlock(Block block) { /** * Just returns proper pipe tile entity */ - public IPipeTile getPipeTileEntity(IBlockAccess world, BlockPos selfPos) { + public IPipeTile getPipeTileEntity(IBlockAccess world, BlockPos selfPos) { TileEntity tileEntityAtPos = world.getTileEntity(selfPos); return getPipeTileEntity(tileEntityAtPos); } - public IPipeTile getPipeTileEntity(TileEntity tileEntityAtPos) { + public IPipeTile getPipeTileEntity(TileEntity tileEntityAtPos) { if (tileEntityAtPos instanceof IPipeTile && - isThisPipeBlock(((IPipeTile) tileEntityAtPos).getPipeBlock())) { - return (IPipeTile) tileEntityAtPos; + isThisPipeBlock(((IPipeTile) tileEntityAtPos).getPipeBlock())) { + return (IPipeTile) tileEntityAtPos; } return null; } - public boolean canConnect(IPipeTile selfTile, EnumFacing facing) { + public boolean canConnect(IPipeTile selfTile, EnumFacing facing) { if (selfTile.getPipeWorld().getBlockState(selfTile.getPipePos().offset(facing)).getBlock() == Blocks.AIR) return false; Cover cover = selfTile.getCoverableImplementation().getCoverAtSide(facing); @@ -582,22 +587,28 @@ public boolean canConnect(IPipeTile selfTile, EnumFacing } TileEntity other = selfTile.getNeighbor(facing); if (other instanceof IPipeTile) { - cover = ((IPipeTile) other).getCoverableImplementation().getCoverAtSide(facing.getOpposite()); + cover = ((IPipeTile) other).getCoverableImplementation().getCoverAtSide(facing.getOpposite()); if (cover != null && !cover.canPipePassThrough()) return false; - return canPipesConnect(selfTile, facing, (IPipeTile) other); + return canPipesConnect(selfTile, facing, (IPipeTile) other); } return canPipeConnectToBlock(selfTile, facing, other); } - public abstract boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile); + public abstract boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, + IPipeTile sideTile); - public abstract boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, + public abstract boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, @Nullable TileEntity tile); + public boolean canPipeConnectToBlock(World world, BlockPos pos, EnumFacing side, @Nullable TileEntity tile) { + var te = getPipeTileEntity(world, pos); + if (te == null) return false; + return canPipeConnectToBlock(te, side, tile); + } + private List getCollisionBox(IBlockAccess world, BlockPos pos, @Nullable Entity entityIn) { - IPipeTile pipeTile = getPipeTileEntity(world, pos); + IPipeTile pipeTile = getPipeTileEntity(world, pos); if (pipeTile == null) { return Collections.emptyList(); } @@ -645,7 +656,7 @@ public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, En public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, ItemStack stack) { if (isPipeTool(stack)) return true; - IPipeTile pipeTile = getPipeTileEntity(world, pos); + IPipeTile pipeTile = getPipeTileEntity(world, pos); if (pipeTile == null) return false; PipeCoverableImplementation coverable = pipeTile.getCoverableImplementation(); @@ -672,7 +683,7 @@ public IBlockState getFacade(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull @Override public IBlockState getFacade(@NotNull IBlockAccess world, @NotNull BlockPos pos, EnumFacing side) { - IPipeTile pipeTileEntity = getPipeTileEntity(world, pos); + IPipeTile pipeTileEntity = getPipeTileEntity(world, pos); if (pipeTileEntity != null && side != null) { Cover cover = pipeTileEntity.getCoverableImplementation().getCoverAtSide(side); if (cover instanceof IFacadeCover) { diff --git a/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java b/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java index 961cb1307df..8ec0406531c 100644 --- a/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java @@ -18,9 +18,9 @@ public class ItemBlockPipe & IPipeType, NodeDataType extends INodeData> extends ItemBlock { - protected final BlockPipe blockPipe; + protected final BlockPipe blockPipe; - public ItemBlockPipe(BlockPipe block) { + public ItemBlockPipe(BlockPipe block) { super(block); this.blockPipe = block; setHasSubtypes(true); diff --git a/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java b/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java index 17f93eafbba..6cc49be9342 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java @@ -2,9 +2,10 @@ import gregtech.api.GTValues; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.WorldPipeNetSimple; +import gregtech.api.pipenet.WorldPipeNetBase; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; @@ -28,9 +29,9 @@ public abstract class BlockMaterialPipe< PipeType extends Enum & IPipeType & IMaterialPipeType, - NodeDataType extends INodeData, - WorldPipeNetType extends WorldPipeNetSimple> - extends BlockPipe { + NodeDataType extends INodeData, Edge extends NetEdge, + WorldPipeNetType extends WorldPipeNetBase> + extends BlockPipe { protected final PipeType pipeType; private final MaterialRegistry registry; @@ -41,9 +42,9 @@ public BlockMaterialPipe(@NotNull PipeType pipeType, @NotNull MaterialRegistry r } @Override - public NodeDataType createProperties(IPipeTile pipeTile) { + public NodeDataType createProperties(IPipeTile pipeTile) { PipeType pipeType = pipeTile.getPipeType(); - Material material = ((IMaterialPipeTile) pipeTile).getPipeMaterial(); + Material material = ((IMaterialPipeTile) pipeTile).getPipeMaterial(); if (pipeType == null || material == null) { return getFallbackType(); } @@ -70,14 +71,14 @@ public Material getItemMaterial(ItemStack itemStack) { } @Override - public void setTileEntityData(TileEntityPipeBase pipeTile, ItemStack itemStack) { - ((TileEntityMaterialPipeBase) pipeTile).setPipeData(this, pipeType, + public void setTileEntityData(TileEntityPipeBase pipeTile, ItemStack itemStack) { + ((TileEntityMaterialPipeBase) pipeTile).setPipeData(this, pipeType, getItemMaterial(itemStack)); } @Override - public ItemStack getDropItem(IPipeTile pipeTile) { - Material material = ((IMaterialPipeTile) pipeTile).getPipeMaterial(); + public ItemStack getDropItem(IPipeTile pipeTile) { + Material material = ((IMaterialPipeTile) pipeTile).getPipeMaterial(); return getItem(material); } diff --git a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java b/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java index 9f72c027806..85c2838d466 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java +++ b/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java @@ -2,12 +2,13 @@ import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.Material; public interface IMaterialPipeTile & IPipeType, - NodeDataType extends INodeData> - extends IPipeTile { + NodeDataType extends INodeData, Edge extends NetEdge> + extends IPipeTile { Material getPipeMaterial(); } diff --git a/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java b/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java index d8aaf57d31d..a348fa05379 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java @@ -12,7 +12,7 @@ public class ItemBlockMaterialPipe & IMaterialPi NodeDataType extends INodeData> extends ItemBlockPipe { - public ItemBlockMaterialPipe(BlockMaterialPipe block) { + public ItemBlockMaterialPipe(BlockMaterialPipe block) { super(block); } @@ -20,7 +20,7 @@ public ItemBlockMaterialPipe(BlockMaterialPipe block) @Override public String getItemStackDisplayName(@NotNull ItemStack stack) { PipeType pipeType = blockPipe.getItemPipeType(stack); - Material material = ((BlockMaterialPipe) blockPipe).getItemMaterial(stack); + Material material = ((BlockMaterialPipe) blockPipe).getItemMaterial(stack); return material == null ? " " : pipeType.getOrePrefix().getLocalNameForItem(material); } } diff --git a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java index 90101a6e5e1..632c2ca4365 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java @@ -2,6 +2,7 @@ import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.block.BlockPipe; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; @@ -16,8 +17,9 @@ import static gregtech.api.capability.GregtechDataCodes.UPDATE_PIPE_MATERIAL; public abstract class TileEntityMaterialPipeBase & IMaterialPipeType, - NodeDataType extends INodeData> extends TileEntityPipeBase - implements IMaterialPipeTile { + NodeDataType extends INodeData, Edge extends NetEdge> + extends TileEntityPipeBase + implements IMaterialPipeTile { private Material pipeMaterial = Materials.Aluminium; @@ -26,7 +28,8 @@ public Material getPipeMaterial() { return pipeMaterial; } - public void setPipeData(BlockPipe pipeBlock, PipeType pipeType, Material pipeMaterial) { + public void setPipeData(BlockPipe pipeBlock, PipeType pipeType, + Material pipeMaterial) { super.setPipeData(pipeBlock, pipeType); this.pipeMaterial = pipeMaterial; if (!getWorld().isRemote) { @@ -35,7 +38,7 @@ public void setPipeData(BlockPipe pipeBlock, PipeType } @Override - public void setPipeData(BlockPipe pipeBlock, PipeType pipeType) { + public void setPipeData(BlockPipe pipeBlock, PipeType pipeType) { throw new UnsupportedOperationException("Unsupported for TileEntityMaterialMaterialPipeBase"); } @@ -45,14 +48,14 @@ public int getDefaultPaintingColor() { } @Override - public BlockMaterialPipe getPipeBlock() { - return (BlockMaterialPipe) super.getPipeBlock(); + public BlockMaterialPipe getPipeBlock() { + return (BlockMaterialPipe) super.getPipeBlock(); } @Override - public void transferDataFrom(IPipeTile tileEntity) { + public void transferDataFrom(IPipeTile tileEntity) { super.transferDataFrom(tileEntity); - this.pipeMaterial = ((IMaterialPipeTile) tileEntity).getPipeMaterial(); + this.pipeMaterial = ((IMaterialPipeTile) tileEntity).getPipeMaterial(); } @NotNull diff --git a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java index 7bfa18461ff..164b60fb14f 100644 --- a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java +++ b/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java @@ -1,21 +1,22 @@ package gregtech.api.pipenet.block.simple; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.WorldPipeNetSimple; +import gregtech.api.pipenet.WorldPipeNetBase; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import net.minecraft.item.ItemStack; public abstract class BlockSimplePipe & IPipeType, - NodeDataType extends INodeData, - WorldPipeNetType extends WorldPipeNetSimple> - extends BlockPipe { + NodeDataType extends INodeData, Edge extends NetEdge, + WorldPipeNetType extends WorldPipeNetBase> + extends BlockPipe { @Override - public NodeDataType createProperties(IPipeTile pipeTile) { + public NodeDataType createProperties(IPipeTile pipeTile) { return createProperties(pipeTile.getPipeType()); } @@ -27,7 +28,7 @@ public NodeDataType createItemProperties(ItemStack itemStack) { protected abstract NodeDataType createProperties(PipeType pipeType); @Override - public ItemStack getDropItem(IPipeTile pipeTile) { + public ItemStack getDropItem(IPipeTile pipeTile) { return new ItemStack(this, 1, pipeTile.getPipeType().ordinal()); } @@ -37,7 +38,7 @@ public PipeType getItemPipeType(ItemStack itemStack) { } @Override - public void setTileEntityData(TileEntityPipeBase pipeTile, ItemStack itemStack) { + public void setTileEntityData(TileEntityPipeBase pipeTile, ItemStack itemStack) { pipeTile.setPipeData(this, getItemPipeType(itemStack)); } } diff --git a/src/main/java/gregtech/api/pipenet/block/simple/EmptyNodeData.java b/src/main/java/gregtech/api/pipenet/block/simple/EmptyNodeData.java deleted file mode 100644 index 7be0f955629..00000000000 --- a/src/main/java/gregtech/api/pipenet/block/simple/EmptyNodeData.java +++ /dev/null @@ -1,13 +0,0 @@ -package gregtech.api.pipenet.block.simple; - -import org.jetbrains.annotations.ApiStatus; - -@Deprecated -@ApiStatus.ScheduledForRemoval(inVersion = "2.9") -@SuppressWarnings("ALL") -public class EmptyNodeData { - - public static final EmptyNodeData INSTANCE = new EmptyNodeData(); - - private EmptyNodeData() {} -} diff --git a/src/main/java/gregtech/api/pipenet/edge/INetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/INetFlowEdge.java new file mode 100644 index 00000000000..b9ad592c3be --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/edge/INetFlowEdge.java @@ -0,0 +1,42 @@ +package gregtech.api.pipenet.edge; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.block.IPipeType; + +import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; + +public interface INetFlowEdge> { + + /** + * Claims a new, unique simulator instance for properly simulating flow edge limits without actually changing them. + *
+ * This simulator must be discarded after use so that the garbage collector can clean up. + */ + static ChannelSimulatorKey getNewSimulatorInstance() { + return new ChannelSimulatorKey(); + } + + & IPipeType, NDT extends INodeData> void consumeFlowLimit( + Object channel, + Graph, E> graph, + int amount, long queryTick, + @Nullable INetFlowEdge.ChannelSimulatorKey simulator); + + final class ChannelSimulatorKey { + + private static int ID; + private final int id; + + private ChannelSimulatorKey() { + this.id = ID++; + } + + @Override + public int hashCode() { + // enforcing hash uniqueness improves weak map performance + return id; + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java new file mode 100644 index 00000000000..2c7e462874e --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java @@ -0,0 +1,114 @@ +package gregtech.api.pipenet.edge; + +import gregtech.api.pipenet.AbstractEdgePredicate; +import gregtech.api.pipenet.INBTBuilder; +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.util.function.QuadConsumer; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.util.INBTSerializable; + +import org.jgrapht.graph.DefaultWeightedEdge; + +import java.util.Map; +import java.util.function.Predicate; + +public class NetEdge extends DefaultWeightedEdge implements INBTSerializable { + + private AbstractEdgePredicate predicate; + private boolean invertedPredicate; + + @SuppressWarnings("unused") // used via reflection + public NetEdge() {} + + public void setPredicate(AbstractEdgePredicate predicate) { + this.predicate = predicate; + this.invertedPredicate = predicate.getSourcePos() != this.getSource().getNodePos(); + } + + public Predicate getPredicate() { + // if we don't have a predicate, just assume that we're good. + if (predicate == null) return (a) -> true; + return predicate; + } + + public boolean isPredicateInverted() { + return invertedPredicate; + } + + @Override + public NetNode getSource() { + return (NetNode) super.getSource(); + } + + @Override + public NetNode getTarget() { + return (NetNode) super.getTarget(); + } + + @SuppressWarnings("unchecked") + public & IPipeType, NDT extends INodeData, + E extends NetEdge> NetNode getCastSource() { + return (NetNode) getSource(); + } + + @SuppressWarnings("unchecked") + public & IPipeType, NDT extends INodeData, + E extends NetEdge> NetNode getCastTarget() { + return (NetNode) getTarget(); + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setLong("SourceLongPos", getSource().getLongPos()); + tag.setLong("TargetLongPos", getTarget().getLongPos()); + tag.setDouble("Weight", getWeight()); + if (predicate != null) tag.setTag("Predicate", AbstractEdgePredicate.toNBT(predicate)); + tag.setBoolean("InvertedPredicate", isPredicateInverted()); + return tag; + } + + /** + * Use {@link NBTBuilder} instead, this does nothing. + */ + @Override + @Deprecated + public void deserializeNBT(NBTTagCompound nbt) {} + + public static final class NBTBuilder & IPipeType, + NodeDataType extends INodeData, E extends NetEdge> implements INBTBuilder { + + private final NetNode node1; + private final NetNode node2; + private final AbstractEdgePredicate predicate; + private final double weight; + private final boolean buildable; + + private final QuadConsumer, NetNode, Double, AbstractEdgePredicate> edgeProducer; + + public NBTBuilder(Map> longPosMap, NBTTagCompound tag, + QuadConsumer, NetNode, Double, AbstractEdgePredicate> edgeProducer) { + this.node1 = longPosMap.get(tag.getLong("SourceLongPos")); + this.node2 = longPosMap.get(tag.getLong("TargetLongPos")); + this.weight = tag.getDouble("Weight"); + this.predicate = AbstractEdgePredicate.nbtPredicate(tag.getCompoundTag("Predicate")); + if (predicate != null) { + if (tag.getBoolean("InvertedPredicate")) + this.predicate.setPosInfo(this.node2.getNodePos(), this.node1.getNodePos()); + else this.predicate.setPosInfo(this.node1.getNodePos(), this.node2.getNodePos()); + } + this.edgeProducer = edgeProducer; + this.buildable = node1 != null && node2 != null; + } + + @Override + public void build() { + if (buildable) { + edgeProducer.accept(node1, node2, weight, predicate); + } + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java new file mode 100644 index 00000000000..989c2dbed1e --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java @@ -0,0 +1,157 @@ +package gregtech.api.pipenet.edge; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.block.IPipeType; + +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; + +import java.util.List; +import java.util.WeakHashMap; + +public class NetFlowEdge extends NetEdge implements INetFlowEdge { + + private final int flowBufferTicks; + private final ChannelsHolder channels; + private final WeakHashMap simulatedChannels; + + private INodeData> minData; + + /** + * NetEdge that provides standard flow behavior handling + * + * @param flowBufferTicks Determines how many ticks of 'buffer' flow capacity can be built up along edges. Allows + * for once-an-interval push/pull operations instead of needing them every tick for maximum + * throughput. + */ + public NetFlowEdge(int flowBufferTicks) { + this.flowBufferTicks = flowBufferTicks; + this.channels = new ChannelsHolder(); + this.simulatedChannels = new WeakHashMap<>(9); + } + + private ChannelsHolder getChannels(@Nullable INetFlowEdge.ChannelSimulatorKey simulator) { + if (simulator == null) return this.channels; + else { + ChannelsHolder channels = simulatedChannels.get(simulator); + if (channels == null) { + channels = new ChannelsHolder(this.channels); + simulatedChannels.put(simulator, channels); + } + return channels; + } + } + + private INodeData> getMinData() { + if (this.minData == null) + this.minData = this.getCastSource().getData().getMinData(this.getCastTarget().getData()); + return this.minData; + } + + private int getAdjustedThroughput() { + return getMinData().getThroughput() * flowBufferTicks; + } + + private boolean cannotSupportChannel(Object channel, long queryTick, + @Nullable INetFlowEdge.ChannelSimulatorKey simulator) { + var channels = getChannels(simulator); + channels.recalculateFlowLimits(queryTick); + return channels.map.size() >= getMinData().getChannelMaxCount() && !channels.map.containsKey(channel); + } + + public & IPipeType, NDT extends INodeData> int getFlowLimit( + Object channel, + Graph, NetFlowEdge> graph, + long queryTick, + @Nullable INetFlowEdge.ChannelSimulatorKey simulator) { + if (this.cannotSupportChannel(channel, queryTick, simulator)) { + return 0; + } + int limit = getChannels(simulator).map.getOrDefault(channel, getAdjustedThroughput()); + + NetFlowEdge inverse = graph.getEdge(this.getCastTarget(), this.getCastSource()); + if (inverse != null && inverse != this) { + if (inverse.cannotSupportChannel(channel, queryTick, simulator)) return 0; + limit += inverse.getConsumedLimit(channel, queryTick, simulator); + } + + return limit; + } + + public & IPipeType, NDT extends INodeData> int getConsumedLimit( + Object channel, + long queryTick, + @Nullable INetFlowEdge.ChannelSimulatorKey simulator) { + var channels = getChannels(simulator); + channels.recalculateFlowLimits(queryTick); + int limit = getAdjustedThroughput(); + return limit - channels.map.getOrDefault(channel, limit); + } + + @Override + public & IPipeType, NDT extends INodeData> void consumeFlowLimit( + Object channel, + Graph, NetFlowEdge> graph, + int amount, + long queryTick, + @Nullable INetFlowEdge.ChannelSimulatorKey simulator) { + if (amount == 0) return; + var channels = getChannels(simulator); + channels.recalculateFlowLimits(queryTick); + + // check against reverse edge + NetFlowEdge inverse = graph.getEdge(this.getCastTarget(), this.getCastSource()); + if (inverse != null && inverse != this) { + int inverseConsumed = inverse.getConsumedLimit(channel, queryTick, simulator); + if (inverseConsumed != 0) { + int toFreeUp = Math.min(inverseConsumed, amount); + inverse.consumeFlowLimit(channel, graph, -toFreeUp, queryTick, simulator); + if (toFreeUp == amount) return; + amount -= toFreeUp; + } + } + + int finalAmount = amount; + channels.map.compute(channel, (k, v) -> { + int d = getAdjustedThroughput(); + if (v == null) v = d; + v -= finalAmount; + if (v >= d) return null; + return v; + }); + } + + private final class ChannelsHolder { + + public final Object2IntOpenHashMap map; + public long lastQueryTick; + + public ChannelsHolder() { + this.map = new Object2IntOpenHashMap<>(9); + } + + public ChannelsHolder(ChannelsHolder prototype) { + this.map = prototype.map.clone(); + this.lastQueryTick = prototype.lastQueryTick; + } + + public void recalculateFlowLimits(long queryTick) { + int time = (int) (queryTick - this.lastQueryTick); + if (time < 0) { + this.map.clear(); + } else { + List toRemove = new ObjectArrayList<>(); + this.map.replaceAll((k, v) -> { + v += time * getMinData().getThroughput(); + if (v >= getAdjustedThroughput()) toRemove.add(k); + return v; + }); + toRemove.forEach(this.map::removeInt); + } + this.lastQueryTick = queryTick; + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java new file mode 100644 index 00000000000..c38a28bc475 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java @@ -0,0 +1,44 @@ +package gregtech.api.pipenet.edge.util; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.INetFlowEdge; +import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.util.FluidTestObject; + +import org.jgrapht.Graph; + +import java.util.function.Consumer; + +public class FlowConsumer & IPipeType, NDT extends INodeData, + E extends NetEdge & INetFlowEdge> implements Consumer { + + private final INetFlowEdge edge; + private final FluidTestObject testObject; + private final Graph, E> graph; + private final int flow; + private final long tick; + private final INetFlowEdge.ChannelSimulatorKey simulatorKey; + + private double ratio = 1; + + public FlowConsumer(INetFlowEdge edge, FluidTestObject testObject, Graph, E> graph, int flow, + long tick, INetFlowEdge.ChannelSimulatorKey simulatorKey) { + this.edge = edge; + this.testObject = testObject; + this.graph = graph; + this.flow = flow; + this.tick = tick; + this.simulatorKey = simulatorKey; + } + + public void modifyRatio(Double ratio) { + this.ratio *= ratio; + } + + @Override + public void accept(Double finalRatio) { + edge.consumeFlowLimit(testObject, graph, (int) (finalRatio * ratio * flow), tick, simulatorKey); + } +} diff --git a/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java b/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java index b0511ed7668..898df301336 100644 --- a/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java +++ b/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java @@ -1,6 +1,6 @@ package gregtech.api.pipenet.longdist; -import gregtech.api.pipenet.WorldPipeNetSimple; +import gregtech.api.pipenet.WorldPipeNetBase; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; @@ -331,7 +331,7 @@ public static WorldData get(World world) { if (worldData != null) { return worldData; } - String DATA_ID = WorldPipeNetSimple.getDataID("long_dist_pipe", world); + String DATA_ID = WorldPipeNetBase.getDataID("long_dist_pipe", world); WorldData netWorldData = (WorldData) world.loadData(WorldData.class, DATA_ID); if (netWorldData == null) { netWorldData = new WorldData(DATA_ID); diff --git a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java deleted file mode 100644 index 0fcd26e631e..00000000000 --- a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNet.java +++ /dev/null @@ -1,145 +0,0 @@ -package gregtech.api.pipenet.tickable; - -import gregtech.api.pipenet.PipeNet; -import gregtech.api.pipenet.WorldPipeNet; - -import net.minecraft.util.ITickable; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.WorldServer; -import net.minecraft.world.chunk.Chunk; - -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.ApiStatus; - -import java.util.*; -import java.util.stream.Collectors; - -@Deprecated -@ApiStatus.ScheduledForRemoval(inVersion = "2.9") -public abstract class TickableWorldPipeNet & ITickable> - extends WorldPipeNet { - - private final Map> loadedChunksByPipeNet = new HashMap<>(); - private final Set tickingPipeNets = new HashSet<>(); - private final Set removeLater = new HashSet<>(); - - public TickableWorldPipeNet(String name) { - super(name); - } - - private boolean isChunkLoaded(ChunkPos chunkPos) { - WorldServer worldServer = (WorldServer) getWorld(); - if (worldServer == null) return false; - return worldServer.getChunkProvider().chunkExists(chunkPos.x, chunkPos.z); - } - - protected abstract int getUpdateRate(); - - public void update() { - if (getWorld().getTotalWorldTime() % getUpdateRate() == 0L) { - tickingPipeNets.forEach(ITickable::update); - } - if (removeLater.size() > 0) { - removeLater.forEach(tickingPipeNets::remove); - removeLater.clear(); - } - } - - public void onChunkLoaded(Chunk chunk) { - ChunkPos chunkPos = chunk.getPos(); - List pipeNetsInThisChunk = this.pipeNetsByChunk.get(chunkPos); - if (pipeNetsInThisChunk == null) return; - for (T pipeNet : pipeNetsInThisChunk) { - List loadedChunks = getOrCreateChunkListForPipeNet(pipeNet); - if (loadedChunks.isEmpty()) { - this.tickingPipeNets.add(pipeNet); - } - loadedChunks.add(chunkPos); - } - } - - public void onChunkUnloaded(Chunk chunk) { - ChunkPos chunkPos = chunk.getPos(); - List pipeNetsInThisChunk = this.pipeNetsByChunk.get(chunkPos); - if (pipeNetsInThisChunk == null) return; - for (T pipeNet : pipeNetsInThisChunk) { - List loadedChunks = this.loadedChunksByPipeNet.get(pipeNet); - if (loadedChunks != null && loadedChunks.contains(chunkPos)) { - loadedChunks.remove(chunkPos); - if (loadedChunks.isEmpty()) { - removeFromTicking(pipeNet); - } - } - } - } - - @Override - protected void onWorldSet() { - super.onWorldSet(); - Map> pipeNetByLoadedChunks = pipeNets.stream() - .map(pipeNet -> Pair.of(pipeNet, getPipeNetLoadedChunks(pipeNet))) - .filter(pair -> !pair.getRight().isEmpty()) - .collect(Collectors.toMap(Pair::getLeft, Pair::getRight)); - if (!pipeNetByLoadedChunks.isEmpty()) { - this.tickingPipeNets.addAll(pipeNetByLoadedChunks.keySet()); - this.loadedChunksByPipeNet.putAll(pipeNetByLoadedChunks); - } - } - - @Override - protected void addPipeNet(T pipeNet) { - super.addPipeNet(pipeNet); - List loadedChunks = getPipeNetLoadedChunks(pipeNet); - if (!loadedChunks.isEmpty()) { - this.loadedChunksByPipeNet.put(pipeNet, loadedChunks); - this.tickingPipeNets.add(pipeNet); - } - } - - private List getPipeNetLoadedChunks(T pipeNet) { - return pipeNet.getContainedChunks().stream() - .filter(this::isChunkLoaded) - .collect(Collectors.toList()); - } - - @Override - protected void removePipeNet(T pipeNet) { - super.removePipeNet(pipeNet); - if (loadedChunksByPipeNet.containsKey(pipeNet)) { - removeFromTicking(pipeNet); - } - } - - private void removeFromTicking(T pipeNet) { - this.loadedChunksByPipeNet.remove(pipeNet); - this.removeLater.add(pipeNet); - } - - private List getOrCreateChunkListForPipeNet(T pipeNet) { - return this.loadedChunksByPipeNet.computeIfAbsent(pipeNet, k -> new ArrayList<>()); - } - - @Override - protected void addPipeNetToChunk(ChunkPos chunkPos, T pipeNet) { - super.addPipeNetToChunk(chunkPos, pipeNet); - if (isChunkLoaded(chunkPos)) { - List loadedChunks = getOrCreateChunkListForPipeNet(pipeNet); - if (loadedChunks.isEmpty()) { - this.tickingPipeNets.add(pipeNet); - } - loadedChunks.add(chunkPos); - } - } - - @Override - protected void removePipeNetFromChunk(ChunkPos chunkPos, T pipeNet) { - super.removePipeNetFromChunk(chunkPos, pipeNet); - List loadedChunks = this.loadedChunksByPipeNet.get(pipeNet); - if (loadedChunks != null && loadedChunks.contains(chunkPos)) { - loadedChunks.remove(chunkPos); - if (loadedChunks.isEmpty()) { - removeFromTicking(pipeNet); - } - } - } -} diff --git a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java b/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java deleted file mode 100644 index f1b9f64aa23..00000000000 --- a/src/main/java/gregtech/api/pipenet/tickable/TickableWorldPipeNetEventHandler.java +++ /dev/null @@ -1,56 +0,0 @@ -package gregtech.api.pipenet.tickable; - -import gregtech.api.GTValues; - -import net.minecraft.world.World; -import net.minecraftforge.event.world.ChunkEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent.WorldTickEvent; - -import org.jetbrains.annotations.ApiStatus; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Stream; - -@Deprecated -@ApiStatus.ScheduledForRemoval(inVersion = "2.9") -@EventBusSubscriber(modid = GTValues.MODID) -public class TickableWorldPipeNetEventHandler { - - private static final List>> pipeNetAccessors = new ArrayList<>(); - - public static void registerTickablePipeNet(Function> pipeNetAccessor) { - pipeNetAccessors.add(pipeNetAccessor); - } - - private static Stream> getPipeNetsForWorld(World world) { - return pipeNetAccessors.stream().map(accessor -> accessor.apply(world)); - } - - @SubscribeEvent - public static void onWorldTick(WorldTickEvent event) { - World world = event.world; - if (world.isRemote) - return; - getPipeNetsForWorld(world).forEach(TickableWorldPipeNet::update); - } - - @SubscribeEvent - public static void onChunkLoad(ChunkEvent.Load event) { - World world = event.getWorld(); - if (world.isRemote) - return; - getPipeNetsForWorld(world).forEach(it -> it.onChunkLoaded(event.getChunk())); - } - - @SubscribeEvent - public static void onChunkUnload(ChunkEvent.Unload event) { - World world = event.getWorld(); - if (world.isRemote) - return; - getPipeNetsForWorld(world).forEach(it -> it.onChunkUnloaded(event.getChunk())); - } -} diff --git a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java index 4660839c988..c58403b4815 100644 --- a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java +++ b/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java @@ -2,9 +2,10 @@ import gregtech.api.metatileentity.interfaces.INeighborCache; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.unification.material.Material; import net.minecraft.network.PacketBuffer; @@ -19,7 +20,7 @@ import java.util.function.Consumer; public interface IPipeTile & IPipeType, - NodeDataType extends INodeData> extends INeighborCache { + NodeDataType extends INodeData, Edge extends NetEdge> extends INeighborCache { World getPipeWorld(); @@ -39,9 +40,9 @@ default long getTickTimer() { return getPipeWorld().getTotalWorldTime(); } - BlockPipe getPipeBlock(); + BlockPipe getPipeBlock(); - void transferDataFrom(IPipeTile sourceTile); + void transferDataFrom(IPipeTile sourceTile); int getPaintingColor(); @@ -80,7 +81,7 @@ default boolean canHaveBlockedFaces() { NodeDataType getNodeData(); - NodeG getNode(); + NetNode getNode(); @Nullable TileEntity getNonPipeNeighbour(EnumFacing facing); @@ -92,7 +93,7 @@ default boolean canHaveBlockedFaces() { boolean supportsTicking(); - IPipeTile setSupportsTicking(); + IPipeTile setSupportsTicking(); boolean canPlaceCoverOnSide(EnumFacing side); diff --git a/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java b/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java index a6adca33761..30a6a6c4ceb 100644 --- a/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java +++ b/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java @@ -27,11 +27,11 @@ public class PipeCoverableImplementation implements CoverHolder { - private IPipeTile holder; + private IPipeTile holder; private final EnumMap covers = new EnumMap<>(EnumFacing.class); private final int[] sidedRedstoneInput = new int[6]; - public PipeCoverableImplementation(IPipeTile holder) { + public PipeCoverableImplementation(IPipeTile holder) { this.holder = holder; } @@ -50,7 +50,7 @@ public void transferDataTo(PipeCoverableImplementation destImpl) { @Override public final void addCover(@NotNull EnumFacing side, @NotNull Cover cover) { if (cover instanceof ITickable && !holder.supportsTicking()) { - IPipeTile newHolderTile = holder.setSupportsTicking(); + IPipeTile newHolderTile = holder.setSupportsTicking(); newHolderTile.getCoverableImplementation().addCover(side, cover); holder = newHolderTile; return; diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index fb3a914fd68..99ede3ea469 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -6,10 +6,11 @@ import gregtech.api.metatileentity.NeighborCacheTileEntityBase; import gregtech.api.metatileentity.SyncedTileEntityBase; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NodeG; -import gregtech.api.pipenet.WorldPipeNetSimple; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.WorldPipeNetBase; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.unification.material.Material; import net.minecraft.block.Block; @@ -36,8 +37,8 @@ import static gregtech.api.capability.GregtechDataCodes.*; public abstract class TileEntityPipeBase & IPipeType, - NodeDataType extends INodeData> extends NeighborCacheTileEntityBase - implements IPipeTile { + NodeDataType extends INodeData, Edge extends NetEdge> extends NeighborCacheTileEntityBase + implements IPipeTile { protected final PipeCoverableImplementation coverableImplementation = new PipeCoverableImplementation(this); /** @@ -51,13 +52,13 @@ public abstract class TileEntityPipeBase & IPipe /** * Our node stores connection data and NodeData data */ - protected @Nullable NodeG netNode; - private BlockPipe pipeBlock; + protected @Nullable NetNode netNode; + private BlockPipe pipeBlock; private PipeType pipeType = getPipeTypeClass().getEnumConstants()[0]; @Nullable private Material frameMaterial; // set when this pipe is replaced with a ticking variant to redirect sync packets - private TileEntityPipeBase tickingPipe; + private TileEntityPipeBase tickingPipe; private boolean nbtLoad = false; private boolean needsOldNetSetup = false; @@ -67,7 +68,7 @@ public TileEntityPipeBase() { invalidateNeighbors(); } - public void setPipeData(BlockPipe pipeBlock, PipeType pipeType) { + public void setPipeData(BlockPipe pipeBlock, PipeType pipeType) { this.pipeBlock = pipeBlock; this.pipeType = pipeType; if (!getWorld().isRemote) { @@ -76,7 +77,7 @@ public void setPipeData(BlockPipe pipeBlock, PipeType } @Override - public void transferDataFrom(IPipeTile tileEntity) { + public void transferDataFrom(IPipeTile tileEntity) { this.pipeType = tileEntity.getPipeType(); this.paintingColor = tileEntity.getPaintingColor(); this.netNode = tileEntity.getNode(); @@ -88,10 +89,10 @@ public void transferDataFrom(IPipeTile tileEntity) { } @Override - public NodeG getNode() { + public NetNode getNode() { if (netNode == null) { if (this.getPipeWorld().isRemote) - netNode = new NodeG<>(this); + netNode = new NetNode<>(this); else netNode = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()).getOrCreateNode(this); } return netNode; @@ -159,7 +160,7 @@ protected void invalidateNeighbors() { if (neighbor == null) return null; if (neighbor == this || (neighbor.isInvalid())) { neighbor = getNeighbor(facing); - if (neighbor instanceof IPipeTile) neighbor = null; + if (neighbor instanceof IPipeTile) neighbor = null; this.nonPipeNeighbors[i] = neighbor; this.nonPipeNeighborsInvalidated = false; } @@ -183,7 +184,7 @@ public boolean canPlaceCoverOnSide(EnumFacing side) { } @Override - public IPipeTile setSupportsTicking() { + public IPipeTile setSupportsTicking() { if (supportsTicking()) { return this; } @@ -193,7 +194,7 @@ public IPipeTile setSupportsTicking() { return this.tickingPipe; } // create new tickable tile entity, transfer data, and replace it - TileEntityPipeBase newTile = getPipeBlock().createNewTileEntity(true); + TileEntityPipeBase newTile = getPipeBlock().createNewTileEntity(true); if (!newTile.supportsTicking()) throw new IllegalStateException("Expected pipe to be ticking, but isn't!"); newTile.transferDataFrom(this); getWorld().setTileEntity(getPos(), newTile); @@ -202,12 +203,12 @@ public IPipeTile setSupportsTicking() { } @Override - public BlockPipe getPipeBlock() { + public BlockPipe getPipeBlock() { if (pipeBlock == null) { Block block = getBlockState().getBlock(); // noinspection unchecked - this.pipeBlock = block instanceof BlockPipeblockPipe ? - (BlockPipe) blockPipe : null; + this.pipeBlock = block instanceof BlockPipeblockPipe ? + (BlockPipe) blockPipe : null; } return pipeBlock; } @@ -340,7 +341,7 @@ public int getVisualConnections() { float selfThickness = getPipeType().getThickness(); for (EnumFacing facing : EnumFacing.values()) { if (isConnected(facing)) { - if (world.getTileEntity(pos.offset(facing)) instanceof IPipeTilepipeTile && + if (world.getTileEntity(pos.offset(facing)) instanceof IPipeTilepipeTile && pipeTile.isConnected(facing.getOpposite()) && pipeTile.getPipeType().getThickness() < selfThickness) { connections |= 1 << (facing.getIndex() + 6); @@ -396,7 +397,7 @@ public final boolean hasCapability(@NotNull Capability capability, @Nullable @Override public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { super.writeToNBT(compound); - BlockPipe pipeBlock = getPipeBlock(); + BlockPipe pipeBlock = getPipeBlock(); if (pipeBlock != null) { // noinspection ConstantConditions compound.setString("PipeBlock", pipeBlock.getRegistryName().toString()); @@ -423,8 +424,8 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { if (compound.hasKey("PipeBlock", NBT.TAG_STRING)) { Block block = Block.REGISTRY.getObject(new ResourceLocation(compound.getString("PipeBlock"))); // noinspection unchecked - this.pipeBlock = block instanceof BlockPipeblockPipe ? - (BlockPipe) blockPipe : null; + this.pipeBlock = block instanceof BlockPipeblockPipe ? + (BlockPipe) blockPipe : null; } this.pipeType = getPipeTypeClass().getEnumConstants()[compound.getInteger("PipeType")]; @@ -467,10 +468,10 @@ protected void markAsNeedingOldNetSetup() { protected void doOldNetSetup() { // TODO inexplicable crash during world load when old net setup required // something to do with removing the tile entities that the chunk is iterating over to load - WorldPipeNetSimple net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); + WorldPipeNetBase net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); net.markNodeAsOldData(this.getNode()); for (EnumFacing facing : EnumFacing.VALUES) { - NodeG nodeOffset = net.getNode(this.getPipePos().offset(facing)); + NetNode nodeOffset = net.getNode(this.getPipePos().offset(facing)); if (nodeOffset == null) continue; if (net.isDirected()) { // offset node might've been read before us, so we have to cover for it. @@ -536,7 +537,7 @@ public void receiveInitialSyncData(PacketBuffer buf) { } @Override - public void receiveCustomData(int discriminator, PacketBuffer buf) { + public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { if (this.tickingPipe != null) { this.tickingPipe.receiveCustomData(discriminator, buf); return; diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index ba5fb88027e..a22822d659c 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -8,28 +8,24 @@ import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.pipenet.INodeData; - -import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.util.EntityDamageUtil; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; -import it.unimi.dsi.fastutil.objects.Object2BooleanMap; -import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.Tuple; - import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; +import it.unimi.dsi.fastutil.objects.Object2BooleanMap; +import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.UnmodifiableView; @@ -204,35 +200,40 @@ public PipeLossResult determineFluidPassthroughResult(@NotNull FluidStack stack, } public PipeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBurning, boolean isLeaking, - boolean isCorroding, boolean isShattering, - boolean isMelting, World world, BlockPos pos) { + boolean isCorroding, boolean isShattering, + boolean isMelting, World world, BlockPos pos) { List particleActions = new ObjectArrayList<>(); Consumer damageAction = tile -> {}; Runnable destructionAction = () -> {}; double mult = 1; if (isLeaking) { - particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.SMOKE_NORMAL, 7 + GTValues.RNG.nextInt(2))); + particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, + EnumParticleTypes.SMOKE_NORMAL, 7 + GTValues.RNG.nextInt(2))); // voids 10% mult *= 0.9; // apply heat damage in area surrounding the pipe - damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, stack.getFluid().getTemperature(stack), 2.0F, 10)); + damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + stack.getFluid().getTemperature(stack), 2.0F, 10)); // chance to do a small explosion if (GTValues.RNG.nextInt(isBurning ? 3 : 7) == 0) { destructionAction = () -> world.setBlockToAir(pos); if (!world.isRemote) { - particleActions.add(() -> ((WorldServer) world).spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.2, 0.2, 0.2, 0.0)); + particleActions.add(() -> ((WorldServer) world).spawnParticle(EnumParticleTypes.SMOKE_LARGE, + pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.2, 0.2, 0.2, 0.0)); } - particleActions.add(() -> world.createExplosion(null, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, - 1.0f + GTValues.RNG.nextFloat(), false)); + particleActions + .add(() -> world.createExplosion(null, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, + 1.0f + GTValues.RNG.nextFloat(), false)); } } if (isCorroding) { - particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.CRIT_MAGIC, 3 + GTValues.RNG.nextInt(2))); + particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, + EnumParticleTypes.CRIT_MAGIC, 3 + GTValues.RNG.nextInt(2))); // voids 25% mult *= 0.75; @@ -248,7 +249,8 @@ public PipeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBu } if (isBurning || isMelting) { - particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.FLAME, (isMelting ? 7 : 3) + GTValues.RNG.nextInt(2))); + particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, + EnumParticleTypes.FLAME, (isMelting ? 7 : 3) + GTValues.RNG.nextInt(2))); // voids 75% mult *= 0.25; @@ -259,7 +261,8 @@ public PipeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBu } // apply heat damage in area surrounding the pipe - damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, stack.getFluid().getTemperature(stack), 2.0F, 10)); + damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + stack.getFluid().getTemperature(stack), 2.0F, 10)); // 1/10 chance to void everything and burn the pipe if (GTValues.RNG.nextInt(10) == 0) { @@ -269,13 +272,15 @@ public PipeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBu } if (isShattering) { - particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2))); + particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, + EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2))); // voids 75% mult *= 0.75; // apply frost damage in area surrounding the pipe - damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, stack.getFluid().getTemperature(stack), 2.0F, 10)); + damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + stack.getFluid().getTemperature(stack), 2.0F, 10)); // 1/10 chance to void everything and freeze the pipe if (GTValues.RNG.nextInt(10) == 0) { @@ -288,7 +293,7 @@ public PipeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBu return new PipeLossResult(nodeG -> { // only do 'extra' actions if the node already holds its MTE. // don't go fetch it from the world as this 9 times out of 10 means loading a chunk unnecessarily. - IPipeTile tile = nodeG.getHeldMTEUnsafe(); + IPipeTile tile = nodeG.getHeldMTEUnsafe(); if (tile instanceof TileEntityFluidPipe pipe) { pipe.playDamageSound(); particleActions.forEach(Runnable::run); @@ -349,13 +354,13 @@ public String toString() { '}'; } - public static class PipeLossResult extends Tuple>, Double> { + public static class PipeLossResult extends Tuple>, Double> { - public PipeLossResult(Consumer> postAction, Double lossFunction) { + public PipeLossResult(Consumer> postAction, Double lossFunction) { super(postAction, lossFunction); } - public Consumer> getPostAction() { + public Consumer> getPostAction() { return this.getFirst(); } diff --git a/src/main/java/gregtech/api/util/FluidTestObject.java b/src/main/java/gregtech/api/util/FluidTestObject.java new file mode 100644 index 00000000000..e875fa35983 --- /dev/null +++ b/src/main/java/gregtech/api/util/FluidTestObject.java @@ -0,0 +1,31 @@ +package gregtech.api.util; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; + +import java.util.Objects; + +public final class FluidTestObject { + + public final Fluid fluid; + public final NBTTagCompound tag; + + public FluidTestObject(FluidStack stack) { + this.fluid = stack.getFluid(); + this.tag = stack.tag; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + FluidTestObject that = (FluidTestObject) o; + return Objects.equals(fluid, that.fluid) && Objects.equals(tag, that.tag); + } + + @Override + public int hashCode() { + return Objects.hash(fluid, tag); + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/CableRenderer.java b/src/main/java/gregtech/client/renderer/pipe/CableRenderer.java index 17edbcd501d..ce2ec2b9d59 100644 --- a/src/main/java/gregtech/client/renderer/pipe/CableRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/CableRenderer.java @@ -40,7 +40,8 @@ public void registerIcons(TextureMap map) { } @Override - public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, IPipeTile pipeTile, + public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, + IPipeTile pipeTile, IPipeType pipeType, @Nullable Material material) { if (material == null || !(pipeType instanceof Insulation)) { return; @@ -82,7 +83,7 @@ public TextureAtlasSprite getParticleTexture(IPipeType pipeType, @Nullable Ma } @Override - public Pair getParticleTexture(IPipeTile pipeTile) { + public Pair getParticleTexture(IPipeTile pipeTile) { if (pipeTile == null) { return Pair.of(TextureUtils.getMissingSprite(), 0xFFFFFF); } @@ -91,7 +92,7 @@ public Pair getParticleTexture(IPipeTile pipe return Pair.of(TextureUtils.getMissingSprite(), 0xFFFFFF); } Material material = pipeTile instanceof TileEntityMaterialPipeBase ? - ((TileEntityMaterialPipeBase) pipeTile).getPipeMaterial() : null; + ((TileEntityMaterialPipeBase) pipeTile).getPipeMaterial() : null; TextureAtlasSprite atlasSprite; int particleColor; diff --git a/src/main/java/gregtech/client/renderer/pipe/FluidPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipe/FluidPipeRenderer.java index f729afb3b57..91df50b0d47 100644 --- a/src/main/java/gregtech/client/renderer/pipe/FluidPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/FluidPipeRenderer.java @@ -43,8 +43,8 @@ public void registerIcons(TextureMap map) { } @Override - public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, IPipeTile pipeTile, - IPipeType pipeType, @Nullable Material material) { + public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, + IPipeTile pipeTile, IPipeType pipeType, @Nullable Material material) { if (material == null || !(pipeType instanceof FluidPipeType)) { return; } diff --git a/src/main/java/gregtech/client/renderer/pipe/ItemPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipe/ItemPipeRenderer.java index e6d7604b3b4..9e4df421227 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ItemPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/ItemPipeRenderer.java @@ -38,8 +38,8 @@ public void registerIcons(TextureMap map) { } @Override - public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, IPipeTile pipeTile, - IPipeType pipeType, @Nullable Material material) { + public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, + IPipeTile pipeTile, IPipeType pipeType, @Nullable Material material) { if (material == null || !(pipeType instanceof ItemPipeType)) { return; } diff --git a/src/main/java/gregtech/client/renderer/pipe/LaserPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipe/LaserPipeRenderer.java index adc2fda4af4..f67beda6a1d 100644 --- a/src/main/java/gregtech/client/renderer/pipe/LaserPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/LaserPipeRenderer.java @@ -41,8 +41,9 @@ public void registerIcons(TextureMap map) { } @Override - public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, - @Nullable IPipeTile pipeTile, IPipeType pipeType, @Nullable Material material) { + public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, + @Nullable IPipeTile pipeTile, IPipeType pipeType, + @Nullable Material material) { if (pipeType instanceof LaserPipeType) { renderContext.addOpenFaceRender(new IconTransformation(pipeTextures.get(pipeType))) .addSideRender(false, new IconTransformation(Textures.LASER_PIPE_SIDE)); diff --git a/src/main/java/gregtech/client/renderer/pipe/OpticalPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipe/OpticalPipeRenderer.java index ab63a9560a4..5eae9211e3d 100644 --- a/src/main/java/gregtech/client/renderer/pipe/OpticalPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/OpticalPipeRenderer.java @@ -33,8 +33,9 @@ public void registerIcons(TextureMap map) { } @Override - public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, - @Nullable IPipeTile pipeTile, IPipeType pipeType, @Nullable Material material) { + public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, + @Nullable IPipeTile pipeTile, IPipeType pipeType, + @Nullable Material material) { if (pipeType instanceof OpticalPipeType) { renderContext.addOpenFaceRender(new IconTransformation(pipeTextures.get(pipeType))) .addSideRender(false, new IconTransformation(Textures.OPTICAL_PIPE_SIDE)); diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java b/src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java index e3195dba22c..f046a76f876 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java @@ -144,8 +144,8 @@ public void onModelsBake(ModelBakeEvent event) { event.getModelRegistry().putObject(modelLocation, this); } - public abstract void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, - @Nullable IPipeTile pipeTile, IPipeType pipeType, + public abstract void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, + @Nullable IPipeTile pipeTile, IPipeType pipeType, @Nullable Material material); @Override @@ -158,9 +158,10 @@ public void renderItem(ItemStack rawItemStack, TransformType transformType) { GlStateManager.enableBlend(); renderState.reset(); renderState.startDrawing(GL11.GL_QUADS, DefaultVertexFormats.ITEM); - BlockPipe blockFluidPipe = (BlockPipe) ((ItemBlockPipe) stack.getItem()).getBlock(); + BlockPipe blockFluidPipe = (BlockPipe) ((ItemBlockPipe) stack.getItem()) + .getBlock(); IPipeType pipeType = blockFluidPipe.getItemPipeType(stack); - Material material = blockFluidPipe instanceof BlockMaterialPipe blockMaterialPipe ? + Material material = blockFluidPipe instanceof BlockMaterialPipeblockMaterialPipe ? blockMaterialPipe.getItemMaterial(stack) : null; if (pipeType != null) { // 12 == 0b1100 is North and South connection (index 2 & 3) @@ -180,8 +181,8 @@ public boolean renderBlock(IBlockAccess world, BlockPos pos, IBlockState state, renderState.bind(buffer); renderState.setBrightness(world, pos); - BlockPipe blockPipe = (BlockPipe) state.getBlock(); - IPipeTile pipeTile = blockPipe.getPipeTileEntity(world, pos); + BlockPipe blockPipe = (BlockPipe) state.getBlock(); + IPipeTile pipeTile = blockPipe.getPipeTileEntity(world, pos); if (pipeTile == null) { return false; @@ -189,7 +190,7 @@ public boolean renderBlock(IBlockAccess world, BlockPos pos, IBlockState state, IPipeType pipeType = pipeTile.getPipeType(); Material pipeMaterial = pipeTile instanceof TileEntityMaterialPipeBase ? - ((TileEntityMaterialPipeBase) pipeTile).getPipeMaterial() : null; + ((TileEntityMaterialPipeBase) pipeTile).getPipeMaterial() : null; int paintingColor = pipeTile.getPaintingColor(); int connectedSidesMap = pipeTile.getVisualConnections(); int blockedConnections = pipeTile.getBlockedConnections(); @@ -223,7 +224,7 @@ public boolean renderBlock(IBlockAccess world, BlockPos pos, IBlockState state, return true; } - private static void renderFrame(IPipeTile pipeTile, BlockPos pos, CCRenderState renderState, + private static void renderFrame(IPipeTile pipeTile, BlockPos pos, CCRenderState renderState, int connections) { Material frameMaterial = pipeTile.getFrameMaterial(); if (frameMaterial != null) { @@ -377,8 +378,8 @@ public void handleRenderBlockDamage(IBlockAccess world, BlockPos pos, IBlockStat renderState.reset(); renderState.bind(buffer); renderState.setPipeline(new Vector3(new Vec3d(pos)).translation(), new IconTransformation(sprite)); - BlockPipe blockPipe = (BlockPipe) state.getBlock(); - IPipeTile pipeTile = blockPipe.getPipeTileEntity(world, pos); + BlockPipe blockPipe = (BlockPipe) state.getBlock(); + IPipeTile pipeTile = blockPipe.getPipeTileEntity(world, pos); if (pipeTile == null) { return; } @@ -426,13 +427,13 @@ public boolean isGui3d() { return true; } - public Pair getParticleTexture(IPipeTile pipeTile) { + public Pair getParticleTexture(IPipeTile pipeTile) { if (pipeTile == null) { return Pair.of(TextureUtils.getMissingSprite(), 0xFFFFFF); } IPipeType pipeType = pipeTile.getPipeType(); Material material = pipeTile instanceof TileEntityMaterialPipeBase ? - ((TileEntityMaterialPipeBase) pipeTile).getPipeMaterial() : null; + ((TileEntityMaterialPipeBase) pipeTile).getPipeMaterial() : null; if (pipeType == null) { return Pair.of(TextureUtils.getMissingSprite(), 0xFFFFFF); } diff --git a/src/main/java/gregtech/common/EventHandlers.java b/src/main/java/gregtech/common/EventHandlers.java index 8fa23091b99..9d2db26a6fe 100644 --- a/src/main/java/gregtech/common/EventHandlers.java +++ b/src/main/java/gregtech/common/EventHandlers.java @@ -101,7 +101,7 @@ public static void onPlayerInteractionRightClickBlock(PlayerInteractEvent.RightC TileEntity tileEntity = event.getWorld().getTileEntity(event.getPos()); if (tileEntity instanceof IGregTechTileEntity) { event.setUseBlock(Event.Result.ALLOW); - } else if (tileEntity instanceof IPipeTile) { + } else if (tileEntity instanceof IPipeTile) { event.setUseBlock(Event.Result.ALLOW); } diff --git a/src/main/java/gregtech/common/ToolEventHandlers.java b/src/main/java/gregtech/common/ToolEventHandlers.java index 62195e49791..141b7a14a17 100644 --- a/src/main/java/gregtech/common/ToolEventHandlers.java +++ b/src/main/java/gregtech/common/ToolEventHandlers.java @@ -303,7 +303,7 @@ private static void postRenderDamagedBlocks() { @SideOnly(Side.CLIENT) private static boolean shouldRenderGridOverlays(@NotNull IBlockState state, @Nullable TileEntity tile, ItemStack mainHand, ItemStack offHand, boolean isSneaking) { - if (state.getBlock() instanceof BlockPipepipe) { + if (state.getBlock() instanceof BlockPipepipe) { if (isSneaking && (mainHand.isEmpty() || mainHand.getItem().getClass() == Item.getItemFromBlock(pipe).getClass())) { return true; @@ -316,7 +316,7 @@ private static boolean shouldRenderGridOverlays(@NotNull IBlockState state, @Nul BooleanSupplier hasCover; Predicate canCover; - if (tile instanceof IPipeTilepipeTile) { + if (tile instanceof IPipeTilepipeTile) { final boolean hasAnyCover = pipeTile.getCoverableImplementation().hasAnyCover(); if (hasAnyCover) { if (mainToolClasses.contains(ToolClasses.SCREWDRIVER)) return true; @@ -384,8 +384,7 @@ private static boolean renderGridOverlays(@NotNull EntityPlayer player, BlockPos rColour = gColour = bColour = 0.2F + (float) Math.sin((float) (System.currentTimeMillis() % (Math.PI * 800)) / 800) / 2; - if (tile instanceof TileEntityPipeBase) { - TileEntityPipeBase tepb = (TileEntityPipeBase) tile; + if (tile instanceof TileEntityPipeBasetepb) { drawGridOverlays(facing, box, face -> tepb.isConnected(face) || tepb.getCoverableImplementation().getCoverAtSide(face) != null); } else if (tile instanceof MetaTileEntityHolder) { diff --git a/src/main/java/gregtech/common/blocks/BlockFrame.java b/src/main/java/gregtech/common/blocks/BlockFrame.java index 88bbf3c2374..bc727d38e50 100644 --- a/src/main/java/gregtech/common/blocks/BlockFrame.java +++ b/src/main/java/gregtech/common/blocks/BlockFrame.java @@ -123,15 +123,16 @@ public boolean canCreatureSpawn(@NotNull IBlockState state, @NotNull IBlockAcces public boolean replaceWithFramedPipe(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, ItemStack stackInHand, EnumFacing facing) { - BlockPipe blockPipe = (BlockPipe) ((ItemBlockPipe) stackInHand.getItem()).getBlock(); + BlockPipe blockPipe = (BlockPipe) ((ItemBlockPipe) stackInHand.getItem()) + .getBlock(); if (blockPipe.getItemPipeType(stackInHand).getThickness() < 1) { ItemBlock itemBlock = (ItemBlock) stackInHand.getItem(); IBlockState pipeState = blockPipe.getDefaultState(); // these 0 values are not actually used by forge itemBlock.placeBlockAt(stackInHand, playerIn, worldIn, pos, facing, 0, 0, 0, pipeState); - IPipeTile pipeTile = blockPipe.getPipeTileEntity(worldIn, pos); - if (pipeTile instanceof TileEntityPipeBase) { - ((TileEntityPipeBase) pipeTile).setFrameMaterial(getGtMaterial(state)); + IPipeTile pipeTile = blockPipe.getPipeTileEntity(worldIn, pos); + if (pipeTile instanceof TileEntityPipeBasetile) { + tile.setFrameMaterial(getGtMaterial(state)); } else { GTLog.logger.error("Pipe was not placed!"); return false; @@ -149,8 +150,7 @@ public boolean replaceWithFramedPipe(World worldIn, BlockPos pos, IBlockState st public boolean removeFrame(World world, BlockPos pos, EntityPlayer player, ItemStack stack) { TileEntity te = world.getTileEntity(pos); - if (te instanceof TileEntityPipeBase) { - TileEntityPipeBase pipeTile = (TileEntityPipeBase) te; + if (te instanceof TileEntityPipeBasepipeTile) { Material frameMaterial = pipeTile.getFrameMaterial(); if (frameMaterial != null) { pipeTile.setFrameMaterial(null); @@ -191,7 +191,7 @@ public boolean onBlockActivated(@NotNull World world, @NotNull BlockPos pos, @No continue; } TileEntity te = world.getTileEntity(blockPos); - if (te instanceof IPipeTile && ((IPipeTile) te).getFrameMaterial() != null) { + if (te instanceof IPipeTile && ((IPipeTile) te).getFrameMaterial() != null) { blockPos.move(EnumFacing.UP); continue; } @@ -206,8 +206,8 @@ public boolean onBlockActivated(@NotNull World world, @NotNull BlockPos pos, @No } blockPos.release(); return true; - } else if (te instanceof TileEntityPipeBase && ((TileEntityPipeBase) te).getFrameMaterial() == null) { - ((TileEntityPipeBase) te).setFrameMaterial(frameBlock.getGtMaterial(stack)); + } else if (te instanceof TileEntityPipeBasetile && tile.getFrameMaterial() == null) { + tile.setFrameMaterial(frameBlock.getGtMaterial(stack)); SoundType type = getSoundType(stack); world.playSound(null, pos, type.getPlaceSound(), SoundCategory.BLOCKS, (type.getVolume() + 1.0F) / 2.0F, type.getPitch() * 0.8F); diff --git a/src/main/java/gregtech/common/command/CommandRecipeCheck.java b/src/main/java/gregtech/common/command/CommandRecipeCheck.java index 5ca03112db5..9aff5b7c070 100644 --- a/src/main/java/gregtech/common/command/CommandRecipeCheck.java +++ b/src/main/java/gregtech/common/command/CommandRecipeCheck.java @@ -328,7 +328,7 @@ public static String prettyPrintItemStack(ItemStack stack) { id = "block" + ((BlockCompressed) block).getGtMaterial(stack).toCamelCaseString(); } else if (block instanceof BlockFrame) { id = "frame" + ((BlockFrame) block).getGtMaterial(stack).toCamelCaseString(); - } else if (block instanceof BlockMaterialPipeblockMaterialPipe) { + } else if (block instanceof BlockMaterialPipeblockMaterialPipe) { id = blockMaterialPipe.getPrefix().name + blockMaterialPipe.getItemMaterial(stack).toCamelCaseString(); } diff --git a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java index 35ef46bd4aa..4ee96e5418a 100644 --- a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java +++ b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java @@ -9,7 +9,7 @@ import java.util.List; /** - * Node-based, state-based evaluator for oreGlob. + * NetNode-based, state-based evaluator for oreGlob. *

* OreGlob nodes are evaluated by simulating match for each possible branch of states. * Each state corresponds to index of character the next match will start. All matches diff --git a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java index 5c7410b78e8..f06aef71fb8 100644 --- a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java +++ b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java @@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; /** - * Node-based implementation of oreglob. + * NetNode-based implementation of oreglob. */ public final class NodeOreGlob extends OreGlob { diff --git a/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java index 69bf9e9640c..629fdd24c1c 100644 --- a/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java @@ -94,8 +94,7 @@ private boolean tryPaintSpecialBlock(EntityPlayer player, World world, BlockPos } if (Mods.AppliedEnergistics2.isModLoaded()) { TileEntity te = world.getTileEntity(pos); - if (te instanceof TileCableBus) { - TileCableBus cable = (TileCableBus) te; + if (te instanceof TileCableBus cable) { // do not try to recolor if it already is this color if (cable.getColor().ordinal() != color.ordinal()) { cable.recolourBlock(null, AEColor.values()[color.ordinal()], player); @@ -136,8 +135,7 @@ private static boolean tryStripBlockColor(EntityPlayer player, World world, Bloc } // TileEntityPipeBase special case - if (te instanceof IPipeTile) { - IPipeTile pipe = (IPipeTile) te; + if (te instanceof IPipeTilepipe) { if (pipe.isPainted()) { pipe.setPaintingColor(-1); return true; @@ -146,8 +144,7 @@ private static boolean tryStripBlockColor(EntityPlayer player, World world, Bloc // AE2 cable special case if (Mods.AppliedEnergistics2.isModLoaded()) { - if (te instanceof TileCableBus) { - TileCableBus cable = (TileCableBus) te; + if (te instanceof TileCableBus cable) { // do not try to strip color if it is already colorless if (cable.getColor() != AEColor.TRANSPARENT) { cable.recolourBlock(null, AEColor.TRANSPARENT, player); diff --git a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java index 82a2f46c854..204139a5680 100644 --- a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java @@ -263,9 +263,8 @@ else if (metaTileEntity instanceof IDataInfoProvider) list.addAll(provider.getDataInfo()); } - } else if (tileEntity instanceof IPipeTile) { + } else if (tileEntity instanceof IPipeTilepipeTile) { // pipes need special name handling - IPipeTile pipeTile = (IPipeTile) tileEntity; if (pipeTile.getPipeBlock().getRegistryName() != null) { list.add(new TextComponentTranslation("behavior.tricorder.block_name", @@ -278,8 +277,7 @@ else if (metaTileEntity instanceof IDataInfoProvider) } // pipe-specific info - if (tileEntity instanceof IDataInfoProvider) { - IDataInfoProvider provider = (IDataInfoProvider) tileEntity; + if (tileEntity instanceof IDataInfoProvider provider) { list.add(new TextComponentTranslation("behavior.tricorder.divider")); diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java index 46bcafb51d5..cf920b2105c 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java @@ -128,7 +128,7 @@ public CoverDigitalInterface getCoverFromPosSide(FacingPos posFacing) { IGregTechTileEntity holder = getHolderFromPos(posFacing.getPos()); if (holder == null) { TileEntity te = this.getWorld() == null ? null : this.getWorld().getTileEntity(posFacing.getPos()); - if (te instanceof IPipeTilepipeTile) { + if (te instanceof IPipeTilepipeTile) { coverHolder = pipeTile.getCoverableImplementation(); } } else { diff --git a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java index 255655d8bad..570de1bdb9a 100644 --- a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java @@ -5,6 +5,7 @@ import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.pipenet.block.material.BlockMaterialPipe; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; @@ -47,7 +48,7 @@ import java.util.Map; import java.util.TreeMap; -public class BlockCable extends BlockMaterialPipe +public class BlockCable extends BlockMaterialPipe implements ITileEntityProvider { private final Map enabledMaterials = new TreeMap<>(); @@ -139,13 +140,13 @@ public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull I } @Override - public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile) { + public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, + IPipeTile sideTile) { return selfTile instanceof TileEntityCable && sideTile instanceof TileEntityCable; } @Override - public boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, + public boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, TileEntity tile) { return tile != null && tile.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, side.getOpposite()) != null; @@ -192,7 +193,7 @@ public EnumBlockRenderType getRenderType(@NotNull IBlockState state) { } @Override - public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { + public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { return supportsTicking ? new TileEntityCableTickable() : new TileEntityCable(); } diff --git a/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java b/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java index f054c37746f..05d8d419014 100644 --- a/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java @@ -48,7 +48,7 @@ public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @N } if (ConfigHolder.misc.debug) { - BlockMaterialPipe blockMaterialPipe = (BlockMaterialPipe) blockPipe; + BlockMaterialPipe blockMaterialPipe = (BlockMaterialPipe) blockPipe; tooltip.add("MetaItem Id: " + blockMaterialPipe.getPrefix().name + blockMaterialPipe.getItemMaterial(stack).toCamelCaseString()); } diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java index 05b0fe11838..c6b2d963c04 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -4,8 +4,9 @@ import gregtech.api.capability.IEnergyContainer; import gregtech.api.pipenet.AbstractGroupData; import gregtech.api.pipenet.IPipeNetHandler; +import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; @@ -73,7 +74,7 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage long amperesUsed = 0L; mainloop: - for (NetPath routePath : net.getPaths(cable, null)) { + for (NetPath routePath : net.getPaths(cable, null)) { Iterator iterator = routePath.getFacingIterator(); // weight = loss if (routePath.getWeight() >= voltage) { @@ -81,7 +82,7 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage continue; } while (iterator.hasNext()) { - NetPath.FacedNetPath path = routePath.withFacing(iterator.next()); + NetPath.FacedNetPath path = routePath.withFacing(iterator.next()); EnumFacing facing = path.facing.getOpposite(); @@ -93,7 +94,7 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage long pathVoltage = voltage - (long) routePath.getWeight(); boolean cableBroken = false; - for (NodeG node : path.getNodeList()) { + for (NetNode node : path.getNodeList()) { TileEntityCable cable = (TileEntityCable) node.getHeldMTE(); if (cable.getMaxVoltage() < voltage) { int heat = (int) (Math.log( @@ -123,7 +124,7 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage amperesUsed += amps; long voltageTraveled = voltage; // TODO compress wire path operations into a single for loop - for (NodeG node : path.getNodeList()) { + for (NetNode node : path.getNodeList()) { TileEntityCable cable = (TileEntityCable) node.getHeldMTE(); voltageTraveled -= cable.getNodeData().getLossPerBlock(); if (voltageTraveled <= 0) break; diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java index 73195e5bdcd..c74103494d9 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -2,6 +2,7 @@ import gregtech.api.pipenet.AbstractGroupData; import gregtech.api.pipenet.WorldPipeNetSimple; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.WireProperties; import gregtech.common.pipelike.cable.Insulation; @@ -38,7 +39,7 @@ protected Capability[] getConnectionCapabilities() { } @Override - protected Class> getBasePipeClass() { + protected Class> getBasePipeClass() { return TileEntityCable.class; } diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java index e8af710b987..56d5e3189e3 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java @@ -6,6 +6,7 @@ import gregtech.api.metatileentity.IDataInfoProvider; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.TaskScheduler; import gregtech.api.util.TextFormattingUtil; @@ -40,7 +41,7 @@ import static gregtech.api.capability.GregtechDataCodes.CABLE_TEMPERATURE; import static gregtech.api.capability.GregtechDataCodes.UPDATE_CONNECTIONS; -public class TileEntityCable extends TileEntityMaterialPipeBase +public class TileEntityCable extends TileEntityMaterialPipeBase implements IDataInfoProvider { private static final int meltTemp = 3000; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java index c192d8a134a..4f13817f613 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java @@ -2,6 +2,7 @@ import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.pipenet.block.material.BlockMaterialPipe; +import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; @@ -42,7 +43,8 @@ import java.util.SortedMap; import java.util.TreeMap; -public class BlockFluidPipe extends BlockMaterialPipe { +public class BlockFluidPipe extends + BlockMaterialPipe { private final SortedMap enabledMaterials = new TreeMap<>(); @@ -105,13 +107,14 @@ public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull I } @Override - public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile) { + public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, + IPipeTile sideTile) { return selfTile instanceof TileEntityFluidPipe && sideTile instanceof TileEntityFluidPipe; } @Override - public boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, + public boolean canPipeConnectToBlock(IPipeTile selfTile, + EnumFacing side, TileEntity tile) { return tile != null && tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side.getOpposite()) != null; @@ -166,7 +169,7 @@ public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @No } @Override - public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { + public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { return supportsTicking ? new TileEntityFluidPipeTickable() : new TileEntityFluidPipe(); } @@ -181,6 +184,6 @@ public EnumBlockRenderType getRenderType(@NotNull IBlockState state) { @Override @SideOnly(Side.CLIENT) protected Pair getParticleTexture(World world, BlockPos blockPos) { - return FluidPipeRenderer.INSTANCE.getParticleTexture((IPipeTile) world.getTileEntity(blockPos)); + return FluidPipeRenderer.INSTANCE.getParticleTexture((IPipeTile) world.getTileEntity(blockPos)); } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/ItemBlockFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/ItemBlockFluidPipe.java index 150879cd4b2..1dfc763b283 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/ItemBlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/ItemBlockFluidPipe.java @@ -44,7 +44,7 @@ public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @N tooltip.add(I18n.format("gregtech.tool_action.crowbar")); } - BlockMaterialPipe blockMaterialPipe = (BlockMaterialPipe) blockPipe; + BlockMaterialPipe blockMaterialPipe = (BlockMaterialPipe) blockPipe; if (ConfigHolder.misc.debug) { tooltip.add("MetaItem Id: " + blockMaterialPipe.getPrefix().name + diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java index cff06562b02..e051da518ee 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java @@ -2,21 +2,19 @@ import gregtech.api.cover.Cover; import gregtech.api.pipenet.IPipeNetHandler; -import gregtech.api.pipenet.NetEdge; +import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.edge.INetFlowEdge; +import gregtech.api.pipenet.edge.NetFlowEdge; +import gregtech.api.pipenet.edge.util.FlowConsumer; import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.api.util.FluidTestObject; import gregtech.common.covers.CoverFluidRegulator; import gregtech.common.covers.CoverPump; import gregtech.common.pipelike.fluidpipe.FluidPipeType; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; -import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; @@ -24,11 +22,12 @@ import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fml.common.FMLCommonHandler; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.function.Consumer; public class FluidNetHandler implements IFluidHandler, IPipeNetHandler { @@ -40,9 +39,9 @@ public class FluidNetHandler implements IFluidHandler, IPipeNetHandler { private final IFluidHandler testHandler = new FluidTank(Integer.MAX_VALUE); - private NetEdge.ChannelSimulatorKey simulatorKey; + private INetFlowEdge.ChannelSimulatorKey simulatorKey; private FluidStack lastFillResource; - private final Map, FluidPipeProperties.PipeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); + private final Map, FluidPipeProperties.PipeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); public FluidNetHandler(WorldFluidPipeNet net, TileEntityFluidPipe pipe, EnumFacing facing) { this.net = net; @@ -84,16 +83,16 @@ public int fill(FluidStack resource, boolean doFill) { FluidTestObject testObject = new FluidTestObject(resource); long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); // push flow through net - List> paths = - this.getNet().getPaths(pipe, testObject); + List> paths = this.getNet().getPaths(pipe, testObject); FluidStack helper = resource.copy(); - if (!doFill) this.simulatorKey = NetEdge.getNewSimulatorInstance(); + if (!doFill) this.simulatorKey = INetFlowEdge.getNewSimulatorInstance(); else this.simulatorKey = null; mainloop: - for (NetPath path : paths) { - for (Iterator it = path.getFacingIterator(); it.hasNext(); ) { + for (NetPath path : paths) { + for (Iterator it = path.getFacingIterator(); it.hasNext();) { EnumFacing facing = it.next(); - NetPath.FacedNetPath routePath = path.withFacing(facing); + NetPath.FacedNetPath routePath = path + .withFacing(facing); helper.amount -= this.fill(routePath, testObject, tick, helper, doFill); if (helper.amount <= 0) break mainloop; } @@ -106,8 +105,8 @@ public int fill(FluidStack resource, boolean doFill) { return resource.amount - helper.amount; } - public int fill(NetPath.FacedNetPath routePath, - FluidTestObject testObject, long tick, FluidStack resource, boolean doFill) { + public int fill(NetPath.FacedNetPath routePath, + FluidTestObject testObject, long tick, FluidStack resource, boolean doFill) { if (routePath.getTargetNode().getNodePos().equals(this.pipe.getPos()) && routePath.facing == this.facing) { return 0; } @@ -124,7 +123,7 @@ public int fill(NetPath.FacedNetPath routePa testHandler); if (fluidHandler == null || (fluidHandler != testHandler && ((helper = fluidHandler.drain(resource, false)) == null || - (allowed = helper.amount) <= 0))) { + (allowed = helper.amount) <= 0))) { testHandler.drain(Integer.MAX_VALUE, true); return 0; } @@ -140,14 +139,15 @@ public int fill(NetPath.FacedNetPath routePa resource, allowed, doFill); } else if (tileCover instanceof CoverFluidRegulator && ((CoverFluidRegulator) tileCover).getPumpMode() == CoverPump.PumpMode.IMPORT) { - return fillOverRegulator(routePath, neighbourHandler, testObject, tick, (CoverFluidRegulator) tileCover, - resource, allowed, doFill); - } else { - return fill(routePath, neighbourHandler, testObject, tick, resource, allowed, doFill); - } + return fillOverRegulator(routePath, neighbourHandler, testObject, tick, + (CoverFluidRegulator) tileCover, + resource, allowed, doFill); + } else { + return fill(routePath, neighbourHandler, testObject, tick, resource, allowed, doFill); + } } - public int fillOverRegulator(NetPath.FacedNetPath routePath, + public int fillOverRegulator(NetPath.FacedNetPath routePath, IFluidHandler handler, FluidTestObject testObject, long tick, CoverFluidRegulator regulator, FluidStack resource, int allowed, boolean doFill) { var matched = regulator.getFluidFilterContainer().match(resource); @@ -187,33 +187,35 @@ public int fillOverRegulator(NetPath.FacedNetPath routePath, IFluidHandler handler, + private int fill(NetPath.FacedNetPath routePath, + IFluidHandler handler, FluidTestObject testObject, long tick, FluidStack resource, int allowed, boolean doFill) { FluidStack helper = new FluidStack(resource, allowed); allowed = handler.fill(helper, false); // iterate through path - List> nodeList = routePath.getNodeList(); - List edgeList = routePath.getEdgeList(); - List flowLimitConsumers = new ObjectArrayList<>(); + List> nodeList = routePath.getNodeList(); + List edgeList = routePath.getEdgeList(); + List> flowLimitConsumers = new ObjectArrayList<>(); int inputAmount = resource.amount; int outputAmount = resource.amount; // always 1 less edge than nodes for (int i = 0; i < edgeList.size(); i++) { - NetEdge edge = edgeList.get(i); + NetFlowEdge edge = edgeList.get(i); if (!edge.getPredicate().test(resource)) return 0; int flow = Math.min(edge.getFlowLimit(testObject, getNet().getGraph(), tick, simulatorKey), outputAmount); double ratio = (double) flow / outputAmount; inputAmount *= ratio; flowLimitConsumers.forEach(c -> c.modifyRatio(ratio)); - flowLimitConsumers.add(new FlowConsumer(edge, testObject, flow, tick)); + flowLimitConsumers.add(new FlowConsumer<>(edge, testObject, getNet().getGraph(), flow, tick, simulatorKey)); // TODO undo loss when backflowing -// var sourceResult = getOrGenerateLossResult(nodeList.get(i), resource); + // var sourceResult = getOrGenerateLossResult(nodeList.get(i), resource); var targetResult = getOrGenerateLossResult(nodeList.get(i + 1), resource); double loss = targetResult.getLossFunction(); outputAmount = (int) (flow * loss); } - // outputAmount is currently the maximum flow to the endpoint, and inputAmount is the requisite flow into the net + // outputAmount is currently the maximum flow to the endpoint, and inputAmount is the requisite flow into the + // net allowed = Math.min(allowed, outputAmount); helper.amount = allowed; @@ -222,10 +224,10 @@ private int fill(NetPath.FacedNetPath routeP flowLimitConsumers.forEach(a -> a.accept(ratio)); return (int) (inputAmount * ratio); - } - public static int countStack(IFluidHandler handler, FluidStack stack, CoverFluidRegulator regulator, boolean isStackSpecific) { + public static int countStack(IFluidHandler handler, FluidStack stack, CoverFluidRegulator regulator, + boolean isStackSpecific) { if (regulator == null) return 0; int count = 0; for (int i = 0; i < handler.getTankProperties().length; i++) { @@ -251,7 +253,8 @@ public FluidStack drain(int maxDrain, boolean doDrain) { return null; } - protected FluidPipeProperties.PipeLossResult getOrGenerateLossResult(NodeG node, + protected FluidPipeProperties.PipeLossResult getOrGenerateLossResult( + NetNode node, FluidStack resource) { var cachedResult = this.lossResultCache.get(node); if (cachedResult == null) { @@ -260,54 +263,4 @@ protected FluidPipeProperties.PipeLossResult getOrGenerateLossResult(NodeG { - - private final NetEdge edge; - private final FluidTestObject testObject; - private final int flow; - private final long tick; - - private double ratio = 1; - - public FlowConsumer(NetEdge edge, FluidTestObject testObject, int flow, long tick) { - this.edge = edge; - this.testObject = testObject; - this.flow = flow; - this.tick = tick; - } - - public void modifyRatio(Double ratio) { - this.ratio *= ratio; - } - - @Override - public void accept(Double finalRatio) { - edge.consumeFlowLimit(testObject, getNet().getGraph(), (int) (finalRatio * ratio * flow), tick, simulatorKey); - } - } - - public static final class FluidTestObject { - - public final Fluid fluid; - public final NBTTagCompound tag; - - public FluidTestObject(FluidStack stack) { - this.fluid = stack.getFluid(); - this.tag = stack.tag; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - FluidTestObject that = (FluidTestObject) o; - return Objects.equals(fluid, that.fluid) && Objects.equals(tag, that.tag); - } - - @Override - public int hashCode() { - return Objects.hash(fluid, tag); - } - } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index 06e158ceccf..c0dc1191e63 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -2,8 +2,8 @@ import gregtech.api.cover.Cover; import gregtech.api.pipenet.AbstractEdgePredicate; -import gregtech.api.pipenet.NodeG; import gregtech.api.pipenet.WorldPipeNetComplex; +import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.covers.CoverFluidFilter; @@ -13,16 +13,12 @@ import gregtech.common.pipelike.fluidpipe.FluidPipeType; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import java.util.Set; - -public class WorldFluidPipeNet extends WorldPipeNetComplex { +public class WorldFluidPipeNet extends WorldPipeNetComplex { // TODO handle fluids in old fluid pipes @@ -40,7 +36,7 @@ public static WorldFluidPipeNet getWorldPipeNet(World world) { } public WorldFluidPipeNet(String name) { - super(name, true, false, 20); + super(name, true, false, () -> new NetFlowEdge(20)); } @Override @@ -49,7 +45,7 @@ protected Capability[] getConnectionCapabilities() { } @Override - protected Class> getBasePipeClass() { + protected Class> getBasePipeClass() { return TileEntityFluidPipe.class; } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java index e31573c1373..0f10e8e03cd 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java @@ -2,12 +2,12 @@ import gregtech.api.GTValues; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; +import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.pipelike.fluidpipe.FluidPipeType; import gregtech.common.pipelike.fluidpipe.net.FluidNetHandler; import gregtech.common.pipelike.fluidpipe.net.PipeTankList; - import gregtech.common.pipelike.fluidpipe.net.WorldFluidPipeNet; import net.minecraft.block.state.IBlockState; @@ -37,7 +37,7 @@ import java.util.List; import java.util.function.Consumer; -public class TileEntityFluidPipe extends TileEntityMaterialPipeBase { +public class TileEntityFluidPipe extends TileEntityMaterialPipeBase { // old code to maintain compat with old worlds // private PipeTankList pipeTankList; @@ -80,7 +80,7 @@ private void initHandlers() { } @Override - public void transferDataFrom(IPipeTile tileEntity) { + public void transferDataFrom(IPipeTile tileEntity) { super.transferDataFrom(tileEntity); TileEntityFluidPipe fluidPipe = (TileEntityFluidPipe) tileEntity; // take handlers from old pipe @@ -105,7 +105,8 @@ public void checkAndDestroy(@NotNull FluidStack stack) { public void destroyPipe(FluidStack stack, boolean isBurning, boolean isLeaking, boolean isCorroding, boolean isShattering, boolean isMelting) { - var result = getNodeData().determineDestroyPipeResults(stack, isBurning, isLeaking, isCorroding, isShattering, isMelting, world, pos); + var result = getNodeData().determineDestroyPipeResults(stack, isBurning, isLeaking, isCorroding, isShattering, + isMelting, world, pos); stack.amount *= result.getLossFunction(); result.getPostAction().accept(this.getNode()); } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/BlockItemPipe.java b/src/main/java/gregtech/common/pipelike/itempipe/BlockItemPipe.java index 85a18ca231c..8a6698fe8b9 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/BlockItemPipe.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/BlockItemPipe.java @@ -2,6 +2,7 @@ import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.pipenet.block.material.BlockMaterialPipe; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; @@ -38,7 +39,7 @@ import java.util.HashMap; import java.util.Map; -public class BlockItemPipe extends BlockMaterialPipe { +public class BlockItemPipe extends BlockMaterialPipe { private final Map enabledMaterials = new HashMap<>(); @@ -57,7 +58,7 @@ public void addPipeMaterial(Material material, ItemPipeProperties properties) { } @Override - public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { + public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { return supportsTicking ? new TileEntityItemPipeTickable() : new TileEntityItemPipe(); } @@ -105,13 +106,13 @@ public void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList selfTile, EnumFacing side, - IPipeTile sideTile) { + public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, + IPipeTile sideTile) { return selfTile instanceof TileEntityItemPipe && sideTile instanceof TileEntityItemPipe; } @Override - public boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, + public boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, TileEntity tile) { return tile != null && tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side.getOpposite()) != null; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/ItemBlockItemPipe.java b/src/main/java/gregtech/common/pipelike/itempipe/ItemBlockItemPipe.java index ae90e8dcab1..6246de9d6d6 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/ItemBlockItemPipe.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/ItemBlockItemPipe.java @@ -48,7 +48,7 @@ public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @N } if (ConfigHolder.misc.debug) { - BlockMaterialPipe blockMaterialPipe = (BlockMaterialPipe) blockPipe; + BlockMaterialPipe blockMaterialPipe = (BlockMaterialPipe) blockPipe; tooltip.add("MetaItem Id: " + blockMaterialPipe.getPrefix().name + blockMaterialPipe.getItemMaterial(stack).toCamelCaseString()); } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index 465979ce077..69e56535d88 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -3,6 +3,7 @@ import gregtech.api.cover.Cover; import gregtech.api.pipenet.IPipeNetHandler; import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.util.FacingPos; import gregtech.api.util.GTTransferUtils; @@ -112,7 +113,7 @@ public static boolean checkImportCover(Cover cover, boolean onPipe, ItemStack st } public ItemStack insertFirst(ItemStack stack, boolean simulate) { - for (NetPath inv : net.getPaths(pipe, null)) { + for (NetPath inv : net.getPaths(pipe, null)) { stack = insert(inv.firstFacing(), stack, simulate); if (stack.isEmpty()) return ItemStack.EMPTY; @@ -121,13 +122,13 @@ public ItemStack insertFirst(ItemStack stack, boolean simulate) { } public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean global) { - List> routePaths = net.getPaths(pipe, null); + List> routePaths = net.getPaths(pipe, null); if (routePaths.isEmpty()) return stack; if (routePaths.size() == 1 && routePaths.get(0).getTargetTEs().size() == 1) { return insert(routePaths.get(0).firstFacing(), stack, simulate); } - List> routePathsCopy = new ArrayList<>(routePaths); + List> routePathsCopy = new ArrayList<>(routePaths); if (global) { stack = insertToHandlersEnhanced(routePathsCopy, stack, simulate); @@ -149,19 +150,19 @@ public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean glo * @param simulate simulate * @return remainder */ - private ItemStack insertToHandlers(List> copy, ItemStack stack, + private ItemStack insertToHandlers(List> copy, ItemStack stack, boolean simulate) { - Iterator> routePathIterator = copy.listIterator(); + Iterator> routePathIterator = copy.listIterator(); int inserted = 0; int count = stack.getCount(); int c = count / copy.size(); int m = c == 0 ? count % copy.size() : 0; mainloop: while (routePathIterator.hasNext()) { - NetPath routePath = routePathIterator.next(); + NetPath routePath = routePathIterator.next(); Iterator iterator = routePath.getFacingIterator(); while (iterator.hasNext()) { - NetPath.FacedNetPath facedNetPath = routePath + NetPath.FacedNetPath facedNetPath = routePath .withFacing(iterator.next()); int amount = c; if (m > 0) { @@ -190,18 +191,19 @@ private ItemStack insertToHandlers(List> copy, ItemStack stack, - boolean simulate) { + private ItemStack insertToHandlersEnhanced(List> copy, + ItemStack stack, boolean simulate) { List transferred = new ArrayList<>(); IntList steps = new IntArrayList(); int min = Integer.MAX_VALUE; ItemStack simStack; // find inventories that are not full and get the amount that was inserted in total - for (NetPath inv : copy) { + for (NetPath inv : copy) { Iterator iterator = inv.getFacingIterator(); while (iterator.hasNext()) { - NetPath.FacedNetPath faceInv = inv.withFacing(iterator.next()); + NetPath.FacedNetPath faceInv = inv + .withFacing(iterator.next()); simStack = stack.copy(); int ins = stack.getCount() - insert(faceInv, simStack, true, true).getCount(); if (ins <= 0) @@ -308,12 +310,12 @@ private ItemStack insertToHandlersEnhanced(List routePath, ItemStack stack, + public ItemStack insert(NetPath.FacedNetPath routePath, ItemStack stack, boolean simulate) { return insert(routePath, stack, simulate, false); } - public ItemStack insert(NetPath.FacedNetPath routePath, ItemStack stack, + public ItemStack insert(NetPath.FacedNetPath routePath, ItemStack stack, boolean simulate, boolean ignoreLimit) { if (routePath.getTargetNode().getNodePos() == this.pipe.getPos() && routePath.facing == this.facing) { return stack; @@ -465,7 +467,7 @@ public int getSlotLimit(int i) { return 64; } - private void transferTo(NetPath.FacedNetPath routePath, boolean simulate, + private void transferTo(NetPath.FacedNetPath routePath, boolean simulate, int amount) { if (simulate) simulatedTransfersGlobalRoundRobin.merge(routePath.toFacingPos(), amount, Integer::sum); @@ -473,12 +475,14 @@ private void transferTo(NetPath.FacedNetPath r pipe.getTransferred().merge(routePath.toFacingPos(), amount, Integer::sum); } - private boolean contains(NetPath.FacedNetPath routePath, boolean simulate) { + private boolean contains(NetPath.FacedNetPath routePath, + boolean simulate) { return simulate ? simulatedTransfersGlobalRoundRobin.containsKey(routePath.toFacingPos()) : pipe.getTransferred().containsKey(routePath.toFacingPos()); } - private int didTransferTo(NetPath.FacedNetPath routePath, boolean simulate) { + private int didTransferTo(NetPath.FacedNetPath routePath, + boolean simulate) { if (simulate) return simulatedTransfersGlobalRoundRobin.getInt(routePath.toFacingPos()); return pipe.getTransferred().getInt(routePath.toFacingPos()); @@ -499,12 +503,12 @@ private void decrementBy(int amount) { private static class EnhancedRoundRobinData { - private final NetPath.FacedNetPath routePath; + private final NetPath.FacedNetPath routePath; private final int maxInsertable; private int transferred; private int toTransfer = 0; - private EnhancedRoundRobinData(NetPath.FacedNetPath routePath, + private EnhancedRoundRobinData(NetPath.FacedNetPath routePath, int maxInsertable, int transferred) { this.maxInsertable = maxInsertable; this.transferred = transferred; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index 02cc922d56f..93b02bc6d49 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -3,6 +3,7 @@ import gregtech.api.cover.Cover; import gregtech.api.pipenet.AbstractEdgePredicate; import gregtech.api.pipenet.WorldPipeNetSimple; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.common.covers.CoverConveyor; @@ -15,7 +16,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; - import net.minecraftforge.items.CapabilityItemHandler; // TODO move onto complex net @@ -43,7 +43,7 @@ protected Capability[] getConnectionCapabilities() { } @Override - protected Class> getBasePipeClass() { + protected Class> getBasePipeClass() { return TileEntityItemPipe.class; } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java index cc0d78f4868..78abaa5271c 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java @@ -1,6 +1,7 @@ package gregtech.common.pipelike.itempipe.tile; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.util.FacingPos; @@ -20,7 +21,7 @@ import java.util.EnumMap; -public class TileEntityItemPipe extends TileEntityMaterialPipeBase { +public class TileEntityItemPipe extends TileEntityMaterialPipeBase { private final EnumMap handlers = new EnumMap<>(EnumFacing.class); private final Object2IntMap transferred = new Object2IntOpenHashMap<>(); @@ -76,7 +77,7 @@ public Object2IntMap getTransferred() { } @Override - public void transferDataFrom(IPipeTile tileEntity) { + public void transferDataFrom(IPipeTile tileEntity) { super.transferDataFrom(tileEntity); TileEntityItemPipe itemPipe = (TileEntityItemPipe) tileEntity; // take handlers from old pipe diff --git a/src/main/java/gregtech/common/pipelike/laser/BlockLaserPipe.java b/src/main/java/gregtech/common/pipelike/laser/BlockLaserPipe.java index ff6f9c693f8..855bff71cad 100644 --- a/src/main/java/gregtech/common/pipelike/laser/BlockLaserPipe.java +++ b/src/main/java/gregtech/common/pipelike/laser/BlockLaserPipe.java @@ -4,6 +4,7 @@ import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.pipenet.block.BlockPipe; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.client.renderer.pipe.LaserPipeRenderer; @@ -31,7 +32,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class BlockLaserPipe extends BlockPipe { +public class BlockLaserPipe extends BlockPipe { private final LaserPipeType pipeType; private final LaserPipeProperties properties; @@ -59,12 +60,12 @@ public WorldLaserPipeNet getWorldPipeNet(World world) { } @Override - public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { + public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { return new TileEntityLaserPipe(); } @Override - public LaserPipeProperties createProperties(IPipeTile pipeTile) { + public LaserPipeProperties createProperties(IPipeTile pipeTile) { LaserPipeType pipeType = pipeTile.getPipeType(); if (pipeType == null) return getFallbackType(); return this.pipeType.modifyProperties(properties); @@ -79,7 +80,7 @@ public LaserPipeProperties createItemProperties(ItemStack itemStack) { } @Override - public ItemStack getDropItem(IPipeTile pipeTile) { + public ItemStack getDropItem(IPipeTile pipeTile) { return new ItemStack(this, 1, pipeType.ordinal()); } @@ -97,7 +98,7 @@ public LaserPipeType getItemPipeType(ItemStack itemStack) { } @Override - public void setTileEntityData(TileEntityPipeBase pipeTile, + public void setTileEntityData(TileEntityPipeBase pipeTile, ItemStack itemStack) { pipeTile.setPipeData(this, pipeType); } @@ -113,14 +114,14 @@ protected boolean isPipeTool(@NotNull ItemStack stack) { } @Override - public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile) { + public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, + IPipeTile sideTile) { return selfTile instanceof TileEntityLaserPipe && sideTile instanceof TileEntityLaserPipe; } @Override - public boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, - @Nullable TileEntity tile) { + public boolean canPipeConnectToBlock(IPipeTile selfTile, + EnumFacing side, @Nullable TileEntity tile) { return tile != null && tile.getCapability(GregtechTileCapabilities.CAPABILITY_LASER, side.getOpposite()) != null; } diff --git a/src/main/java/gregtech/common/pipelike/laser/ItemBlockLaserPipe.java b/src/main/java/gregtech/common/pipelike/laser/ItemBlockLaserPipe.java index 18e9b0157d9..3f1faaf893a 100644 --- a/src/main/java/gregtech/common/pipelike/laser/ItemBlockLaserPipe.java +++ b/src/main/java/gregtech/common/pipelike/laser/ItemBlockLaserPipe.java @@ -2,6 +2,7 @@ import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.ItemBlockPipe; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.client.utils.TooltipHelper; import net.minecraft.client.resources.I18n; @@ -16,7 +17,7 @@ public class ItemBlockLaserPipe extends ItemBlockPipe { - public ItemBlockLaserPipe(BlockPipe block) { + public ItemBlockLaserPipe(BlockPipe block) { super(block); } diff --git a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java index 4cb90b94e03..d9b25c0edde 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java @@ -4,8 +4,9 @@ import gregtech.api.capability.ILaserContainer; import gregtech.api.pipenet.IPipeNetHandler; import gregtech.api.pipenet.NetGroup; +import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.common.pipelike.laser.LaserPipeProperties; import gregtech.common.pipelike.laser.LaserPipeType; import gregtech.common.pipelike.laser.tile.TileEntityLaserPipe; @@ -42,9 +43,10 @@ public EnumFacing getFacing() { } private void setPipesActive() { - NetGroup group = getNet().getNode(this.pipe.getPipePos()).getGroupSafe(); + NetGroup group = getNet().getNode(this.pipe.getPipePos()) + .getGroupSafe(); if (group != null) { - for (NodeG node : group.getNodes()) { + for (NetNode node : group.getNodes()) { if (node.getHeldMTE() instanceof TileEntityLaserPipe laserPipe) { laserPipe.setActive(true, 100); } @@ -58,7 +60,7 @@ private ILaserContainer getInnerContainer() { return null; } - List> data = net.getPaths(this.pipe, null); + List> data = net.getPaths(this.pipe, null); if (data == null || data.size() != 1) return null; Map connecteds = data.get(0).getTargetTEs(); if (connecteds.size() != 1) return null; diff --git a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java b/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java index 0bde1623b2c..c7172679809 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java @@ -2,6 +2,7 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.pipenet.WorldPipeNetSimple; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.common.pipelike.laser.LaserPipeProperties; import gregtech.common.pipelike.laser.LaserPipeType; @@ -9,7 +10,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; - import net.minecraftforge.common.capabilities.Capability; import org.jetbrains.annotations.NotNull; @@ -28,7 +28,7 @@ protected Capability[] getConnectionCapabilities() { } @Override - protected Class> getBasePipeClass() { + protected Class> getBasePipeClass() { return TileEntityLaserPipe.class; } diff --git a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java b/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java index 533ca3cef92..e289b02d1bd 100644 --- a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java +++ b/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java @@ -3,6 +3,7 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserContainer; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.api.util.TaskScheduler; @@ -23,7 +24,7 @@ import java.util.EnumMap; -public class TileEntityLaserPipe extends TileEntityPipeBase { +public class TileEntityLaserPipe extends TileEntityPipeBase { private final EnumMap handlers = new EnumMap<>(EnumFacing.class); // the LaserNetHandler can only be created on the server, so we have an empty placeholder for the client @@ -74,7 +75,7 @@ public T getCapabilityInternal(Capability capability, @Nullable EnumFacin } @Override - public void transferDataFrom(IPipeTile tileEntity) { + public void transferDataFrom(IPipeTile tileEntity) { super.transferDataFrom(tileEntity); if (getPipeBlock().getWorldPipeNet(getPipeWorld()) == null) { return; @@ -103,7 +104,7 @@ public void setConnection(EnumFacing side, boolean connected, boolean fromNeighb // check the same for the targeted pipe TileEntity tile = getWorld().getTileEntity(getPos().offset(side)); - if (tile instanceof IPipeTilepipeTile && + if (tile instanceof IPipeTilepipeTile && pipeTile.getPipeType().getClass() == this.getPipeType().getClass()) { connections = pipeTile.getConnections(); connections &= ~(1 << side.getIndex()); diff --git a/src/main/java/gregtech/common/pipelike/optical/BlockOpticalPipe.java b/src/main/java/gregtech/common/pipelike/optical/BlockOpticalPipe.java index 8590ecea771..d87803e3f9f 100644 --- a/src/main/java/gregtech/common/pipelike/optical/BlockOpticalPipe.java +++ b/src/main/java/gregtech/common/pipelike/optical/BlockOpticalPipe.java @@ -4,6 +4,7 @@ import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.pipenet.block.BlockPipe; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.client.renderer.pipe.OpticalPipeRenderer; @@ -29,7 +30,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class BlockOpticalPipe extends BlockPipe { +public class BlockOpticalPipe extends BlockPipe { private final OpticalPipeType pipeType; private final OpticalPipeProperties properties; @@ -57,12 +58,12 @@ public WorldOpticalPipeNet getWorldPipeNet(World world) { } @Override - public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { + public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { return new TileEntityOpticalPipe(); } @Override - public OpticalPipeProperties createProperties(@NotNull IPipeTile pipeTile) { + public OpticalPipeProperties createProperties(@NotNull IPipeTile pipeTile) { OpticalPipeType pipeType = pipeTile.getPipeType(); if (pipeType == null) return getFallbackType(); return this.pipeType.modifyProperties(properties); @@ -77,7 +78,7 @@ public OpticalPipeProperties createItemProperties(@NotNull ItemStack itemStack) } @Override - public ItemStack getDropItem(IPipeTile pipeTile) { + public ItemStack getDropItem(IPipeTile pipeTile) { return new ItemStack(this, 1, pipeType.ordinal()); } @@ -95,7 +96,7 @@ public OpticalPipeType getItemPipeType(@NotNull ItemStack itemStack) { } @Override - public void setTileEntityData(@NotNull TileEntityPipeBase pipeTile, + public void setTileEntityData(@NotNull TileEntityPipeBase pipeTile, ItemStack itemStack) { pipeTile.setPipeData(this, pipeType); } @@ -111,14 +112,14 @@ protected boolean isPipeTool(@NotNull ItemStack stack) { } @Override - public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile) { + public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, + IPipeTile sideTile) { return selfTile instanceof TileEntityOpticalPipe && sideTile instanceof TileEntityOpticalPipe; } @Override - public boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, - @Nullable TileEntity tile) { + public boolean canPipeConnectToBlock(IPipeTile selfTile, + EnumFacing side, @Nullable TileEntity tile) { if (tile == null) return false; if (tile.hasCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, side.getOpposite())) return true; return tile.hasCapability(GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER, side.getOpposite()); diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java index 8d31e474637..849a9abea11 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java @@ -6,8 +6,9 @@ import gregtech.api.capability.IOpticalDataAccessHatch; import gregtech.api.pipenet.IPipeNetHandler; import gregtech.api.pipenet.NetGroup; +import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.NodeG; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.recipes.Recipe; import gregtech.common.pipelike.optical.OpticalPipeProperties; import gregtech.common.pipelike.optical.OpticalPipeType; @@ -77,10 +78,10 @@ public boolean canBridge(@NotNull Collection seen) } private void setPipesActive() { - NetGroup group = getNet().getNode(this.pipe.getPipePos()) + NetGroup group = getNet().getNode(this.pipe.getPipePos()) .getGroupSafe(); if (group != null) { - for (NodeG node : group.getNodes()) { + for (NetNode node : group.getNodes()) { if (node.getHeldMTE() instanceof TileEntityOpticalPipe opticalPipe) { opticalPipe.setActive(true, 100); } @@ -95,7 +96,7 @@ private boolean isNetInvalidForTraversal() { private boolean traverseRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { if (isNetInvalidForTraversal()) return false; - List> inv = net.getPaths(this.pipe, null); + List> inv = net.getPaths(this.pipe, null); if (inv == null || inv.size() != 1) return false; Map connecteds = inv.get(0).getTargetTEs(); if (connecteds.size() != 1) return false; @@ -133,7 +134,7 @@ private boolean traverseCanBridge(@NotNull Collection seen) { if (isNetInvalidForTraversal()) return null; - List> inv = net.getPaths(this.pipe, null); + List> inv = net.getPaths(this.pipe, null); if (inv == null || inv.size() != 1) return null; Map connecteds = inv.get(0).getTargetTEs(); if (connecteds.size() != 1) return null; diff --git a/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java b/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java index 8f85f99e485..38424ad1aeb 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java @@ -2,6 +2,7 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.pipenet.WorldPipeNetSimple; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.common.pipelike.optical.OpticalPipeProperties; import gregtech.common.pipelike.optical.OpticalPipeType; @@ -9,7 +10,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; - import net.minecraftforge.common.capabilities.Capability; import org.jetbrains.annotations.NotNull; @@ -29,7 +29,7 @@ protected Capability[] getConnectionCapabilities() { } @Override - protected Class> getBasePipeClass() { + protected Class> getBasePipeClass() { return TileEntityOpticalPipe.class; } diff --git a/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java b/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java index 3a730e2e81f..445166738d1 100644 --- a/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java +++ b/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java @@ -4,6 +4,7 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IDataAccessHatch; import gregtech.api.capability.IOpticalComputationProvider; +import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.api.recipes.Recipe; @@ -24,7 +25,7 @@ import java.util.Collection; import java.util.EnumMap; -public class TileEntityOpticalPipe extends TileEntityPipeBase { +public class TileEntityOpticalPipe extends TileEntityPipeBase { private final EnumMap handlers = new EnumMap<>(EnumFacing.class); // the OpticalNetHandler can only be created on the server, so we have an empty placeholder for the client @@ -85,7 +86,7 @@ public T getCapabilityInternal(Capability capability, @Nullable EnumFacin } @Override - public void transferDataFrom(IPipeTile tileEntity) { + public void transferDataFrom(IPipeTile tileEntity) { super.transferDataFrom(tileEntity); TileEntityOpticalPipe pipe = (TileEntityOpticalPipe) tileEntity; if (!pipe.handlers.isEmpty() && pipe.defaultHandler != null) { @@ -107,7 +108,7 @@ public void setConnection(EnumFacing side, boolean connected, boolean fromNeighb // also check the other pipe TileEntity tile = getWorld().getTileEntity(getPos().offset(side)); - if (tile instanceof IPipeTilepipeTile && + if (tile instanceof IPipeTilepipeTile && pipeTile.getPipeType().getClass() == this.getPipeType().getClass()) { if (pipeTile.getNumConnections() >= 2) return; } diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java index 6bd63b109cf..f6c34615e96 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java @@ -2,8 +2,8 @@ import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.pipenet.NodeG; -import gregtech.api.pipenet.WorldPipeNetSimple; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.WorldPipeNetBase; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -45,20 +45,22 @@ public void addProbeInfo(@NotNull ProbeMode mode, @NotNull IProbeInfo probeInfo, } } if (tileEntity instanceof TileEntityPipeBase) { - IPipeTile pipeTile = (IPipeTile) tileEntity; - BlockPipe blockPipe = pipeTile.getPipeBlock(); - WorldPipeNetSimple pipeNet = blockPipe.getWorldPipeNet(world); + IPipeTile pipeTile = (IPipeTile) tileEntity; + BlockPipe blockPipe = pipeTile.getPipeBlock(); + WorldPipeNetBase pipeNet = blockPipe.getWorldPipeNet(world); if (pipeNet != null) { probeInfo.text("Net: " + pipeNet.hashCode()); - probeInfo.text("Node Info: "); + probeInfo.text("NetNode Info: "); StringBuilder builder = new StringBuilder(); - NodeG node = pipeNet.getNode(data.getPos()); - builder.append("{") - .append("active: ").append(node.isActive) - .append(", mark: ").append(node.mark) - .append(", open: ").append(node.getOpenConnections()) - .append(", blocked: ").append(node.getBlockedConnections()) - .append("}"); + NetNode node = pipeNet.getNode(data.getPos()); + if (node != null) { + builder.append("{") + .append("active: ").append(node.isActive) + .append(", mark: ").append(node.mark) + .append(", open: ").append(node.getOpenConnections()) + .append(", blocked: ").append(node.getBlockedConnections()) + .append("}"); + } probeInfo.text(builder.toString()); } probeInfo.text("tile open: " + pipeTile.getConnections()); From 801563fb7d7ef95c4ec0fe347aa45394fc5f1e3e Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 21 Jun 2024 16:56:33 -0400 Subject: [PATCH 061/157] misc --- .../java/gregtech/api/pipenet/NetGroup.java | 58 +++--- .../api/pipenet/WorldPipeNetBase.java | 3 + .../api/pipenet/WorldPipeNetComplex.java | 4 +- .../api/pipenet/alg/SinglePathAlgorithm.java | 7 +- .../api/pipenet/edge/AbstractNetFlowEdge.java | 115 ++++++++++++ .../java/gregtech/api/pipenet/edge/IEdge.java | 8 + .../api/pipenet/edge/INetFlowEdge.java | 42 ----- .../gregtech/api/pipenet/edge/NetEdge.java | 15 +- .../api/pipenet/edge/NetFlowEdge.java | 167 +++++++----------- .../api/pipenet/edge/NetFlowSharedEdge.java | 137 ++++++++++++++ .../api/pipenet/edge/util/FlowConsumer.java | 12 +- .../AbstractEdgePredicate.java | 2 +- .../{ => predicate}/BasicEdgePredicate.java | 2 +- .../FilteredEdgePredicate.java | 4 +- .../IShutteredEdgePredicate.java | 2 +- .../properties/FluidPipeProperties.java | 6 + .../fluidpipe/net/FluidEdgePredicate.java | 2 +- .../fluidpipe/net/FluidNetHandler.java | 6 +- .../fluidpipe/net/WorldFluidPipeNet.java | 2 +- .../itempipe/net/ItemEdgePredicate.java | 2 +- .../itempipe/net/WorldItemPipeNet.java | 3 +- 21 files changed, 401 insertions(+), 198 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java create mode 100644 src/main/java/gregtech/api/pipenet/edge/IEdge.java delete mode 100644 src/main/java/gregtech/api/pipenet/edge/INetFlowEdge.java create mode 100644 src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java rename src/main/java/gregtech/api/pipenet/{ => predicate}/AbstractEdgePredicate.java (98%) rename src/main/java/gregtech/api/pipenet/{ => predicate}/BasicEdgePredicate.java (97%) rename src/main/java/gregtech/api/pipenet/{ => predicate}/FilteredEdgePredicate.java (95%) rename src/main/java/gregtech/api/pipenet/{ => predicate}/IShutteredEdgePredicate.java (79%) diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 55b44ab7c2a..39119c5ba89 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -16,44 +16,44 @@ import java.util.stream.Collectors; public class NetGroup & IPipeType, - NodeDataType extends INodeData, E extends NetEdge> implements INBTSerializable { + NodeDataType extends INodeData, Edge extends NetEdge> implements INBTSerializable { - public final WorldPipeNetBase net; + public final WorldPipeNetBase net; - private final Graph, E> graph; + private final Graph, Edge> graph; - private final Set> nodes; + private final Set> nodes; private final AbstractGroupData data; - public NetGroup(Graph, E> graph, - WorldPipeNetBase net) { + public NetGroup(Graph, Edge> graph, + WorldPipeNetBase net) { this.graph = graph; this.nodes = new ObjectOpenHashSet<>(); this.net = net; - this.data = net.getBlankGroupData(); + this.data = net.getBlankGroupData().withGroup(this); } - public NetGroup(Graph, E> graph, WorldPipeNetBase net, - Set> nodes) { + public NetGroup(Graph, Edge> graph, WorldPipeNetBase net, + Set> nodes) { this.graph = graph; this.nodes = nodes; this.net = net; this.nodes.forEach(b -> b.setGroup(this)); - this.data = net.getBlankGroupData(); + this.data = net.getBlankGroupData().withGroup(this); } private void clear() { this.nodes.clear(); } - protected void addNode(NetNode node) { + protected void addNode(NetNode node) { this.nodes.add(node); node.setGroup(this); this.connectionChange(node); } - protected void addNodes(Set> nodes) { + protected void addNodes(Set> nodes) { this.nodes.addAll(nodes); nodes.forEach(a -> { a.setGroup(this); @@ -62,14 +62,14 @@ protected void addNodes(Set> nodes) { } @SafeVarargs - protected final void addNodes(NetNode... nodes) { - for (NetNode node : nodes) { + protected final void addNodes(NetNode... nodes) { + for (NetNode node : nodes) { this.addNode(node); this.connectionChange(node); } } - public void connectionChange(NetNode node) { + public void connectionChange(NetNode node) { // TODO simplify path search by only checking nodes that have connections // use net's connection capabilities } @@ -102,8 +102,8 @@ NDT extends INodeData, E extends NetEdge> void mergeEdge( } } - protected void mergeNode(NetNode node) { - NetGroup group = node.getGroupUnsafe(); + protected void mergeNode(NetNode node) { + NetGroup group = node.getGroupUnsafe(); if (group != null) { this.addNodes(group.getNodes()); group.clear(); @@ -117,7 +117,7 @@ protected void mergeNode(NetNode node) { * @param source node to remove * @return Whether the node existed in the graph */ - public boolean splitNode(NetNode source) { + public boolean splitNode(NetNode source) { if (this.graph.containsVertex(source)) { this.clearCaches(); List> targets = graph.outgoingEdgesOf(source).stream().map(a -> { @@ -130,13 +130,13 @@ public boolean splitNode(NetNode source) { while (!targets.isEmpty()) { // get the last target; if this throws a cast exception, something is very wrong with the graph. @SuppressWarnings("unchecked") - NetNode target = (NetNode) targets + NetNode target = (NetNode) targets .remove(targets.size() - 1); - Set> targetGroup = new ObjectOpenHashSet<>(); - BreadthFirstIterator, E> i = new BreadthFirstIterator<>(graph, + Set> targetGroup = new ObjectOpenHashSet<>(); + BreadthFirstIterator, Edge> i = new BreadthFirstIterator<>(graph, target); - NetNode temp; + NetNode temp; while (i.hasNext()) { temp = i.next(); targetGroup.add(temp); @@ -160,12 +160,12 @@ public boolean splitNode(NetNode source) { * @param target target of the edge * @return Whether the edge existed in the graph */ - public boolean splitEdge(NetNode source, NetNode target) { + public boolean splitEdge(NetNode source, NetNode target) { if (graph.removeEdge(source, target) != null) { this.clearCaches(); - Set> targetGroup = new ObjectOpenHashSet<>(); - BreadthFirstIterator, E> i = new BreadthFirstIterator<>(graph, target); - NetNode temp; + Set> targetGroup = new ObjectOpenHashSet<>(); + BreadthFirstIterator, Edge> i = new BreadthFirstIterator<>(graph, target); + NetNode temp; while (i.hasNext()) { temp = i.next(); // if there's a another complete path to the source node from the target node, there's no need to split @@ -184,7 +184,7 @@ public boolean splitEdge(NetNode source, NetNode> getNodes() { + public Set> getNodes() { return nodes; } @@ -192,7 +192,7 @@ protected void clearCaches() { this.nodes.forEach(NetNode::clearPathCache); } - public Graph, E> getGraph() { + public Graph, Edge> getGraph() { return graph; } @@ -204,7 +204,7 @@ public AbstractGroupData getData() { public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); int i = 0; - for (NetNode node : this.nodes) { + for (NetNode node : this.nodes) { tag.setLong(String.valueOf(i), node.getLongPos()); i++; } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java index 8d1378e0492..6e1ee0f6b19 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java @@ -6,6 +6,9 @@ import gregtech.api.pipenet.alg.SinglePathAlgorithm; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.predicate.AbstractEdgePredicate; +import gregtech.api.pipenet.predicate.BasicEdgePredicate; +import gregtech.api.pipenet.predicate.IShutteredEdgePredicate; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.common.covers.CoverShutter; diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java index 0acbb4ff256..260b03ec360 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java @@ -15,9 +15,7 @@ public abstract class WorldPipeNetComplex - * Note - undirected versions of this pipenet will treat flow in either direction along an edge towards its - * capacity, - * while directed versions will cancel out reverse flow for improved behavior. + * Note - These child edges cannot be allowed to store information, they must only perform runtime behavior. * * @param isDirected Determines whether this net needs directed graph handling. * Used to respect filter directions in the item net and fluid net, for example. diff --git a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java index 86918e9f7ef..1c104801678 100644 --- a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.Graph; +import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -28,7 +29,6 @@ public List> getPathsList(NetNode source) { if (!this.graph.containsVertex(source)) { throw new IllegalArgumentException("Graph must contain the source vertex"); } - List> paths = new ObjectArrayList<>(); List edges = new ObjectArrayList<>(); List> nodes = new ObjectArrayList<>(); nodes.add(source); @@ -55,8 +55,7 @@ public List> getPathsList(NetNode source) { nodes.add(node); sumWeight += node.getData().getWeightFactor(); } - if (!valid) return paths; - paths.add(new NetPath<>(nodes, edges, sumWeight)); - return paths; + if (!valid) return Collections.emptyList(); + return List.of(new NetPath<>(nodes, edges, sumWeight)); } } diff --git a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java new file mode 100644 index 00000000000..3e6282387ba --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java @@ -0,0 +1,115 @@ +package gregtech.api.pipenet.edge; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.block.IPipeType; + +import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; + +import java.lang.ref.WeakReference; +import java.util.WeakHashMap; + +public abstract class AbstractNetFlowEdge> extends NetEdge { + + private final AbstractChannelsHolder channels; + private final WeakHashMap> simulatedChannels; + + public AbstractNetFlowEdge() { + this.channels = getNewHolder(null, null); + this.simulatedChannels = new WeakHashMap<>(9); + } + + /** + * Claims a new, unique simulator instance for properly simulating flow edge limits without actually changing them. + *
+ * This simulator must be discarded after use so that the garbage collector can clean up. + */ + public static ChannelSimulatorKey getNewSimulatorInstance() { + return new ChannelSimulatorKey(); + } + + + public boolean cannotSupportChannel(Object channel, long queryTick, @Nullable ChannelSimulatorKey simulator) { + return getChannels(simulator).cannotSupportChannel(channel, queryTick); + } + + protected AbstractChannelsHolder getChannels(@Nullable ChannelSimulatorKey simulator) { + if (simulator == null) return this.channels; + else { + AbstractChannelsHolder channels = simulatedChannels.get(simulator); + if (channels == null) { + channels = getNewHolder(this.channels, simulator); + simulatedChannels.put(simulator, channels); + } + return channels; + } + } + + public & IPipeType, NDT extends INodeData> int getFlowLimit( + Object channel, + Graph, E> graph, + long queryTick, + @Nullable ChannelSimulatorKey simulator) { + return getChannels(simulator).getFlowLimit(channel, graph, queryTick); + } + + public int getConsumedLimit(Object channel, long queryTick, @Nullable ChannelSimulatorKey simulator) { + return getChannels(simulator).getConsumedLimit(channel, queryTick); + } + + public & IPipeType, NDT extends INodeData> void consumeFlowLimit( + Object channel, + Graph, E> graph, + int amount, long queryTick, + @Nullable ChannelSimulatorKey simulator) { + getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); + } + + protected abstract AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, ChannelSimulatorKey simulator); + + protected abstract static class AbstractChannelsHolder> { + + private final WeakReference simulator; + + public AbstractChannelsHolder(ChannelSimulatorKey simulator) { + this.simulator = new WeakReference<>(simulator); + } + + public ChannelSimulatorKey getSimulator() { + return simulator.get(); + } + + abstract void recalculateFlowLimits(long queryTick); + + abstract boolean cannotSupportChannel(Object channel, long queryTick); + + abstract & IPipeType, NDT extends INodeData> int getFlowLimit( + Object channel, + Graph, E> graph, + long queryTick); + + abstract int getConsumedLimit(Object channel, long queryTick); + + abstract & IPipeType, NDT extends INodeData> void consumeFlowLimit( + Object channel, + Graph, E> graph, + int amount, long queryTick); + } + + public static final class ChannelSimulatorKey { + + private static int ID; + private final int id; + + private ChannelSimulatorKey() { + this.id = ID++; + } + + @Override + public int hashCode() { + // enforcing hash uniqueness improves weak map performance + return id; + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/edge/IEdge.java b/src/main/java/gregtech/api/pipenet/edge/IEdge.java new file mode 100644 index 00000000000..ca471342d41 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/edge/IEdge.java @@ -0,0 +1,8 @@ +package gregtech.api.pipenet.edge; + +public interface IEdge { + + V getSource(); + + V getTarget(); +} diff --git a/src/main/java/gregtech/api/pipenet/edge/INetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/INetFlowEdge.java deleted file mode 100644 index b9ad592c3be..00000000000 --- a/src/main/java/gregtech/api/pipenet/edge/INetFlowEdge.java +++ /dev/null @@ -1,42 +0,0 @@ -package gregtech.api.pipenet.edge; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.block.IPipeType; - -import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; - -public interface INetFlowEdge> { - - /** - * Claims a new, unique simulator instance for properly simulating flow edge limits without actually changing them. - *
- * This simulator must be discarded after use so that the garbage collector can clean up. - */ - static ChannelSimulatorKey getNewSimulatorInstance() { - return new ChannelSimulatorKey(); - } - - & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, - Graph, E> graph, - int amount, long queryTick, - @Nullable INetFlowEdge.ChannelSimulatorKey simulator); - - final class ChannelSimulatorKey { - - private static int ID; - private final int id; - - private ChannelSimulatorKey() { - this.id = ID++; - } - - @Override - public int hashCode() { - // enforcing hash uniqueness improves weak map performance - return id; - } - } -} diff --git a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java index 2c7e462874e..80817d44ad1 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java @@ -1,6 +1,6 @@ package gregtech.api.pipenet.edge; -import gregtech.api.pipenet.AbstractEdgePredicate; +import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.pipenet.INBTBuilder; import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.NetNode; @@ -15,11 +15,16 @@ import java.util.Map; import java.util.function.Predicate; -public class NetEdge extends DefaultWeightedEdge implements INBTSerializable { +public class NetEdge extends DefaultWeightedEdge implements INBTSerializable, IEdge> { private AbstractEdgePredicate predicate; private boolean invertedPredicate; + private INodeData> minData; + + /** + * Most basic NetEdge that provides predicate handling & NBT storage capability + */ @SuppressWarnings("unused") // used via reflection public NetEdge() {} @@ -34,6 +39,12 @@ public Predicate getPredicate() { return predicate; } + public INodeData> getMinData() { + if (this.minData == null) + this.minData = this.getCastSource().getData().getMinData(this.getCastTarget().getData()); + return this.minData; + } + public boolean isPredicateInverted() { return invertedPredicate; } diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java index 989c2dbed1e..5dc98383778 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java @@ -6,19 +6,13 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; import java.util.List; -import java.util.WeakHashMap; -public class NetFlowEdge extends NetEdge implements INetFlowEdge { +public final class NetFlowEdge extends AbstractNetFlowEdge { private final int flowBufferTicks; - private final ChannelsHolder channels; - private final WeakHashMap simulatedChannels; - - private INodeData> minData; /** * NetEdge that provides standard flow behavior handling @@ -29,115 +23,90 @@ public class NetFlowEdge extends NetEdge implements INetFlowEdge { */ public NetFlowEdge(int flowBufferTicks) { this.flowBufferTicks = flowBufferTicks; - this.channels = new ChannelsHolder(); - this.simulatedChannels = new WeakHashMap<>(9); } - private ChannelsHolder getChannels(@Nullable INetFlowEdge.ChannelSimulatorKey simulator) { - if (simulator == null) return this.channels; - else { - ChannelsHolder channels = simulatedChannels.get(simulator); - if (channels == null) { - channels = new ChannelsHolder(this.channels); - simulatedChannels.put(simulator, channels); - } - return channels; - } + @Override + protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, ChannelSimulatorKey simulator) { + if (prototype instanceof ChannelsHolder holder) return new ChannelsHolder(holder, simulator); + return new ChannelsHolder(simulator); } - private INodeData> getMinData() { - if (this.minData == null) - this.minData = this.getCastSource().getData().getMinData(this.getCastTarget().getData()); - return this.minData; - } + private final class ChannelsHolder extends AbstractChannelsHolder { - private int getAdjustedThroughput() { - return getMinData().getThroughput() * flowBufferTicks; - } + private final Object2IntOpenHashMap map; + private long lastQueryTick; - private boolean cannotSupportChannel(Object channel, long queryTick, - @Nullable INetFlowEdge.ChannelSimulatorKey simulator) { - var channels = getChannels(simulator); - channels.recalculateFlowLimits(queryTick); - return channels.map.size() >= getMinData().getChannelMaxCount() && !channels.map.containsKey(channel); - } - - public & IPipeType, NDT extends INodeData> int getFlowLimit( - Object channel, - Graph, NetFlowEdge> graph, - long queryTick, - @Nullable INetFlowEdge.ChannelSimulatorKey simulator) { - if (this.cannotSupportChannel(channel, queryTick, simulator)) { - return 0; + public ChannelsHolder(ChannelSimulatorKey simulator) { + super(simulator); + this.map = new Object2IntOpenHashMap<>(9); + this.map.defaultReturnValue(getMinData().getThroughput() * flowBufferTicks); } - int limit = getChannels(simulator).map.getOrDefault(channel, getAdjustedThroughput()); - NetFlowEdge inverse = graph.getEdge(this.getCastTarget(), this.getCastSource()); - if (inverse != null && inverse != this) { - if (inverse.cannotSupportChannel(channel, queryTick, simulator)) return 0; - limit += inverse.getConsumedLimit(channel, queryTick, simulator); + public ChannelsHolder(ChannelsHolder prototype, ChannelSimulatorKey simulator) { + super(simulator); + this.map = prototype.map.clone(); + this.lastQueryTick = prototype.lastQueryTick; } - return limit; - } - - public & IPipeType, NDT extends INodeData> int getConsumedLimit( - Object channel, - long queryTick, - @Nullable INetFlowEdge.ChannelSimulatorKey simulator) { - var channels = getChannels(simulator); - channels.recalculateFlowLimits(queryTick); - int limit = getAdjustedThroughput(); - return limit - channels.map.getOrDefault(channel, limit); - } - - @Override - public & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, - Graph, NetFlowEdge> graph, - int amount, - long queryTick, - @Nullable INetFlowEdge.ChannelSimulatorKey simulator) { - if (amount == 0) return; - var channels = getChannels(simulator); - channels.recalculateFlowLimits(queryTick); - - // check against reverse edge - NetFlowEdge inverse = graph.getEdge(this.getCastTarget(), this.getCastSource()); - if (inverse != null && inverse != this) { - int inverseConsumed = inverse.getConsumedLimit(channel, queryTick, simulator); - if (inverseConsumed != 0) { - int toFreeUp = Math.min(inverseConsumed, amount); - inverse.consumeFlowLimit(channel, graph, -toFreeUp, queryTick, simulator); - if (toFreeUp == amount) return; - amount -= toFreeUp; - } + @Override + public boolean cannotSupportChannel(Object channel, long queryTick) { + recalculateFlowLimits(queryTick); + if (map.containsKey(channel)) return map.getInt(channel) <= 0; + else return map.size() >= getMinData().getChannelMaxCount(); } - int finalAmount = amount; - channels.map.compute(channel, (k, v) -> { - int d = getAdjustedThroughput(); - if (v == null) v = d; - v -= finalAmount; - if (v >= d) return null; - return v; - }); - } - - private final class ChannelsHolder { + @Override + public & IPipeType, NDT extends INodeData> int getFlowLimit(Object channel, + Graph, NetFlowEdge> graph, + long queryTick) { + if (cannotSupportChannel(channel, queryTick)) return 0; + int limit = map.getInt(channel); + + NetFlowEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); + if (inverse != null && inverse != NetFlowEdge.this) { + if (inverse.cannotSupportChannel(channel, queryTick, getSimulator())) return 0; + limit += inverse.getConsumedLimit(channel, queryTick, getSimulator()); + } - public final Object2IntOpenHashMap map; - public long lastQueryTick; + return limit; + } - public ChannelsHolder() { - this.map = new Object2IntOpenHashMap<>(9); + @Override + int getConsumedLimit(Object channel, long queryTick) { + recalculateFlowLimits(queryTick); + int limit = map.defaultReturnValue(); + return limit - map.getInt(channel); } - public ChannelsHolder(ChannelsHolder prototype) { - this.map = prototype.map.clone(); - this.lastQueryTick = prototype.lastQueryTick; + @Override + & IPipeType, NDT extends INodeData> void consumeFlowLimit( + Object channel, Graph, NetFlowEdge> graph, int amount, long queryTick) { + if (amount == 0) return; + recalculateFlowLimits(queryTick); + + // check against reverse edge + NetFlowEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); + if (inverse != null && inverse != NetFlowEdge.this) { + int inverseConsumed = inverse.getConsumedLimit(channel, queryTick, getSimulator()); + if (inverseConsumed != 0) { + int toFreeUp = Math.min(inverseConsumed, amount); + inverse.consumeFlowLimit(channel, graph, -toFreeUp, queryTick, getSimulator()); + if (toFreeUp == amount) return; + amount -= toFreeUp; + } + } + + int finalAmount = amount; + map.compute(channel, (k, v) -> { + int d = map.defaultReturnValue(); + if (v == null) v = d; + v -= finalAmount; + if (v >= d) return null; + return v; + }); } + @Override public void recalculateFlowLimits(long queryTick) { int time = (int) (queryTick - this.lastQueryTick); if (time < 0) { @@ -146,7 +115,7 @@ public void recalculateFlowLimits(long queryTick) { List toRemove = new ObjectArrayList<>(); this.map.replaceAll((k, v) -> { v += time * getMinData().getThroughput(); - if (v >= getAdjustedThroughput()) toRemove.add(k); + if (v >= map.defaultReturnValue()) toRemove.add(k); return v; }); toRemove.forEach(this.map::removeInt); diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java new file mode 100644 index 00000000000..50dc12519ac --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java @@ -0,0 +1,137 @@ +package gregtech.api.pipenet.edge; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.block.IPipeType; + +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraft.util.math.MathHelper; + +import org.jgrapht.Graph; + +import java.util.List; + +public class NetFlowSharedEdge extends AbstractNetFlowEdge { + + private final int flowBufferTicks; + + /** + * NetEdge that provides flow behavior where the capacity along an edge is shared by all channels. + * + * @param flowBufferTicks Determines how many ticks of 'buffer' flow capacity can be built up along edges. Allows + * for once-an-interval push/pull operations instead of needing them every tick for maximum + * throughput. + */ + public NetFlowSharedEdge(int flowBufferTicks) { + this.flowBufferTicks = flowBufferTicks; + } + + @Override + protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, ChannelSimulatorKey simulator) { + if (prototype instanceof ChannelsHolder holder) return new ChannelsHolder(holder, simulator); + return new ChannelsHolder(simulator); + } + + private final class ChannelsHolder extends AbstractChannelsHolder { + + private int maxCapacity; + private int sharedCapacity; + private final Object2IntOpenHashMap map; + private long lastQueryTick; + + public ChannelsHolder(ChannelSimulatorKey simulator) { + super(simulator); + this.map = new Object2IntOpenHashMap<>(9); + this.map.defaultReturnValue(0); + this.maxCapacity = getMinData().getThroughput() * flowBufferTicks; + } + + public ChannelsHolder(ChannelsHolder prototype, ChannelSimulatorKey simulator) { + super(simulator); + this.map = prototype.map.clone(); + this.lastQueryTick = prototype.lastQueryTick; + } + + @Override + public boolean cannotSupportChannel(Object channel, long queryTick) { + recalculateFlowLimits(queryTick); + if (sharedCapacity <= 0) return true; + else return map.size() >= getMinData().getChannelMaxCount(); + } + + @Override + public & IPipeType, NDT extends INodeData> int getFlowLimit(Object channel, + Graph, NetFlowSharedEdge> graph, + long queryTick) { + if (cannotSupportChannel(channel, queryTick)) return 0; + + NetFlowSharedEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); + if (inverse != null && inverse != NetFlowSharedEdge.this) { + if (inverse.cannotSupportChannel(channel, queryTick, getSimulator())) return 0; + return sharedCapacity + inverse.getConsumedLimit(channel, queryTick, getSimulator()); + } else return sharedCapacity; + } + + @Override + int getConsumedLimit(Object channel, long queryTick) { + recalculateFlowLimits(queryTick); + return map.getInt(channel); + } + + @Override + & IPipeType, NDT extends INodeData> void consumeFlowLimit( + Object channel, Graph, NetFlowSharedEdge> graph, int amount, long queryTick) { + if (amount == 0) return; + recalculateFlowLimits(queryTick); + + // check against reverse edge + NetFlowSharedEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); + if (inverse != null && inverse != NetFlowSharedEdge.this) { + int inverseConsumed = inverse.getConsumedLimit(channel, queryTick, getSimulator()); + if (inverseConsumed != 0) { + int toFreeUp = Math.min(inverseConsumed, amount); + inverse.consumeFlowLimit(channel, graph, -toFreeUp, queryTick, getSimulator()); + if (toFreeUp == amount) return; + amount -= toFreeUp; + } + } + + int finalAmount = amount; + map.compute(channel, (k, v) -> { + if (v == null) v = 0; + v += finalAmount; + if (v <= 0) return null; + return v; + }); + sharedCapacity -= finalAmount; + boundCapacity(); + } + + @Override + public void recalculateFlowLimits(long queryTick) { + int time = (int) (queryTick - this.lastQueryTick); + if (time < 0) { + this.map.clear(); + } else { + List toRemove = new ObjectArrayList<>(); + int regenerationPer = MathHelper.ceil((float) time * getMinData().getThroughput() / map.size()); + map.replaceAll((k, v) -> { + v -= regenerationPer; + if (v <= 0) toRemove.add(k); + return v; + }); + sharedCapacity += regenerationPer * map.size(); + boundCapacity(); + toRemove.forEach(map::removeInt); + } + this.lastQueryTick = queryTick; + } + + private void boundCapacity() { + if (this.sharedCapacity > this.maxCapacity) this.sharedCapacity = this.maxCapacity; + else if (this.sharedCapacity < 0) this.sharedCapacity = 0; + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java index c38a28bc475..d5686f04c8a 100644 --- a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java +++ b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java @@ -3,7 +3,7 @@ import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.INetFlowEdge; +import gregtech.api.pipenet.edge.AbstractNetFlowEdge; import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.util.FluidTestObject; @@ -12,19 +12,19 @@ import java.util.function.Consumer; public class FlowConsumer & IPipeType, NDT extends INodeData, - E extends NetEdge & INetFlowEdge> implements Consumer { + E extends AbstractNetFlowEdge> implements Consumer { - private final INetFlowEdge edge; + private final AbstractNetFlowEdge edge; private final FluidTestObject testObject; private final Graph, E> graph; private final int flow; private final long tick; - private final INetFlowEdge.ChannelSimulatorKey simulatorKey; + private final AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey; private double ratio = 1; - public FlowConsumer(INetFlowEdge edge, FluidTestObject testObject, Graph, E> graph, int flow, - long tick, INetFlowEdge.ChannelSimulatorKey simulatorKey) { + public FlowConsumer(AbstractNetFlowEdge edge, FluidTestObject testObject, Graph, E> graph, int flow, + long tick, AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey) { this.edge = edge; this.testObject = testObject; this.graph = graph; diff --git a/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java b/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java similarity index 98% rename from src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java rename to src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java index 921e7d298d3..1c193883f64 100644 --- a/src/main/java/gregtech/api/pipenet/AbstractEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet; +package gregtech.api.pipenet.predicate; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java b/src/main/java/gregtech/api/pipenet/predicate/BasicEdgePredicate.java similarity index 97% rename from src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java rename to src/main/java/gregtech/api/pipenet/predicate/BasicEdgePredicate.java index 32776ca3534..db3a07aaa4b 100644 --- a/src/main/java/gregtech/api/pipenet/BasicEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/predicate/BasicEdgePredicate.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet; +package gregtech.api.pipenet.predicate; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/api/pipenet/FilteredEdgePredicate.java b/src/main/java/gregtech/api/pipenet/predicate/FilteredEdgePredicate.java similarity index 95% rename from src/main/java/gregtech/api/pipenet/FilteredEdgePredicate.java rename to src/main/java/gregtech/api/pipenet/predicate/FilteredEdgePredicate.java index d485253a1bb..6d23df21c64 100644 --- a/src/main/java/gregtech/api/pipenet/FilteredEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/predicate/FilteredEdgePredicate.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet; +package gregtech.api.pipenet.predicate; import gregtech.api.util.IDirtyNotifiable; import gregtech.common.covers.filter.BaseFilterContainer; @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; public abstract class FilteredEdgePredicate> extends AbstractEdgePredicate - implements IShutteredEdgePredicate { + implements IShutteredEdgePredicate { protected static final IDirtyNotifiable DECOY = () -> {}; diff --git a/src/main/java/gregtech/api/pipenet/IShutteredEdgePredicate.java b/src/main/java/gregtech/api/pipenet/predicate/IShutteredEdgePredicate.java similarity index 79% rename from src/main/java/gregtech/api/pipenet/IShutteredEdgePredicate.java rename to src/main/java/gregtech/api/pipenet/predicate/IShutteredEdgePredicate.java index 106ec1a7b86..d68ea3369e1 100644 --- a/src/main/java/gregtech/api/pipenet/IShutteredEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/predicate/IShutteredEdgePredicate.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet; +package gregtech.api.pipenet.predicate; public interface IShutteredEdgePredicate { diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index a22822d659c..f6765f78b24 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -91,6 +91,12 @@ public int getTanks() { return tanks; } + @Override + public double getWeightFactor() { + float factor = 100f / this.throughput; + return factor * factor; + } + public int getThroughput() { return throughput; } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java index b1ade12d8bf..d03294e1bad 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java @@ -1,6 +1,6 @@ package gregtech.common.pipelike.fluidpipe.net; -import gregtech.api.pipenet.FilteredEdgePredicate; +import gregtech.api.pipenet.predicate.FilteredEdgePredicate; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.FluidFilterContainer; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java index e051da518ee..c5d6b4786ee 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java @@ -4,7 +4,7 @@ import gregtech.api.pipenet.IPipeNetHandler; import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.edge.INetFlowEdge; +import gregtech.api.pipenet.edge.AbstractNetFlowEdge; import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.edge.util.FlowConsumer; import gregtech.api.unification.material.properties.FluidPipeProperties; @@ -39,7 +39,7 @@ public class FluidNetHandler implements IFluidHandler, IPipeNetHandler { private final IFluidHandler testHandler = new FluidTank(Integer.MAX_VALUE); - private INetFlowEdge.ChannelSimulatorKey simulatorKey; + private AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey; private FluidStack lastFillResource; private final Map, FluidPipeProperties.PipeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); @@ -85,7 +85,7 @@ public int fill(FluidStack resource, boolean doFill) { // push flow through net List> paths = this.getNet().getPaths(pipe, testObject); FluidStack helper = resource.copy(); - if (!doFill) this.simulatorKey = INetFlowEdge.getNewSimulatorInstance(); + if (!doFill) this.simulatorKey = AbstractNetFlowEdge.getNewSimulatorInstance(); else this.simulatorKey = null; mainloop: for (NetPath path : paths) { diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index c0dc1191e63..d265f9db44a 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -1,7 +1,7 @@ package gregtech.common.pipelike.fluidpipe.net; import gregtech.api.cover.Cover; -import gregtech.api.pipenet.AbstractEdgePredicate; +import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.pipenet.WorldPipeNetComplex; import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java index 805d3a76a37..f98ec5c97e3 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java @@ -1,6 +1,6 @@ package gregtech.common.pipelike.itempipe.net; -import gregtech.api.pipenet.FilteredEdgePredicate; +import gregtech.api.pipenet.predicate.FilteredEdgePredicate; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.ItemFilterContainer; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java index 93b02bc6d49..84c62ae5e72 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java @@ -1,9 +1,9 @@ package gregtech.common.pipelike.itempipe.net; import gregtech.api.cover.Cover; -import gregtech.api.pipenet.AbstractEdgePredicate; import gregtech.api.pipenet.WorldPipeNetSimple; import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.common.covers.CoverConveyor; @@ -18,7 +18,6 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.items.CapabilityItemHandler; -// TODO move onto complex net public class WorldItemPipeNet extends WorldPipeNetSimple { private static final String DATA_ID = "gregtech.item_pipe_net"; From 044f325370d232f4a5f9f6b42da3072323964151 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 23 Jun 2024 12:11:43 -0400 Subject: [PATCH 062/157] Energy net overhaul --- .../api/capability/IEnergyContainer.java | 14 +- .../api/capability/impl/EUToFEProvider.java | 26 +- .../impl/EnergyContainerBatteryBuffer.java | 8 +- .../impl/EnergyContainerBatteryCharger.java | 5 +- .../impl/EnergyContainerHandler.java | 10 +- .../capability/impl/EnergyContainerList.java | 4 +- .../java/gregtech/api/pipenet/NetGroup.java | 67 ++-- .../java/gregtech/api/pipenet/NetNode.java | 6 +- .../java/gregtech/api/pipenet/NetPath.java | 33 +- .../gregtech/api/pipenet/NodeLossResult.java | 20 ++ .../api/pipenet/WorldPipeNetBase.java | 70 ++--- .../api/pipenet/WorldPipeNetComplex.java | 30 +- .../api/pipenet/WorldPipeNetSimple.java | 26 +- .../api/pipenet/alg/AllPathsAlgorithm.java | 34 ++ .../pipenet/alg/ShortestPathsAlgorithm.java | 27 +- .../api/pipenet/alg/SinglePathAlgorithm.java | 11 +- .../gregtech/api/pipenet/block/BlockPipe.java | 34 +- .../material/TileEntityMaterialPipeBase.java | 2 +- .../api/pipenet/edge/AbstractNetFlowEdge.java | 12 +- .../java/gregtech/api/pipenet/edge/IEdge.java | 2 + .../gregtech/api/pipenet/edge/NetEdge.java | 5 + .../api/pipenet/edge/NetFlowEdge.java | 39 ++- .../api/pipenet/edge/NetFlowSharedEdge.java | 37 ++- .../api/pipenet/edge/util/FlowConsumer.java | 20 +- .../pipenet/edge/util/FlowConsumerList.java | 39 +++ .../api/pipenet/tile/TileEntityPipeBase.java | 5 +- .../properties/FluidPipeProperties.java | 26 +- .../material/properties/WireProperties.java | 5 + .../java/gregtech/api/util/GTUtility.java | 8 + .../common/covers/CoverDigitalInterface.java | 4 +- .../converter/ConverterTrait.java | 10 +- .../storage/MetaTileEntityCreativeEnergy.java | 16 +- .../common/pipelike/cable/BlockCable.java | 11 +- .../pipelike/cable/net/EnergyNetHandler.java | 295 ++++++++++++++---- .../pipelike/cable/net/WorldEnergyNet.java | 18 +- .../pipelike/cable/tile/TileEntityCable.java | 107 +++---- .../fluidpipe/net/FluidNetHandler.java | 38 ++- .../fluidpipe/net/WorldFluidPipeNet.java | 3 +- .../pipelike/itempipe/net/ItemNetHandler.java | 8 +- .../pipelike/laser/net/LaserNetHandler.java | 6 +- .../laser/tile/TileEntityLaserPipe.java | 2 +- .../optical/net/OpticalNetHandler.java | 4 +- .../converter/ConverterTraitTest.java | 3 +- 43 files changed, 739 insertions(+), 411 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/NodeLossResult.java create mode 100644 src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java create mode 100644 src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java diff --git a/src/main/java/gregtech/api/capability/IEnergyContainer.java b/src/main/java/gregtech/api/capability/IEnergyContainer.java index 14e9c7f158d..e88dae53274 100644 --- a/src/main/java/gregtech/api/capability/IEnergyContainer.java +++ b/src/main/java/gregtech/api/capability/IEnergyContainer.java @@ -5,14 +5,18 @@ public interface IEnergyContainer { /** - * This method is basically {@link #changeEnergy(long)}, but it also handles amperes. + * This method is basically {@link #changeEnergy(long)}, but it also handles amperes and simulation. * This method should always be used when energy is passed between blocks. * - * @param voltage amount of energy packets (energy to add / input voltage) - * @param amperage packet size (energy to add / input amperage) + * @param voltage packet size (energy to add divided by input amperage) + * @param amperage amount of energy packets (energy to add divided by input voltage) * @return amount of used amperes. 0 if not accepted anything. */ - long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage); + long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate); + + default long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + return acceptEnergyFromNetwork(side, voltage, amperage, false); + } /** * @return if this container accepts energy from the given side @@ -123,7 +127,7 @@ default boolean isOneProbeHidden() { IEnergyContainer DEFAULT = new IEnergyContainer() { @Override - public long acceptEnergyFromNetwork(EnumFacing enumFacing, long l, long l1) { + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { return 0; } diff --git a/src/main/java/gregtech/api/capability/impl/EUToFEProvider.java b/src/main/java/gregtech/api/capability/impl/EUToFEProvider.java index 299e8f2af14..cbb4e3f68c7 100644 --- a/src/main/java/gregtech/api/capability/impl/EUToFEProvider.java +++ b/src/main/java/gregtech/api/capability/impl/EUToFEProvider.java @@ -55,7 +55,7 @@ public GTEnergyWrapper(IEnergyStorage energyStorage) { } @Override - public long acceptEnergyFromNetwork(EnumFacing facing, long voltage, long amperage) { + public long acceptEnergyFromNetwork(EnumFacing facing, long voltage, long amperage, boolean simulate) { int receive = 0; // Try to use the internal buffer before consuming a new packet @@ -68,14 +68,14 @@ public long acceptEnergyFromNetwork(EnumFacing facing, long voltage, long ampera // Internal Buffer could provide the max RF the consumer could consume if (feBuffer > receive) { - feBuffer -= receive; - energyStorage.receiveEnergy(receive, false); + if (!simulate) feBuffer -= receive; + energyStorage.receiveEnergy(receive, simulate); return 0; // Buffer could not provide max value, save the remainder and continue processing } else { receive = safeCastLongToInt(feBuffer); - feBuffer = 0; + if (!simulate) feBuffer = 0; } } @@ -93,13 +93,13 @@ public long acceptEnergyFromNetwork(EnumFacing facing, long voltage, long ampera // Only able to consume our buffered amount if (consumable == receive) { - energyStorage.receiveEnergy(consumable, false); + energyStorage.receiveEnergy(consumable, simulate); return 0; } // Able to consume our full packet as well as our remainder buffer if (consumable == maximalValue + receive) { - energyStorage.receiveEnergy(consumable, false); + energyStorage.receiveEnergy(consumable, simulate); return amperage; } @@ -107,13 +107,13 @@ public long acceptEnergyFromNetwork(EnumFacing facing, long voltage, long ampera // Able to consume buffered amount plus an even amount of packets (no buffer needed) if (newPower % maxPacket == 0) { - return energyStorage.receiveEnergy(consumable, false) / maxPacket; + return energyStorage.receiveEnergy(consumable, simulate) / maxPacket; } // Able to consume buffered amount plus some amount of power with a packet remainder int ampsToConsume = safeCastLongToInt((newPower / maxPacket) + 1); - feBuffer = safeCastLongToInt((maxPacket * ampsToConsume) - consumable); - energyStorage.receiveEnergy(consumable, false); + if (!simulate) feBuffer = safeCastLongToInt((maxPacket * ampsToConsume) - consumable); + energyStorage.receiveEnergy(consumable, simulate); return ampsToConsume; // Else try to draw 1 full packet @@ -127,19 +127,19 @@ public long acceptEnergyFromNetwork(EnumFacing facing, long voltage, long ampera // Able to accept the full amount of power if (consumable == maximalValue) { - energyStorage.receiveEnergy(consumable, false); + energyStorage.receiveEnergy(consumable, simulate); return amperage; } // Able to consume an even amount of packets if (consumable % maxPacket == 0) { - return energyStorage.receiveEnergy(consumable, false) / maxPacket; + return energyStorage.receiveEnergy(consumable, simulate) / maxPacket; } // Able to consume power with some amount of power remainder in the packet int ampsToConsume = safeCastLongToInt((consumable / maxPacket) + 1); - feBuffer = safeCastLongToInt((maxPacket * ampsToConsume) - consumable); - energyStorage.receiveEnergy(consumable, false); + if (!simulate) feBuffer = safeCastLongToInt((maxPacket * ampsToConsume) - consumable); + energyStorage.receiveEnergy(consumable, simulate); return ampsToConsume; } } diff --git a/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryBuffer.java b/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryBuffer.java index b9f124c2400..e3f8b279aeb 100644 --- a/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryBuffer.java +++ b/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryBuffer.java @@ -31,7 +31,7 @@ public EnergyContainerBatteryBuffer(MetaTileEntity metaTileEntity, int tier, int } @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { if (amperage <= 0 || voltage <= 0) return 0; @@ -43,7 +43,7 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage if (side == null || inputsEnergy(side)) { if (voltage > getInputVoltage()) { - metaTileEntity.doExplosion(GTUtility.getExplosionPower(voltage)); + if (!simulate) metaTileEntity.doExplosion(GTUtility.getExplosionPower(voltage)); return usedAmps; } @@ -51,6 +51,8 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage long internalAmps = Math.min(maxAmps, Math.max(0, getInternalStorage() / voltage)); usedAmps = Math.min(usedAmps, maxAmps - internalAmps); + if (simulate) return usedAmps; + amps += usedAmps; energyInputPerSec += usedAmps * voltage; @@ -110,7 +112,7 @@ public void update() { long outAmps = 0L; if (genAmps > 0) { - outAmps = energyContainer.acceptEnergyFromNetwork(outFacing.getOpposite(), voltage, genAmps); + outAmps = energyContainer.acceptEnergyFromNetwork(outFacing.getOpposite(), voltage, genAmps, false); if (outAmps == 0 && internalAmps == 0) return; energyOutputPerSec += outAmps * voltage; diff --git a/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryCharger.java b/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryCharger.java index c335e09ddca..681bb2ad9bd 100644 --- a/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryCharger.java +++ b/src/main/java/gregtech/api/capability/impl/EnergyContainerBatteryCharger.java @@ -29,7 +29,7 @@ public EnergyContainerBatteryCharger(MetaTileEntity metaTileEntity, int tier, in } @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { if (amperage <= 0 || voltage <= 0) return 0; @@ -41,13 +41,14 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage if (side == null || inputsEnergy(side)) { if (voltage > getInputVoltage()) { - metaTileEntity.doExplosion(GTUtility.getExplosionPower(voltage)); + if (!simulate) metaTileEntity.doExplosion(GTUtility.getExplosionPower(voltage)); } // Prioritizes as many packets as available from the buffer long internalAmps = Math.min(maxAmps, Math.max(0, getInternalStorage() / voltage)); usedAmps = Math.min(usedAmps, maxAmps - internalAmps); + if (simulate) return usedAmps; amps += usedAmps; energyInputPerSec += usedAmps * voltage; diff --git a/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java b/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java index 37688a4deec..c40f25403e5 100644 --- a/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java +++ b/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java @@ -223,19 +223,21 @@ public void update() { } @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { if (amps >= getInputAmperage()) return 0; long canAccept = getEnergyCapacity() - getEnergyStored(); if (voltage > 0L && (side == null || inputsEnergy(side))) { if (voltage > getInputVoltage()) { - metaTileEntity.doExplosion(GTUtility.getExplosionPower(voltage)); + if (!simulate) metaTileEntity.doExplosion(GTUtility.getExplosionPower(voltage)); return Math.min(amperage, getInputAmperage() - amps); } if (canAccept >= voltage) { long amperesAccepted = Math.min(canAccept / voltage, Math.min(amperage, getInputAmperage() - amps)); if (amperesAccepted > 0) { - setEnergyStored(getEnergyStored() + voltage * amperesAccepted); - amps += amperesAccepted; + if (!simulate) { + setEnergyStored(getEnergyStored() + voltage * amperesAccepted); + amps += amperesAccepted; + } return amperesAccepted; } } diff --git a/src/main/java/gregtech/api/capability/impl/EnergyContainerList.java b/src/main/java/gregtech/api/capability/impl/EnergyContainerList.java index 5db650b32d2..a38c56a9159 100644 --- a/src/main/java/gregtech/api/capability/impl/EnergyContainerList.java +++ b/src/main/java/gregtech/api/capability/impl/EnergyContainerList.java @@ -138,11 +138,11 @@ public long getOutputPerSec() { } @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { long amperesUsed = 0L; List energyContainerList = this.energyContainerList; for (IEnergyContainer iEnergyContainer : energyContainerList) { - amperesUsed += iEnergyContainer.acceptEnergyFromNetwork(null, voltage, amperage); + amperesUsed += iEnergyContainer.acceptEnergyFromNetwork(null, voltage, amperage, simulate); if (amperage == amperesUsed) { return amperesUsed; } diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 39119c5ba89..10508dddb82 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -10,6 +10,7 @@ import org.jgrapht.Graph; import org.jgrapht.traverse.BreadthFirstIterator; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; @@ -28,45 +29,43 @@ public class NetGroup & IPipeType, public NetGroup(Graph, Edge> graph, WorldPipeNetBase net) { - this.graph = graph; - this.nodes = new ObjectOpenHashSet<>(); - this.net = net; - this.data = net.getBlankGroupData().withGroup(this); + this(graph, net, new ObjectOpenHashSet<>()); } public NetGroup(Graph, Edge> graph, WorldPipeNetBase net, Set> nodes) { this.graph = graph; - this.nodes = nodes; this.net = net; - this.nodes.forEach(b -> b.setGroup(this)); - this.data = net.getBlankGroupData().withGroup(this); - } - - private void clear() { - this.nodes.clear(); + this.data = net.getBlankGroupData(); + if (data != null) data.withGroup(this); + this.nodes = nodes; + nodes.forEach(this::onAddedToGroup); } protected void addNode(NetNode node) { this.nodes.add(node); - node.setGroup(this); - this.connectionChange(node); + this.onAddedToGroup(node); } - protected void addNodes(Set> nodes) { + protected void addNodes(Collection> nodes) { this.nodes.addAll(nodes); - nodes.forEach(a -> { - a.setGroup(this); - this.connectionChange(a); - }); + nodes.forEach(this::onAddedToGroup); } - @SafeVarargs - protected final void addNodes(NetNode... nodes) { - for (NetNode node : nodes) { - this.addNode(node); - this.connectionChange(node); - } + protected void removeNode(NetNode node) { + this.nodes.remove(node); + } + + protected void removeNodes(Collection> nodes) { + this.nodes.removeAll(nodes); + } + + protected void clearNodes() { + this.nodes.clear(); + } + + protected void onAddedToGroup(NetNode node) { + node.setGroup(this); } public void connectionChange(NetNode node) { @@ -90,7 +89,7 @@ NDT extends INodeData, E extends NetEdge> void mergeEdge( if (sourceGroup == null) { sourceGroup = source.getGroupSafe(); } else { - sourceGroup.clearCaches(); + sourceGroup.clearPathCaches(); return; } } @@ -106,9 +105,9 @@ protected void mergeNode(NetNode node) { NetGroup group = node.getGroupUnsafe(); if (group != null) { this.addNodes(group.getNodes()); - group.clear(); + group.clearNodes(); } else addNode(node); - this.clearCaches(); + this.clearPathCaches(); } /** @@ -119,14 +118,14 @@ protected void mergeNode(NetNode node) { */ public boolean splitNode(NetNode source) { if (this.graph.containsVertex(source)) { - this.clearCaches(); + this.clearPathCaches(); List> targets = graph.outgoingEdgesOf(source).stream().map(a -> { // handling so undirected graphs don't throw an error if (net.isDirected() || a.getTarget().getNodePos() != source.getNodePos()) return a.getTarget(); return a.getSource(); }).collect(Collectors.toList()); this.graph.removeVertex(source); - this.nodes.remove(source); + this.removeNode(source); while (!targets.isEmpty()) { // get the last target; if this throws a cast exception, something is very wrong with the graph. @SuppressWarnings("unchecked") @@ -143,7 +142,7 @@ public boolean splitNode(NetNode source) { // if we find a target node in our search, remove it from the list targets.remove(temp); } - this.nodes.removeAll(targetGroup); + this.removeNodes(targetGroup); if (targetGroup.size() != 0) { new NetGroup<>(this.graph, this.net, targetGroup); } @@ -162,7 +161,7 @@ public boolean splitNode(NetNode source) { */ public boolean splitEdge(NetNode source, NetNode target) { if (graph.removeEdge(source, target) != null) { - this.clearCaches(); + this.clearPathCaches(); Set> targetGroup = new ObjectOpenHashSet<>(); BreadthFirstIterator, Edge> i = new BreadthFirstIterator<>(graph, target); NetNode temp; @@ -172,7 +171,7 @@ public boolean splitEdge(NetNode source, NetNode

(this.graph, this.net, targetGroup); } @@ -188,8 +187,8 @@ public Set> getNodes() { return nodes; } - protected void clearCaches() { - this.nodes.forEach(NetNode::clearPathCache); + protected void clearPathCaches() { + this.getNodes().forEach(NetNode::clearPathCache); } public Graph, Edge> getGraph() { diff --git a/src/main/java/gregtech/api/pipenet/NetNode.java b/src/main/java/gregtech/api/pipenet/NetNode.java index e85ca44a64f..9e24eed051f 100644 --- a/src/main/java/gregtech/api/pipenet/NetNode.java +++ b/src/main/java/gregtech/api/pipenet/NetNode.java @@ -96,7 +96,7 @@ public NetNode(NBTTagCompound tag, WorldPipeNetBase getGroupSafe() { if (this.group == null) { - new NetGroup<>(this.net.pipeGraph, this.net).addNodes(this); + new NetGroup<>(this.net.pipeGraph, this.net).addNode(this); // addNodes automatically sets our group to the new group } return this.group; @@ -248,6 +248,10 @@ public NodeDataType getData() { return data; } + public boolean isActive() { + return isActive; + } + @Nullable public List> getPathCache() { return pathCache; diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index 0713a3260d2..fabde940044 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -17,14 +17,14 @@ import java.util.stream.Collectors; public class NetPath & IPipeType, - NodeDataType extends INodeData, E extends NetEdge> { + NodeDataType extends INodeData, Edge extends NetEdge> { - private List> nodeList; - private List edgeList; + private List> nodeList; + private List edgeList; - private NetNode sourceNode; + private NetNode sourceNode; - private NetNode targetNode; + private NetNode targetNode; private double weight; @@ -35,7 +35,7 @@ public class NetPath & IPipeType, * * @param node the node to */ - public NetPath(NetNode node) { + public NetPath(NetNode node) { this.sourceNode = node; this.targetNode = node; this.nodeList = Collections.singletonList(node); @@ -46,13 +46,12 @@ public NetPath(NetNode node) { /** * Generates a NetPath from an ordered list of nodes, edges, and a weight. - * Used exclusively for single path generation. * * @param nodes List of nodes. * @param edges List of edges. * @param weight Sum weight of the path. */ - public NetPath(List> nodes, List edges, double weight) { + public NetPath(List> nodes, List edges, double weight) { this.sourceNode = nodes.get(0); this.targetNode = nodes.get(nodes.size() - 1); this.nodeList = nodes; @@ -66,7 +65,7 @@ public NetPath(List> nodes, List edges, do * * @param path the GraphPath */ - public NetPath(GraphPath, E> path) { + public NetPath(GraphPath, Edge> path) { this.sourceNode = path.getStartVertex(); this.targetNode = path.getEndVertex(); this.nodeList = path.getVertexList(); @@ -79,19 +78,19 @@ public NetPath(GraphPath, E> path) { protected NetPath() {} - public List> getNodeList() { + public List> getNodeList() { return nodeList; } - public List getEdgeList() { + public List getEdgeList() { return edgeList; } - public NetNode getSourceNode() { + public NetNode getSourceNode() { return sourceNode; } - public NetNode getTargetNode() { + public NetNode getTargetNode() { return targetNode; } @@ -99,11 +98,11 @@ public Iterator getFacingIterator() { return this.getTargetTEs().keySet().iterator(); } - public FacedNetPath firstFacing() { + public FacedNetPath firstFacing() { return this.withFacing(this.getFacingIterator().next()); } - public FacedNetPath withFacing(EnumFacing facing) { + public FacedNetPath withFacing(EnumFacing facing) { return new FacedNetPath<>(this, facing); } @@ -182,5 +181,9 @@ public boolean checkPredicate(Object o) { public FacingPos toFacingPos() { return new FacingPos(path.getTargetNode().getNodePos(), this.facing); } + + public EnumFacing oppositeFacing() { + return facing.getOpposite(); + } } } diff --git a/src/main/java/gregtech/api/pipenet/NodeLossResult.java b/src/main/java/gregtech/api/pipenet/NodeLossResult.java new file mode 100644 index 00000000000..79fdb6ed062 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/NodeLossResult.java @@ -0,0 +1,20 @@ +package gregtech.api.pipenet; + +import net.minecraft.util.Tuple; + +import java.util.function.Consumer; + +public class NodeLossResult extends Tuple>, Double> { + + public NodeLossResult(Consumer> postAction, Double lossFunction) { + super(postAction, lossFunction); + } + + public Consumer> getPostAction() { + return this.getFirst(); + } + + public Double getLossFunction() { + return this.getSecond(); + } +} diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java index 6e1ee0f6b19..fe13f189500 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java @@ -36,34 +36,33 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; -@ApiStatus.Internal public abstract class WorldPipeNetBase, PipeType extends Enum & IPipeType, Edge extends NetEdge> extends WorldSavedData { private final boolean isDirected; - private final boolean isSinglePath; - private final boolean isFlow; + private final Function, INetAlgorithm> algorithmBuilder; private Set builders = null; private WeakReference worldRef = new WeakReference<>(null); protected final Graph, Edge> pipeGraph; - final Map> pipeMap = new Object2ObjectOpenHashMap<>(); + protected final Map> pipeMap = new Object2ObjectOpenHashMap<>(); - final INetAlgorithm.NetAlgorithmWrapper netAlgorithm; + private final INetAlgorithm.NetAlgorithmWrapper netAlgorithm; private boolean validAlgorithmInstance = false; - protected WorldPipeNetBase(String name, boolean isDirected, boolean isSinglePath, + WorldPipeNetBase(String name, boolean isDirected, + Function, INetAlgorithm> algorithmBuilder, Graph, Edge> graph) { super(name); this.pipeGraph = graph; this.netAlgorithm = new INetAlgorithm.NetAlgorithmWrapper<>(); this.isDirected = isDirected; - this.isSinglePath = isSinglePath; - this.isFlow = true; + this.algorithmBuilder = algorithmBuilder; } public Graph, Edge> getGraph() { @@ -74,14 +73,6 @@ public final boolean isDirected() { return isDirected; } - public final boolean isSinglePath() { - return isSinglePath; - } - - public final boolean isFlow() { - return isFlow; - } - protected void markAlgInvalid() { this.validAlgorithmInstance = false; } @@ -122,28 +113,24 @@ protected void onWorldSet() { * Preferred override. Only collects a fresh TE from the server if the provided TE is invalid. * * @param tile The {@link TileEntityPipeBase} that paths are being requested for - * @param testObject Can be null for simple nets. Complex nets need this for their behavior. * @return the ordered list of paths associated with the {@link TileEntityPipeBase} */ - public List> getPaths(TileEntityPipeBase tile, - Object testObject) { - return getPaths(this.pipeMap.get(tile.getPipePos()), tile, testObject); + public List> getPaths(TileEntityPipeBase tile) { + return getPaths(this.pipeMap.get(tile.getPipePos()), tile); } /** * Special-case override. Forces the collection of a fresh TE from the server. * * @param pos The {@link BlockPos} that paths are being requested for - * @param testObject Can be null for simple nets. Complex nets need this for their behavior. * @return the ordered list of paths associated with the {@link BlockPos} */ - public List> getPaths(BlockPos pos, Object testObject) { - return getPaths(this.pipeMap.get(pos), null, testObject); + public List> getPaths(BlockPos pos) { + return getPaths(this.pipeMap.get(pos), null); } public List> getPaths(@Nullable NetNode node, - @Nullable TileEntityPipeBase tile, - Object testObject) { + @Nullable TileEntityPipeBase tile) { if (node == null) return new ObjectArrayList<>(); node.setHeldMTE(tile); @@ -151,12 +138,10 @@ public List> getPaths(@Nullable NetNode> cache = node.getPathCache(); - if (cache != null) { - return verifyList(cache, node); - } + if (cache != null) return cache; List> list = this.netAlgorithm.getPathsList(node); - return verifyList(node.setPathCache(list), node); + return node.setPathCache(list); } /** @@ -188,7 +173,9 @@ protected TileEntityPipeBase castTE(TileEntity te) return null; } - public void markNodeAsOldData(NetNode node) {} + public void markNodeAsOldData(NetNode node) { + markNodeAsActive(node, shouldNodeBeActive(node)); + } protected abstract Class> getBasePipeClass(); @@ -240,6 +227,7 @@ public void updateActiveConnections(BlockPos nodePos, EnumFacing side, boolean c if (node == null || node.isConnected(side) == connect) return; node.setConnected(side, connect); + markNodeAsActive(node, shouldNodeBeActive(node)); NetNode nodeOffset = pipeMap.get(nodePos.offset(side)); if (nodeOffset == null) return; @@ -443,9 +431,21 @@ public NetGroup getGroup(BlockPos pos) { return node.setGroup(new NetGroup<>(this.pipeGraph, this)); } - public boolean markNodeAsActive(BlockPos nodePos, boolean isActive) { - NetNode node = this.pipeMap.get(nodePos); + public boolean shouldNodeBeActive(NetNode node) { + var connecteds = node.getConnecteds(); + if (connecteds != null) return connecteds.entrySet().stream().filter(entry -> { + if (entry.getValue() instanceof IPipeTile) return false; + for (Capability cap : this.getConnectionCapabilities()) { + if (entry.getValue().hasCapability(cap, entry.getKey())) return true; + } + return false; + }).toArray().length > 0; + return false; + } + + public boolean markNodeAsActive(NetNode node, boolean isActive) { if (node != null && node.isActive != isActive) { + node.getGroupSafe().clearPathCaches(); node.isActive = isActive; this.markDirty(); return true; @@ -454,11 +454,7 @@ public boolean markNodeAsActive(BlockPos nodePos, boolean isActive) { } protected void rebuildNetAlgorithm() { - if (!this.isSinglePath()) { - this.netAlgorithm.setAlg(new ShortestPathsAlgorithm<>(pipeGraph)); - } else { - this.netAlgorithm.setAlg(new SinglePathAlgorithm<>(pipeGraph, isDirected())); - } + this.netAlgorithm.setAlg(algorithmBuilder.apply(this)); this.markAlgValid(); } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java index 260b03ec360..a77180a22d7 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java @@ -1,16 +1,20 @@ package gregtech.api.pipenet; +import gregtech.api.pipenet.alg.INetAlgorithm; +import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; +import gregtech.api.pipenet.alg.SinglePathAlgorithm; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; import org.jgrapht.graph.SimpleDirectedWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph; +import java.util.function.Function; import java.util.function.Supplier; public abstract class WorldPipeNetComplex, PipeType extends Enum & IPipeType, - E extends NetEdge> extends WorldPipeNetBase { + Edge extends NetEdge> extends WorldPipeNetBase { /** * Alternate pipenet representation. Allows for using children of the {@link NetEdge} class as edges. @@ -21,13 +25,29 @@ public abstract class WorldPipeNetComplex edgeSupplier) { + this(name, isDirected, edgeSupplier, isSinglePath ? SinglePathAlgorithm::new : ShortestPathsAlgorithm::new); + } + + /** + * Alternate pipenet representation. Allows for using children of the {@link NetEdge} class as edges. + *

+ * Note - These child edges cannot be allowed to store information, they must only perform runtime behavior. + * + * @param isDirected Determines whether this net needs directed graph handling. + * Used to respect filter directions in the item net and fluid net, for example. + * If the graph is not directed, pipes should not support blocked connections + * or unidirectional covers. * @param edgeSupplier The supplier for the custom NetEdge child class. + * @param algorithmBuilder custom function to construct a new algorithm when the old one is invalidated. */ - public WorldPipeNetComplex(String name, boolean isDirected, boolean isSinglePath, Supplier edgeSupplier) { - super(name, isDirected, isSinglePath, - isDirected ? new SimpleDirectedWeightedGraph<>(null, edgeSupplier) : + public WorldPipeNetComplex(String name, boolean isDirected, Supplier edgeSupplier, + Function, INetAlgorithm> algorithmBuilder) { + super(name, isDirected, algorithmBuilder, isDirected ? new SimpleDirectedWeightedGraph<>(null, edgeSupplier) : new SimpleWeightedGraph<>(null, edgeSupplier)); } } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java index 01e6a3f78a7..95aba2674d1 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java @@ -1,11 +1,16 @@ package gregtech.api.pipenet; +import gregtech.api.pipenet.alg.INetAlgorithm; +import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; +import gregtech.api.pipenet.alg.SinglePathAlgorithm; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; import org.jgrapht.graph.SimpleDirectedWeightedGraph; import org.jgrapht.graph.SimpleWeightedGraph; +import java.util.function.Function; + public abstract class WorldPipeNetSimple, PipeType extends Enum & IPipeType> extends WorldPipeNetBase { @@ -18,11 +23,24 @@ public abstract class WorldPipeNetSimple(NetEdge.class) : - new SimpleWeightedGraph<>(NetEdge.class)); + this(name, isDirected, isSinglePath ? SinglePathAlgorithm::new : ShortestPathsAlgorithm::new); + } + + /** + * Standard pipenet representation. Provides the base form of the pipenet abstraction. + * + * @param isDirected Determines whether this net needs directed graph handling. + * Used to respect filter directions in the item net and fluid net, for example. + * If the graph is not directed, pipes should not support blocked connections + * or unidirectional covers. + * @param algorithmBuilder custom function to construct a new algorithm when the old one is invalidated. + */ + public WorldPipeNetSimple(String name, boolean isDirected, + Function, INetAlgorithm> algorithmBuilder) { + super(name, isDirected, algorithmBuilder, isDirected ? new SimpleDirectedWeightedGraph<>(NetEdge.class) : + new SimpleWeightedGraph<>(NetEdge.class)); } } diff --git a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java new file mode 100644 index 00000000000..45711a27a5c --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java @@ -0,0 +1,34 @@ +package gregtech.api.pipenet.alg; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.WorldPipeNetBase; +import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; + +import org.jgrapht.alg.shortestpath.AllDirectedPaths; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class AllPathsAlgorithm & IPipeType, NDT extends INodeData, + E extends NetEdge> extends AllDirectedPaths, E> implements INetAlgorithm { + + public AllPathsAlgorithm(WorldPipeNetBase pipenet) { + super(pipenet.getGraph()); + if (!pipenet.isDirected()) throw new IllegalArgumentException("Cannot build all paths on an undirected graph!"); + } + + @Override + public List> getPathsList(NetNode source) { + Set> searchSpace = source.getGroupSafe().getNodes().stream() + .filter(NetNode::isActive).collect(Collectors.toSet()); + return getAllPaths(Collections.singleton(source), searchSpace, true, (int) Short.MAX_VALUE) + .stream().map(NetPath::new).sorted(Comparator.comparingDouble(NetPath::getWeight)) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java index 17aac266f6e..a142e1e06ad 100644 --- a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java @@ -3,6 +3,7 @@ import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.WorldPipeNetBase; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; @@ -14,13 +15,15 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; public final class ShortestPathsAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> extends CHManyToManyShortestPaths, E> implements INetAlgorithm { - public ShortestPathsAlgorithm(Graph, E> graph) { - super(graph); + public ShortestPathsAlgorithm(WorldPipeNetBase pipenet) { + super(pipenet.getGraph()); } @Override @@ -28,20 +31,14 @@ public List> getPathsList(NetNode source) { if (!graph.containsVertex(source)) { throw new IllegalArgumentException("Graph must contain the source vertex"); } - List> paths = new ObjectArrayList<>(); - paths.add(new NetPath<>(source)); // if the source has no group, it has no paths other than the path to itself. - if (source.getGroupUnsafe() == null) return paths; + if (source.getGroupUnsafe() == null) return Collections.singletonList(new NetPath<>(source)); + + Set> searchSpace = source.getGroupSafe().getNodes().stream() + .filter(NetNode::isActive).collect(Collectors.toSet()); ManyToManyShortestPaths, E> manyToManyPaths = getManyToManyPaths( - Collections.singleton(source), source.getGroupSafe().getNodes()); - for (NetNode v : source.getGroupSafe().getNodes()) { - if (v == source) continue; - GraphPath, E> path = manyToManyPaths.getPath(source, v); - if (path != null) { - paths.add(new NetPath<>(path)); - } - } - paths.sort(Comparator.comparingDouble(NetPath::getWeight)); - return paths; + Collections.singleton(source), searchSpace); + return searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)).map(NetPath::new) + .sorted(Comparator.comparingDouble(NetPath::getWeight)).collect(Collectors.toList()); } } diff --git a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java index 1c104801678..1f0c62ce48e 100644 --- a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java @@ -1,8 +1,11 @@ package gregtech.api.pipenet.alg; +import com.google.common.collect.ImmutableList; + import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.WorldPipeNetBase; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; @@ -19,9 +22,9 @@ public final class SinglePathAlgorithm & IPipeType, NDT private final Graph, E> graph; private final boolean isDirected; - public SinglePathAlgorithm(Graph, E> graph, boolean isDirected) { - this.graph = graph; - this.isDirected = isDirected; + public SinglePathAlgorithm(WorldPipeNetBase pipenet) { + this.graph = pipenet.getGraph(); + this.isDirected = pipenet.isDirected(); } @Override @@ -56,6 +59,6 @@ public List> getPathsList(NetNode source) { sumWeight += node.getData().getWeightFactor(); } if (!valid) return Collections.emptyList(); - return List.of(new NetPath<>(nodes, edges, sumWeight)); + return ImmutableList.of(new NetPath<>(nodes, edges, sumWeight)); } } diff --git a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java index 7cbc1d1a1f3..3b4ec581fb1 100644 --- a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java @@ -9,6 +9,7 @@ import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.pipenet.IBlockAppearance; import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.WorldPipeNetBase; import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; @@ -60,7 +61,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Random; import static gregtech.api.metatileentity.MetaTileEntity.FULL_CUBE_COLLISION; @@ -147,18 +147,6 @@ public void onBlockAdded(World worldIn, @NotNull BlockPos pos, @NotNull IBlockSt worldIn.scheduleUpdate(pos, this, 1); } - @Override - public void updateTick(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, - @NotNull Random rand) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); - if (pipeTile != null) { - if (worldIn.isRemote) return; - int activeConnections = pipeTile.getConnections(); - boolean isActiveNode = activeConnections != 0; - onActiveModeChange(worldIn, pos, isActiveNode, true); - } - } - @Override public void onBlockPlacedBy(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, @NotNull EntityLivingBase placer, @NotNull ItemStack stack) { @@ -199,7 +187,7 @@ public void neighborChanged(@NotNull IBlockState state, @NotNull World worldIn, pipeTile.setConnection(facing, true, false); if (open && !canConnect) pipeTile.setConnection(facing, false, false); - updateActiveNodeStatus(worldIn, pos, pipeTile); + updateActiveNodeStatus(worldIn, pipeTile); } } } @@ -237,18 +225,14 @@ public int getWeakPower(@NotNull IBlockState blockState, @NotNull IBlockAccess b return pipeTile == null ? 0 : pipeTile.getCoverableImplementation().getOutputRedstoneSignal(side.getOpposite()); } - public void updateActiveNodeStatus(@NotNull World worldIn, BlockPos pos, + public void updateActiveNodeStatus(@NotNull World worldIn, IPipeTile pipeTile) { if (worldIn.isRemote) return; - WorldPipeNetBase pipeNet = getWorldPipeNet(worldIn); + WorldPipeNetBase pipeNet = getWorldPipeNet(worldIn); if (pipeNet != null && pipeTile != null) { - int activeConnections = pipeTile.getConnections(); // remove blocked connections - boolean isActiveNodeNow = activeConnections != 0; - boolean modeChanged = pipeNet.markNodeAsActive(pos, isActiveNodeNow); - if (modeChanged) { - onActiveModeChange(worldIn, pos, isActiveNodeNow, false); - } + NetNode node = pipeTile.getNode(); + pipeNet.markNodeAsActive(node, pipeNet.shouldNodeBeActive(node)); } } @@ -258,12 +242,6 @@ public TileEntity createNewTileEntity(@NotNull World worldIn, int meta) { return createNewTileEntity(false); } - /** - * Can be used to update tile entity to tickable when node becomes active - * usable for fluid pipes, as example - */ - protected void onActiveModeChange(World world, BlockPos pos, boolean isActiveNow, boolean isInitialChange) {} - @NotNull @Override public ItemStack getPickBlock(@NotNull IBlockState state, @NotNull RayTraceResult target, @NotNull World world, diff --git a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java index 632c2ca4365..8d3f59f18a2 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java @@ -30,8 +30,8 @@ public Material getPipeMaterial() { public void setPipeData(BlockPipe pipeBlock, PipeType pipeType, Material pipeMaterial) { - super.setPipeData(pipeBlock, pipeType); this.pipeMaterial = pipeMaterial; + super.setPipeData(pipeBlock, pipeType); if (!getWorld().isRemote) { writeCustomData(UPDATE_PIPE_MATERIAL, this::writePipeMaterial); } diff --git a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java index 3e6282387ba..1e7f2c9dc66 100644 --- a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java @@ -46,7 +46,7 @@ protected AbstractChannelsHolder getChannels(@Nullable ChannelSimulatorKey si } } - public & IPipeType, NDT extends INodeData> int getFlowLimit( + public & IPipeType, NDT extends INodeData> long getFlowLimit( Object channel, Graph, E> graph, long queryTick, @@ -54,14 +54,14 @@ public & IPipeType, NDT extends INodeData> int ge return getChannels(simulator).getFlowLimit(channel, graph, queryTick); } - public int getConsumedLimit(Object channel, long queryTick, @Nullable ChannelSimulatorKey simulator) { + public long getConsumedLimit(Object channel, long queryTick, @Nullable ChannelSimulatorKey simulator) { return getChannels(simulator).getConsumedLimit(channel, queryTick); } public & IPipeType, NDT extends INodeData> void consumeFlowLimit( Object channel, Graph, E> graph, - int amount, long queryTick, + long amount, long queryTick, @Nullable ChannelSimulatorKey simulator) { getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); } @@ -84,17 +84,17 @@ public ChannelSimulatorKey getSimulator() { abstract boolean cannotSupportChannel(Object channel, long queryTick); - abstract & IPipeType, NDT extends INodeData> int getFlowLimit( + abstract & IPipeType, NDT extends INodeData> long getFlowLimit( Object channel, Graph, E> graph, long queryTick); - abstract int getConsumedLimit(Object channel, long queryTick); + abstract long getConsumedLimit(Object channel, long queryTick); abstract & IPipeType, NDT extends INodeData> void consumeFlowLimit( Object channel, Graph, E> graph, - int amount, long queryTick); + long amount, long queryTick); } public static final class ChannelSimulatorKey { diff --git a/src/main/java/gregtech/api/pipenet/edge/IEdge.java b/src/main/java/gregtech/api/pipenet/edge/IEdge.java index ca471342d41..0d67f9fa010 100644 --- a/src/main/java/gregtech/api/pipenet/edge/IEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/IEdge.java @@ -5,4 +5,6 @@ public interface IEdge { V getSource(); V getTarget(); + + double getWeight(); } diff --git a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java index 80817d44ad1..89cf7bb6c08 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java @@ -71,6 +71,11 @@ E extends NetEdge> NetNode getCastTarget() { return (NetNode) getTarget(); } + @Override + public double getWeight() { + return super.getWeight(); + } + @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java index 5dc98383778..02194a8ffef 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java @@ -5,6 +5,7 @@ import gregtech.api.pipenet.block.IPipeType; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.Graph; @@ -22,7 +23,7 @@ public final class NetFlowEdge extends AbstractNetFlowEdge { * throughput. */ public NetFlowEdge(int flowBufferTicks) { - this.flowBufferTicks = flowBufferTicks; + this.flowBufferTicks = Math.max(flowBufferTicks, 1); } @Override @@ -33,13 +34,13 @@ protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolde private final class ChannelsHolder extends AbstractChannelsHolder { - private final Object2IntOpenHashMap map; + private final Object2LongOpenHashMap map; private long lastQueryTick; + private boolean init; public ChannelsHolder(ChannelSimulatorKey simulator) { super(simulator); - this.map = new Object2IntOpenHashMap<>(9); - this.map.defaultReturnValue(getMinData().getThroughput() * flowBufferTicks); + this.map = new Object2LongOpenHashMap<>(9); } public ChannelsHolder(ChannelsHolder prototype, ChannelSimulatorKey simulator) { @@ -51,16 +52,16 @@ public ChannelsHolder(ChannelsHolder prototype, ChannelSimulatorKey simulator) { @Override public boolean cannotSupportChannel(Object channel, long queryTick) { recalculateFlowLimits(queryTick); - if (map.containsKey(channel)) return map.getInt(channel) <= 0; + if (map.containsKey(channel)) return map.getLong(channel) <= 0; else return map.size() >= getMinData().getChannelMaxCount(); } @Override - public & IPipeType, NDT extends INodeData> int getFlowLimit(Object channel, + public & IPipeType, NDT extends INodeData> long getFlowLimit(Object channel, Graph, NetFlowEdge> graph, long queryTick) { if (cannotSupportChannel(channel, queryTick)) return 0; - int limit = map.getInt(channel); + long limit = map.getLong(channel); NetFlowEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); if (inverse != null && inverse != NetFlowEdge.this) { @@ -72,33 +73,33 @@ public & IPipeType, NDT extends INodeData> int ge } @Override - int getConsumedLimit(Object channel, long queryTick) { + long getConsumedLimit(Object channel, long queryTick) { recalculateFlowLimits(queryTick); - int limit = map.defaultReturnValue(); - return limit - map.getInt(channel); + long limit = map.defaultReturnValue(); + return limit - map.getLong(channel); } @Override & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, Graph, NetFlowEdge> graph, int amount, long queryTick) { + Object channel, Graph, NetFlowEdge> graph, long amount, long queryTick) { if (amount == 0) return; recalculateFlowLimits(queryTick); // check against reverse edge NetFlowEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); if (inverse != null && inverse != NetFlowEdge.this) { - int inverseConsumed = inverse.getConsumedLimit(channel, queryTick, getSimulator()); + long inverseConsumed = inverse.getConsumedLimit(channel, queryTick, getSimulator()); if (inverseConsumed != 0) { - int toFreeUp = Math.min(inverseConsumed, amount); + long toFreeUp = Math.min(inverseConsumed, amount); inverse.consumeFlowLimit(channel, graph, -toFreeUp, queryTick, getSimulator()); if (toFreeUp == amount) return; amount -= toFreeUp; } } - int finalAmount = amount; + long finalAmount = amount; map.compute(channel, (k, v) -> { - int d = map.defaultReturnValue(); + long d = map.defaultReturnValue(); if (v == null) v = d; v -= finalAmount; if (v >= d) return null; @@ -108,17 +109,21 @@ & IPipeType, NDT extends INodeData> void consumeF @Override public void recalculateFlowLimits(long queryTick) { + if (!this.init) { + this.map.defaultReturnValue((long) getMinData().getThroughput() * flowBufferTicks); + this.init = true; + } int time = (int) (queryTick - this.lastQueryTick); if (time < 0) { this.map.clear(); } else { List toRemove = new ObjectArrayList<>(); this.map.replaceAll((k, v) -> { - v += time * getMinData().getThroughput(); + v += (long) time * getMinData().getThroughput(); if (v >= map.defaultReturnValue()) toRemove.add(k); return v; }); - toRemove.forEach(this.map::removeInt); + toRemove.forEach(this.map::removeLong); } this.lastQueryTick = queryTick; } diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java index 50dc12519ac..2729dd49d50 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java @@ -5,6 +5,7 @@ import gregtech.api.pipenet.block.IPipeType; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.util.math.MathHelper; @@ -25,7 +26,7 @@ public class NetFlowSharedEdge extends AbstractNetFlowEdge { * throughput. */ public NetFlowSharedEdge(int flowBufferTicks) { - this.flowBufferTicks = flowBufferTicks; + this.flowBufferTicks = Math.max(flowBufferTicks, 1); } @Override @@ -36,16 +37,16 @@ protected AbstractChannelsHolder getNewHolder(AbstractChannel private final class ChannelsHolder extends AbstractChannelsHolder { - private int maxCapacity; - private int sharedCapacity; - private final Object2IntOpenHashMap map; + private long maxCapacity; + private long sharedCapacity; + private final Object2LongOpenHashMap map; private long lastQueryTick; + private boolean init; public ChannelsHolder(ChannelSimulatorKey simulator) { super(simulator); - this.map = new Object2IntOpenHashMap<>(9); + this.map = new Object2LongOpenHashMap<>(9); this.map.defaultReturnValue(0); - this.maxCapacity = getMinData().getThroughput() * flowBufferTicks; } public ChannelsHolder(ChannelsHolder prototype, ChannelSimulatorKey simulator) { @@ -62,7 +63,7 @@ public boolean cannotSupportChannel(Object channel, long queryTick) { } @Override - public & IPipeType, NDT extends INodeData> int getFlowLimit(Object channel, + public & IPipeType, NDT extends INodeData> long getFlowLimit(Object channel, Graph, NetFlowSharedEdge> graph, long queryTick) { if (cannotSupportChannel(channel, queryTick)) return 0; @@ -75,32 +76,32 @@ public & IPipeType, NDT extends INodeData> int ge } @Override - int getConsumedLimit(Object channel, long queryTick) { + long getConsumedLimit(Object channel, long queryTick) { recalculateFlowLimits(queryTick); - return map.getInt(channel); + return map.getLong(channel); } @Override & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, Graph, NetFlowSharedEdge> graph, int amount, long queryTick) { + Object channel, Graph, NetFlowSharedEdge> graph, long amount, long queryTick) { if (amount == 0) return; recalculateFlowLimits(queryTick); // check against reverse edge NetFlowSharedEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); if (inverse != null && inverse != NetFlowSharedEdge.this) { - int inverseConsumed = inverse.getConsumedLimit(channel, queryTick, getSimulator()); + long inverseConsumed = inverse.getConsumedLimit(channel, queryTick, getSimulator()); if (inverseConsumed != 0) { - int toFreeUp = Math.min(inverseConsumed, amount); + long toFreeUp = Math.min(inverseConsumed, amount); inverse.consumeFlowLimit(channel, graph, -toFreeUp, queryTick, getSimulator()); if (toFreeUp == amount) return; amount -= toFreeUp; } } - int finalAmount = amount; + long finalAmount = amount; map.compute(channel, (k, v) -> { - if (v == null) v = 0; + if (v == null) v = 0L; v += finalAmount; if (v <= 0) return null; return v; @@ -111,12 +112,16 @@ & IPipeType, NDT extends INodeData> void consumeF @Override public void recalculateFlowLimits(long queryTick) { + if (!this.init) { + this.maxCapacity = (long) getMinData().getThroughput() * flowBufferTicks; + this.init = true; + } int time = (int) (queryTick - this.lastQueryTick); if (time < 0) { this.map.clear(); } else { List toRemove = new ObjectArrayList<>(); - int regenerationPer = MathHelper.ceil((float) time * getMinData().getThroughput() / map.size()); + long regenerationPer = MathHelper.ceil((double) time * getMinData().getThroughput() / map.size()); map.replaceAll((k, v) -> { v -= regenerationPer; if (v <= 0) toRemove.add(k); @@ -124,7 +129,7 @@ public void recalculateFlowLimits(long queryTick) { }); sharedCapacity += regenerationPer * map.size(); boundCapacity(); - toRemove.forEach(map::removeInt); + toRemove.forEach(map::removeLong); } this.lastQueryTick = queryTick; } diff --git a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java index d5686f04c8a..02a8dfda1b7 100644 --- a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java +++ b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java @@ -4,7 +4,6 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.AbstractNetFlowEdge; -import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.util.FluidTestObject; import org.jgrapht.Graph; @@ -12,25 +11,32 @@ import java.util.function.Consumer; public class FlowConsumer & IPipeType, NDT extends INodeData, - E extends AbstractNetFlowEdge> implements Consumer { + E extends AbstractNetFlowEdge> implements Consumer { - private final AbstractNetFlowEdge edge; + private final E edge; private final FluidTestObject testObject; private final Graph, E> graph; - private final int flow; + private final long flow; private final long tick; private final AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey; + private final Consumer extra; private double ratio = 1; - public FlowConsumer(AbstractNetFlowEdge edge, FluidTestObject testObject, Graph, E> graph, int flow, + public FlowConsumer(E edge, FluidTestObject testObject, Graph, E> graph, long flow, long tick, AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey) { + this(edge, testObject, graph, flow, tick, simulatorKey, null); + } + + public FlowConsumer(E edge, FluidTestObject testObject, Graph, E> graph, long flow, + long tick, AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey, Consumer extra) { this.edge = edge; this.testObject = testObject; this.graph = graph; this.flow = flow; this.tick = tick; this.simulatorKey = simulatorKey; + this.extra = extra; } public void modifyRatio(Double ratio) { @@ -39,6 +45,8 @@ public void modifyRatio(Double ratio) { @Override public void accept(Double finalRatio) { - edge.consumeFlowLimit(testObject, graph, (int) (finalRatio * ratio * flow), tick, simulatorKey); + long consumption = (long) (finalRatio * ratio * flow); + edge.consumeFlowLimit(testObject, graph, consumption, tick, simulatorKey); + if (extra != null) extra.accept(consumption); } } diff --git a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java new file mode 100644 index 00000000000..5ea3b1431cb --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java @@ -0,0 +1,39 @@ +package gregtech.api.pipenet.edge.util; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.AbstractNetFlowEdge; + +import gregtech.api.util.FluidTestObject; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jgrapht.Graph; + +import java.util.function.Consumer; + +public class FlowConsumerList & IPipeType, NDT extends INodeData, + E extends AbstractNetFlowEdge> extends ObjectArrayList> { + + public void add(E edge, FluidTestObject testObject, Graph, E> graph, long flow, + long tick, AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey) { + this.add(new FlowConsumer<>(edge, testObject, graph, flow, tick, simulatorKey)); + } + + public void add(E edge, FluidTestObject testObject, Graph, E> graph, long flow, + long tick, AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey, Consumer extra) { + this.add(new FlowConsumer<>(edge, testObject, graph, flow, tick, simulatorKey, extra)); + } + + public void modifyRatios(double ratio) { + for (FlowConsumer consumer : this) { + consumer.modifyRatio(ratio); + } + } + + public void doConsumption(double ratio) { + for (FlowConsumer consumer : this) { + consumer.accept(ratio); + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 99ede3ea469..53057df1bdd 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -71,6 +71,7 @@ public TileEntityPipeBase() { public void setPipeData(BlockPipe pipeBlock, PipeType pipeType) { this.pipeBlock = pipeBlock; this.pipeType = pipeType; + this.getNode().setData(getPipeBlock().createProperties(this)); if (!getWorld().isRemote) { writeCustomData(UPDATE_PIPE_TYPE, this::writePipeProperties); } @@ -81,6 +82,7 @@ public void transferDataFrom(IPipeTile tileEntity) this.pipeType = tileEntity.getPipeType(); this.paintingColor = tileEntity.getPaintingColor(); this.netNode = tileEntity.getNode(); + this.netNode.setData(getPipeBlock().createProperties(this)); if (tileEntity instanceof SyncedTileEntityBase pipeBase) { addPacketsFrom(pipeBase); } @@ -469,7 +471,6 @@ protected void doOldNetSetup() { // TODO inexplicable crash during world load when old net setup required // something to do with removing the tile entities that the chunk is iterating over to load WorldPipeNetBase net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); - net.markNodeAsOldData(this.getNode()); for (EnumFacing facing : EnumFacing.VALUES) { NetNode nodeOffset = net.getNode(this.getPipePos().offset(facing)); if (nodeOffset == null) continue; @@ -485,6 +486,7 @@ protected void doOldNetSetup() { net.predicateEdge(this.getNode(), nodeOffset, facing); } } + net.markNodeAsOldData(this.getNode()); } @Override @@ -575,7 +577,6 @@ public void writeCoverCustomData(int id, Consumer writer) { @Override public void notifyBlockUpdate() { getWorld().notifyNeighborsOfStateChange(getPos(), getBlockType(), true); - getPipeBlock().updateActiveNodeStatus(getWorld(), getPos(), this); } @Override diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index f6765f78b24..1e849ea40b9 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -8,7 +8,7 @@ import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.NodeLossResult; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.util.EntityDamageUtil; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; @@ -16,7 +16,6 @@ import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.Tuple; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldServer; @@ -171,7 +170,7 @@ public int getChannelMaxCount() { return this.tanks; } - public PipeLossResult determineFluidPassthroughResult(@NotNull FluidStack stack, World world, BlockPos pos) { + public NodeLossResult determineFluidPassthroughResult(@NotNull FluidStack stack, World world, BlockPos pos) { Fluid fluid = stack.getFluid(); boolean burning = this.getMaxFluidTemperature() < fluid.getTemperature(stack); @@ -202,10 +201,10 @@ public PipeLossResult determineFluidPassthroughResult(@NotNull FluidStack stack, if (burning || leaking || corroding || shattering || melting) { return determineDestroyPipeResults(stack, burning, leaking, corroding, shattering, melting, world, pos); - } else return new PipeLossResult(n -> {}, 1d); + } else return new NodeLossResult(n -> {}, 1d); } - public PipeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBurning, boolean isLeaking, + public NodeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBurning, boolean isLeaking, boolean isCorroding, boolean isShattering, boolean isMelting, World world, BlockPos pos) { List particleActions = new ObjectArrayList<>(); @@ -296,7 +295,7 @@ public PipeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBu } Runnable finalDestructionAction = destructionAction; Consumer finalDamageAction = damageAction; - return new PipeLossResult(nodeG -> { + return new NodeLossResult(nodeG -> { // only do 'extra' actions if the node already holds its MTE. // don't go fetch it from the world as this 9 times out of 10 means loading a chunk unnecessarily. IPipeTile tile = nodeG.getHeldMTEUnsafe(); @@ -359,19 +358,4 @@ public String toString() { ", containmentPredicate=" + containmentPredicate + '}'; } - - public static class PipeLossResult extends Tuple>, Double> { - - public PipeLossResult(Consumer> postAction, Double lossFunction) { - super(postAction, lossFunction); - } - - public Consumer> getPostAction() { - return this.getFirst(); - } - - public Double getLossFunction() { - return this.getSecond(); - } - } } diff --git a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java index 1976ba2a364..cd44ae4db97 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java @@ -150,6 +150,11 @@ public double getWeightFactor() { return this.getLossPerBlock(); } + @Override + public int getThroughput() { + return this.getAmperage(); + } + @Override public WireProperties getMinData(Set datas) { int amperage = this.getAmperage(); diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 553279c72f4..c230a17df49 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -63,6 +63,7 @@ import org.jetbrains.annotations.Nullable; import java.util.AbstractList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -887,4 +888,11 @@ public double getAsDouble() { (1.0 / (1 - splitPoint)) * (tracker.get() - splitPoint) : 0; return Pair.of(supplier1, supplier2); } + + public static double geometricMean(double first, double... numbers) { + for (double number : numbers) { + first *= number; + } + return Math.pow(first, 1D / (1 + numbers.length)); + } } diff --git a/src/main/java/gregtech/common/covers/CoverDigitalInterface.java b/src/main/java/gregtech/common/covers/CoverDigitalInterface.java index d4950ca4ac7..e5ffa6b2a9e 100644 --- a/src/main/java/gregtech/common/covers/CoverDigitalInterface.java +++ b/src/main/java/gregtech/common/covers/CoverDigitalInterface.java @@ -815,7 +815,9 @@ public IEnergyContainer getEnergyCapability() { if (fe != null) { return new IEnergyContainer() { - public long acceptEnergyFromNetwork(EnumFacing enumFacing, long l, long l1) { + @Override + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, + boolean simulate) { return 0; } diff --git a/src/main/java/gregtech/common/metatileentities/converter/ConverterTrait.java b/src/main/java/gregtech/common/metatileentities/converter/ConverterTrait.java index 82521725571..1c7529131f7 100644 --- a/src/main/java/gregtech/common/metatileentities/converter/ConverterTrait.java +++ b/src/main/java/gregtech/common/metatileentities/converter/ConverterTrait.java @@ -148,20 +148,22 @@ protected T getCapabilityAtFront(Capability capability) { public class EUContainer implements IEnergyContainer { @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { if (amperage <= 0 || voltage <= 0 || feToEu || side == metaTileEntity.getFrontFacing()) return 0; if (usedAmps >= amps) return 0; if (voltage > getInputVoltage()) { - metaTileEntity.doExplosion(GTUtility.getExplosionPower(voltage)); + if (!simulate) metaTileEntity.doExplosion(GTUtility.getExplosionPower(voltage)); return Math.min(amperage, amps - usedAmps); } long space = baseCapacity - storedEU; if (space < voltage) return 0; long maxAmps = Math.min(Math.min(amperage, amps - usedAmps), space / voltage); - storedEU += voltage * maxAmps; - usedAmps += maxAmps; + if (!simulate) { + storedEU += voltage * maxAmps; + usedAmps += maxAmps; + } return maxAmps; } diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java index ec6afb97341..c9504523592 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java @@ -234,20 +234,24 @@ public void readFromNBT(NBTTagCompound data) { } @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { if (source || !active || ampsReceived >= amps) { return 0; } if (voltage > this.voltage) { - if (doExplosion) - return 0; - doExplosion = true; + if (!simulate) { + if (doExplosion) + return 0; + doExplosion = true; + } return Math.min(amperage, getInputAmperage() - ampsReceived); } long amperesAccepted = Math.min(amperage, getInputAmperage() - ampsReceived); if (amperesAccepted > 0) { - ampsReceived += amperesAccepted; - energyIOPerSec += amperesAccepted * voltage; + if (!simulate) { + ampsReceived += amperesAccepted; + energyIOPerSec += amperesAccepted * voltage; + } return amperesAccepted; } return 0; diff --git a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java index 570de1bdb9a..fd1ffb36dac 100644 --- a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java @@ -6,6 +6,7 @@ import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.pipenet.block.material.BlockMaterialPipe; import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; @@ -48,7 +49,7 @@ import java.util.Map; import java.util.TreeMap; -public class BlockCable extends BlockMaterialPipe +public class BlockCable extends BlockMaterialPipe implements ITileEntityProvider { private final Map enabledMaterials = new TreeMap<>(); @@ -140,13 +141,13 @@ public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull I } @Override - public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile) { + public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, + IPipeTile sideTile) { return selfTile instanceof TileEntityCable && sideTile instanceof TileEntityCable; } @Override - public boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, + public boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, TileEntity tile) { return tile != null && tile.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, side.getOpposite()) != null; @@ -193,7 +194,7 @@ public EnumBlockRenderType getRenderType(@NotNull IBlockState state) { } @Override - public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { + public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { return supportsTicking ? new TileEntityCableTickable() : new TileEntityCable(); } diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java index c6b2d963c04..546d8317148 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -6,21 +6,41 @@ import gregtech.api.pipenet.IPipeNetHandler; import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.NodeLossResult; +import gregtech.api.pipenet.edge.AbstractNetFlowEdge; +import gregtech.api.pipenet.edge.NetFlowEdge; +import gregtech.api.pipenet.edge.util.FlowConsumer; +import gregtech.api.pipenet.edge.util.FlowConsumerList; import gregtech.api.unification.material.properties.WireProperties; +import gregtech.api.util.FacingPos; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; import gregtech.common.pipelike.cable.Insulation; import gregtech.common.pipelike.cable.tile.TileEntityCable; +import it.unimi.dsi.fastutil.doubles.DoubleArrayList; +import it.unimi.dsi.fastutil.doubles.DoubleList; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldServer; +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Consumer; public class EnergyNetHandler implements IEnergyContainer, IPipeNetHandler { @@ -28,6 +48,8 @@ public class EnergyNetHandler implements IEnergyContainer, IPipeNetHandler { private boolean transfer; private final TileEntityCable cable; private final EnumFacing facing; + private final Map, NodeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); + private Object2LongOpenHashMap destSimulationCache; public EnergyNetHandler(WorldEnergyNet net, TileEntityCable cable, EnumFacing facing) { this.net = net; @@ -61,94 +83,228 @@ public long getOutputPerSec() { @Override public long getEnergyCanBeInserted() { - return transfer ? 0 : getEnergyCapacity(); + return getEnergyCapacity(); } @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { if (transfer) return 0; if (side == null) { if (facing == null) return 0; side = facing; } + if (amperage <= 0 || voltage <= 0) + return 0; + + long queryTick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + AbstractNetFlowEdge.ChannelSimulatorKey key = simulate ? AbstractNetFlowEdge.getNewSimulatorInstance() : null; + destSimulationCache = simulate ? new Object2LongOpenHashMap<>() : null; + + List> paths = this.net.getPaths(cable); + long amperesUsed = distributionRespectCapacity(side, voltage, amperage, queryTick, paths, key); + if (amperesUsed < amperage) { + // if we still have undistributed amps, attempt to distribute them while going over edge capacities. + amperesUsed += distributionIgnoreCapacity(side, voltage, amperage - amperesUsed, queryTick, paths, key); + } + this.lossResultCache.forEach((k, v) -> v.getPostAction().accept(k)); + this.lossResultCache.clear(); + + this.destSimulationCache = null; + + if (this.cable.getNode().getGroupSafe().getData() instanceof EnergyGroupData data) + data.addEnergyFluxPerSec(amperesUsed * voltage); + return amperesUsed; + } - long amperesUsed = 0L; + private long distributionRespectCapacity(EnumFacing side, long voltage, long amperage, long queryTick, + List> paths, + AbstractNetFlowEdge.ChannelSimulatorKey simulator) { + List> pathsCopy = new ObjectArrayList<>(paths); + long availableAmperage = amperage; mainloop: - for (NetPath routePath : net.getPaths(cable, null)) { - Iterator iterator = routePath.getFacingIterator(); - // weight = loss - if (routePath.getWeight() >= voltage) { - // Will lose all the energy with this path, so don't use it - continue; - } + for (int i = 0; i < pathsCopy.size(); i++) { + NetPath path = pathsCopy.get(i); + // skip paths where loss exceeds available voltage + if (path.getWeight() > voltage) continue; + Iterator iterator = path.getFacingIterator(); + boolean pathDestThis = path.getTargetNode().getNodePos().equals(this.cable.getPipePos()); while (iterator.hasNext()) { - NetPath.FacedNetPath path = routePath.withFacing(iterator.next()); - - EnumFacing facing = path.facing.getOpposite(); - - IEnergyContainer dest = path.getTargetTE().getCapability( - GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facing); - if (dest == null) continue; - - if (!dest.inputsEnergy(facing) || dest.getEnergyCanBeInserted() <= 0) continue; - - long pathVoltage = voltage - (long) routePath.getWeight(); - boolean cableBroken = false; - for (NetNode node : path.getNodeList()) { - TileEntityCable cable = (TileEntityCable) node.getHeldMTE(); - if (cable.getMaxVoltage() < voltage) { - int heat = (int) (Math.log( - GTUtility.getTierByVoltage(voltage) - - GTUtility.getTierByVoltage(cable.getMaxVoltage())) * - 45 + 36.5); - cable.applyHeat(heat); - - cableBroken = cable.isInvalid(); - if (cableBroken) { - // a cable burned away (or insulation melted) - break; - } + NetPath.FacedNetPath facedPath = + path.withFacing(iterator.next()); + if (pathDestThis && facedPath.facing == side) { + // do not distribute power back into our source + continue; + } - // limit transfer to cables max and void rest - pathVoltage = Math.min(cable.getMaxVoltage(), pathVoltage); - } + IEnergyContainer dest = facedPath.getTargetTE().getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facedPath.oppositeFacing()); + if (dest == null || dest == this) continue; + if (!dest.inputsEnergy(facedPath.oppositeFacing()) || dest.getEnergyCanBeInserted() <= 0) continue; + + List> nodeList = facedPath.getNodeList(); + DoubleList voltageCaps = new DoubleArrayList(); + long pathAmperage = availableAmperage; + // loss from the first node + NetNode target = nodeList.get(0); + if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) { + paths.remove(i); + continue mainloop; } - if (cableBroken) continue; + List edgeList = facedPath.getEdgeList(); + FlowConsumerList flowLimitConsumers = new FlowConsumerList<>(); + for (int j = 0; j < edgeList.size(); j++) { + NetFlowEdge edge = edgeList.get(j); + // amperage capping + long max = Math.min(pathAmperage, edge.getFlowLimit(null, this.net.getGraph(), queryTick, simulator)); + double ratio = (double) max / pathAmperage; + pathAmperage = max; + flowLimitConsumers.modifyRatios(ratio); + + target = nodeList.get(j + 1); + TileEntityCable tile = simulator == null ? (TileEntityCable) target.getHeldMTEUnsafe() : null; + flowLimitConsumers.add(edge, null, this.net.getGraph(), pathAmperage, queryTick, + simulator, tile != null ? amps -> { + tile.contributeAmperageFlow(amps); + tile.contributeVoltageFlow(voltage); + } : null); + // voltage loss + if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) { + paths.remove(i); + continue mainloop; + } + } + // skip paths where we can't transfer amperage + if (pathAmperage <= 0) continue; + // complete transfer + this.transfer = true; + // actual voltage that reaches the destination is the geometric mean of the input and all the caps + long finalVoltage = (long) GTUtility.geometricMean((double) voltage, voltageCaps.toArray(new double[]{})); + long accepted = dest.acceptEnergyFromNetwork(facedPath.oppositeFacing(), finalVoltage, pathAmperage, simulator != null); + this.transfer = false; + if (simulator != null) accepted = getSimulatedAccepted(destSimulationCache, facedPath.toFacingPos(), accepted); + flowLimitConsumers.doConsumption((double) accepted / pathAmperage); + availableAmperage -= accepted; + + if (availableAmperage <= 0) return amperage; + } + } + return amperage - availableAmperage; + } - transfer = true; - long amps = dest.acceptEnergyFromNetwork(facing, pathVoltage, amperage - amperesUsed); - transfer = false; - if (amps == 0) continue; + private long distributionIgnoreCapacity(EnumFacing side, long voltage, long amperage, long queryTick, + List> paths, + AbstractNetFlowEdge.ChannelSimulatorKey simulator) { + Object2LongOpenHashMap localDestSimulationCache = new Object2LongOpenHashMap<>(); - amperesUsed += amps; - long voltageTraveled = voltage; - // TODO compress wire path operations into a single for loop - for (NetNode node : path.getNodeList()) { - TileEntityCable cable = (TileEntityCable) node.getHeldMTE(); - voltageTraveled -= cable.getNodeData().getLossPerBlock(); - if (voltageTraveled <= 0) break; + long availableAmperage = amperage; + mainloop: + for (NetPath path : paths) { + // skip paths where loss exceeds available voltage + if (path.getWeight() > voltage) continue; + Iterator iterator = path.getFacingIterator(); + boolean pathDestThis = path.getTargetNode().getNodePos().equals(this.cable.getPipePos()); + while (iterator.hasNext()) { + NetPath.FacedNetPath facedPath = + path.withFacing(iterator.next()); + if (pathDestThis && facedPath.facing == side) { + // do not distribute power back into our source + continue; + } - if (!cable.isInvalid()) { - cable.incrementAmperage(amps, voltageTraveled); + IEnergyContainer dest = facedPath.getTargetTE().getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facedPath.oppositeFacing()); + if (dest == null || dest == this) continue; + if (!dest.inputsEnergy(facedPath.oppositeFacing()) || dest.getEnergyCanBeInserted() <= 0) continue; + + List> nodeList = facedPath.getNodeList(); + DoubleList voltageCaps = new DoubleArrayList(); + long pathAmperage = availableAmperage; + // loss from the first node + NetNode target = nodeList.get(0); + if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) continue; + + List edgeList = facedPath.getEdgeList(); + List> flowLimitConsumers = new ObjectArrayList<>(); + List> amperageLoss = new ObjectArrayList<>(); + for (int j = 0; j < edgeList.size(); j++) { + NetFlowEdge edge = edgeList.get(j); + + long flowLimit = edge.getFlowLimit(null, this.net.getGraph(), queryTick, simulator); + NetNode source = target; + target = nodeList.get(j + 1); + NetNode finalTarget = target; + long finalPathAmperage = pathAmperage; + if (simulator == null && finalPathAmperage != 0) { + amperageLoss.add((ratio) -> { + long adjustedAmperage = (long) (finalPathAmperage * ratio); + if (adjustedAmperage > flowLimit) { + int heat = calculateHeat(adjustedAmperage - flowLimit, adjustedAmperage, 1) / 2; + getOrGenerateLossResult(source, heat, false); + getOrGenerateLossResult(finalTarget, heat, false); + } + }); } + + TileEntityCable tile = simulator == null ? (TileEntityCable) target.getHeldMTEUnsafe() : null; + flowLimitConsumers.add((ratio) -> { + long consumption = Math.min((long) (finalPathAmperage * ratio), flowLimit); + if (consumption == 0) return; + edge.consumeFlowLimit(null, getNet().getGraph(), consumption, queryTick, simulator); + if (tile != null) { + tile.contributeAmperageFlow(consumption); + tile.contributeVoltageFlow(voltage); + } + }); + pathAmperage = Math.min(pathAmperage, flowLimit); + if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) continue mainloop; } - if (amperage == amperesUsed) break mainloop; + long finalVoltage = (long) GTUtility.geometricMean((double) voltage, voltageCaps.toArray(new double[]{})); + long simulatedAccepted = dest.acceptEnergyFromNetwork(facedPath.oppositeFacing(), finalVoltage, availableAmperage, true); + simulatedAccepted = getSimulatedAccepted(localDestSimulationCache, facedPath.toFacingPos(), simulatedAccepted); + if (simulator != null) + simulatedAccepted = getSimulatedAccepted(destSimulationCache, facedPath.toFacingPos(), simulatedAccepted); + double ratio = (double) simulatedAccepted / availableAmperage; + flowLimitConsumers.forEach(consumer -> consumer.accept(ratio)); + amperageLoss.forEach(consumer -> consumer.accept(ratio)); + availableAmperage -= simulatedAccepted; + + if (availableAmperage <= 0) return amperage; } } - if (net.getGroup(this.cable.getPipePos()).getData() instanceof EnergyGroupData data) - data.addEnergyFluxPerSec(amperesUsed * voltage); - return amperesUsed; + return amperage - availableAmperage; } - private void burnCable(World world, BlockPos pos) { - world.setBlockState(pos, Blocks.FIRE.getDefaultState()); - if (!world.isRemote) { - ((WorldServer) world).spawnParticle(EnumParticleTypes.SMOKE_LARGE, - pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, - 5 + world.rand.nextInt(3), 0.0, 0.0, 0.0, 0.1); + private long getSimulatedAccepted(Object2LongOpenHashMap destSimulationCache, + FacingPos facingPos, + long accepted) { + AtomicLong atomicAccepted = new AtomicLong(accepted); + destSimulationCache.compute(facingPos, (k, v) -> { + if (v == null) return atomicAccepted.get(); + atomicAccepted.set(Math.max(atomicAccepted.get() - v, 0)); + return v + atomicAccepted.get(); + }); + return atomicAccepted.get(); + } + + private boolean calculateVoltageLoss(long voltage, AbstractNetFlowEdge.ChannelSimulatorKey simulator, + DoubleList voltageCaps, long pathAmperage, + NetNode target) { + // TODO undo loss & heating on backflow + if (target.getData().getVoltage() < voltage) { + int heat = calculateHeat(pathAmperage, voltage, target.getData().getVoltage()); + NodeLossResult lossResult = getOrGenerateLossResult(target, heat, simulator != null); + + if (lossResult.getLossFunction() == 0) { + // stop this path, a cable burned + return true; + } + voltageCaps.add(target.getData().getVoltage()); } + return false; + } + + private int calculateHeat(long exceedingAmperage, long voltage, long maxVoltage) { + return (int) (exceedingAmperage * (Math.log1p(Math.log((double) voltage / maxVoltage)) * 45 + 36.5)); } @Override @@ -193,4 +349,15 @@ public long getEnergyStored() { public boolean isOneProbeHidden() { return true; } + + protected NodeLossResult getOrGenerateLossResult(NetNode node, + int heat, boolean simulate) { + var cachedResult = this.lossResultCache.get(node); + if (cachedResult == null) { + cachedResult = ((TileEntityCable) node.getHeldMTE()).applyHeat(heat, simulate); + if (cachedResult.getLossFunction() != 0) return cachedResult; + else this.lossResultCache.put(node, cachedResult); + } + return cachedResult; + } } diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java index c74103494d9..81a553c59d9 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -1,8 +1,12 @@ package gregtech.common.pipelike.cable.net; +import gregtech.api.capability.GregtechCapabilities; import gregtech.api.pipenet.AbstractGroupData; -import gregtech.api.pipenet.WorldPipeNetSimple; -import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.WorldPipeNetComplex; +import gregtech.api.pipenet.alg.AllPathsAlgorithm; +import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; +import gregtech.api.pipenet.alg.SinglePathAlgorithm; +import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.WireProperties; import gregtech.common.pipelike.cable.Insulation; @@ -11,10 +15,8 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.energy.CapabilityEnergy; -// TODO move onto complex net -public class WorldEnergyNet extends WorldPipeNetSimple { +public class WorldEnergyNet extends WorldPipeNetComplex { private static final String DATA_ID_BASE = "gregtech.e_net"; @@ -30,16 +32,16 @@ public static WorldEnergyNet getWorldEnergyNet(World world) { } public WorldEnergyNet(String name) { - super(name, false, false); + super(name, true, () -> new NetFlowEdge(1), AllPathsAlgorithm::new); } @Override protected Capability[] getConnectionCapabilities() { - return new Capability[] { CapabilityEnergy.ENERGY }; + return new Capability[] { GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER }; } @Override - protected Class> getBasePipeClass() { + protected Class> getBasePipeClass() { return TileEntityCable.class; } diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java index 56d5e3189e3..0cb0419cf15 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java @@ -4,9 +4,13 @@ import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IEnergyContainer; import gregtech.api.metatileentity.IDataInfoProvider; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.NodeLossResult; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.edge.NetFlowEdge; +import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.TaskScheduler; import gregtech.api.util.TextFormattingUtil; @@ -22,26 +26,30 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.Style; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.WorldServer; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import codechicken.lib.vec.Cuboid6; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; +import java.util.function.Consumer; import static gregtech.api.capability.GregtechDataCodes.CABLE_TEMPERATURE; import static gregtech.api.capability.GregtechDataCodes.UPDATE_CONNECTIONS; -public class TileEntityCable extends TileEntityMaterialPipeBase +public class TileEntityCable extends TileEntityMaterialPipeBase implements IDataInfoProvider { private static final int meltTemp = 3000; @@ -55,7 +63,6 @@ public class TileEntityCable extends TileEntityMaterialPipeBase maxVoltageCounter.get(getWorld())) { - maxVoltageCounter.set(getWorld(), voltage); - } - averageVoltageCounter.increment(getWorld(), voltage); - averageAmperageCounter.increment(getWorld(), amps); - - int dif = (int) (averageAmperageCounter.getLast(getWorld()) - getMaxAmperage()); - if (dif > 0) { - applyHeat(dif * 40); - return true; - } + public NodeLossResult applyHeat(int amount, boolean simulate) { + double loss = 1; + Consumer> destructionResult = null; - return false; - } - - public void applyHeat(int amount) { - heatQueue += amount; - if (!world.isRemote && !isTicking && temperature + heatQueue > getDefaultTemp()) { - TaskScheduler.scheduleTask(world, this::update); - isTicking = true; + if (temperature + amount >= meltTemp) { + // cable melted + destructionResult = node -> { + isTicking = false; + getWorld().setBlockState(pos, Blocks.FIRE.getDefaultState()); + if (!getWorld().isRemote) { + ((WorldServer) getWorld()).spawnParticle(EnumParticleTypes.SMOKE_LARGE, + pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, + 5 + getWorld().rand.nextInt(3), 0.0, 0.0, 0.0, 0.1); + } + }; + loss = 0; } + if (!simulate) setTemperature(temperature + amount); + return new NodeLossResult(destructionResult == null ? node -> {} : destructionResult, loss); } private boolean update() { - if (heatQueue > 0) { - // if received heat from overvolting or overamping, add heat - setTemperature(temperature + heatQueue); - } - - if (temperature >= meltTemp) { - // cable melted - world.setBlockState(pos, Blocks.FIRE.getDefaultState()); - isTicking = false; - return false; - } - if (temperature <= getDefaultTemp()) { isTicking = false; - return false; - } - - if (getPipeType().insulationLevel >= 0 && temperature >= 1500 && GTValues.RNG.nextFloat() < 0.1) { + } else if (getPipeType().insulationLevel >= 0 && temperature >= 1500 && GTValues.RNG.nextFloat() < 0.1) { // insulation melted uninsulate(); isTicking = false; - return false; } - - if (heatQueue == 0) { - // otherwise cool down - setTemperature((int) (temperature - Math.pow(temperature - getDefaultTemp(), 0.35))); - } else { - heatQueue = 0; - } - return true; + // thicker cables cool faster + setTemperature((int) (temperature - Math.pow(temperature - getDefaultTemp(), 0.35) * + Math.sqrt(this.getPipeType().getThickness()) * 4)); + return isTicking; } private void uninsulate() { @@ -168,7 +147,7 @@ private void uninsulate() { world.setBlockState(pos, newBlock.getDefaultState()); TileEntityCable newCable = (TileEntityCable) world.getTileEntity(pos); if (newCable != null) { // should never be null - // TODO: use transfer data method + newCable.transferDataFrom(this); newCable.setPipeData(newBlock, newBlock.getItemPipeType(null), getPipeMaterial()); for (EnumFacing facing : EnumFacing.VALUES) { if (isConnected(facing)) { @@ -188,8 +167,14 @@ public void setTemperature(int temperature) { world.checkLight(pos); if (!world.isRemote) { writeCustomData(CABLE_TEMPERATURE, buf -> buf.writeVarInt(temperature)); + if (!isTicking && temperature > getDefaultTemp()) { + TaskScheduler.scheduleTask(getWorld(), this::update); + isTicking = true; + } } else { + // TODO fix particle sometimes not rendering after world load if (temperature <= getDefaultTemp()) { + if (isParticleAlive()) particle.setExpired(); } else { @@ -201,6 +186,11 @@ public void setTemperature(int temperature) { } } + @Override + public void transferDataFrom(IPipeTile tileEntity) { + super.transferDataFrom(tileEntity); + } + public int getDefaultTemp() { return 293; } @@ -227,6 +217,15 @@ public void killParticle() { } } + public void contributeAmperageFlow(long amperage) { + averageAmperageCounter.increment(getWorld(), amperage); + } + + public void contributeVoltageFlow(long voltage) { + if (voltage > maxVoltageCounter.get(getWorld())) maxVoltageCounter.set(getWorld(), voltage); + averageVoltageCounter.set(getWorld(), maxVoltageCounter.get(getWorld())); + } + public double getAverageAmperage() { return averageAmperageCounter.getAverage(getWorld()); } @@ -243,6 +242,8 @@ public long getMaxAmperage() { return getNodeData().getAmperage(); } + @ApiStatus.ScheduledForRemoval(inVersion = "2.9") + @Deprecated public long getMaxVoltage() { return getNodeData().getVoltage(); } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java index c5d6b4786ee..76abbe7af95 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java @@ -4,9 +4,10 @@ import gregtech.api.pipenet.IPipeNetHandler; import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; +import gregtech.api.pipenet.NodeLossResult; import gregtech.api.pipenet.edge.AbstractNetFlowEdge; import gregtech.api.pipenet.edge.NetFlowEdge; -import gregtech.api.pipenet.edge.util.FlowConsumer; +import gregtech.api.pipenet.edge.util.FlowConsumerList; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.util.FluidTestObject; import gregtech.common.covers.CoverFluidRegulator; @@ -23,7 +24,6 @@ import net.minecraftforge.fml.common.FMLCommonHandler; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.Iterator; import java.util.List; @@ -41,7 +41,7 @@ public class FluidNetHandler implements IFluidHandler, IPipeNetHandler { private AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey; private FluidStack lastFillResource; - private final Map, FluidPipeProperties.PipeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); + private final Map, NodeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); public FluidNetHandler(WorldFluidPipeNet net, TileEntityFluidPipe pipe, EnumFacing facing) { this.net = net; @@ -83,7 +83,7 @@ public int fill(FluidStack resource, boolean doFill) { FluidTestObject testObject = new FluidTestObject(resource); long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); // push flow through net - List> paths = this.getNet().getPaths(pipe, testObject); + List> paths = this.getNet().getPaths(pipe); FluidStack helper = resource.copy(); if (!doFill) this.simulatorKey = AbstractNetFlowEdge.getNewSimulatorInstance(); else this.simulatorKey = null; @@ -114,7 +114,7 @@ public int fill(NetPath.FacedNetPath> nodeList = routePath.getNodeList(); List edgeList = routePath.getEdgeList(); - List> flowLimitConsumers = new ObjectArrayList<>(); - int inputAmount = resource.amount; - int outputAmount = resource.amount; + FlowConsumerList flowLimitConsumers = new FlowConsumerList<>(); + + // loss from the first input node + var targetResult = getOrGenerateLossResult(nodeList.get(0), resource); + double loss = targetResult.getLossFunction(); + int inputAmount = (int) (resource.amount * loss); + int outputAmount = inputAmount; + // always 1 less edge than nodes for (int i = 0; i < edgeList.size(); i++) { NetFlowEdge edge = edgeList.get(i); if (!edge.getPredicate().test(resource)) return 0; - int flow = Math.min(edge.getFlowLimit(testObject, getNet().getGraph(), tick, simulatorKey), outputAmount); + long flow = Math.min(edge.getFlowLimit(testObject, getNet().getGraph(), tick, simulatorKey), outputAmount); double ratio = (double) flow / outputAmount; inputAmount *= ratio; - flowLimitConsumers.forEach(c -> c.modifyRatio(ratio)); - flowLimitConsumers.add(new FlowConsumer<>(edge, testObject, getNet().getGraph(), flow, tick, simulatorKey)); + flowLimitConsumers.modifyRatios(ratio); + flowLimitConsumers.add(edge, testObject, getNet().getGraph(), flow, tick, simulatorKey); // TODO undo loss when backflowing // var sourceResult = getOrGenerateLossResult(nodeList.get(i), resource); - var targetResult = getOrGenerateLossResult(nodeList.get(i + 1), resource); - double loss = targetResult.getLossFunction(); + targetResult = getOrGenerateLossResult(nodeList.get(i + 1), resource); + loss = targetResult.getLossFunction(); outputAmount = (int) (flow * loss); } // outputAmount is currently the maximum flow to the endpoint, and inputAmount is the requisite flow into the @@ -221,7 +226,7 @@ private int fill(NetPath.FacedNetPath a.accept(ratio)); + flowLimitConsumers.doConsumption(ratio); return (int) (inputAmount * ratio); } @@ -253,8 +258,7 @@ public FluidStack drain(int maxDrain, boolean doDrain) { return null; } - protected FluidPipeProperties.PipeLossResult getOrGenerateLossResult( - NetNode node, + protected NodeLossResult getOrGenerateLossResult(NetNode node, FluidStack resource) { var cachedResult = this.lossResultCache.get(node); if (cachedResult == null) { diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index d265f9db44a..aaaca684dc2 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -1,6 +1,7 @@ package gregtech.common.pipelike.fluidpipe.net; import gregtech.api.cover.Cover; +import gregtech.api.pipenet.alg.AllPathsAlgorithm; import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.pipenet.WorldPipeNetComplex; import gregtech.api.pipenet.edge.NetFlowEdge; @@ -36,7 +37,7 @@ public static WorldFluidPipeNet getWorldPipeNet(World world) { } public WorldFluidPipeNet(String name) { - super(name, true, false, () -> new NetFlowEdge(20)); + super(name, true, () -> new NetFlowEdge(20), AllPathsAlgorithm::new); } @Override diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index 69e56535d88..bd2b546d1c7 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -113,7 +113,7 @@ public static boolean checkImportCover(Cover cover, boolean onPipe, ItemStack st } public ItemStack insertFirst(ItemStack stack, boolean simulate) { - for (NetPath inv : net.getPaths(pipe, null)) { + for (NetPath inv : net.getPaths(pipe)) { stack = insert(inv.firstFacing(), stack, simulate); if (stack.isEmpty()) return ItemStack.EMPTY; @@ -122,7 +122,7 @@ public ItemStack insertFirst(ItemStack stack, boolean simulate) { } public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean global) { - List> routePaths = net.getPaths(pipe, null); + List> routePaths = net.getPaths(pipe); if (routePaths.isEmpty()) return stack; if (routePaths.size() == 1 && routePaths.get(0).getTargetTEs().size() == 1) { @@ -327,7 +327,7 @@ public ItemStack insert(NetPath.FacedNetPath> data = net.getPaths(this.pipe, null); + List> data = net.getPaths(this.pipe); if (data == null || data.size() != 1) return null; Map connecteds = data.get(0).getTargetTEs(); if (connecteds.size() != 1) return null; @@ -70,11 +70,11 @@ private ILaserContainer getInnerContainer() { } @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { ILaserContainer handler = getInnerContainer(); if (handler == null) return 0; setPipesActive(); - return handler.acceptEnergyFromNetwork(side, voltage, amperage); + return handler.acceptEnergyFromNetwork(side, voltage, amperage, simulate); } @Override diff --git a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java b/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java index e289b02d1bd..89d597893c1 100644 --- a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java +++ b/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java @@ -195,7 +195,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { private static class DefaultLaserContainer implements ILaserContainer { @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { return 0; } diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java index 849a9abea11..9badc01604d 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java @@ -96,7 +96,7 @@ private boolean isNetInvalidForTraversal() { private boolean traverseRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { if (isNetInvalidForTraversal()) return false; - List> inv = net.getPaths(this.pipe, null); + List> inv = net.getPaths(this.pipe); if (inv == null || inv.size() != 1) return false; Map connecteds = inv.get(0).getTargetTEs(); if (connecteds.size() != 1) return false; @@ -134,7 +134,7 @@ private boolean traverseCanBridge(@NotNull Collection seen) { if (isNetInvalidForTraversal()) return null; - List> inv = net.getPaths(this.pipe, null); + List> inv = net.getPaths(this.pipe); if (inv == null || inv.size() != 1) return null; Map connecteds = inv.get(0).getTargetTEs(); if (connecteds.size() != 1) return null; diff --git a/src/test/java/gregtech/common/metatileentities/converter/ConverterTraitTest.java b/src/test/java/gregtech/common/metatileentities/converter/ConverterTraitTest.java index 48ef15749ab..796a2764e96 100644 --- a/src/test/java/gregtech/common/metatileentities/converter/ConverterTraitTest.java +++ b/src/test/java/gregtech/common/metatileentities/converter/ConverterTraitTest.java @@ -298,7 +298,8 @@ public boolean canReceive() { private long energyStored; @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { + if (simulate) return Math.min(energyCapacity - energyStored, voltage * amperage) / voltage; return addEnergy(voltage * amperage) / voltage; } From 559f63c1620e57b2a6cefd534a4e22f441f4ebe5 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 24 Jun 2024 20:45:30 -0600 Subject: [PATCH 063/157] inflow edges & spotless --- .../java/gregtech/api/pipenet/NetGroup.java | 12 +- .../java/gregtech/api/pipenet/NetNode.java | 16 ++- .../java/gregtech/api/pipenet/NetPath.java | 5 +- .../api/pipenet/WorldPipeNetBase.java | 13 +- .../api/pipenet/WorldPipeNetComplex.java | 12 +- .../api/pipenet/WorldPipeNetSimple.java | 8 +- .../api/pipenet/alg/AllPathsAlgorithm.java | 3 +- .../pipenet/alg/ShortestPathsAlgorithm.java | 5 +- .../api/pipenet/alg/SinglePathAlgorithm.java | 3 +- .../api/pipenet/edge/AbstractNetFlowEdge.java | 34 +++--- .../gregtech/api/pipenet/edge/NetEdge.java | 2 +- .../api/pipenet/edge/NetFlowEdge.java | 15 ++- .../api/pipenet/edge/NetFlowSharedEdge.java | 18 +-- .../pipenet/edge/util/FlowConsumerList.java | 1 - .../predicate/FilteredEdgePredicate.java | 2 +- .../java/gregtech/api/util/GTUtility.java | 1 - .../common/pipelike/cable/BlockCable.java | 1 - .../pipelike/cable/net/EnergyNetHandler.java | 111 +++++++++--------- .../pipelike/cable/net/WorldEnergyNet.java | 2 - .../pipelike/cable/tile/TileEntityCable.java | 17 ++- .../fluidpipe/net/FluidNetHandler.java | 34 ++++-- .../fluidpipe/net/WorldFluidPipeNet.java | 4 +- .../pipelike/itempipe/net/ItemNetHandler.java | 1 + 23 files changed, 177 insertions(+), 143 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java index 10508dddb82..8edfc178fd4 100644 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ b/src/main/java/gregtech/api/pipenet/NetGroup.java @@ -17,7 +17,8 @@ import java.util.stream.Collectors; public class NetGroup & IPipeType, - NodeDataType extends INodeData, Edge extends NetEdge> implements INBTSerializable { + NodeDataType extends INodeData, + Edge extends NetEdge> implements INBTSerializable { public final WorldPipeNetBase net; @@ -32,7 +33,8 @@ public NetGroup(Graph, Edge> graph, this(graph, net, new ObjectOpenHashSet<>()); } - public NetGroup(Graph, Edge> graph, WorldPipeNetBase net, + public NetGroup(Graph, Edge> graph, + WorldPipeNetBase net, Set> nodes) { this.graph = graph; this.net = net; @@ -159,11 +161,13 @@ public boolean splitNode(NetNode source) { * @param target target of the edge * @return Whether the edge existed in the graph */ - public boolean splitEdge(NetNode source, NetNode target) { + public boolean splitEdge(NetNode source, + NetNode target) { if (graph.removeEdge(source, target) != null) { this.clearPathCaches(); Set> targetGroup = new ObjectOpenHashSet<>(); - BreadthFirstIterator, Edge> i = new BreadthFirstIterator<>(graph, target); + BreadthFirstIterator, Edge> i = new BreadthFirstIterator<>(graph, + target); NetNode temp; while (i.hasNext()) { temp = i.next(); diff --git a/src/main/java/gregtech/api/pipenet/NetNode.java b/src/main/java/gregtech/api/pipenet/NetNode.java index 9e24eed051f..34571fa11a8 100644 --- a/src/main/java/gregtech/api/pipenet/NetNode.java +++ b/src/main/java/gregtech/api/pipenet/NetNode.java @@ -55,6 +55,7 @@ public final class NetNode & IPipeType group = null; + @Nullable private List> pathCache = null; public NetNode(NodeDataType data, IPipeTile heldMTE, @@ -83,6 +84,19 @@ public NetNode(IPipeTile heldMTE) { this.blockedConnections = 0; } + /** + * Creates a dummy node for fake flow edges. + * Should never be required to reference its net, mte, or position. + */ + public NetNode(NodeDataType data) { + this.nodePos = null; + this.net = null; + this.data = data; + this.heldMTE = null; + this.openConnections = 0; + this.blockedConnections = 0; + } + /** * For construction during NBT reading only */ @@ -265,7 +279,7 @@ public List> getPathCache() { */ public List> setPathCache(List> pathCache) { this.pathCache = pathCache; - return pathCache; + return getPathCache(); } public void clearPathCache() { diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index fabde940044..37ec8b24816 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -8,6 +8,7 @@ import net.minecraft.util.EnumFacing; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jgrapht.Graph; import org.jgrapht.GraphPath; import java.util.Collections; @@ -72,7 +73,9 @@ public NetPath(GraphPath, Edge> path) { // convert weight to the true value of the involved nodes this.weight = (path.getWeight() + sourceNode.getData().getWeightFactor() + targetNode.getData().getWeightFactor()) / 2; - this.edgeList = path.getEdgeList(); + + Graph, Edge> g = path.getGraph(); + this.edgeList = new ObjectArrayList<>(path.getEdgeList()); assert this.nodeList.size() == this.edgeList.size() + 1; } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java index fe13f189500..dd1d72b7a23 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java @@ -2,8 +2,6 @@ import gregtech.api.cover.Cover; import gregtech.api.pipenet.alg.INetAlgorithm; -import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; -import gregtech.api.pipenet.alg.SinglePathAlgorithm; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.predicate.AbstractEdgePredicate; @@ -27,7 +25,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; @@ -56,8 +53,8 @@ public abstract class WorldPipeNetBase, INetAlgorithm> algorithmBuilder, - Graph, Edge> graph) { + Function, INetAlgorithm> algorithmBuilder, + Graph, Edge> graph) { super(name); this.pipeGraph = graph; this.netAlgorithm = new INetAlgorithm.NetAlgorithmWrapper<>(); @@ -112,7 +109,7 @@ protected void onWorldSet() { /** * Preferred override. Only collects a fresh TE from the server if the provided TE is invalid. * - * @param tile The {@link TileEntityPipeBase} that paths are being requested for + * @param tile The {@link TileEntityPipeBase} that paths are being requested for * @return the ordered list of paths associated with the {@link TileEntityPipeBase} */ public List> getPaths(TileEntityPipeBase tile) { @@ -122,7 +119,7 @@ public List> getPaths(TileEntityPipeBase

> getPaths(BlockPos pos) { @@ -434,7 +431,7 @@ public NetGroup getGroup(BlockPos pos) { public boolean shouldNodeBeActive(NetNode node) { var connecteds = node.getConnecteds(); if (connecteds != null) return connecteds.entrySet().stream().filter(entry -> { - if (entry.getValue() instanceof IPipeTile) return false; + if (entry.getValue() instanceof IPipeTile) return false; for (Capability cap : this.getConnectionCapabilities()) { if (entry.getValue().hasCapability(cap, entry.getKey())) return true; } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java index a77180a22d7..fae9a9c67e3 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java @@ -38,16 +38,16 @@ public WorldPipeNetComplex(String name, boolean isDirected, boolean isSinglePath *

* Note - These child edges cannot be allowed to store information, they must only perform runtime behavior. * - * @param isDirected Determines whether this net needs directed graph handling. - * Used to respect filter directions in the item net and fluid net, for example. - * If the graph is not directed, pipes should not support blocked connections - * or unidirectional covers. - * @param edgeSupplier The supplier for the custom NetEdge child class. + * @param isDirected Determines whether this net needs directed graph handling. + * Used to respect filter directions in the item net and fluid net, for example. + * If the graph is not directed, pipes should not support blocked connections + * or unidirectional covers. + * @param edgeSupplier The supplier for the custom NetEdge child class. * @param algorithmBuilder custom function to construct a new algorithm when the old one is invalidated. */ public WorldPipeNetComplex(String name, boolean isDirected, Supplier edgeSupplier, Function, INetAlgorithm> algorithmBuilder) { super(name, isDirected, algorithmBuilder, isDirected ? new SimpleDirectedWeightedGraph<>(null, edgeSupplier) : - new SimpleWeightedGraph<>(null, edgeSupplier)); + new SimpleWeightedGraph<>(null, edgeSupplier)); } } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java index 95aba2674d1..810851c00ec 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java @@ -32,10 +32,10 @@ public WorldPipeNetSimple(String name, boolean isDirected, boolean isSinglePath) /** * Standard pipenet representation. Provides the base form of the pipenet abstraction. * - * @param isDirected Determines whether this net needs directed graph handling. - * Used to respect filter directions in the item net and fluid net, for example. - * If the graph is not directed, pipes should not support blocked connections - * or unidirectional covers. + * @param isDirected Determines whether this net needs directed graph handling. + * Used to respect filter directions in the item net and fluid net, for example. + * If the graph is not directed, pipes should not support blocked connections + * or unidirectional covers. * @param algorithmBuilder custom function to construct a new algorithm when the old one is invalidated. */ public WorldPipeNetSimple(String name, boolean isDirected, diff --git a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java index 45711a27a5c..ae806e28c47 100644 --- a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java @@ -7,6 +7,7 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.alg.shortestpath.AllDirectedPaths; import java.util.Collections; @@ -29,6 +30,6 @@ public List> getPathsList(NetNode source) { .filter(NetNode::isActive).collect(Collectors.toSet()); return getAllPaths(Collections.singleton(source), searchSpace, true, (int) Short.MAX_VALUE) .stream().map(NetPath::new).sorted(Comparator.comparingDouble(NetPath::getWeight)) - .collect(Collectors.toList()); + .collect(Collectors.toCollection(ObjectArrayList::new)); } } diff --git a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java index a142e1e06ad..5ea66527255 100644 --- a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java @@ -8,8 +8,6 @@ import gregtech.api.pipenet.edge.NetEdge; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jgrapht.Graph; -import org.jgrapht.GraphPath; import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; import java.util.Collections; @@ -39,6 +37,7 @@ public List> getPathsList(NetNode source) { ManyToManyShortestPaths, E> manyToManyPaths = getManyToManyPaths( Collections.singleton(source), searchSpace); return searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)).map(NetPath::new) - .sorted(Comparator.comparingDouble(NetPath::getWeight)).collect(Collectors.toList()); + .sorted(Comparator.comparingDouble(NetPath::getWeight)) + .collect(Collectors.toCollection(ObjectArrayList::new)); } } diff --git a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java index 1f0c62ce48e..b0deaceb450 100644 --- a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java @@ -1,7 +1,5 @@ package gregtech.api.pipenet.alg; -import com.google.common.collect.ImmutableList; - import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; @@ -9,6 +7,7 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; +import com.google.common.collect.ImmutableList; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.Graph; diff --git a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java index 1e7f2c9dc66..9a9cbeb7b55 100644 --- a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java @@ -29,7 +29,6 @@ public static ChannelSimulatorKey getNewSimulatorInstance() { return new ChannelSimulatorKey(); } - public boolean cannotSupportChannel(Object channel, long queryTick, @Nullable ChannelSimulatorKey simulator) { return getChannels(simulator).cannotSupportChannel(channel, queryTick); } @@ -47,10 +46,10 @@ protected AbstractChannelsHolder getChannels(@Nullable ChannelSimulatorKey si } public & IPipeType, NDT extends INodeData> long getFlowLimit( - Object channel, - Graph, E> graph, - long queryTick, - @Nullable ChannelSimulatorKey simulator) { + Object channel, + Graph, E> graph, + long queryTick, + @Nullable ChannelSimulatorKey simulator) { return getChannels(simulator).getFlowLimit(channel, graph, queryTick); } @@ -59,14 +58,16 @@ public long getConsumedLimit(Object channel, long queryTick, @Nullable ChannelSi } public & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, - Graph, E> graph, - long amount, long queryTick, - @Nullable ChannelSimulatorKey simulator) { + Object channel, + Graph, E> graph, + long amount, + long queryTick, + @Nullable ChannelSimulatorKey simulator) { getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); } - protected abstract AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, ChannelSimulatorKey simulator); + protected abstract AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, + ChannelSimulatorKey simulator); protected abstract static class AbstractChannelsHolder> { @@ -85,16 +86,17 @@ public ChannelSimulatorKey getSimulator() { abstract boolean cannotSupportChannel(Object channel, long queryTick); abstract & IPipeType, NDT extends INodeData> long getFlowLimit( - Object channel, - Graph, E> graph, - long queryTick); + Object channel, + Graph, E> graph, + long queryTick); abstract long getConsumedLimit(Object channel, long queryTick); abstract & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, - Graph, E> graph, - long amount, long queryTick); + Object channel, + Graph, E> graph, + long amount, + long queryTick); } public static final class ChannelSimulatorKey { diff --git a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java index 89cf7bb6c08..a4b5ce5041f 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java @@ -1,10 +1,10 @@ package gregtech.api.pipenet.edge; -import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.pipenet.INBTBuilder; import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.util.function.QuadConsumer; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java index 02194a8ffef..0886dfe6a12 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java @@ -4,14 +4,13 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.IPipeType; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.Graph; import java.util.List; -public final class NetFlowEdge extends AbstractNetFlowEdge { +public class NetFlowEdge extends AbstractNetFlowEdge { private final int flowBufferTicks; @@ -27,7 +26,8 @@ public NetFlowEdge(int flowBufferTicks) { } @Override - protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, ChannelSimulatorKey simulator) { + protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, + ChannelSimulatorKey simulator) { if (prototype instanceof ChannelsHolder holder) return new ChannelsHolder(holder, simulator); return new ChannelsHolder(simulator); } @@ -58,8 +58,8 @@ public boolean cannotSupportChannel(Object channel, long queryTick) { @Override public & IPipeType, NDT extends INodeData> long getFlowLimit(Object channel, - Graph, NetFlowEdge> graph, - long queryTick) { + Graph, NetFlowEdge> graph, + long queryTick) { if (cannotSupportChannel(channel, queryTick)) return 0; long limit = map.getLong(channel); @@ -81,7 +81,10 @@ long getConsumedLimit(Object channel, long queryTick) { @Override & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, Graph, NetFlowEdge> graph, long amount, long queryTick) { + Object channel, + Graph, NetFlowEdge> graph, + long amount, + long queryTick) { if (amount == 0) return; recalculateFlowLimits(queryTick); diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java index 2729dd49d50..05697140c88 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java @@ -4,12 +4,10 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.IPipeType; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.util.math.MathHelper; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.Graph; import java.util.List; @@ -30,7 +28,8 @@ public NetFlowSharedEdge(int flowBufferTicks) { } @Override - protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, ChannelSimulatorKey simulator) { + protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, + ChannelSimulatorKey simulator) { if (prototype instanceof ChannelsHolder holder) return new ChannelsHolder(holder, simulator); return new ChannelsHolder(simulator); } @@ -64,8 +63,8 @@ public boolean cannotSupportChannel(Object channel, long queryTick) { @Override public & IPipeType, NDT extends INodeData> long getFlowLimit(Object channel, - Graph, NetFlowSharedEdge> graph, - long queryTick) { + Graph, NetFlowSharedEdge> graph, + long queryTick) { if (cannotSupportChannel(channel, queryTick)) return 0; NetFlowSharedEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); @@ -83,7 +82,10 @@ long getConsumedLimit(Object channel, long queryTick) { @Override & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, Graph, NetFlowSharedEdge> graph, long amount, long queryTick) { + Object channel, + Graph, NetFlowSharedEdge> graph, + long amount, + long queryTick) { if (amount == 0) return; recalculateFlowLimits(queryTick); diff --git a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java index 5ea3b1431cb..ec105c98052 100644 --- a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java +++ b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java @@ -4,7 +4,6 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.AbstractNetFlowEdge; - import gregtech.api.util.FluidTestObject; import it.unimi.dsi.fastutil.objects.ObjectArrayList; diff --git a/src/main/java/gregtech/api/pipenet/predicate/FilteredEdgePredicate.java b/src/main/java/gregtech/api/pipenet/predicate/FilteredEdgePredicate.java index 6d23df21c64..25d15a08bd1 100644 --- a/src/main/java/gregtech/api/pipenet/predicate/FilteredEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/predicate/FilteredEdgePredicate.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; public abstract class FilteredEdgePredicate> extends AbstractEdgePredicate - implements IShutteredEdgePredicate { + implements IShutteredEdgePredicate { protected static final IDirtyNotifiable DECOY = () -> {}; diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index c230a17df49..c751a87c7fb 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -63,7 +63,6 @@ import org.jetbrains.annotations.Nullable; import java.util.AbstractList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Map.Entry; diff --git a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java index fd1ffb36dac..b9ba309c796 100644 --- a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java @@ -5,7 +5,6 @@ import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.pipenet.block.material.BlockMaterialPipe; -import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java index 546d8317148..5eb86ebf03a 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -9,7 +9,6 @@ import gregtech.api.pipenet.NodeLossResult; import gregtech.api.pipenet.edge.AbstractNetFlowEdge; import gregtech.api.pipenet.edge.NetFlowEdge; -import gregtech.api.pipenet.edge.util.FlowConsumer; import gregtech.api.pipenet.edge.util.FlowConsumerList; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.FacingPos; @@ -18,43 +17,50 @@ import gregtech.common.pipelike.cable.Insulation; import gregtech.common.pipelike.cable.tile.TileEntityCable; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.fml.common.FMLCommonHandler; + import it.unimi.dsi.fastutil.doubles.DoubleArrayList; import it.unimi.dsi.fastutil.doubles.DoubleList; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.init.Blocks; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.WorldServer; -import net.minecraftforge.fml.common.FMLCommonHandler; - -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; - import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; public class EnergyNetHandler implements IEnergyContainer, IPipeNetHandler { + protected static final NetNode FAKE_SOURCE = new NetNode<>( + new WireProperties(Integer.MAX_VALUE, Integer.MAX_VALUE, 0, false)); + private final WorldEnergyNet net; private boolean transfer; private final TileEntityCable cable; private final EnumFacing facing; private final Map, NodeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); private Object2LongOpenHashMap destSimulationCache; + private final NetFlowEdge inputEdge; public EnergyNetHandler(WorldEnergyNet net, TileEntityCable cable, EnumFacing facing) { this.net = net; this.cable = cable; this.facing = facing; + this.inputEdge = new NetFlowEdge(1) { + + @Override + public NetNode getSource() { + return FAKE_SOURCE; + } + + @Override + public NetNode getTarget() { + return EnergyNetHandler.this.cable.getNode(); + } + }; } @Override @@ -100,7 +106,7 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage AbstractNetFlowEdge.ChannelSimulatorKey key = simulate ? AbstractNetFlowEdge.getNewSimulatorInstance() : null; destSimulationCache = simulate ? new Object2LongOpenHashMap<>() : null; - List> paths = this.net.getPaths(cable); + List> paths = new ObjectArrayList<>(this.net.getPaths(cable)); long amperesUsed = distributionRespectCapacity(side, voltage, amperage, queryTick, paths, key); if (amperesUsed < amperage) { // if we still have undistributed amps, attempt to distribute them while going over edge capacities. @@ -119,48 +125,43 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage private long distributionRespectCapacity(EnumFacing side, long voltage, long amperage, long queryTick, List> paths, AbstractNetFlowEdge.ChannelSimulatorKey simulator) { - List> pathsCopy = new ObjectArrayList<>(paths); long availableAmperage = amperage; mainloop: - for (int i = 0; i < pathsCopy.size(); i++) { - NetPath path = pathsCopy.get(i); + for (int i = 0; i < paths.size(); i++) { + NetPath path = paths.get(i); // skip paths where loss exceeds available voltage if (path.getWeight() > voltage) continue; Iterator iterator = path.getFacingIterator(); boolean pathDestThis = path.getTargetNode().getNodePos().equals(this.cable.getPipePos()); while (iterator.hasNext()) { - NetPath.FacedNetPath facedPath = - path.withFacing(iterator.next()); + NetPath.FacedNetPath facedPath = path + .withFacing(iterator.next()); if (pathDestThis && facedPath.facing == side) { // do not distribute power back into our source continue; } - IEnergyContainer dest = facedPath.getTargetTE().getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facedPath.oppositeFacing()); + IEnergyContainer dest = facedPath.getTargetTE() + .getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facedPath.oppositeFacing()); if (dest == null || dest == this) continue; if (!dest.inputsEnergy(facedPath.oppositeFacing()) || dest.getEnergyCanBeInserted() <= 0) continue; List> nodeList = facedPath.getNodeList(); DoubleList voltageCaps = new DoubleArrayList(); long pathAmperage = availableAmperage; - // loss from the first node - NetNode target = nodeList.get(0); - if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) { - paths.remove(i); - continue mainloop; - } List edgeList = facedPath.getEdgeList(); FlowConsumerList flowLimitConsumers = new FlowConsumerList<>(); - for (int j = 0; j < edgeList.size(); j++) { - NetFlowEdge edge = edgeList.get(j); + for (int j = 0; j < nodeList.size(); j++) { + NetFlowEdge edge = j == 0 ? inputEdge : edgeList.get(j - 1); + NetNode target = nodeList.get(j); // amperage capping - long max = Math.min(pathAmperage, edge.getFlowLimit(null, this.net.getGraph(), queryTick, simulator)); + long max = Math.min(pathAmperage, + edge.getFlowLimit(null, this.net.getGraph(), queryTick, simulator)); double ratio = (double) max / pathAmperage; pathAmperage = max; flowLimitConsumers.modifyRatios(ratio); - target = nodeList.get(j + 1); TileEntityCable tile = simulator == null ? (TileEntityCable) target.getHeldMTEUnsafe() : null; flowLimitConsumers.add(edge, null, this.net.getGraph(), pathAmperage, queryTick, simulator, tile != null ? amps -> { @@ -178,10 +179,13 @@ private long distributionRespectCapacity(EnumFacing side, long voltage, long amp // complete transfer this.transfer = true; // actual voltage that reaches the destination is the geometric mean of the input and all the caps - long finalVoltage = (long) GTUtility.geometricMean((double) voltage, voltageCaps.toArray(new double[]{})); - long accepted = dest.acceptEnergyFromNetwork(facedPath.oppositeFacing(), finalVoltage, pathAmperage, simulator != null); + long finalVoltage = (long) GTUtility.geometricMean((double) voltage, + voltageCaps.toArray(new double[] {})); + long accepted = dest.acceptEnergyFromNetwork(facedPath.oppositeFacing(), finalVoltage, pathAmperage, + simulator != null); this.transfer = false; - if (simulator != null) accepted = getSimulatedAccepted(destSimulationCache, facedPath.toFacingPos(), accepted); + if (simulator != null) + accepted = getSimulatedAccepted(destSimulationCache, facedPath.toFacingPos(), accepted); flowLimitConsumers.doConsumption((double) accepted / pathAmperage); availableAmperage -= accepted; @@ -204,42 +208,37 @@ private long distributionIgnoreCapacity(EnumFacing side, long voltage, long ampe Iterator iterator = path.getFacingIterator(); boolean pathDestThis = path.getTargetNode().getNodePos().equals(this.cable.getPipePos()); while (iterator.hasNext()) { - NetPath.FacedNetPath facedPath = - path.withFacing(iterator.next()); + NetPath.FacedNetPath facedPath = path + .withFacing(iterator.next()); if (pathDestThis && facedPath.facing == side) { // do not distribute power back into our source continue; } - IEnergyContainer dest = facedPath.getTargetTE().getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facedPath.oppositeFacing()); + IEnergyContainer dest = facedPath.getTargetTE() + .getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facedPath.oppositeFacing()); if (dest == null || dest == this) continue; if (!dest.inputsEnergy(facedPath.oppositeFacing()) || dest.getEnergyCanBeInserted() <= 0) continue; List> nodeList = facedPath.getNodeList(); DoubleList voltageCaps = new DoubleArrayList(); long pathAmperage = availableAmperage; - // loss from the first node - NetNode target = nodeList.get(0); - if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) continue; List edgeList = facedPath.getEdgeList(); List> flowLimitConsumers = new ObjectArrayList<>(); - List> amperageLoss = new ObjectArrayList<>(); - for (int j = 0; j < edgeList.size(); j++) { - NetFlowEdge edge = edgeList.get(j); + List> amperageLossHeat = new ObjectArrayList<>(); + for (int j = 0; j < nodeList.size(); j++) { + NetFlowEdge edge = j == 0 ? inputEdge : edgeList.get(j - 1); + NetNode target = nodeList.get(j); long flowLimit = edge.getFlowLimit(null, this.net.getGraph(), queryTick, simulator); - NetNode source = target; - target = nodeList.get(j + 1); - NetNode finalTarget = target; long finalPathAmperage = pathAmperage; if (simulator == null && finalPathAmperage != 0) { - amperageLoss.add((ratio) -> { + amperageLossHeat.add((ratio) -> { long adjustedAmperage = (long) (finalPathAmperage * ratio); if (adjustedAmperage > flowLimit) { - int heat = calculateHeat(adjustedAmperage - flowLimit, adjustedAmperage, 1) / 2; - getOrGenerateLossResult(source, heat, false); - getOrGenerateLossResult(finalTarget, heat, false); + int heat = calculateHeat(adjustedAmperage - flowLimit, adjustedAmperage, 1); + getOrGenerateLossResult(target, heat, false); } }); } @@ -258,14 +257,18 @@ private long distributionIgnoreCapacity(EnumFacing side, long voltage, long ampe if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) continue mainloop; } - long finalVoltage = (long) GTUtility.geometricMean((double) voltage, voltageCaps.toArray(new double[]{})); - long simulatedAccepted = dest.acceptEnergyFromNetwork(facedPath.oppositeFacing(), finalVoltage, availableAmperage, true); - simulatedAccepted = getSimulatedAccepted(localDestSimulationCache, facedPath.toFacingPos(), simulatedAccepted); + long finalVoltage = (long) GTUtility.geometricMean((double) voltage, + voltageCaps.toArray(new double[] {})); + long simulatedAccepted = dest.acceptEnergyFromNetwork(facedPath.oppositeFacing(), finalVoltage, + availableAmperage, true); + simulatedAccepted = getSimulatedAccepted(localDestSimulationCache, facedPath.toFacingPos(), + simulatedAccepted); if (simulator != null) - simulatedAccepted = getSimulatedAccepted(destSimulationCache, facedPath.toFacingPos(), simulatedAccepted); + simulatedAccepted = getSimulatedAccepted(destSimulationCache, facedPath.toFacingPos(), + simulatedAccepted); double ratio = (double) simulatedAccepted / availableAmperage; flowLimitConsumers.forEach(consumer -> consumer.accept(ratio)); - amperageLoss.forEach(consumer -> consumer.accept(ratio)); + amperageLossHeat.forEach(consumer -> consumer.accept(ratio)); availableAmperage -= simulatedAccepted; if (availableAmperage <= 0) return amperage; diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java index 81a553c59d9..3da6c7df9c7 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -4,8 +4,6 @@ import gregtech.api.pipenet.AbstractGroupData; import gregtech.api.pipenet.WorldPipeNetComplex; import gregtech.api.pipenet.alg.AllPathsAlgorithm; -import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; -import gregtech.api.pipenet.alg.SinglePathAlgorithm; import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.WireProperties; diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java index 0cb0419cf15..aa41496f487 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java @@ -8,7 +8,6 @@ import gregtech.api.pipenet.NodeLossResult; import gregtech.api.pipenet.block.BlockPipe; import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; -import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.WireProperties; @@ -126,16 +125,15 @@ public NodeLossResult applyHeat(int amount, boolean simulate) { } private boolean update() { - if (temperature <= getDefaultTemp()) { - isTicking = false; - } else if (getPipeType().insulationLevel >= 0 && temperature >= 1500 && GTValues.RNG.nextFloat() < 0.1) { + // thicker cables cool faster + setTemperature((int) (temperature - Math.pow(temperature - getDefaultTemp(), 0.35) * + Math.sqrt(this.getPipeType().getThickness()) * 4)); + + if (getPipeType().insulationLevel >= 0 && temperature >= 1500 && GTValues.RNG.nextFloat() < 0.1) { // insulation melted uninsulate(); isTicking = false; } - // thicker cables cool faster - setTemperature((int) (temperature - Math.pow(temperature - getDefaultTemp(), 0.35) * - Math.sqrt(this.getPipeType().getThickness()) * 4)); return isTicking; } @@ -168,13 +166,14 @@ public void setTemperature(int temperature) { if (!world.isRemote) { writeCustomData(CABLE_TEMPERATURE, buf -> buf.writeVarInt(temperature)); if (!isTicking && temperature > getDefaultTemp()) { - TaskScheduler.scheduleTask(getWorld(), this::update); isTicking = true; + TaskScheduler.scheduleTask(getWorld(), this::update); + } else if (isTicking && temperature <= getDefaultTemp()) { + isTicking = false; } } else { // TODO fix particle sometimes not rendering after world load if (temperature <= getDefaultTemp()) { - if (isParticleAlive()) particle.setExpired(); } else { diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java index 76abbe7af95..09c43eaba07 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java @@ -31,6 +31,9 @@ public class FluidNetHandler implements IFluidHandler, IPipeNetHandler { + protected static final NetNode FAKE_SOURCE = new NetNode<>( + new FluidPipeProperties(Integer.MAX_VALUE, Integer.MAX_VALUE, true, true, true, true, Integer.MAX_VALUE)); + private static final IFluidTankProperties[] EMPTY = new IFluidTankProperties[0]; private final WorldFluidPipeNet net; @@ -43,10 +46,24 @@ public class FluidNetHandler implements IFluidHandler, IPipeNetHandler { private FluidStack lastFillResource; private final Map, NodeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); + private final NetFlowEdge inputEdge; + public FluidNetHandler(WorldFluidPipeNet net, TileEntityFluidPipe pipe, EnumFacing facing) { this.net = net; this.pipe = pipe; this.facing = facing; + this.inputEdge = new NetFlowEdge(1) { + + @Override + public NetNode getSource() { + return FAKE_SOURCE; + } + + @Override + public NetNode getTarget() { + return FluidNetHandler.this.pipe.getNode(); + } + }; } public void updatePipe(TileEntityFluidPipe pipe) { @@ -84,6 +101,7 @@ public int fill(FluidStack resource, boolean doFill) { long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); // push flow through net List> paths = this.getNet().getPaths(pipe); + paths.forEach(path -> path.getEdgeList().add(0, inputEdge)); // add our fake edge for flow handling FluidStack helper = resource.copy(); if (!doFill) this.simulatorKey = AbstractNetFlowEdge.getNewSimulatorInstance(); else this.simulatorKey = null; @@ -198,13 +216,9 @@ private int fill(NetPath.FacedNetPath edgeList = routePath.getEdgeList(); FlowConsumerList flowLimitConsumers = new FlowConsumerList<>(); - // loss from the first input node - var targetResult = getOrGenerateLossResult(nodeList.get(0), resource); - double loss = targetResult.getLossFunction(); - int inputAmount = (int) (resource.amount * loss); - int outputAmount = inputAmount; + int inputAmount = resource.amount; + int outputAmount = resource.amount; - // always 1 less edge than nodes for (int i = 0; i < edgeList.size(); i++) { NetFlowEdge edge = edgeList.get(i); if (!edge.getPredicate().test(resource)) return 0; @@ -214,10 +228,8 @@ private int fill(NetPath.FacedNetPath node, - FluidStack resource) { + FluidStack resource) { var cachedResult = this.lossResultCache.get(node); if (cachedResult == null) { cachedResult = node.getData().determineFluidPassthroughResult(resource, net.getWorld(), node.getNodePos()); diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index aaaca684dc2..437073864be 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -1,10 +1,10 @@ package gregtech.common.pipelike.fluidpipe.net; import gregtech.api.cover.Cover; -import gregtech.api.pipenet.alg.AllPathsAlgorithm; -import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.pipenet.WorldPipeNetComplex; +import gregtech.api.pipenet.alg.AllPathsAlgorithm; import gregtech.api.pipenet.edge.NetFlowEdge; +import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.covers.CoverFluidFilter; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index bd2b546d1c7..ff506a9d83e 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -33,6 +33,7 @@ import java.util.Iterator; import java.util.List; +// TODO exploit flow edges for itemnet public class ItemNetHandler implements IItemHandler, IPipeNetHandler { private final WorldItemPipeNet net; From 9fc3e79dc9eb7962fac0aeb6e22ee1c37b8f0163 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 24 Jun 2024 21:13:49 -0600 Subject: [PATCH 064/157] adjust cable heating behavior --- .../material/properties/WireProperties.java | 3 +-- .../pipelike/cable/tile/TileEntityCable.java | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java index cd44ae4db97..8d9b8ce81fc 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java @@ -146,8 +146,7 @@ public void verifyProperty(MaterialProperties properties) { @Override public double getWeightFactor() { - // aren't weighted graphs great? - return this.getLossPerBlock(); + return this.getLossPerBlock() + 0.001 / this.getAmperage(); } @Override diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java index aa41496f487..07be5d453dd 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java @@ -10,6 +10,7 @@ import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.TaskScheduler; import gregtech.api.util.TextFormattingUtil; @@ -45,13 +46,12 @@ import java.util.List; import java.util.function.Consumer; -import static gregtech.api.capability.GregtechDataCodes.CABLE_TEMPERATURE; -import static gregtech.api.capability.GregtechDataCodes.UPDATE_CONNECTIONS; +import static gregtech.api.capability.GregtechDataCodes.*; public class TileEntityCable extends TileEntityMaterialPipeBase implements IDataInfoProvider { - private static final int meltTemp = 3000; + private int meltTemp = 3000; private final EnumMap handlers = new EnumMap<>(EnumFacing.class); private final PerTickLongCounter maxVoltageCounter = new PerTickLongCounter(); @@ -265,6 +265,13 @@ public int getDefaultPaintingColor() { return 0x404040; } + @Override + public void setPipeData(BlockPipe pipeBlock, Insulation insulation, + Material pipeMaterial) { + super.setPipeData(pipeBlock, insulation, pipeMaterial); + updateMeltTemperature(); + } + @Override public void receiveCustomData(int discriminator, PacketBuffer buf) { if (discriminator == CABLE_TEMPERATURE) { @@ -274,9 +281,15 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { if (isParticleAlive() && discriminator == UPDATE_CONNECTIONS) { particle.updatePipeBoxes(getPipeBoxes()); } + if (discriminator == UPDATE_PIPE_MATERIAL) updateMeltTemperature(); } } + protected void updateMeltTemperature() { + this.meltTemp = this.getPipeMaterial().getBlastTemperature(); + if (this.meltTemp == 0) this.meltTemp = 1000; + } + @SideOnly(Side.CLIENT) public boolean isParticleAlive() { return particle != null && particle.isAlive(); From a9203463f365a53a024ddd0d13c6649a157ee4a7 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 26 Jun 2024 14:57:30 -0600 Subject: [PATCH 065/157] fluid net improvements --- .../api/pipenet/edge/AbstractNetFlowEdge.java | 7 + .../api/pipenet/edge/NetFlowEdge.java | 7 + .../api/pipenet/edge/NetFlowSharedEdge.java | 7 + .../properties/FluidPipeProperties.java | 10 +- .../gregtech/api/util/FluidTestObject.java | 4 + .../pipelike/fluidpipe/BlockFluidPipe.java | 51 ++++--- .../fluidpipe/net/FluidNetHandler.java | 17 ++- .../pipelike/fluidpipe/net/PipeTankList.java | 127 ------------------ .../fluidpipe/tile/TileEntityFluidPipe.java | 97 ++++--------- 9 files changed, 92 insertions(+), 235 deletions(-) delete mode 100644 src/main/java/gregtech/common/pipelike/fluidpipe/net/PipeTankList.java diff --git a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java index 9a9cbeb7b55..18c5b57de8d 100644 --- a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java @@ -8,6 +8,7 @@ import org.jgrapht.Graph; import java.lang.ref.WeakReference; +import java.util.Set; import java.util.WeakHashMap; public abstract class AbstractNetFlowEdge> extends NetEdge { @@ -66,6 +67,10 @@ public & IPipeType, NDT extends INodeData> void c getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); } + public Set getActiveChannels(@Nullable ChannelSimulatorKey simulator, long queryTick) { + return getChannels(simulator).getActiveChannels(queryTick); + } + protected abstract AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, ChannelSimulatorKey simulator); @@ -97,6 +102,8 @@ abstract & IPipeType, NDT extends INodeData> void Graph, E> graph, long amount, long queryTick); + + abstract Set getActiveChannels(long queryTick); } public static final class ChannelSimulatorKey { diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java index 0886dfe6a12..ec2db2328e1 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java @@ -9,6 +9,7 @@ import org.jgrapht.Graph; import java.util.List; +import java.util.Set; public class NetFlowEdge extends AbstractNetFlowEdge { @@ -130,5 +131,11 @@ public void recalculateFlowLimits(long queryTick) { } this.lastQueryTick = queryTick; } + + @Override + Set getActiveChannels(long queryTick) { + recalculateFlowLimits(queryTick); + return map.keySet(); + } } } diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java index 05697140c88..79a182b4cd7 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java @@ -11,6 +11,7 @@ import org.jgrapht.Graph; import java.util.List; +import java.util.Set; public class NetFlowSharedEdge extends AbstractNetFlowEdge { @@ -140,5 +141,11 @@ private void boundCapacity() { if (this.sharedCapacity > this.maxCapacity) this.sharedCapacity = this.maxCapacity; else if (this.sharedCapacity < 0) this.sharedCapacity = 0; } + + @Override + Set getActiveChannels(long queryTick) { + recalculateFlowLimits(queryTick); + return map.keySet(); + } } } diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 1e849ea40b9..91987dfce87 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -220,7 +220,7 @@ public NodeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBu mult *= 0.9; // apply heat damage in area surrounding the pipe - damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + damageAction = tile -> tile.dealAreaDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, stack.getFluid().getTemperature(stack), 2.0F, 10)); // chance to do a small explosion @@ -244,7 +244,7 @@ public NodeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBu mult *= 0.75; // apply chemical damage in area surrounding the pipe - damageAction = tile -> tile.dealDamage(1, entity -> EntityDamageUtil.applyChemicalDamage(entity, 2)); + damageAction = tile -> tile.dealAreaDamage(1, entity -> EntityDamageUtil.applyChemicalDamage(entity, 2)); // 1/10 chance to void everything and destroy the pipe if (GTValues.RNG.nextInt(10) == 0) { @@ -266,7 +266,7 @@ public NodeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBu } // apply heat damage in area surrounding the pipe - damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + damageAction = tile -> tile.dealAreaDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, stack.getFluid().getTemperature(stack), 2.0F, 10)); // 1/10 chance to void everything and burn the pipe @@ -284,7 +284,7 @@ public NodeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBu mult *= 0.75; // apply frost damage in area surrounding the pipe - damageAction = tile -> tile.dealDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + damageAction = tile -> tile.dealAreaDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, stack.getFluid().getTemperature(stack), 2.0F, 10)); // 1/10 chance to void everything and freeze the pipe @@ -300,7 +300,7 @@ public NodeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBu // don't go fetch it from the world as this 9 times out of 10 means loading a chunk unnecessarily. IPipeTile tile = nodeG.getHeldMTEUnsafe(); if (tile instanceof TileEntityFluidPipe pipe) { - pipe.playDamageSound(); + pipe.playLossSound(); particleActions.forEach(Runnable::run); finalDamageAction.accept(pipe); } diff --git a/src/main/java/gregtech/api/util/FluidTestObject.java b/src/main/java/gregtech/api/util/FluidTestObject.java index e875fa35983..b89e9788409 100644 --- a/src/main/java/gregtech/api/util/FluidTestObject.java +++ b/src/main/java/gregtech/api/util/FluidTestObject.java @@ -16,6 +16,10 @@ public FluidTestObject(FluidStack stack) { this.tag = stack.tag; } + public FluidStack recombine() { + return new FluidStack(fluid, 1, tag); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java index 4f13817f613..e857fed7f59 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java @@ -1,6 +1,8 @@ package gregtech.common.pipelike.fluidpipe; +import gregtech.api.fluids.FluidConstants; import gregtech.api.items.toolitem.ToolClasses; +import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.material.BlockMaterialPipe; import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; @@ -9,6 +11,7 @@ import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.util.EntityDamageUtil; +import gregtech.api.util.FluidTestObject; import gregtech.client.renderer.pipe.FluidPipeRenderer; import gregtech.client.renderer.pipe.PipeRenderer; import gregtech.common.creativetab.GTCreativeTabs; @@ -16,6 +19,8 @@ import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipeTickable; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.creativetab.CreativeTabs; @@ -29,8 +34,10 @@ import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -40,6 +47,7 @@ import java.util.Collection; import java.util.Collections; +import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; @@ -136,34 +144,25 @@ public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @No if (worldIn.isRemote) return; TileEntityFluidPipe pipe = (TileEntityFluidPipe) getPipeTileEntity(worldIn, pos); if (pipe.getFrameMaterial() == null && pipe.getOffsetTimer() % 10 == 0) { - if (entityIn instanceof EntityLivingBase) { - // TODO detection for what fluids have flowed through a pipe recently - if (pipe.getFluidTanks().length > 1) { - // apply temperature damage for the hottest and coldest pipe (multi fluid pipes) - int maxTemperature = Integer.MIN_VALUE; - int minTemperature = Integer.MAX_VALUE; - for (FluidTank tank : pipe.getFluidTanks()) { - if (tank.getFluid() != null && tank.getFluid().amount > 0) { - maxTemperature = Math.max(maxTemperature, - tank.getFluid().getFluid().getTemperature(tank.getFluid())); - minTemperature = Math.min(minTemperature, - tank.getFluid().getFluid().getTemperature(tank.getFluid())); - } - } - if (maxTemperature != Integer.MIN_VALUE) { - EntityDamageUtil.applyTemperatureDamage((EntityLivingBase) entityIn, maxTemperature, 1.0F, 5); - } - if (minTemperature != Integer.MAX_VALUE) { - EntityDamageUtil.applyTemperatureDamage((EntityLivingBase) entityIn, minTemperature, 1.0F, 5); - } - } else { - FluidTank tank = pipe.getFluidTanks()[0]; - if (tank.getFluid() != null && tank.getFluid().amount > 0) { - // Apply temperature damage for the pipe (single fluid pipes) - EntityDamageUtil.applyTemperatureDamage((EntityLivingBase) entityIn, - tank.getFluid().getFluid().getTemperature(), 1.0F, 5); + if (entityIn instanceof EntityLivingBase living) { + NetNode node = pipe.getNode(); + var net = node.getGroupSafe().net; + Set fluids = new ObjectOpenHashSet<>(); + for (NetFlowEdge edge : net.getGraph().edgesOf(node)) { + for (Object obj : edge.getActiveChannels(null, + FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter())) { + if (obj instanceof FluidTestObject tester) fluids.add(tester); } } + int maxTemp = FluidConstants.ROOM_TEMPERATURE; + int minTemp = FluidConstants.ROOM_TEMPERATURE; + for (FluidTestObject fluid : fluids) { + int temp = fluid.fluid.getTemperature(fluid.recombine()); + maxTemp = Math.max(temp, maxTemp); + minTemp = Math.min(temp, minTemp); + } + EntityDamageUtil.applyTemperatureDamage(living, maxTemp, 1.0F, 5); + EntityDamageUtil.applyTemperatureDamage(living, minTemp, 1.0F, 5); } } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java index 09c43eaba07..e2b5664530f 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java @@ -99,9 +99,7 @@ public int fill(FluidStack resource, boolean doFill) { FluidTestObject testObject = new FluidTestObject(resource); long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - // push flow through net List> paths = this.getNet().getPaths(pipe); - paths.forEach(path -> path.getEdgeList().add(0, inputEdge)); // add our fake edge for flow handling FluidStack helper = resource.copy(); if (!doFill) this.simulatorKey = AbstractNetFlowEdge.getNewSimulatorInstance(); else this.simulatorKey = null; @@ -210,6 +208,7 @@ private int fill(NetPath.FacedNetPath> nodeList = routePath.getNodeList(); @@ -219,8 +218,8 @@ private int fill(NetPath.FacedNetPath { - - private final TileEntityFluidPipe pipe; - private final FluidTank[] tanks; - private IFluidTankProperties[] properties; - private final EnumFacing facing; - - public PipeTankList(TileEntityFluidPipe pipe, EnumFacing facing, FluidTank... fluidTanks) { - this.tanks = fluidTanks; - this.pipe = pipe; - this.facing = facing; - } - - @Override - public IFluidTankProperties[] getTankProperties() { - if (properties == null) { - properties = new IFluidTankProperties[tanks.length]; - for (int i = 0; i < tanks.length; i++) { - properties[i] = new FluidTankPropertiesWrapper(tanks[i]); - } - } - return properties; - } - - private int findChannel(FluidStack stack) { - if (stack == null || tanks == null) - return -1; - int empty = -1; - for (int i = tanks.length - 1; i >= 0; i--) { - FluidStack f = tanks[i].getFluid(); - if (f == null) - empty = i; - else if (f.isFluidEqual(stack)) - return i; - } - return empty; - } - - @Override - public int fill(FluidStack resource, boolean doFill) { - int channel; - if (pipe.isFaceBlocked(facing) || resource == null || resource.amount <= 0 || - (channel = findChannel(resource)) < 0) - return 0; - - return fill(resource, doFill, channel); - } - - private int fullCapacity() { - return tanks.length * pipe.getCapacityPerTank(); - } - - private int fill(FluidStack resource, boolean doFill, int channel) { - if (channel >= tanks.length) return 0; - FluidTank tank = tanks[channel]; - FluidStack currentFluid = tank.getFluid(); - - if (currentFluid == null || currentFluid.amount <= 0) { - FluidStack newFluid = resource.copy(); - newFluid.amount = Math.min(pipe.getCapacityPerTank(), newFluid.amount); - if (doFill) { - tank.setFluid(newFluid); - pipe.checkAndDestroy(newFluid); - } - return newFluid.amount; - } - if (currentFluid.isFluidEqual(resource)) { - int toAdd = Math.min(tank.getCapacity() - currentFluid.amount, resource.amount); - if (toAdd > 0) { - if (doFill) { - currentFluid.amount += toAdd; - pipe.checkAndDestroy(currentFluid); - } - return toAdd; - } - } - - return 0; - } - - @Nullable - @Override - public FluidStack drain(int maxDrain, boolean doDrain) { - if (maxDrain <= 0) return null; - for (FluidTank tank : tanks) { - FluidStack drained = tank.drain(maxDrain, doDrain); - if (drained != null) return drained; - } - return null; - } - - @Nullable - @Override - public FluidStack drain(FluidStack fluidStack, boolean doDrain) { - if (fluidStack == null || fluidStack.amount <= 0) return null; - fluidStack = fluidStack.copy(); - for (FluidTank tank : tanks) { - FluidStack drained = tank.drain(fluidStack, doDrain); - if (drained != null) return drained; - } - return null; - } - - @Override - @NotNull - public Iterator iterator() { - return Arrays.stream(tanks).iterator(); - } -} diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java index 0f10e8e03cd..210c0d3cb09 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java @@ -5,9 +5,9 @@ import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.api.util.TaskScheduler; import gregtech.common.pipelike.fluidpipe.FluidPipeType; import gregtech.common.pipelike.fluidpipe.net.FluidNetHandler; -import gregtech.common.pipelike.fluidpipe.net.PipeTankList; import gregtech.common.pipelike.fluidpipe.net.WorldFluidPipeNet; import net.minecraft.block.state.IBlockState; @@ -39,11 +39,7 @@ public class TileEntityFluidPipe extends TileEntityMaterialPipeBase { - // old code to maintain compat with old worlds // - private PipeTankList pipeTankList; - private final EnumMap tankLists = new EnumMap<>(EnumFacing.class); - private FluidTank[] fluidTanks; - // ------------------------------------------- // + private FluidTank[] fluidTanks = null; private final EnumMap handlers = new EnumMap<>(EnumFacing.class); private FluidNetHandler defaultHandler; @@ -97,21 +93,7 @@ public void transferDataFrom(IPipeTile= this.nextSoundTime) { getPipeWorld().playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); @@ -119,7 +101,7 @@ public void playDamageSound() { } } - public void dealDamage(int size, Consumer damageFunction) { + public void dealAreaDamage(int size, Consumer damageFunction) { long timer = getOffsetTimer(); if (timer >= this.nextDamageTime) { List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, @@ -129,51 +111,6 @@ public void dealDamage(int size, Consumer damageFunction) { } } - public FluidStack getContainedFluid(int channel) { - if (channel < 0 || channel >= getFluidTanks().length) return null; - return getFluidTanks()[channel].getFluid(); - } - - private void createTanksList() { - fluidTanks = new FluidTank[getNodeData().getTanks()]; - for (int i = 0; i < getNodeData().getTanks(); i++) { - fluidTanks[i] = new FluidTank(getCapacityPerTank()); - } - pipeTankList = new PipeTankList(this, null, fluidTanks); - for (EnumFacing facing : EnumFacing.VALUES) { - tankLists.put(facing, new PipeTankList(this, facing, fluidTanks)); - } - } - - public PipeTankList getTankList() { - if (pipeTankList == null || fluidTanks == null) { - createTanksList(); - } - return pipeTankList; - } - - public PipeTankList getTankList(EnumFacing facing) { - if (tankLists.isEmpty() || fluidTanks == null) { - createTanksList(); - } - return tankLists.getOrDefault(facing, pipeTankList); - } - - public FluidTank[] getFluidTanks() { - if (pipeTankList == null || fluidTanks == null) { - createTanksList(); - } - return fluidTanks; - } - - public FluidStack[] getContainedFluids() { - FluidStack[] fluids = new FluidStack[getFluidTanks().length]; - for (int i = 0; i < fluids.length; i++) { - fluids[i] = fluidTanks[i].getFluid(); - } - return fluids; - } - @Override public Class getPipeTypeClass() { return FluidPipeType.class; @@ -219,9 +156,10 @@ public static void spawnParticles(World worldIn, BlockPos pos, EnumFacing direct @Override public NBTTagCompound writeToNBT(@NotNull NBTTagCompound nbt) { super.writeToNBT(nbt); + if (fluidTanks == null) return nbt; NBTTagList list = new NBTTagList(); - for (int i = 0; i < getFluidTanks().length; i++) { - FluidStack stack1 = getContainedFluid(i); + for (FluidTank fluidTank : fluidTanks) { + FluidStack stack1 = fluidTank.getFluid(); NBTTagCompound fluidTag = new NBTTagCompound(); if (stack1 == null || stack1.amount <= 0) fluidTag.setBoolean("isNull", true); @@ -237,15 +175,32 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound nbt) { public void readFromNBT(@NotNull NBTTagCompound nbt) { super.readFromNBT(nbt); if (!nbt.hasKey("Fluids")) return; + fluidTanks = new FluidTank[getNodeData().getTanks()]; + for (int i = 0; i < getNodeData().getTanks(); i++) { + fluidTanks[i] = new FluidTank(getCapacityPerTank()); + } NBTTagList list = (NBTTagList) nbt.getTag("Fluids"); - createTanksList(); for (int i = 0; i < list.tagCount(); i++) { NBTTagCompound tag = list.getCompoundTagAt(i); if (!tag.getBoolean("isNull")) { FluidStack stack = FluidStack.loadFluidStackFromNBT(tag); if (stack == null) continue; - // TODO old fluid in pipes handling + fluidTanks[i].setFluid(stack); } } + TaskScheduler.scheduleTask(world, this::pushFluids); + } + + private boolean pushFluids() { + boolean remaining = false; + for (FluidTank tank : fluidTanks) { + if (tank == null || tank.getFluidAmount() == 0) continue; + assert tank.getFluid() != null; + int fill = defaultHandler.fill(tank.getFluid(), true); + if (fill <= tank.getFluidAmount()) remaining = true; + tank.getFluid().amount -= fill; + } + if (!remaining) fluidTanks = null; + return remaining; } } From 6adfa6b51bdb7e4577e9f52caa660df2acff3029 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 26 Jun 2024 18:30:54 -0600 Subject: [PATCH 066/157] iteratorification --- .../java/gregtech/api/pipenet/NetNode.java | 19 +-- .../java/gregtech/api/pipenet/NetPath.java | 9 +- .../api/pipenet/WorldPipeNetBase.java | 116 ++++++++++++++++-- .../api/pipenet/WorldPipeNetComplex.java | 4 +- .../api/pipenet/WorldPipeNetSimple.java | 4 +- .../api/pipenet/alg/AllPathsAlgorithm.java | 75 +++++++++-- .../api/pipenet/alg/INetAlgorithm.java | 17 ++- .../pipenet/alg/ShortestPathsAlgorithm.java | 15 +-- .../api/pipenet/alg/SinglePathAlgorithm.java | 7 +- .../pipenet/alg/iter/ICacheableIterator.java | 10 ++ .../alg/iter/SimpleCacheableIterator.java | 49 ++++++++ .../api/pipenet/edge/AbstractNetFlowEdge.java | 53 +++----- .../java/gregtech/api/pipenet/edge/IEdge.java | 4 +- .../gregtech/api/pipenet/edge/NetEdge.java | 10 +- .../api/pipenet/edge/NetFlowEdge.java | 6 +- .../api/pipenet/edge/NetFlowSharedEdge.java | 6 +- .../api/pipenet/edge/SimulatorKey.java | 26 ++++ .../api/pipenet/edge/util/FlowConsumer.java | 9 +- .../pipenet/edge/util/FlowConsumerList.java | 7 +- .../predicate/AbstractEdgePredicate.java | 3 +- .../pipenet/predicate/BasicEdgePredicate.java | 2 +- .../predicate}/FluidTestObject.java | 4 +- .../predicate/IPredicateTestObject.java | 4 + .../api/pipenet/predicate/ItemTestObject.java | 37 ++++++ .../pipelike/cable/net/EnergyNetHandler.java | 32 +++-- .../pipelike/fluidpipe/BlockFluidPipe.java | 4 +- .../fluidpipe/net/FluidEdgePredicate.java | 7 +- .../fluidpipe/net/FluidNetHandler.java | 19 +-- .../itempipe/net/ItemEdgePredicate.java | 7 +- .../pipelike/itempipe/net/ItemNetHandler.java | 19 +-- .../pipelike/laser/net/LaserNetHandler.java | 8 +- .../optical/net/OpticalNetHandler.java | 15 ++- 32 files changed, 450 insertions(+), 157 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/alg/iter/ICacheableIterator.java create mode 100644 src/main/java/gregtech/api/pipenet/alg/iter/SimpleCacheableIterator.java create mode 100644 src/main/java/gregtech/api/pipenet/edge/SimulatorKey.java rename src/main/java/gregtech/api/{util => pipenet/predicate}/FluidTestObject.java (88%) create mode 100644 src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java create mode 100644 src/main/java/gregtech/api/pipenet/predicate/ItemTestObject.java diff --git a/src/main/java/gregtech/api/pipenet/NetNode.java b/src/main/java/gregtech/api/pipenet/NetNode.java index 34571fa11a8..3a8a55fa7dd 100644 --- a/src/main/java/gregtech/api/pipenet/NetNode.java +++ b/src/main/java/gregtech/api/pipenet/NetNode.java @@ -1,5 +1,6 @@ package gregtech.api.pipenet; +import gregtech.api.pipenet.alg.iter.ICacheableIterator; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; @@ -16,7 +17,7 @@ import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; -import java.util.List; +import java.util.Iterator; import java.util.Map; import java.util.Objects; @@ -56,7 +57,7 @@ public final class NetNode & IPipeType group = null; @Nullable - private List> pathCache = null; + private ICacheableIterator> pathCache = null; public NetNode(NodeDataType data, IPipeTile heldMTE, WorldPipeNetBase net) { @@ -262,22 +263,26 @@ public NodeDataType getData() { return data; } - public boolean isActive() { + public boolean validTarget() { + if (!isActive) return false; + this.net.markNodeAsActive(this, this.net.shouldNodeBeActive(this)); return isActive; } @Nullable - public List> getPathCache() { - return pathCache; + public Iterator> getPathCache() { + if (pathCache == null) return null; + return pathCache.newIterator(); } /** - * Sets the path cache to the provided cache. Returns the provided cache for convenience. + * Sets the path cache to the provided cache. Returns a new iterator from the cache for convenience. * * @param pathCache The new cache. * @return The new cache. */ - public List> setPathCache(List> pathCache) { + public Iterator> setPathCache( + ICacheableIterator> pathCache) { this.pathCache = pathCache; return getPathCache(); } diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index 37ec8b24816..8b4443f8001 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -2,6 +2,7 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.predicate.IPredicateTestObject; import gregtech.api.util.FacingPos; import net.minecraft.tileentity.TileEntity; @@ -126,9 +127,9 @@ public NodeDataType getMinData() { return data; } - public boolean checkPredicate(Object o) { + public boolean checkPredicate(IPredicateTestObject testObject) { for (NetEdge edge : this.edgeList) { - if (!edge.getPredicate().test(o)) return false; + if (!edge.getPredicate().test(testObject)) return false; } return true; } @@ -177,8 +178,8 @@ public NDT getMinData() { return path.getMinData(); } - public boolean checkPredicate(Object o) { - return path.checkPredicate(o); + public boolean checkPredicate(IPredicateTestObject testObject) { + return path.checkPredicate(testObject); } public FacingPos toFacingPos() { diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java index dd1d72b7a23..57738d557a3 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java @@ -1,11 +1,14 @@ package gregtech.api.pipenet; import gregtech.api.cover.Cover; +import gregtech.api.pipenet.alg.iter.ICacheableIterator; import gregtech.api.pipenet.alg.INetAlgorithm; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.SimulatorKey; import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.pipenet.predicate.BasicEdgePredicate; +import gregtech.api.pipenet.predicate.IPredicateTestObject; import gregtech.api.pipenet.predicate.IShutteredEdgePredicate; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -25,15 +28,21 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; +import org.jgrapht.graph.SimpleDirectedWeightedGraph; +import org.jgrapht.graph.SimpleWeightedGraph; import java.lang.ref.WeakReference; +import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Collectors; public abstract class WorldPipeNetBase, @@ -45,7 +54,7 @@ public abstract class WorldPipeNetBase builders = null; private WeakReference worldRef = new WeakReference<>(null); - protected final Graph, Edge> pipeGraph; + protected final ICustomGraph pipeGraph; protected final Map> pipeMap = new Object2ObjectOpenHashMap<>(); private final INetAlgorithm.NetAlgorithmWrapper netAlgorithm; @@ -54,15 +63,16 @@ public abstract class WorldPipeNetBase, INetAlgorithm> algorithmBuilder, - Graph, Edge> graph) { + ICustomGraph graph) { super(name); + graph.setOwningNet(this); this.pipeGraph = graph; this.netAlgorithm = new INetAlgorithm.NetAlgorithmWrapper<>(); this.isDirected = isDirected; this.algorithmBuilder = algorithmBuilder; } - public Graph, Edge> getGraph() { + public ICustomGraph getGraph() { return this.pipeGraph; } @@ -112,7 +122,7 @@ protected void onWorldSet() { * @param tile The {@link TileEntityPipeBase} that paths are being requested for * @return the ordered list of paths associated with the {@link TileEntityPipeBase} */ - public List> getPaths(TileEntityPipeBase tile) { + public Iterator> getPaths(TileEntityPipeBase tile) { return getPaths(this.pipeMap.get(tile.getPipePos()), tile); } @@ -122,23 +132,25 @@ public List> getPaths(TileEntityPipeBase

> getPaths(BlockPos pos) { + public Iterator> getPaths(BlockPos pos) { return getPaths(this.pipeMap.get(pos), null); } - public List> getPaths(@Nullable NetNode node, + public Iterator> getPaths(@Nullable NetNode node, @Nullable TileEntityPipeBase tile) { - if (node == null) return new ObjectArrayList<>(); + if (node == null) return Collections.emptyIterator(); node.setHeldMTE(tile); if (!this.hasValidAlg()) this.rebuildNetAlgorithm(); - List> cache = node.getPathCache(); + Iterator> cache = node.getPathCache(); if (cache != null) return cache; - List> list = this.netAlgorithm.getPathsList(node); - return node.setPathCache(list); + Iterator> iter = this.netAlgorithm.getPathsIterator(node); + if (iter instanceof ICacheableIterator> cacheable) { + return node.setPathCache(cacheable); + } else return iter; } /** @@ -522,4 +534,88 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { * Used for reading persistent node data */ protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); + + public interface ICustomGraph & IPipeType, NDT extends INodeData, E extends NetEdge> extends Graph, E> { + + @ApiStatus.Internal + void setOwningNet(WorldPipeNetBase net); + + void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, long queryTick); + } + + static class CustomDirectedGraph & IPipeType, NDT extends INodeData, E extends NetEdge> extends SimpleDirectedWeightedGraph, E> implements ICustomGraph { + + private WorldPipeNetBase net = null; + + private IPredicateTestObject testObject; + private SimulatorKey simulator; + private long queryTick; + + @Override + public void setOwningNet(WorldPipeNetBase net) { + if (this.net != null) throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); + this.net = net; + } + + @Override + public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, + long queryTick) { + this.testObject = testObject; + this.simulator = simulator; + this.queryTick = queryTick; + } + + public CustomDirectedGraph(Class edgeClass) { + super(edgeClass); + } + + public CustomDirectedGraph(Supplier> vertexSupplier, Supplier edgeSupplier) { + super(vertexSupplier, edgeSupplier); + } + + @Override + public double getEdgeWeight(E edge) { + if (net.netAlgorithm.supportsDynamicWeights()) { + return edge.getPredicate().test(testObject) ? edge.getWeight(testObject, simulator, queryTick) : Double.POSITIVE_INFINITY; + } else return super.getEdgeWeight(edge); + } + } + + static class CustomUndirectedGraph & IPipeType, NDT extends INodeData, E extends NetEdge> extends SimpleWeightedGraph, E> implements ICustomGraph { + + private WorldPipeNetBase net = null; + + private IPredicateTestObject testObject; + private SimulatorKey simulator; + private long queryTick; + + @Override + public void setOwningNet(WorldPipeNetBase net) { + if (this.net != null) throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); + this.net = net; + } + + @Override + public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, + long queryTick) { + this.testObject = testObject; + this.simulator = simulator; + this.queryTick = queryTick; + } + + public CustomUndirectedGraph(Class edgeClass) { + super(edgeClass); + } + + public CustomUndirectedGraph(Supplier> vertexSupplier, Supplier edgeSupplier) { + super(vertexSupplier, edgeSupplier); + } + + @Override + public double getEdgeWeight(E edge) { + if (net.netAlgorithm.supportsDynamicWeights()) { + return edge.getPredicate().test(testObject) ? edge.getWeight(testObject, simulator, queryTick) : Double.POSITIVE_INFINITY; + } else return super.getEdgeWeight(edge); + } + } } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java index fae9a9c67e3..1f74b79b347 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java @@ -47,7 +47,7 @@ public WorldPipeNetComplex(String name, boolean isDirected, boolean isSinglePath */ public WorldPipeNetComplex(String name, boolean isDirected, Supplier edgeSupplier, Function, INetAlgorithm> algorithmBuilder) { - super(name, isDirected, algorithmBuilder, isDirected ? new SimpleDirectedWeightedGraph<>(null, edgeSupplier) : - new SimpleWeightedGraph<>(null, edgeSupplier)); + super(name, isDirected, algorithmBuilder, isDirected ? new CustomDirectedGraph<>(null, edgeSupplier) : + new CustomUndirectedGraph<>(null, edgeSupplier)); } } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java index 810851c00ec..02a72e77fcd 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java @@ -40,7 +40,7 @@ public WorldPipeNetSimple(String name, boolean isDirected, boolean isSinglePath) */ public WorldPipeNetSimple(String name, boolean isDirected, Function, INetAlgorithm> algorithmBuilder) { - super(name, isDirected, algorithmBuilder, isDirected ? new SimpleDirectedWeightedGraph<>(NetEdge.class) : - new SimpleWeightedGraph<>(NetEdge.class)); + super(name, isDirected, algorithmBuilder, isDirected ? new CustomDirectedGraph<>(NetEdge.class) : + new CustomUndirectedGraph<>(NetEdge.class)); } } diff --git a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java index ae806e28c47..74f15540606 100644 --- a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java @@ -4,20 +4,21 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.WorldPipeNetBase; +import gregtech.api.pipenet.alg.iter.ICacheableIterator; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jgrapht.alg.shortestpath.AllDirectedPaths; +import org.jgrapht.alg.shortestpath.DijkstraManyToManyShortestPaths; import java.util.Collections; import java.util.Comparator; -import java.util.List; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; -public class AllPathsAlgorithm & IPipeType, NDT extends INodeData, - E extends NetEdge> extends AllDirectedPaths, E> implements INetAlgorithm { +public class AllPathsAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> extends DijkstraManyToManyShortestPaths, E> implements INetAlgorithm { public AllPathsAlgorithm(WorldPipeNetBase pipenet) { super(pipenet.getGraph()); @@ -25,11 +26,65 @@ public AllPathsAlgorithm(WorldPipeNetBase pipenet) { } @Override - public List> getPathsList(NetNode source) { + public Iterator> getPathsIterator(NetNode source) { Set> searchSpace = source.getGroupSafe().getNodes().stream() - .filter(NetNode::isActive).collect(Collectors.toSet()); - return getAllPaths(Collections.singleton(source), searchSpace, true, (int) Short.MAX_VALUE) - .stream().map(NetPath::new).sorted(Comparator.comparingDouble(NetPath::getWeight)) - .collect(Collectors.toCollection(ObjectArrayList::new)); + .filter(NetNode::validTarget).filter(node -> !source.equals(node)).collect(Collectors.toSet()); + return new LimitedIterator(source, searchSpace); + } + + @Override + public boolean supportsDynamicWeights() { + return true; + } + + protected class LimitedIterator implements ICacheableIterator> { + + private static final int MAX_ITERATIONS = 100; + + private final NetNode source; + private final Set> searchSpace; + + private int iterationCount = 0; + private NetPath cachedNext; + + public LimitedIterator(NetNode source, Set> searchSpace) { + this.source = source; + this.searchSpace = searchSpace; + } + + @Override + public ICacheableIterator> newCacheableIterator() { + return new LimitedIterator(source, searchSpace); + } + + @Override + public Iterator> newIterator() { + return new LimitedIterator(source, searchSpace); + } + + @Override + public boolean hasNext() { + if (cachedNext == null && iterationCount < MAX_ITERATIONS) calculateNext(); + return cachedNext != null; + } + + @Override + public NetPath next() { + if (!hasNext()) throw new NoSuchElementException(); + var temp = cachedNext; + cachedNext = null; + return temp; + } + + private void calculateNext() { + iterationCount++; + if (iterationCount == 1) { + cachedNext = new NetPath<>(source); + return; + } + var paths = getManyToManyPaths(Collections.singleton(source), searchSpace); + cachedNext = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) + .map(NetPath::new).min(Comparator.comparingDouble(NetPath::getWeight)).orElse(null); + } } } diff --git a/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java index daa72eb288f..89e3658508e 100644 --- a/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java @@ -6,12 +6,16 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; +import java.util.Iterator; import java.util.List; -@FunctionalInterface public interface INetAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> { - List> getPathsList(NetNode source); + Iterator> getPathsIterator(NetNode source); + + default boolean supportsDynamicWeights() { + return false; + } class NetAlgorithmWrapper & IPipeType, NodeDataType extends INodeData, E extends NetEdge> { @@ -26,9 +30,14 @@ public INetAlgorithm getAlg() { return alg; } - public List> getPathsList(NetNode source) { + public boolean supportsDynamicWeights() { + if (alg == null) return false; + return alg.supportsDynamicWeights(); + } + + public Iterator> getPathsIterator(NetNode source) { if (alg == null) return null; - return alg.getPathsList(source); + return alg.getPathsIterator(source); } } } diff --git a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java index 5ea66527255..df6f689efe4 100644 --- a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java @@ -4,6 +4,7 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.WorldPipeNetBase; +import gregtech.api.pipenet.alg.iter.SimpleCacheableIterator; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; @@ -12,7 +13,7 @@ import java.util.Collections; import java.util.Comparator; -import java.util.List; +import java.util.Iterator; import java.util.Set; import java.util.stream.Collectors; @@ -25,19 +26,19 @@ public ShortestPathsAlgorithm(WorldPipeNetBase pipenet) { } @Override - public List> getPathsList(NetNode source) { + public Iterator> getPathsIterator(NetNode source) { if (!graph.containsVertex(source)) { throw new IllegalArgumentException("Graph must contain the source vertex"); } // if the source has no group, it has no paths other than the path to itself. - if (source.getGroupUnsafe() == null) return Collections.singletonList(new NetPath<>(source)); + if (source.getGroupUnsafe() == null) return Collections.singletonList(new NetPath<>(source)).iterator(); Set> searchSpace = source.getGroupSafe().getNodes().stream() - .filter(NetNode::isActive).collect(Collectors.toSet()); + .filter(NetNode::validTarget).collect(Collectors.toSet()); ManyToManyShortestPaths, E> manyToManyPaths = getManyToManyPaths( Collections.singleton(source), searchSpace); - return searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)).map(NetPath::new) - .sorted(Comparator.comparingDouble(NetPath::getWeight)) - .collect(Collectors.toCollection(ObjectArrayList::new)); + return new SimpleCacheableIterator<>(searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)) + .map(NetPath::new).sorted(Comparator.comparingDouble(NetPath::getWeight)) + .collect(Collectors.toCollection(ObjectArrayList::new))); } } diff --git a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java index b0deaceb450..f0420188d8c 100644 --- a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java @@ -4,6 +4,7 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.WorldPipeNetBase; +import gregtech.api.pipenet.alg.iter.SimpleCacheableIterator; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; @@ -27,7 +28,7 @@ public SinglePathAlgorithm(WorldPipeNetBase pipenet) { } @Override - public List> getPathsList(NetNode source) { + public Iterator> getPathsIterator(NetNode source) { if (!this.graph.containsVertex(source)) { throw new IllegalArgumentException("Graph must contain the source vertex"); } @@ -57,7 +58,7 @@ public List> getPathsList(NetNode source) { nodes.add(node); sumWeight += node.getData().getWeightFactor(); } - if (!valid) return Collections.emptyList(); - return ImmutableList.of(new NetPath<>(nodes, edges, sumWeight)); + if (!valid) return Collections.emptyIterator(); + return new SimpleCacheableIterator<>(ImmutableList.of(new NetPath<>(nodes, edges, sumWeight))); } } diff --git a/src/main/java/gregtech/api/pipenet/alg/iter/ICacheableIterator.java b/src/main/java/gregtech/api/pipenet/alg/iter/ICacheableIterator.java new file mode 100644 index 00000000000..adcf2fe6695 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/alg/iter/ICacheableIterator.java @@ -0,0 +1,10 @@ +package gregtech.api.pipenet.alg.iter; + +import java.util.Iterator; + +public interface ICacheableIterator extends Iterator { + + ICacheableIterator newCacheableIterator(); + + Iterator newIterator(); +} diff --git a/src/main/java/gregtech/api/pipenet/alg/iter/SimpleCacheableIterator.java b/src/main/java/gregtech/api/pipenet/alg/iter/SimpleCacheableIterator.java new file mode 100644 index 00000000000..3b1cc8c2fe7 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/alg/iter/SimpleCacheableIterator.java @@ -0,0 +1,49 @@ +package gregtech.api.pipenet.alg.iter; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import java.util.Collection; +import java.util.Iterator; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class SimpleCacheableIterator implements ICacheableIterator { + + private final Iterable prototype; + private final Iterator backingIterator; + + public SimpleCacheableIterator(Iterable prototype) { + this.prototype = prototype; + this.backingIterator = prototype.iterator(); + } + + @Override + public SimpleCacheableIterator newCacheableIterator() { + return new SimpleCacheableIterator<>(prototype); + } + + @Override + public Iterator newIterator() { + return prototype.iterator(); + } + + @Override + public boolean hasNext() { + return backingIterator.hasNext(); + } + + @Override + public T next() { + return backingIterator.next(); + } + + @Override + public void remove() { + backingIterator.remove(); + } + + @Override + public void forEachRemaining(Consumer action) { + backingIterator.forEachRemaining(action); + } +} diff --git a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java index 18c5b57de8d..5bc9b970bab 100644 --- a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java @@ -4,6 +4,8 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.predicate.IPredicateTestObject; + import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; @@ -14,27 +16,26 @@ public abstract class AbstractNetFlowEdge> extends NetEdge { private final AbstractChannelsHolder channels; - private final WeakHashMap> simulatedChannels; + private final WeakHashMap> simulatedChannels; public AbstractNetFlowEdge() { this.channels = getNewHolder(null, null); this.simulatedChannels = new WeakHashMap<>(9); } - /** - * Claims a new, unique simulator instance for properly simulating flow edge limits without actually changing them. - *
- * This simulator must be discarded after use so that the garbage collector can clean up. - */ - public static ChannelSimulatorKey getNewSimulatorInstance() { - return new ChannelSimulatorKey(); + @Override + public double getWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick) { + if (channel == NBT || !cannotSupportChannel(channel, queryTick, simulator)) { + return super.getWeight(); + } + return Double.POSITIVE_INFINITY; } - public boolean cannotSupportChannel(Object channel, long queryTick, @Nullable ChannelSimulatorKey simulator) { + public boolean cannotSupportChannel(Object channel, long queryTick, @Nullable SimulatorKey simulator) { return getChannels(simulator).cannotSupportChannel(channel, queryTick); } - protected AbstractChannelsHolder getChannels(@Nullable ChannelSimulatorKey simulator) { + protected AbstractChannelsHolder getChannels(@Nullable SimulatorKey simulator) { if (simulator == null) return this.channels; else { AbstractChannelsHolder channels = simulatedChannels.get(simulator); @@ -50,11 +51,11 @@ public & IPipeType, NDT extends INodeData> long g Object channel, Graph, E> graph, long queryTick, - @Nullable ChannelSimulatorKey simulator) { + @Nullable SimulatorKey simulator) { return getChannels(simulator).getFlowLimit(channel, graph, queryTick); } - public long getConsumedLimit(Object channel, long queryTick, @Nullable ChannelSimulatorKey simulator) { + public long getConsumedLimit(Object channel, long queryTick, @Nullable SimulatorKey simulator) { return getChannels(simulator).getConsumedLimit(channel, queryTick); } @@ -63,26 +64,26 @@ public & IPipeType, NDT extends INodeData> void c Graph, E> graph, long amount, long queryTick, - @Nullable ChannelSimulatorKey simulator) { + @Nullable SimulatorKey simulator) { getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); } - public Set getActiveChannels(@Nullable ChannelSimulatorKey simulator, long queryTick) { + public Set getActiveChannels(@Nullable SimulatorKey simulator, long queryTick) { return getChannels(simulator).getActiveChannels(queryTick); } protected abstract AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, - ChannelSimulatorKey simulator); + SimulatorKey simulator); protected abstract static class AbstractChannelsHolder> { - private final WeakReference simulator; + private final WeakReference simulator; - public AbstractChannelsHolder(ChannelSimulatorKey simulator) { + public AbstractChannelsHolder(SimulatorKey simulator) { this.simulator = new WeakReference<>(simulator); } - public ChannelSimulatorKey getSimulator() { + public SimulatorKey getSimulator() { return simulator.get(); } @@ -105,20 +106,4 @@ abstract & IPipeType, NDT extends INodeData> void abstract Set getActiveChannels(long queryTick); } - - public static final class ChannelSimulatorKey { - - private static int ID; - private final int id; - - private ChannelSimulatorKey() { - this.id = ID++; - } - - @Override - public int hashCode() { - // enforcing hash uniqueness improves weak map performance - return id; - } - } } diff --git a/src/main/java/gregtech/api/pipenet/edge/IEdge.java b/src/main/java/gregtech/api/pipenet/edge/IEdge.java index 0d67f9fa010..695e8c961d1 100644 --- a/src/main/java/gregtech/api/pipenet/edge/IEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/IEdge.java @@ -1,10 +1,12 @@ package gregtech.api.pipenet.edge; +import gregtech.api.pipenet.predicate.IPredicateTestObject; + public interface IEdge { V getSource(); V getTarget(); - double getWeight(); + double getWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick); } diff --git a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java index a4b5ce5041f..efb03d34b86 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java @@ -5,6 +5,7 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.predicate.AbstractEdgePredicate; +import gregtech.api.pipenet.predicate.IPredicateTestObject; import gregtech.api.util.function.QuadConsumer; import net.minecraft.nbt.NBTTagCompound; @@ -17,6 +18,8 @@ public class NetEdge extends DefaultWeightedEdge implements INBTSerializable, IEdge> { + protected static final IPredicateTestObject NBT = new IPredicateTestObject() {}; + private AbstractEdgePredicate predicate; private boolean invertedPredicate; @@ -33,7 +36,7 @@ public void setPredicate(AbstractEdgePredicate predicate) { this.invertedPredicate = predicate.getSourcePos() != this.getSource().getNodePos(); } - public Predicate getPredicate() { + public Predicate getPredicate() { // if we don't have a predicate, just assume that we're good. if (predicate == null) return (a) -> true; return predicate; @@ -71,8 +74,7 @@ E extends NetEdge> NetNode getCastTarget() { return (NetNode) getTarget(); } - @Override - public double getWeight() { + public double getWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick) { return super.getWeight(); } @@ -81,7 +83,7 @@ public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); tag.setLong("SourceLongPos", getSource().getLongPos()); tag.setLong("TargetLongPos", getTarget().getLongPos()); - tag.setDouble("Weight", getWeight()); + tag.setDouble("Weight", getWeight(NBT, null, 0)); if (predicate != null) tag.setTag("Predicate", AbstractEdgePredicate.toNBT(predicate)); tag.setBoolean("InvertedPredicate", isPredicateInverted()); return tag; diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java index ec2db2328e1..a6243935a77 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java @@ -28,7 +28,7 @@ public NetFlowEdge(int flowBufferTicks) { @Override protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, - ChannelSimulatorKey simulator) { + SimulatorKey simulator) { if (prototype instanceof ChannelsHolder holder) return new ChannelsHolder(holder, simulator); return new ChannelsHolder(simulator); } @@ -39,12 +39,12 @@ private final class ChannelsHolder extends AbstractChannelsHolder { private long lastQueryTick; private boolean init; - public ChannelsHolder(ChannelSimulatorKey simulator) { + public ChannelsHolder(SimulatorKey simulator) { super(simulator); this.map = new Object2LongOpenHashMap<>(9); } - public ChannelsHolder(ChannelsHolder prototype, ChannelSimulatorKey simulator) { + public ChannelsHolder(ChannelsHolder prototype, SimulatorKey simulator) { super(simulator); this.map = prototype.map.clone(); this.lastQueryTick = prototype.lastQueryTick; diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java index 79a182b4cd7..f7381a316f7 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java @@ -30,7 +30,7 @@ public NetFlowSharedEdge(int flowBufferTicks) { @Override protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, - ChannelSimulatorKey simulator) { + SimulatorKey simulator) { if (prototype instanceof ChannelsHolder holder) return new ChannelsHolder(holder, simulator); return new ChannelsHolder(simulator); } @@ -43,13 +43,13 @@ private final class ChannelsHolder extends AbstractChannelsHolder(9); this.map.defaultReturnValue(0); } - public ChannelsHolder(ChannelsHolder prototype, ChannelSimulatorKey simulator) { + public ChannelsHolder(ChannelsHolder prototype, SimulatorKey simulator) { super(simulator); this.map = prototype.map.clone(); this.lastQueryTick = prototype.lastQueryTick; diff --git a/src/main/java/gregtech/api/pipenet/edge/SimulatorKey.java b/src/main/java/gregtech/api/pipenet/edge/SimulatorKey.java new file mode 100644 index 00000000000..ec4f8c69db9 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/edge/SimulatorKey.java @@ -0,0 +1,26 @@ +package gregtech.api.pipenet.edge; + +public final class SimulatorKey { + + private static int ID; + private final int id; + + private SimulatorKey() { + this.id = ID++; + } + + /** + * Claims a new, unique simulator instance for properly simulating flow edge limits without actually changing them. + *
+ * This simulator must be discarded after use so that the garbage collector can clean up. + */ + public static SimulatorKey getNewSimulatorInstance() { + return new SimulatorKey(); + } + + @Override + public int hashCode() { + // enforcing hash uniqueness improves weak map performance + return id; + } +} diff --git a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java index 02a8dfda1b7..376df509d3b 100644 --- a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java +++ b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java @@ -4,7 +4,8 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.AbstractNetFlowEdge; -import gregtech.api.util.FluidTestObject; +import gregtech.api.pipenet.edge.SimulatorKey; +import gregtech.api.pipenet.predicate.FluidTestObject; import org.jgrapht.Graph; @@ -18,18 +19,18 @@ public class FlowConsumer & IPipeType, NDT extends INod private final Graph, E> graph; private final long flow; private final long tick; - private final AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey; + private final SimulatorKey simulatorKey; private final Consumer extra; private double ratio = 1; public FlowConsumer(E edge, FluidTestObject testObject, Graph, E> graph, long flow, - long tick, AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey) { + long tick, SimulatorKey simulatorKey) { this(edge, testObject, graph, flow, tick, simulatorKey, null); } public FlowConsumer(E edge, FluidTestObject testObject, Graph, E> graph, long flow, - long tick, AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey, Consumer extra) { + long tick, SimulatorKey simulatorKey, Consumer extra) { this.edge = edge; this.testObject = testObject; this.graph = graph; diff --git a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java index ec105c98052..94a99f8ff29 100644 --- a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java +++ b/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java @@ -4,7 +4,8 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.AbstractNetFlowEdge; -import gregtech.api.util.FluidTestObject; +import gregtech.api.pipenet.edge.SimulatorKey; +import gregtech.api.pipenet.predicate.FluidTestObject; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.Graph; @@ -15,12 +16,12 @@ public class FlowConsumerList & IPipeType, NDT extends E extends AbstractNetFlowEdge> extends ObjectArrayList> { public void add(E edge, FluidTestObject testObject, Graph, E> graph, long flow, - long tick, AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey) { + long tick, SimulatorKey simulatorKey) { this.add(new FlowConsumer<>(edge, testObject, graph, flow, tick, simulatorKey)); } public void add(E edge, FluidTestObject testObject, Graph, E> graph, long flow, - long tick, AbstractNetFlowEdge.ChannelSimulatorKey simulatorKey, Consumer extra) { + long tick, SimulatorKey simulatorKey, Consumer extra) { this.add(new FlowConsumer<>(edge, testObject, graph, flow, tick, simulatorKey, extra)); } diff --git a/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java b/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java index 1c193883f64..c4fa25ec975 100644 --- a/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java @@ -12,8 +12,7 @@ import java.util.function.Predicate; import java.util.function.Supplier; -public abstract class AbstractEdgePredicate> - implements Predicate, INBTSerializable { +public abstract class AbstractEdgePredicate> implements Predicate, INBTSerializable { protected static final Map>> PREDICATE_SUPPLIERS = new Object2ObjectOpenHashMap<>(); diff --git a/src/main/java/gregtech/api/pipenet/predicate/BasicEdgePredicate.java b/src/main/java/gregtech/api/pipenet/predicate/BasicEdgePredicate.java index db3a07aaa4b..cbd09fba42d 100644 --- a/src/main/java/gregtech/api/pipenet/predicate/BasicEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/predicate/BasicEdgePredicate.java @@ -26,7 +26,7 @@ public void setShutteredTarget(boolean shutteredTarget) { } @Override - public boolean test(Object o) { + public boolean test(IPredicateTestObject o) { return !(shutteredSource || shutteredTarget); } diff --git a/src/main/java/gregtech/api/util/FluidTestObject.java b/src/main/java/gregtech/api/pipenet/predicate/FluidTestObject.java similarity index 88% rename from src/main/java/gregtech/api/util/FluidTestObject.java rename to src/main/java/gregtech/api/pipenet/predicate/FluidTestObject.java index b89e9788409..c03d260a3e6 100644 --- a/src/main/java/gregtech/api/util/FluidTestObject.java +++ b/src/main/java/gregtech/api/pipenet/predicate/FluidTestObject.java @@ -1,4 +1,4 @@ -package gregtech.api.util; +package gregtech.api.pipenet.predicate; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.Fluid; @@ -6,7 +6,7 @@ import java.util.Objects; -public final class FluidTestObject { +public final class FluidTestObject implements IPredicateTestObject { public final Fluid fluid; public final NBTTagCompound tag; diff --git a/src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java b/src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java new file mode 100644 index 00000000000..59964c13347 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java @@ -0,0 +1,4 @@ +package gregtech.api.pipenet.predicate; + +public interface IPredicateTestObject { +} diff --git a/src/main/java/gregtech/api/pipenet/predicate/ItemTestObject.java b/src/main/java/gregtech/api/pipenet/predicate/ItemTestObject.java new file mode 100644 index 00000000000..f39450aedbd --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/predicate/ItemTestObject.java @@ -0,0 +1,37 @@ +package gregtech.api.pipenet.predicate; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import java.util.Objects; + +public class ItemTestObject implements IPredicateTestObject { + + public final Item item; + public final int meta; + public final NBTTagCompound tag; + + public ItemTestObject(ItemStack stack) { + item = stack.getItem(); + meta = stack.getMetadata(); + tag = stack.getTagCompound(); + } + + public ItemStack recombine() { + return new ItemStack(item, 1, meta, tag); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ItemTestObject that = (ItemTestObject) o; + return meta == that.meta && Objects.equals(item, that.item) && Objects.equals(tag, that.tag); + } + + @Override + public int hashCode() { + return Objects.hash(item, meta, tag); + } +} diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java index 5eb86ebf03a..14ff11bbdf8 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -7,7 +7,7 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.NodeLossResult; -import gregtech.api.pipenet.edge.AbstractNetFlowEdge; +import gregtech.api.pipenet.edge.SimulatorKey; import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.edge.util.FlowConsumerList; import gregtech.api.unification.material.properties.WireProperties; @@ -103,14 +103,14 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage return 0; long queryTick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - AbstractNetFlowEdge.ChannelSimulatorKey key = simulate ? AbstractNetFlowEdge.getNewSimulatorInstance() : null; + SimulatorKey simulator = simulate ? SimulatorKey.getNewSimulatorInstance() : null; destSimulationCache = simulate ? new Object2LongOpenHashMap<>() : null; - List> paths = new ObjectArrayList<>(this.net.getPaths(cable)); - long amperesUsed = distributionRespectCapacity(side, voltage, amperage, queryTick, paths, key); + this.getNet().getGraph().prepareForDynamicWeightAlgorithmRun(null, simulator, queryTick); + long amperesUsed = distributionRespectCapacity(side, voltage, amperage, queryTick, this.getNet().getPaths(cable), simulator); if (amperesUsed < amperage) { // if we still have undistributed amps, attempt to distribute them while going over edge capacities. - amperesUsed += distributionIgnoreCapacity(side, voltage, amperage - amperesUsed, queryTick, paths, key); + amperesUsed += distributionIgnoreCapacity(side, voltage, amperage - amperesUsed, queryTick, this.getNet().getPaths(cable), simulator); } this.lossResultCache.forEach((k, v) -> v.getPostAction().accept(k)); this.lossResultCache.clear(); @@ -123,12 +123,12 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage } private long distributionRespectCapacity(EnumFacing side, long voltage, long amperage, long queryTick, - List> paths, - AbstractNetFlowEdge.ChannelSimulatorKey simulator) { + Iterator> paths, + SimulatorKey simulator) { long availableAmperage = amperage; mainloop: - for (int i = 0; i < paths.size(); i++) { - NetPath path = paths.get(i); + while (paths.hasNext()) { + NetPath path = paths.next(); // skip paths where loss exceeds available voltage if (path.getWeight() > voltage) continue; Iterator iterator = path.getFacingIterator(); @@ -169,10 +169,7 @@ private long distributionRespectCapacity(EnumFacing side, long voltage, long amp tile.contributeVoltageFlow(voltage); } : null); // voltage loss - if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) { - paths.remove(i); - continue mainloop; - } + if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) continue mainloop; } // skip paths where we can't transfer amperage if (pathAmperage <= 0) continue; @@ -196,13 +193,14 @@ private long distributionRespectCapacity(EnumFacing side, long voltage, long amp } private long distributionIgnoreCapacity(EnumFacing side, long voltage, long amperage, long queryTick, - List> paths, - AbstractNetFlowEdge.ChannelSimulatorKey simulator) { + Iterator> paths, + SimulatorKey simulator) { Object2LongOpenHashMap localDestSimulationCache = new Object2LongOpenHashMap<>(); long availableAmperage = amperage; mainloop: - for (NetPath path : paths) { + while (paths.hasNext()) { + NetPath path = paths.next(); // skip paths where loss exceeds available voltage if (path.getWeight() > voltage) continue; Iterator iterator = path.getFacingIterator(); @@ -289,7 +287,7 @@ private long getSimulatedAccepted(Object2LongOpenHashMap destSimulati return atomicAccepted.get(); } - private boolean calculateVoltageLoss(long voltage, AbstractNetFlowEdge.ChannelSimulatorKey simulator, + private boolean calculateVoltageLoss(long voltage, SimulatorKey simulator, DoubleList voltageCaps, long pathAmperage, NetNode target) { // TODO undo loss & heating on backflow diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java index e857fed7f59..f5d70bb34d1 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java @@ -11,7 +11,7 @@ import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.util.EntityDamageUtil; -import gregtech.api.util.FluidTestObject; +import gregtech.api.pipenet.predicate.FluidTestObject; import gregtech.client.renderer.pipe.FluidPipeRenderer; import gregtech.client.renderer.pipe.PipeRenderer; import gregtech.common.creativetab.GTCreativeTabs; @@ -34,8 +34,6 @@ import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java index d03294e1bad..b6c5fadc148 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java @@ -1,6 +1,8 @@ package gregtech.common.pipelike.fluidpipe.net; import gregtech.api.pipenet.predicate.FilteredEdgePredicate; +import gregtech.api.pipenet.predicate.FluidTestObject; +import gregtech.api.pipenet.predicate.IPredicateTestObject; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.FluidFilterContainer; @@ -17,9 +19,10 @@ public class FluidEdgePredicate extends FilteredEdgePredicate, NodeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); @@ -98,18 +98,19 @@ public int fill(FluidStack resource, boolean doFill) { } FluidTestObject testObject = new FluidTestObject(resource); - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - List> paths = this.getNet().getPaths(pipe); + long queryTick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); FluidStack helper = resource.copy(); - if (!doFill) this.simulatorKey = AbstractNetFlowEdge.getNewSimulatorInstance(); + if (!doFill) this.simulatorKey = SimulatorKey.getNewSimulatorInstance(); else this.simulatorKey = null; + this.getNet().getGraph().prepareForDynamicWeightAlgorithmRun(testObject, simulatorKey, queryTick); mainloop: - for (NetPath path : paths) { + for (Iterator> iter = this.getNet().getPaths(pipe); iter.hasNext(); ) { + NetPath path = iter.next(); for (Iterator it = path.getFacingIterator(); it.hasNext();) { EnumFacing facing = it.next(); NetPath.FacedNetPath routePath = path .withFacing(facing); - helper.amount -= this.fill(routePath, testObject, tick, helper, doFill); + helper.amount -= this.fill(routePath, testObject, queryTick, helper, doFill); if (helper.amount <= 0) break mainloop; } } @@ -220,7 +221,7 @@ private int fill(NetPath.FacedNetPath } @Override - public boolean test(Object o) { + public boolean test(IPredicateTestObject o) { if (shutteredSource || shutteredTarget) return false; - if (!(o instanceof ItemStack stack)) return false; + if (!(o instanceof ItemTestObject tester)) return false; + ItemStack stack = tester.recombine(); return sourceFilter.test(stack) && targetFilter.test(stack); } diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index ff506a9d83e..979df37f6fa 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -4,6 +4,7 @@ import gregtech.api.pipenet.IPipeNetHandler; import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.predicate.ItemTestObject; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.util.FacingPos; import gregtech.api.util.GTTransferUtils; @@ -16,6 +17,8 @@ import gregtech.common.pipelike.itempipe.ItemPipeType; import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraftforge.items.CapabilityItemHandler; @@ -114,7 +117,8 @@ public static boolean checkImportCover(Cover cover, boolean onPipe, ItemStack st } public ItemStack insertFirst(ItemStack stack, boolean simulate) { - for (NetPath inv : net.getPaths(pipe)) { + for (Iterator> it = net.getPaths(pipe); it.hasNext(); ) { + NetPath inv = it.next(); stack = insert(inv.firstFacing(), stack, simulate); if (stack.isEmpty()) return ItemStack.EMPTY; @@ -123,13 +127,10 @@ public ItemStack insertFirst(ItemStack stack, boolean simulate) { } public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean global) { - List> routePaths = net.getPaths(pipe); - if (routePaths.isEmpty()) - return stack; - if (routePaths.size() == 1 && routePaths.get(0).getTargetTEs().size() == 1) { - return insert(routePaths.get(0).firstFacing(), stack, simulate); - } - List> routePathsCopy = new ArrayList<>(routePaths); + Iterator> routePaths = net.getPaths(pipe); + if (!routePaths.hasNext()) return stack; + List> routePathsCopy = new ObjectArrayList<>(); + routePaths.forEachRemaining(routePathsCopy::add); if (global) { stack = insertToHandlersEnhanced(routePathsCopy, stack, simulate); @@ -323,7 +324,7 @@ public ItemStack insert(NetPath.FacedNetPath> data = net.getPaths(this.pipe); - if (data == null || data.size() != 1) return null; - Map connecteds = data.get(0).getTargetTEs(); + Iterator> data = net.getPaths(this.pipe); + if (data == null || !data.hasNext()) return null; + Map connecteds = data.next().getTargetTEs(); + if (data.hasNext()) return null; if (connecteds.size() != 1) return null; EnumFacing facing = connecteds.keySet().iterator().next(); diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java index 9badc01604d..9032c3432f3 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -96,9 +97,10 @@ private boolean isNetInvalidForTraversal() { private boolean traverseRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { if (isNetInvalidForTraversal()) return false; - List> inv = net.getPaths(this.pipe); - if (inv == null || inv.size() != 1) return false; - Map connecteds = inv.get(0).getTargetTEs(); + Iterator> inv = net.getPaths(this.pipe); + if (inv == null || !inv.hasNext()) return false; + Map connecteds = inv.next().getTargetTEs(); + if (inv.hasNext()) return false; if (connecteds.size() != 1) return false; EnumFacing facing = connecteds.keySet().iterator().next(); @@ -134,9 +136,10 @@ private boolean traverseCanBridge(@NotNull Collection seen) { if (isNetInvalidForTraversal()) return null; - List> inv = net.getPaths(this.pipe); - if (inv == null || inv.size() != 1) return null; - Map connecteds = inv.get(0).getTargetTEs(); + Iterator> inv = net.getPaths(this.pipe); + if (inv == null || !inv.hasNext()) return null; + Map connecteds = inv.next().getTargetTEs(); + if (inv.hasNext()) return null; if (connecteds.size() != 1) return null; EnumFacing facing = connecteds.keySet().iterator().next(); From 569f23a53b62a66fe09d143d67e70518f0bd842c Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 26 Jun 2024 18:35:13 -0600 Subject: [PATCH 067/157] nth time running spotless --- .../java/gregtech/api/pipenet/NetNode.java | 2 +- .../api/pipenet/WorldPipeNetBase.java | 33 ++++++++++++------- .../api/pipenet/WorldPipeNetComplex.java | 3 -- .../api/pipenet/WorldPipeNetSimple.java | 3 -- .../api/pipenet/alg/AllPathsAlgorithm.java | 4 ++- .../api/pipenet/alg/INetAlgorithm.java | 1 - .../alg/iter/SimpleCacheableIterator.java | 4 --- .../api/pipenet/edge/AbstractNetFlowEdge.java | 1 - .../predicate/AbstractEdgePredicate.java | 3 +- .../predicate/IPredicateTestObject.java | 3 +- .../pipelike/cable/net/EnergyNetHandler.java | 8 +++-- .../pipelike/fluidpipe/BlockFluidPipe.java | 5 ++- .../fluidpipe/net/FluidNetHandler.java | 7 ++-- .../pipelike/itempipe/net/ItemNetHandler.java | 5 ++- .../pipelike/laser/net/LaserNetHandler.java | 1 - .../optical/net/OpticalNetHandler.java | 1 - 16 files changed, 41 insertions(+), 43 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/NetNode.java b/src/main/java/gregtech/api/pipenet/NetNode.java index 3a8a55fa7dd..c7e6d1ab60c 100644 --- a/src/main/java/gregtech/api/pipenet/NetNode.java +++ b/src/main/java/gregtech/api/pipenet/NetNode.java @@ -282,7 +282,7 @@ public Iterator> getPathCache() { * @return The new cache. */ public Iterator> setPathCache( - ICacheableIterator> pathCache) { + ICacheableIterator> pathCache) { this.pathCache = pathCache; return getPathCache(); } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java index 57738d557a3..22c6b6471f0 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java @@ -1,11 +1,11 @@ package gregtech.api.pipenet; import gregtech.api.cover.Cover; -import gregtech.api.pipenet.alg.iter.ICacheableIterator; import gregtech.api.pipenet.alg.INetAlgorithm; +import gregtech.api.pipenet.alg.iter.ICacheableIterator; import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.SimulatorKey; import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.edge.SimulatorKey; import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.pipenet.predicate.BasicEdgePredicate; import gregtech.api.pipenet.predicate.IPredicateTestObject; @@ -137,7 +137,7 @@ public Iterator> getPaths(BlockPos pos) { } public Iterator> getPaths(@Nullable NetNode node, - @Nullable TileEntityPipeBase tile) { + @Nullable TileEntityPipeBase tile) { if (node == null) return Collections.emptyIterator(); node.setHeldMTE(tile); @@ -148,7 +148,7 @@ public Iterator> getPaths(@Nullable NetNod if (cache != null) return cache; Iterator> iter = this.netAlgorithm.getPathsIterator(node); - if (iter instanceof ICacheableIterator> cacheable) { + if (iter instanceof ICacheableIterator>cacheable) { return node.setPathCache(cacheable); } else return iter; } @@ -535,15 +535,19 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { */ protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); - public interface ICustomGraph & IPipeType, NDT extends INodeData, E extends NetEdge> extends Graph, E> { + public interface ICustomGraph & IPipeType, NDT extends INodeData, E extends NetEdge> + extends Graph, E> { @ApiStatus.Internal void setOwningNet(WorldPipeNetBase net); - void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, long queryTick); + void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, + long queryTick); } - static class CustomDirectedGraph & IPipeType, NDT extends INodeData, E extends NetEdge> extends SimpleDirectedWeightedGraph, E> implements ICustomGraph { + static class CustomDirectedGraph & IPipeType, NDT extends INodeData, + E extends NetEdge> extends SimpleDirectedWeightedGraph, E> + implements ICustomGraph { private WorldPipeNetBase net = null; @@ -553,7 +557,8 @@ static class CustomDirectedGraph & IPipeType, NDT exten @Override public void setOwningNet(WorldPipeNetBase net) { - if (this.net != null) throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); + if (this.net != null) + throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); this.net = net; } @@ -576,12 +581,14 @@ public CustomDirectedGraph(Supplier> vertexSupplier, Supplie @Override public double getEdgeWeight(E edge) { if (net.netAlgorithm.supportsDynamicWeights()) { - return edge.getPredicate().test(testObject) ? edge.getWeight(testObject, simulator, queryTick) : Double.POSITIVE_INFINITY; + return edge.getPredicate().test(testObject) ? edge.getWeight(testObject, simulator, queryTick) : + Double.POSITIVE_INFINITY; } else return super.getEdgeWeight(edge); } } - static class CustomUndirectedGraph & IPipeType, NDT extends INodeData, E extends NetEdge> extends SimpleWeightedGraph, E> implements ICustomGraph { + static class CustomUndirectedGraph & IPipeType, NDT extends INodeData, + E extends NetEdge> extends SimpleWeightedGraph, E> implements ICustomGraph { private WorldPipeNetBase net = null; @@ -591,7 +598,8 @@ static class CustomUndirectedGraph & IPipeType, NDT ext @Override public void setOwningNet(WorldPipeNetBase net) { - if (this.net != null) throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); + if (this.net != null) + throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); this.net = net; } @@ -614,7 +622,8 @@ public CustomUndirectedGraph(Supplier> vertexSupplier, Suppl @Override public double getEdgeWeight(E edge) { if (net.netAlgorithm.supportsDynamicWeights()) { - return edge.getPredicate().test(testObject) ? edge.getWeight(testObject, simulator, queryTick) : Double.POSITIVE_INFINITY; + return edge.getPredicate().test(testObject) ? edge.getWeight(testObject, simulator, queryTick) : + Double.POSITIVE_INFINITY; } else return super.getEdgeWeight(edge); } } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java index 1f74b79b347..66df8c42c95 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java @@ -6,9 +6,6 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; -import org.jgrapht.graph.SimpleDirectedWeightedGraph; -import org.jgrapht.graph.SimpleWeightedGraph; - import java.util.function.Function; import java.util.function.Supplier; diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java index 02a72e77fcd..b687c0f248e 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java @@ -6,9 +6,6 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; -import org.jgrapht.graph.SimpleDirectedWeightedGraph; -import org.jgrapht.graph.SimpleWeightedGraph; - import java.util.function.Function; public abstract class WorldPipeNetSimple, diff --git a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java index 74f15540606..ddac68e43cc 100644 --- a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java @@ -18,7 +18,9 @@ import java.util.Set; import java.util.stream.Collectors; -public class AllPathsAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> extends DijkstraManyToManyShortestPaths, E> implements INetAlgorithm { +public class AllPathsAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> + extends DijkstraManyToManyShortestPaths, E> + implements INetAlgorithm { public AllPathsAlgorithm(WorldPipeNetBase pipenet) { super(pipenet.getGraph()); diff --git a/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java index 89e3658508e..05cd29665b8 100644 --- a/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java @@ -7,7 +7,6 @@ import gregtech.api.pipenet.edge.NetEdge; import java.util.Iterator; -import java.util.List; public interface INetAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> { diff --git a/src/main/java/gregtech/api/pipenet/alg/iter/SimpleCacheableIterator.java b/src/main/java/gregtech/api/pipenet/alg/iter/SimpleCacheableIterator.java index 3b1cc8c2fe7..718a0525d85 100644 --- a/src/main/java/gregtech/api/pipenet/alg/iter/SimpleCacheableIterator.java +++ b/src/main/java/gregtech/api/pipenet/alg/iter/SimpleCacheableIterator.java @@ -1,11 +1,7 @@ package gregtech.api.pipenet.alg.iter; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import java.util.Collection; import java.util.Iterator; import java.util.function.Consumer; -import java.util.stream.Collectors; public class SimpleCacheableIterator implements ICacheableIterator { diff --git a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java index 5bc9b970bab..5e629d979a9 100644 --- a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java @@ -3,7 +3,6 @@ import gregtech.api.pipenet.INodeData; import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.IPipeType; - import gregtech.api.pipenet.predicate.IPredicateTestObject; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java b/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java index c4fa25ec975..e14f63c226c 100644 --- a/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java +++ b/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java @@ -12,7 +12,8 @@ import java.util.function.Predicate; import java.util.function.Supplier; -public abstract class AbstractEdgePredicate> implements Predicate, INBTSerializable { +public abstract class AbstractEdgePredicate> implements + Predicate, INBTSerializable { protected static final Map>> PREDICATE_SUPPLIERS = new Object2ObjectOpenHashMap<>(); diff --git a/src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java b/src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java index 59964c13347..aa1f794a982 100644 --- a/src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java +++ b/src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java @@ -1,4 +1,3 @@ package gregtech.api.pipenet.predicate; -public interface IPredicateTestObject { -} +public interface IPredicateTestObject {} diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java index 14ff11bbdf8..cc63fa5569a 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -7,8 +7,8 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.NodeLossResult; -import gregtech.api.pipenet.edge.SimulatorKey; import gregtech.api.pipenet.edge.NetFlowEdge; +import gregtech.api.pipenet.edge.SimulatorKey; import gregtech.api.pipenet.edge.util.FlowConsumerList; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.FacingPos; @@ -107,10 +107,12 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage destSimulationCache = simulate ? new Object2LongOpenHashMap<>() : null; this.getNet().getGraph().prepareForDynamicWeightAlgorithmRun(null, simulator, queryTick); - long amperesUsed = distributionRespectCapacity(side, voltage, amperage, queryTick, this.getNet().getPaths(cable), simulator); + long amperesUsed = distributionRespectCapacity(side, voltage, amperage, queryTick, + this.getNet().getPaths(cable), simulator); if (amperesUsed < amperage) { // if we still have undistributed amps, attempt to distribute them while going over edge capacities. - amperesUsed += distributionIgnoreCapacity(side, voltage, amperage - amperesUsed, queryTick, this.getNet().getPaths(cable), simulator); + amperesUsed += distributionIgnoreCapacity(side, voltage, amperage - amperesUsed, queryTick, + this.getNet().getPaths(cable), simulator); } this.lossResultCache.forEach((k, v) -> v.getPostAction().accept(k)); this.lossResultCache.clear(); diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java index f5d70bb34d1..96673e4268d 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java @@ -5,13 +5,13 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.block.material.BlockMaterialPipe; import gregtech.api.pipenet.edge.NetFlowEdge; +import gregtech.api.pipenet.predicate.FluidTestObject; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.util.EntityDamageUtil; -import gregtech.api.pipenet.predicate.FluidTestObject; import gregtech.client.renderer.pipe.FluidPipeRenderer; import gregtech.client.renderer.pipe.PipeRenderer; import gregtech.common.creativetab.GTCreativeTabs; @@ -19,8 +19,6 @@ import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipeTickable; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.creativetab.CreativeTabs; @@ -40,6 +38,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import com.google.common.base.Preconditions; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java index 4687c0f511f..06c605a682e 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidNetHandler.java @@ -5,11 +5,11 @@ import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.NetPath; import gregtech.api.pipenet.NodeLossResult; -import gregtech.api.pipenet.edge.SimulatorKey; import gregtech.api.pipenet.edge.NetFlowEdge; +import gregtech.api.pipenet.edge.SimulatorKey; import gregtech.api.pipenet.edge.util.FlowConsumerList; -import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.pipenet.predicate.FluidTestObject; +import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.covers.CoverFluidRegulator; import gregtech.common.covers.CoverPump; import gregtech.common.pipelike.fluidpipe.FluidPipeType; @@ -104,7 +104,8 @@ public int fill(FluidStack resource, boolean doFill) { else this.simulatorKey = null; this.getNet().getGraph().prepareForDynamicWeightAlgorithmRun(testObject, simulatorKey, queryTick); mainloop: - for (Iterator> iter = this.getNet().getPaths(pipe); iter.hasNext(); ) { + for (Iterator> iter = this.getNet() + .getPaths(pipe); iter.hasNext();) { NetPath path = iter.next(); for (Iterator it = path.getFacingIterator(); it.hasNext();) { EnumFacing facing = it.next(); diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index 979df37f6fa..385ddbbb5cd 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -17,8 +17,6 @@ import gregtech.common.pipelike.itempipe.ItemPipeType; import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraftforge.items.CapabilityItemHandler; @@ -29,6 +27,7 @@ import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -117,7 +116,7 @@ public static boolean checkImportCover(Cover cover, boolean onPipe, ItemStack st } public ItemStack insertFirst(ItemStack stack, boolean simulate) { - for (Iterator> it = net.getPaths(pipe); it.hasNext(); ) { + for (Iterator> it = net.getPaths(pipe); it.hasNext();) { NetPath inv = it.next(); stack = insert(inv.firstFacing(), stack, simulate); if (stack.isEmpty()) diff --git a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java index c3531741be7..b0f327e642a 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java @@ -18,7 +18,6 @@ import org.jetbrains.annotations.Nullable; import java.util.Iterator; -import java.util.List; import java.util.Map; public class LaserNetHandler implements ILaserContainer, IPipeNetHandler { diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java index 9032c3432f3..1b25fbab57a 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java @@ -22,7 +22,6 @@ import java.util.Collection; import java.util.Iterator; -import java.util.List; import java.util.Map; public class OpticalNetHandler implements IDataAccessHatch, IOpticalComputationProvider, IPipeNetHandler { From da26fe786d0c4b0903a3103a8a81413af6b308d8 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 27 Jun 2024 15:13:44 -0600 Subject: [PATCH 068/157] misc improvements & fixes --- .../java/gregtech/api/pipenet/NetNode.java | 6 +-- .../java/gregtech/api/pipenet/NetPath.java | 10 +++-- .../api/pipenet/WorldPipeNetBase.java | 12 ++++-- .../api/pipenet/alg/AllPathsAlgorithm.java | 41 +++++++++++++------ .../pipenet/alg/ShortestPathsAlgorithm.java | 2 +- .../gregtech/api/pipenet/block/BlockPipe.java | 13 ------ .../api/pipenet/tile/TileEntityPipeBase.java | 1 + 7 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/NetNode.java b/src/main/java/gregtech/api/pipenet/NetNode.java index c7e6d1ab60c..2cabb96f2af 100644 --- a/src/main/java/gregtech/api/pipenet/NetNode.java +++ b/src/main/java/gregtech/api/pipenet/NetNode.java @@ -27,7 +27,7 @@ public final class NetNode & IPipeType net; + public final WorldPipeNetBase net; private NodeDataType data; /** @@ -263,9 +263,7 @@ public NodeDataType getData() { return data; } - public boolean validTarget() { - if (!isActive) return false; - this.net.markNodeAsActive(this, this.net.shouldNodeBeActive(this)); + public boolean isActive() { return isActive; } diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index 8b4443f8001..2b95bffc9de 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -12,10 +12,7 @@ import org.jgrapht.Graph; import org.jgrapht.GraphPath; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; public class NetPath & IPipeType, @@ -134,6 +131,11 @@ public boolean checkPredicate(IPredicateTestObject testObject) { return true; } + public boolean matches(NetPath other) { + // if the edge list and node list match content and order, then we definitely match. + return Objects.equals(nodeList, other.nodeList) && Objects.equals(edgeList, other.edgeList); + } + public static class FacedNetPath & IPipeType, NDT extends INodeData, E extends NetEdge> { diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java index 22c6b6471f0..8ab0df4b71c 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java @@ -148,8 +148,8 @@ public Iterator> getPaths(@Nullable NetNod if (cache != null) return cache; Iterator> iter = this.netAlgorithm.getPathsIterator(node); - if (iter instanceof ICacheableIterator>cacheable) { - return node.setPathCache(cacheable); + if (iter instanceof ICacheableIterator>) { + return node.setPathCache((ICacheableIterator>) iter); } else return iter; } @@ -183,7 +183,7 @@ protected TileEntityPipeBase castTE(TileEntity te) } public void markNodeAsOldData(NetNode node) { - markNodeAsActive(node, shouldNodeBeActive(node)); + updateActiveNodeStatus(node); } protected abstract Class> getBasePipeClass(); @@ -236,7 +236,7 @@ public void updateActiveConnections(BlockPos nodePos, EnumFacing side, boolean c if (node == null || node.isConnected(side) == connect) return; node.setConnected(side, connect); - markNodeAsActive(node, shouldNodeBeActive(node)); + updateActiveNodeStatus(node); NetNode nodeOffset = pipeMap.get(nodePos.offset(side)); if (nodeOffset == null) return; @@ -440,6 +440,10 @@ public NetGroup getGroup(BlockPos pos) { return node.setGroup(new NetGroup<>(this.pipeGraph, this)); } + public boolean updateActiveNodeStatus(NetNode node) { + return markNodeAsActive(node, shouldNodeBeActive(node)); + } + public boolean shouldNodeBeActive(NetNode node) { var connecteds = node.getConnecteds(); if (connecteds != null) return connecteds.entrySet().stream().filter(entry -> { diff --git a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java index ddac68e43cc..be38aac1d37 100644 --- a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java @@ -8,7 +8,8 @@ import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; -import org.jgrapht.alg.shortestpath.DijkstraManyToManyShortestPaths; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jgrapht.alg.shortestpath.DefaultManyToManyShortestPaths; import java.util.Collections; import java.util.Comparator; @@ -19,7 +20,7 @@ import java.util.stream.Collectors; public class AllPathsAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> - extends DijkstraManyToManyShortestPaths, E> + extends DefaultManyToManyShortestPaths, E> implements INetAlgorithm { public AllPathsAlgorithm(WorldPipeNetBase pipenet) { @@ -30,7 +31,7 @@ public AllPathsAlgorithm(WorldPipeNetBase pipenet) { @Override public Iterator> getPathsIterator(NetNode source) { Set> searchSpace = source.getGroupSafe().getNodes().stream() - .filter(NetNode::validTarget).filter(node -> !source.equals(node)).collect(Collectors.toSet()); + .filter(NetNode::isActive).filter(node -> !source.equals(node)).collect(Collectors.toSet()); return new LimitedIterator(source, searchSpace); } @@ -47,7 +48,8 @@ protected class LimitedIterator implements ICacheableIterator> searchSpace; private int iterationCount = 0; - private NetPath cachedNext; + private final ObjectArrayList> visited = new ObjectArrayList<>(); + private NetPath next; public LimitedIterator(NetNode source, Set> searchSpace) { this.source = source; @@ -61,32 +63,47 @@ public ICacheableIterator> newCacheableIterator() { @Override public Iterator> newIterator() { - return new LimitedIterator(source, searchSpace); + return newCacheableIterator(); } @Override public boolean hasNext() { - if (cachedNext == null && iterationCount < MAX_ITERATIONS) calculateNext(); - return cachedNext != null; + if (next == null && iterationCount < MAX_ITERATIONS) calculateNext(); + return next != null; } @Override public NetPath next() { if (!hasNext()) throw new NoSuchElementException(); - var temp = cachedNext; - cachedNext = null; + NetPath temp = next; + next = null; return temp; } private void calculateNext() { iterationCount++; if (iterationCount == 1) { - cachedNext = new NetPath<>(source); + next = new NetPath<>(source); return; } var paths = getManyToManyPaths(Collections.singleton(source), searchSpace); - cachedNext = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) - .map(NetPath::new).min(Comparator.comparingDouble(NetPath::getWeight)).orElse(null); + var iter = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) + .map(NetPath::new).sorted(Comparator.comparingDouble(NetPath::getWeight)).iterator(); + while (iter.hasNext()) { + var next = iter.next(); + if (isUnique(next)) { + this.next = next; + break; + } + } + if (next != null) visited.add(next); + } + + private boolean isUnique(NetPath path) { + for (NetPath other : visited) { + if (path.matches(other)) return false; + } + return true; } } } diff --git a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java index df6f689efe4..09b992e9a27 100644 --- a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java @@ -34,7 +34,7 @@ public Iterator> getPathsIterator(NetNode source if (source.getGroupUnsafe() == null) return Collections.singletonList(new NetPath<>(source)).iterator(); Set> searchSpace = source.getGroupSafe().getNodes().stream() - .filter(NetNode::validTarget).collect(Collectors.toSet()); + .filter(NetNode::isActive).collect(Collectors.toSet()); ManyToManyShortestPaths, E> manyToManyPaths = getManyToManyPaths( Collections.singleton(source), searchSpace); return new SimpleCacheableIterator<>(searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)) diff --git a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java index 3b4ec581fb1..3bd613757f3 100644 --- a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java +++ b/src/main/java/gregtech/api/pipenet/block/BlockPipe.java @@ -9,7 +9,6 @@ import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.pipenet.IBlockAppearance; import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; import gregtech.api.pipenet.WorldPipeNetBase; import gregtech.api.pipenet.edge.NetEdge; import gregtech.api.pipenet.tile.IPipeTile; @@ -187,7 +186,6 @@ public void neighborChanged(@NotNull IBlockState state, @NotNull World worldIn, pipeTile.setConnection(facing, true, false); if (open && !canConnect) pipeTile.setConnection(facing, false, false); - updateActiveNodeStatus(worldIn, pipeTile); } } } @@ -225,17 +223,6 @@ public int getWeakPower(@NotNull IBlockState blockState, @NotNull IBlockAccess b return pipeTile == null ? 0 : pipeTile.getCoverableImplementation().getOutputRedstoneSignal(side.getOpposite()); } - public void updateActiveNodeStatus(@NotNull World worldIn, - IPipeTile pipeTile) { - if (worldIn.isRemote) return; - - WorldPipeNetBase pipeNet = getWorldPipeNet(worldIn); - if (pipeNet != null && pipeTile != null) { - NetNode node = pipeTile.getNode(); - pipeNet.markNodeAsActive(node, pipeNet.shouldNodeBeActive(node)); - } - } - @Nullable @Override public TileEntity createNewTileEntity(@NotNull World worldIn, int meta) { diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java index 53057df1bdd..c622a7502b5 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java @@ -173,6 +173,7 @@ protected void invalidateNeighbors() { public void onNeighborChanged(@NotNull EnumFacing facing) { super.onNeighborChanged(facing); this.nonPipeNeighbors[facing.getIndex()] = this; + if (!this.getPipeWorld().isRemote) this.getNode().net.updateActiveNodeStatus(this.getNode()); } @Override From 5f6c9f179071606fd107e664c6bacd84d1c44823 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 27 Jun 2024 16:59:08 -0600 Subject: [PATCH 069/157] Fix weird compile failure issue --- src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java index 8ab0df4b71c..5d8eab523ed 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java @@ -148,7 +148,7 @@ public Iterator> getPaths(@Nullable NetNod if (cache != null) return cache; Iterator> iter = this.netAlgorithm.getPathsIterator(node); - if (iter instanceof ICacheableIterator>) { + if (iter instanceof ICacheableIterator) { return node.setPathCache((ICacheableIterator>) iter); } else return iter; } From d24b2d4f9c968cbc1a06f9e3841740bec8fb96a8 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 27 Jun 2024 17:48:13 -0600 Subject: [PATCH 070/157] refactor --- .../api/pipenet/WorldPipeNetBase.java | 110 ++---------------- .../api/pipenet/WorldPipeNetComplex.java | 2 + .../api/pipenet/WorldPipeNetSimple.java | 2 + .../api/pipenet/alg/AllPathsAlgorithm.java | 19 ++- .../api/pipenet/edge/AbstractNetFlowEdge.java | 6 +- .../java/gregtech/api/pipenet/edge/IEdge.java | 2 +- .../gregtech/api/pipenet/edge/NetEdge.java | 11 +- .../pipenet/graph/CustomDirectedGraph.java | 56 +++++++++ .../pipenet/graph/CustomUndirectedGraph.java | 55 +++++++++ .../api/pipenet/graph/ICustomGraph.java | 22 ++++ .../pipelike/cable/net/WorldEnergyNet.java | 5 + .../fluidpipe/net/WorldFluidPipeNet.java | 5 + 12 files changed, 185 insertions(+), 110 deletions(-) create mode 100644 src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java create mode 100644 src/main/java/gregtech/api/pipenet/graph/CustomUndirectedGraph.java create mode 100644 src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java index 5d8eab523ed..f7ac8de73bd 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java @@ -5,10 +5,9 @@ import gregtech.api.pipenet.alg.iter.ICacheableIterator; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.edge.SimulatorKey; +import gregtech.api.pipenet.graph.ICustomGraph; import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.pipenet.predicate.BasicEdgePredicate; -import gregtech.api.pipenet.predicate.IPredicateTestObject; import gregtech.api.pipenet.predicate.IShutteredEdgePredicate; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; @@ -28,12 +27,8 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; -import org.jgrapht.graph.SimpleDirectedWeightedGraph; -import org.jgrapht.graph.SimpleWeightedGraph; import java.lang.ref.WeakReference; import java.util.Collections; @@ -42,7 +37,6 @@ import java.util.Map; import java.util.Set; import java.util.function.Function; -import java.util.function.Supplier; import java.util.stream.Collectors; public abstract class WorldPipeNetBase, @@ -96,6 +90,16 @@ public World getWorld() { return this.worldRef.get(); } + public final boolean usesDynamicWeights() { + if (!needsDynamicWeights()) return false; + if (!this.hasValidAlg()) this.rebuildNetAlgorithm(); + return this.netAlgorithm.supportsDynamicWeights(); + } + + protected boolean needsDynamicWeights() { + return false; + } + protected void setWorldAndInit(World world) { if (world != this.worldRef.get()) { this.worldRef = new WeakReference<>(world); @@ -539,96 +543,4 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { */ protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); - public interface ICustomGraph & IPipeType, NDT extends INodeData, E extends NetEdge> - extends Graph, E> { - - @ApiStatus.Internal - void setOwningNet(WorldPipeNetBase net); - - void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, - long queryTick); - } - - static class CustomDirectedGraph & IPipeType, NDT extends INodeData, - E extends NetEdge> extends SimpleDirectedWeightedGraph, E> - implements ICustomGraph { - - private WorldPipeNetBase net = null; - - private IPredicateTestObject testObject; - private SimulatorKey simulator; - private long queryTick; - - @Override - public void setOwningNet(WorldPipeNetBase net) { - if (this.net != null) - throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); - this.net = net; - } - - @Override - public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, - long queryTick) { - this.testObject = testObject; - this.simulator = simulator; - this.queryTick = queryTick; - } - - public CustomDirectedGraph(Class edgeClass) { - super(edgeClass); - } - - public CustomDirectedGraph(Supplier> vertexSupplier, Supplier edgeSupplier) { - super(vertexSupplier, edgeSupplier); - } - - @Override - public double getEdgeWeight(E edge) { - if (net.netAlgorithm.supportsDynamicWeights()) { - return edge.getPredicate().test(testObject) ? edge.getWeight(testObject, simulator, queryTick) : - Double.POSITIVE_INFINITY; - } else return super.getEdgeWeight(edge); - } - } - - static class CustomUndirectedGraph & IPipeType, NDT extends INodeData, - E extends NetEdge> extends SimpleWeightedGraph, E> implements ICustomGraph { - - private WorldPipeNetBase net = null; - - private IPredicateTestObject testObject; - private SimulatorKey simulator; - private long queryTick; - - @Override - public void setOwningNet(WorldPipeNetBase net) { - if (this.net != null) - throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); - this.net = net; - } - - @Override - public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, - long queryTick) { - this.testObject = testObject; - this.simulator = simulator; - this.queryTick = queryTick; - } - - public CustomUndirectedGraph(Class edgeClass) { - super(edgeClass); - } - - public CustomUndirectedGraph(Supplier> vertexSupplier, Supplier edgeSupplier) { - super(vertexSupplier, edgeSupplier); - } - - @Override - public double getEdgeWeight(E edge) { - if (net.netAlgorithm.supportsDynamicWeights()) { - return edge.getPredicate().test(testObject) ? edge.getWeight(testObject, simulator, queryTick) : - Double.POSITIVE_INFINITY; - } else return super.getEdgeWeight(edge); - } - } } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java index 66df8c42c95..b6c7fd7f40a 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java @@ -5,6 +5,8 @@ import gregtech.api.pipenet.alg.SinglePathAlgorithm; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.graph.CustomDirectedGraph; +import gregtech.api.pipenet.graph.CustomUndirectedGraph; import java.util.function.Function; import java.util.function.Supplier; diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java index b687c0f248e..bbb456e6e63 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java @@ -5,6 +5,8 @@ import gregtech.api.pipenet.alg.SinglePathAlgorithm; import gregtech.api.pipenet.block.IPipeType; import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.graph.CustomDirectedGraph; +import gregtech.api.pipenet.graph.CustomUndirectedGraph; import java.util.function.Function; diff --git a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java index be38aac1d37..c56690cf7f1 100644 --- a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java @@ -23,9 +23,11 @@ public class AllPathsAlgorithm & IPipeType, NDT extends extends DefaultManyToManyShortestPaths, E> implements INetAlgorithm { + private final WorldPipeNetBase pipenet; + public AllPathsAlgorithm(WorldPipeNetBase pipenet) { super(pipenet.getGraph()); - if (!pipenet.isDirected()) throw new IllegalArgumentException("Cannot build all paths on an undirected graph!"); + this.pipenet = pipenet; } @Override @@ -47,6 +49,8 @@ protected class LimitedIterator implements ICacheableIterator source; private final Set> searchSpace; + private final ManyToManyShortestPaths, E> manyToManyShortestPaths; + private int iterationCount = 0; private final ObjectArrayList> visited = new ObjectArrayList<>(); private NetPath next; @@ -54,11 +58,19 @@ protected class LimitedIterator implements ICacheableIterator source, Set> searchSpace) { this.source = source; this.searchSpace = searchSpace; + this.manyToManyShortestPaths = pipenet.usesDynamicWeights() ? null : getManyToManyPaths(Collections.singleton(source), searchSpace); + } + + public LimitedIterator(NetNode source, Set> searchSpace, + ManyToManyShortestPaths, E> manyToManyShortestPaths) { + this.source = source; + this.searchSpace = searchSpace; + this.manyToManyShortestPaths = manyToManyShortestPaths; } @Override public ICacheableIterator> newCacheableIterator() { - return new LimitedIterator(source, searchSpace); + return new LimitedIterator(source, searchSpace, manyToManyShortestPaths); } @Override @@ -86,7 +98,8 @@ private void calculateNext() { next = new NetPath<>(source); return; } - var paths = getManyToManyPaths(Collections.singleton(source), searchSpace); + ManyToManyShortestPaths, E> paths = manyToManyShortestPaths != null ? + manyToManyShortestPaths : getManyToManyPaths(Collections.singleton(source), searchSpace); var iter = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) .map(NetPath::new).sorted(Comparator.comparingDouble(NetPath::getWeight)).iterator(); while (iter.hasNext()) { diff --git a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java index 5e629d979a9..51d2ab6fea3 100644 --- a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java @@ -23,9 +23,9 @@ public AbstractNetFlowEdge() { } @Override - public double getWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick) { - if (channel == NBT || !cannotSupportChannel(channel, queryTick, simulator)) { - return super.getWeight(); + public double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick) { + if (!cannotSupportChannel(channel, queryTick, simulator)) { + return getWeight(); } return Double.POSITIVE_INFINITY; } diff --git a/src/main/java/gregtech/api/pipenet/edge/IEdge.java b/src/main/java/gregtech/api/pipenet/edge/IEdge.java index 695e8c961d1..885f6f3419d 100644 --- a/src/main/java/gregtech/api/pipenet/edge/IEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/IEdge.java @@ -8,5 +8,5 @@ public interface IEdge { V getTarget(); - double getWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick); + double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick); } diff --git a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java index efb03d34b86..1e95cd1f022 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java @@ -18,8 +18,6 @@ public class NetEdge extends DefaultWeightedEdge implements INBTSerializable, IEdge> { - protected static final IPredicateTestObject NBT = new IPredicateTestObject() {}; - private AbstractEdgePredicate predicate; private boolean invertedPredicate; @@ -74,16 +72,21 @@ E extends NetEdge> NetNode getCastTarget() { return (NetNode) getTarget(); } - public double getWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick) { + @Override + protected final double getWeight() { return super.getWeight(); } + public double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick) { + return getWeight(); + } + @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); tag.setLong("SourceLongPos", getSource().getLongPos()); tag.setLong("TargetLongPos", getTarget().getLongPos()); - tag.setDouble("Weight", getWeight(NBT, null, 0)); + tag.setDouble("Weight", getWeight()); if (predicate != null) tag.setTag("Predicate", AbstractEdgePredicate.toNBT(predicate)); tag.setBoolean("InvertedPredicate", isPredicateInverted()); return tag; diff --git a/src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java b/src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java new file mode 100644 index 00000000000..492fb2909b4 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java @@ -0,0 +1,56 @@ +package gregtech.api.pipenet.graph; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.WorldPipeNetBase; +import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.edge.SimulatorKey; +import gregtech.api.pipenet.predicate.IPredicateTestObject; + +import org.jgrapht.graph.SimpleDirectedWeightedGraph; + +import java.util.function.Supplier; + +public class CustomDirectedGraph & IPipeType, NDT extends INodeData, + E extends NetEdge> extends SimpleDirectedWeightedGraph, E> + implements ICustomGraph { + + private WorldPipeNetBase net = null; + + private IPredicateTestObject testObject; + private SimulatorKey simulator; + private long queryTick; + + @Override + public void setOwningNet(WorldPipeNetBase net) { + if (this.net != null) + throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); + this.net = net; + } + + @Override + public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, + long queryTick) { + if (!net.usesDynamicWeights()) throw new IllegalStateException("Net does not support dynamic weights!"); + this.testObject = testObject; + this.simulator = simulator; + this.queryTick = queryTick; + } + + public CustomDirectedGraph(Class edgeClass) { + super(edgeClass); + } + + public CustomDirectedGraph(Supplier> vertexSupplier, Supplier edgeSupplier) { + super(vertexSupplier, edgeSupplier); + } + + @Override + public double getEdgeWeight(E edge) { + if (net.usesDynamicWeights()) { + return edge.getPredicate().test(testObject) ? edge.getDynamicWeight(testObject, simulator, queryTick) : + Double.POSITIVE_INFINITY; + } else return super.getEdgeWeight(edge); + } +} diff --git a/src/main/java/gregtech/api/pipenet/graph/CustomUndirectedGraph.java b/src/main/java/gregtech/api/pipenet/graph/CustomUndirectedGraph.java new file mode 100644 index 00000000000..4777a6d7228 --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/graph/CustomUndirectedGraph.java @@ -0,0 +1,55 @@ +package gregtech.api.pipenet.graph; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.WorldPipeNetBase; +import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.edge.SimulatorKey; +import gregtech.api.pipenet.predicate.IPredicateTestObject; + +import org.jgrapht.graph.SimpleWeightedGraph; + +import java.util.function.Supplier; + +public class CustomUndirectedGraph & IPipeType, NDT extends INodeData, + E extends NetEdge> extends SimpleWeightedGraph, E> implements ICustomGraph { + + private WorldPipeNetBase net = null; + + private IPredicateTestObject testObject; + private SimulatorKey simulator; + private long queryTick; + + @Override + public void setOwningNet(WorldPipeNetBase net) { + if (this.net != null) + throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); + this.net = net; + } + + @Override + public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, + long queryTick) { + if (!net.usesDynamicWeights()) throw new IllegalStateException("Net does not support dynamic weights!"); + this.testObject = testObject; + this.simulator = simulator; + this.queryTick = queryTick; + } + + public CustomUndirectedGraph(Class edgeClass) { + super(edgeClass); + } + + public CustomUndirectedGraph(Supplier> vertexSupplier, Supplier edgeSupplier) { + super(vertexSupplier, edgeSupplier); + } + + @Override + public double getEdgeWeight(E edge) { + if (net.usesDynamicWeights()) { + return edge.getPredicate().test(testObject) ? edge.getDynamicWeight(testObject, simulator, queryTick) : + Double.POSITIVE_INFINITY; + } else return super.getEdgeWeight(edge); + } +} diff --git a/src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java b/src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java new file mode 100644 index 00000000000..183915ba6ac --- /dev/null +++ b/src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java @@ -0,0 +1,22 @@ +package gregtech.api.pipenet.graph; + +import gregtech.api.pipenet.INodeData; +import gregtech.api.pipenet.NetNode; +import gregtech.api.pipenet.WorldPipeNetBase; +import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.pipenet.edge.SimulatorKey; +import gregtech.api.pipenet.predicate.IPredicateTestObject; + +import org.jetbrains.annotations.ApiStatus; +import org.jgrapht.Graph; + +public interface ICustomGraph & IPipeType, NDT extends INodeData, E extends NetEdge> + extends Graph, E> { + + @ApiStatus.Internal + void setOwningNet(WorldPipeNetBase net); + + void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, + long queryTick); +} diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java index 3da6c7df9c7..195e3e12c91 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -33,6 +33,11 @@ public WorldEnergyNet(String name) { super(name, true, () -> new NetFlowEdge(1), AllPathsAlgorithm::new); } + @Override + protected boolean needsDynamicWeights() { + return true; + } + @Override protected Capability[] getConnectionCapabilities() { return new Capability[] { GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER }; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index 437073864be..dc88745b01b 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -40,6 +40,11 @@ public WorldFluidPipeNet(String name) { super(name, true, () -> new NetFlowEdge(20), AllPathsAlgorithm::new); } + @Override + protected boolean needsDynamicWeights() { + return true; + } + @Override protected Capability[] getConnectionCapabilities() { return new Capability[] { CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY }; From 907526cbce2e1c8a0b33fec5c374d605c86aec4b Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 27 Jun 2024 18:40:39 -0600 Subject: [PATCH 071/157] fix energy net overamping --- ...va => DynamicWeightsShortestPathsAlgorithm.java} | 13 ++++--------- .../api/pipenet/edge/AbstractNetFlowEdge.java | 2 +- .../common/pipelike/cable/net/EnergyNetHandler.java | 2 -- .../common/pipelike/cable/net/WorldEnergyNet.java | 4 ++-- .../pipelike/fluidpipe/net/WorldFluidPipeNet.java | 4 ++-- 5 files changed, 9 insertions(+), 16 deletions(-) rename src/main/java/gregtech/api/pipenet/alg/{AllPathsAlgorithm.java => DynamicWeightsShortestPathsAlgorithm.java} (84%) diff --git a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/DynamicWeightsShortestPathsAlgorithm.java similarity index 84% rename from src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java rename to src/main/java/gregtech/api/pipenet/alg/DynamicWeightsShortestPathsAlgorithm.java index c56690cf7f1..2c379100f24 100644 --- a/src/main/java/gregtech/api/pipenet/alg/AllPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/DynamicWeightsShortestPathsAlgorithm.java @@ -19,13 +19,13 @@ import java.util.Set; import java.util.stream.Collectors; -public class AllPathsAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> +public class DynamicWeightsShortestPathsAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> extends DefaultManyToManyShortestPaths, E> implements INetAlgorithm { private final WorldPipeNetBase pipenet; - public AllPathsAlgorithm(WorldPipeNetBase pipenet) { + public DynamicWeightsShortestPathsAlgorithm(WorldPipeNetBase pipenet) { super(pipenet.getGraph()); this.pipenet = pipenet; } @@ -49,8 +49,6 @@ protected class LimitedIterator implements ICacheableIterator source; private final Set> searchSpace; - private final ManyToManyShortestPaths, E> manyToManyShortestPaths; - private int iterationCount = 0; private final ObjectArrayList> visited = new ObjectArrayList<>(); private NetPath next; @@ -58,19 +56,17 @@ protected class LimitedIterator implements ICacheableIterator source, Set> searchSpace) { this.source = source; this.searchSpace = searchSpace; - this.manyToManyShortestPaths = pipenet.usesDynamicWeights() ? null : getManyToManyPaths(Collections.singleton(source), searchSpace); } public LimitedIterator(NetNode source, Set> searchSpace, ManyToManyShortestPaths, E> manyToManyShortestPaths) { this.source = source; this.searchSpace = searchSpace; - this.manyToManyShortestPaths = manyToManyShortestPaths; } @Override public ICacheableIterator> newCacheableIterator() { - return new LimitedIterator(source, searchSpace, manyToManyShortestPaths); + return new LimitedIterator(source, searchSpace); } @Override @@ -98,8 +94,7 @@ private void calculateNext() { next = new NetPath<>(source); return; } - ManyToManyShortestPaths, E> paths = manyToManyShortestPaths != null ? - manyToManyShortestPaths : getManyToManyPaths(Collections.singleton(source), searchSpace); + ManyToManyShortestPaths, E> paths = getManyToManyPaths(Collections.singleton(source), searchSpace); var iter = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) .map(NetPath::new).sorted(Comparator.comparingDouble(NetPath::getWeight)).iterator(); while (iter.hasNext()) { diff --git a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java index 51d2ab6fea3..06b51bba366 100644 --- a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java @@ -27,7 +27,7 @@ public double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simula if (!cannotSupportChannel(channel, queryTick, simulator)) { return getWeight(); } - return Double.POSITIVE_INFINITY; + return getWeight() * 1000000; } public boolean cannotSupportChannel(Object channel, long queryTick, @Nullable SimulatorKey simulator) { diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java index cc63fa5569a..de5fb643079 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -203,8 +203,6 @@ private long distributionIgnoreCapacity(EnumFacing side, long voltage, long ampe mainloop: while (paths.hasNext()) { NetPath path = paths.next(); - // skip paths where loss exceeds available voltage - if (path.getWeight() > voltage) continue; Iterator iterator = path.getFacingIterator(); boolean pathDestThis = path.getTargetNode().getNodePos().equals(this.cable.getPipePos()); while (iterator.hasNext()) { diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java index 195e3e12c91..37fe20c9a8c 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -3,7 +3,7 @@ import gregtech.api.capability.GregtechCapabilities; import gregtech.api.pipenet.AbstractGroupData; import gregtech.api.pipenet.WorldPipeNetComplex; -import gregtech.api.pipenet.alg.AllPathsAlgorithm; +import gregtech.api.pipenet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.unification.material.properties.WireProperties; @@ -30,7 +30,7 @@ public static WorldEnergyNet getWorldEnergyNet(World world) { } public WorldEnergyNet(String name) { - super(name, true, () -> new NetFlowEdge(1), AllPathsAlgorithm::new); + super(name, true, () -> new NetFlowEdge(1), DynamicWeightsShortestPathsAlgorithm::new); } @Override diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java index dc88745b01b..6bebb251ee6 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java @@ -2,7 +2,7 @@ import gregtech.api.cover.Cover; import gregtech.api.pipenet.WorldPipeNetComplex; -import gregtech.api.pipenet.alg.AllPathsAlgorithm; +import gregtech.api.pipenet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.predicate.AbstractEdgePredicate; import gregtech.api.pipenet.tile.IPipeTile; @@ -37,7 +37,7 @@ public static WorldFluidPipeNet getWorldPipeNet(World world) { } public WorldFluidPipeNet(String name) { - super(name, true, () -> new NetFlowEdge(20), AllPathsAlgorithm::new); + super(name, true, () -> new NetFlowEdge(20), DynamicWeightsShortestPathsAlgorithm::new); } @Override From d6949345d13642945204faf17e6d56fcbb03d112 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 27 Jun 2024 20:13:45 -0600 Subject: [PATCH 072/157] Fully realized dynamic temp limits for cables --- .../gregtech/api/fluids/FluidBuilder.java | 6 ++ .../java/gregtech/api/pipenet/INodeData.java | 11 +-- .../java/gregtech/api/pipenet/NetPath.java | 8 +- .../gregtech/api/pipenet/edge/NetEdge.java | 2 +- .../api/unification/material/Material.java | 20 ++++- .../properties/FluidPipeProperties.java | 2 +- .../properties/ItemPipeProperties.java | 7 +- .../material/properties/WireProperties.java | 76 +++++++++++++++---- .../common/pipelike/cable/BlockCable.java | 2 +- .../common/pipelike/cable/Insulation.java | 7 +- .../common/pipelike/cable/ItemBlockCable.java | 2 +- .../pipelike/cable/net/EnergyNetHandler.java | 28 ++++--- .../pipelike/cable/net/WorldEnergyNet.java | 6 +- .../pipelike/cable/tile/TileEntityCable.java | 22 +----- .../pipelike/itempipe/net/ItemNetHandler.java | 2 +- .../pipelike/laser/LaserPipeProperties.java | 3 +- .../optical/OpticalPipeProperties.java | 3 +- .../material/MaterialPropertyExpansion.java | 6 +- .../groovy/MaterialPropertyExpansion.java | 8 +- 19 files changed, 148 insertions(+), 73 deletions(-) diff --git a/src/main/java/gregtech/api/fluids/FluidBuilder.java b/src/main/java/gregtech/api/fluids/FluidBuilder.java index a7c9d6528ef..28b440edbc0 100644 --- a/src/main/java/gregtech/api/fluids/FluidBuilder.java +++ b/src/main/java/gregtech/api/fluids/FluidBuilder.java @@ -21,6 +21,7 @@ import com.google.common.base.Preconditions; import io.github.drmanganese.topaddons.reference.Colors; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -99,6 +100,11 @@ public FluidBuilder() {} return this; } + @ApiStatus.Internal + public int currentTemp() { + return this.temperature; + } + /** * The color may be in either {@code RGB} or {@code ARGB} format. * RGB format will assume an alpha of {@code 0xFF}. diff --git a/src/main/java/gregtech/api/pipenet/INodeData.java b/src/main/java/gregtech/api/pipenet/INodeData.java index 235bfd3938d..7ed17c339cf 100644 --- a/src/main/java/gregtech/api/pipenet/INodeData.java +++ b/src/main/java/gregtech/api/pipenet/INodeData.java @@ -1,7 +1,7 @@ package gregtech.api.pipenet; import java.util.Collections; -import java.util.Set; +import java.util.List; public interface INodeData> { @@ -17,12 +17,9 @@ default int getThroughput() { return 1; } - /** - * Note - since datas is a set, no summative operations are allowed. - */ - T getMinData(Set datas); + T getSumData(List datas); - default T getMinData(Object data) { - return getMinData(Collections.singleton((T) data)); + default T getSumData(Object data) { + return getSumData(Collections.singletonList((T) data)); } } diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java index 2b95bffc9de..13d365292cc 100644 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ b/src/main/java/gregtech/api/pipenet/NetPath.java @@ -115,11 +115,11 @@ public double getWeight() { return weight; } - public NodeDataType getMinData() { + public NodeDataType getSumData() { // generate min data on-demand and cache it, rather than generating for every path always if (this.data == null) { this.data = sourceNode.getData() - .getMinData(this.nodeList.stream().map(NetNode::getData).collect(Collectors.toSet())); + .getSumData(this.nodeList.stream().map(NetNode::getData).collect(Collectors.toList())); } return data; } @@ -176,8 +176,8 @@ public double getWeight() { return path.getWeight(); } - public NDT getMinData() { - return path.getMinData(); + public NDT getSumData() { + return path.getSumData(); } public boolean checkPredicate(IPredicateTestObject testObject) { diff --git a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java index 1e95cd1f022..3f3e65e92b5 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java @@ -42,7 +42,7 @@ public Predicate getPredicate() { public INodeData> getMinData() { if (this.minData == null) - this.minData = this.getCastSource().getData().getMinData(this.getCastTarget().getData()); + this.minData = this.getCastSource().getData().getSumData(this.getCastTarget().getData()); return this.minData; } diff --git a/src/main/java/gregtech/api/unification/material/Material.java b/src/main/java/gregtech/api/unification/material/Material.java index 8a80801af48..1532faabc24 100644 --- a/src/main/java/gregtech/api/unification/material/Material.java +++ b/src/main/java/gregtech/api/unification/material/Material.java @@ -1033,19 +1033,33 @@ public Builder addOreByproducts(Material... byproducts) { } public Builder cableProperties(long voltage, int amperage, int loss) { - cableProperties((int) voltage, amperage, loss, false); + properties.setProperty(PropertyKey.WIRE, new WireProperties((int) voltage, amperage, loss)); + return this; + } + + public Builder cableProperties(long voltage, int amperage, int loss, int meltTemperature) { + properties.setProperty(PropertyKey.WIRE, new WireProperties((int) voltage, amperage, loss, meltTemperature)); return this; } public Builder cableProperties(long voltage, int amperage, int loss, boolean isSuperCon) { - properties.setProperty(PropertyKey.WIRE, new WireProperties((int) voltage, amperage, loss, isSuperCon)); + return cableProperties(voltage, amperage, loss, 0, isSuperCon); + } + + public Builder cableProperties(long voltage, int amperage, int loss, int meltTemperature, boolean isSuperCon) { + properties.setProperty(PropertyKey.WIRE, new WireProperties((int) voltage, amperage, loss, meltTemperature, isSuperCon)); return this; } public Builder cableProperties(long voltage, int amperage, int loss, boolean isSuperCon, int criticalTemperature) { + return cableProperties(voltage, amperage, loss, 0, isSuperCon, criticalTemperature); + } + + public Builder cableProperties(long voltage, int amperage, int loss, int meltTemperature, boolean isSuperCon, + int criticalTemperature) { properties.setProperty(PropertyKey.WIRE, - new WireProperties((int) voltage, amperage, loss, isSuperCon, criticalTemperature)); + new WireProperties((int) voltage, amperage, loss, meltTemperature, isSuperCon, criticalTemperature)); return this; } diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 91987dfce87..6a17908333c 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -309,7 +309,7 @@ public NodeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBu } @Override - public FluidPipeProperties getMinData(Set datas) { + public FluidPipeProperties getSumData(List datas) { int maxFluidTemperature = this.getMaxFluidTemperature(); int throughput = this.getThroughput(); boolean gasProof = this.isGasProof(); diff --git a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java index 341c8b1b131..ddc825363c4 100644 --- a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java @@ -2,6 +2,7 @@ import gregtech.api.pipenet.INodeData; +import java.util.List; import java.util.Objects; import java.util.Set; @@ -83,12 +84,14 @@ public double getWeightFactor() { } @Override - public ItemPipeProperties getMinData(Set datas) { + public ItemPipeProperties getSumData(List datas) { float transferRate = this.getTransferRate(); + int priority = this.getPriority(); for (ItemPipeProperties data : datas) { transferRate = Math.min(transferRate, data.getTransferRate()); + priority += data.getPriority(); } - return new ItemPipeProperties(-1, transferRate); + return new ItemPipeProperties(priority, transferRate); } @Override diff --git a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java index 8d9b8ce81fc..660383072be 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java @@ -1,11 +1,15 @@ package gregtech.api.unification.material.properties; import gregtech.api.GTValues; +import gregtech.api.fluids.FluidBuilder; +import gregtech.api.fluids.store.FluidStorageKeys; import gregtech.api.pipenet.INodeData; import gregtech.api.unification.material.Material; +import net.minecraftforge.fluids.Fluid; + +import java.util.List; import java.util.Objects; -import java.util.Set; import static gregtech.api.unification.material.info.MaterialFlags.GENERATE_FOIL; @@ -14,22 +18,28 @@ public class WireProperties implements IMaterialProperty, INodeData datas) { + public WireProperties getSumData(List datas) { int amperage = this.getAmperage(); + int voltage = this.getVoltage(); + int loss = this.getLoss(); for (WireProperties data : datas) { amperage = Math.min(amperage, data.getAmperage()); + voltage = Math.min(voltage, data.getVoltage()); + loss += data.getLoss(); } - return new WireProperties(-1, amperage, -1); + return new WireProperties(voltage, amperage, loss); } @Override public boolean equals(Object o) { if (this == o) return true; - if (!(o instanceof WireProperties that)) return false; - return voltage == that.voltage && - amperage == that.amperage && - lossPerBlock == that.lossPerBlock && + if (o == null || getClass() != o.getClass()) return false; + WireProperties that = (WireProperties) o; + return voltage == that.voltage && amperage == that.amperage && lossPerBlock == that.lossPerBlock && + meltTemperature == that.meltTemperature && superconductorCriticalTemperature == that.superconductorCriticalTemperature && isSuperconductor == that.isSuperconductor; } @Override public int hashCode() { - return Objects.hash(voltage, amperage, lossPerBlock); + return Objects.hash(voltage, amperage, lossPerBlock, meltTemperature, superconductorCriticalTemperature, + isSuperconductor); } } diff --git a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java index b9ba309c796..723512f528b 100644 --- a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/BlockCable.java @@ -170,7 +170,7 @@ public void onEntityCollision(World worldIn, @NotNull BlockPos pos, @NotNull IBl if (insulation.insulationLevel == -1 && entityIn instanceof EntityLivingBase) { EntityLivingBase entityLiving = (EntityLivingBase) entityIn; TileEntityCable cable = (TileEntityCable) getPipeTileEntity(worldIn, pos); - if (cable != null && cable.getFrameMaterial() == null && cable.getNodeData().getLossPerBlock() > 0) { + if (cable != null && cable.getFrameMaterial() == null && cable.getNodeData().getLoss() > 0) { long voltage = cable.getCurrentMaxVoltage(); double amperage = cable.getAverageAmperage(); if (voltage > 0L && amperage > 0L) { diff --git a/src/main/java/gregtech/common/pipelike/cable/Insulation.java b/src/main/java/gregtech/common/pipelike/cable/Insulation.java index c1312db34de..5739ad1a3d4 100644 --- a/src/main/java/gregtech/common/pipelike/cable/Insulation.java +++ b/src/main/java/gregtech/common/pipelike/cable/Insulation.java @@ -61,12 +61,13 @@ public boolean isCable() { @Override public WireProperties modifyProperties(WireProperties baseProperties) { int lossPerBlock; - if (!baseProperties.isSuperconductor() && baseProperties.getLossPerBlock() == 0) + if (!baseProperties.isSuperconductor() && baseProperties.getLoss() == 0) lossPerBlock = (int) (0.75 * lossMultiplier); - else lossPerBlock = baseProperties.getLossPerBlock() * lossMultiplier; + else lossPerBlock = baseProperties.getLoss() * lossMultiplier; return new WireProperties(baseProperties.getVoltage(), baseProperties.getAmperage() * amperage, lossPerBlock, - baseProperties.isSuperconductor()); + baseProperties.getMeltTemperature(), baseProperties.isSuperconductor(), + baseProperties.getSuperconductorCriticalTemperature()); } @Override diff --git a/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java b/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java index 05d8d419014..9f8458796ad 100644 --- a/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java @@ -37,7 +37,7 @@ public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @N tooltip.add(I18n.format("gregtech.cable.superconductor", GTValues.VN[tier])); tooltip.add(I18n.format("gregtech.cable.voltage", wireProperties.getVoltage(), GTValues.VNF[tier])); tooltip.add(I18n.format("gregtech.cable.amperage", wireProperties.getAmperage())); - tooltip.add(I18n.format("gregtech.cable.loss_per_block", wireProperties.getLossPerBlock())); + tooltip.add(I18n.format("gregtech.cable.loss_per_block", wireProperties.getLoss())); if (TooltipHelper.isShiftDown()) { tooltip.add(I18n.format("gregtech.tool_action.wire_cutter.connect")); diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java index de5fb643079..961b21aca75 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java @@ -35,7 +35,7 @@ public class EnergyNetHandler implements IEnergyContainer, IPipeNetHandler { protected static final NetNode FAKE_SOURCE = new NetNode<>( - new WireProperties(Integer.MAX_VALUE, Integer.MAX_VALUE, 0, false)); + new WireProperties(Integer.MAX_VALUE, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, false)); private final WorldEnergyNet net; private boolean transfer; @@ -132,7 +132,7 @@ private long distributionRespectCapacity(EnumFacing side, long voltage, long amp while (paths.hasNext()) { NetPath path = paths.next(); // skip paths where loss exceeds available voltage - if (path.getWeight() > voltage) continue; + if (path.getSumData().getLoss() > voltage) continue; Iterator iterator = path.getFacingIterator(); boolean pathDestThis = path.getTargetNode().getNodePos().equals(this.cable.getPipePos()); while (iterator.hasNext()) { @@ -165,12 +165,14 @@ private long distributionRespectCapacity(EnumFacing side, long voltage, long amp flowLimitConsumers.modifyRatios(ratio); TileEntityCable tile = simulator == null ? (TileEntityCable) target.getHeldMTEUnsafe() : null; + long finalVoltage = voltage; flowLimitConsumers.add(edge, null, this.net.getGraph(), pathAmperage, queryTick, simulator, tile != null ? amps -> { tile.contributeAmperageFlow(amps); - tile.contributeVoltageFlow(voltage); + tile.contributeVoltageFlow(finalVoltage); } : null); // voltage loss + voltage -= target.getData().getLoss(); if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) continue mainloop; } // skip paths where we can't transfer amperage @@ -178,8 +180,8 @@ private long distributionRespectCapacity(EnumFacing side, long voltage, long amp // complete transfer this.transfer = true; // actual voltage that reaches the destination is the geometric mean of the input and all the caps - long finalVoltage = (long) GTUtility.geometricMean((double) voltage, - voltageCaps.toArray(new double[] {})); + long finalVoltage = Math.min((long) GTUtility.geometricMean((double) voltage, + voltageCaps.toArray(new double[] {})), voltage); long accepted = dest.acceptEnergyFromNetwork(facedPath.oppositeFacing(), finalVoltage, pathAmperage, simulator != null); this.transfer = false; @@ -203,6 +205,8 @@ private long distributionIgnoreCapacity(EnumFacing side, long voltage, long ampe mainloop: while (paths.hasNext()) { NetPath path = paths.next(); + // skip paths where loss exceeds available voltage + if (path.getSumData().getLoss() > voltage) continue; Iterator iterator = path.getFacingIterator(); boolean pathDestThis = path.getTargetNode().getNodePos().equals(this.cable.getPipePos()); while (iterator.hasNext()) { @@ -228,7 +232,7 @@ private long distributionIgnoreCapacity(EnumFacing side, long voltage, long ampe for (int j = 0; j < nodeList.size(); j++) { NetFlowEdge edge = j == 0 ? inputEdge : edgeList.get(j - 1); NetNode target = nodeList.get(j); - + // amperage capping long flowLimit = edge.getFlowLimit(null, this.net.getGraph(), queryTick, simulator); long finalPathAmperage = pathAmperage; if (simulator == null && finalPathAmperage != 0) { @@ -242,23 +246,29 @@ private long distributionIgnoreCapacity(EnumFacing side, long voltage, long ampe } TileEntityCable tile = simulator == null ? (TileEntityCable) target.getHeldMTEUnsafe() : null; + long finalVoltage = voltage; flowLimitConsumers.add((ratio) -> { long consumption = Math.min((long) (finalPathAmperage * ratio), flowLimit); if (consumption == 0) return; edge.consumeFlowLimit(null, getNet().getGraph(), consumption, queryTick, simulator); if (tile != null) { tile.contributeAmperageFlow(consumption); - tile.contributeVoltageFlow(voltage); + tile.contributeVoltageFlow(finalVoltage); } }); pathAmperage = Math.min(pathAmperage, flowLimit); + // voltage loss + voltage -= target.getData().getLoss(); if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) continue mainloop; } - long finalVoltage = (long) GTUtility.geometricMean((double) voltage, - voltageCaps.toArray(new double[] {})); + // actual voltage that reaches the destination is the geometric mean of the input and all the caps + this.transfer = true; + long finalVoltage = Math.min((long) GTUtility.geometricMean((double) voltage, + voltageCaps.toArray(new double[] {})), voltage); long simulatedAccepted = dest.acceptEnergyFromNetwork(facedPath.oppositeFacing(), finalVoltage, availableAmperage, true); + this.transfer = false; simulatedAccepted = getSimulatedAccepted(localDestSimulationCache, facedPath.toFacingPos(), simulatedAccepted); if (simulator != null) diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java index 37fe20c9a8c..38581010589 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java @@ -57,7 +57,8 @@ protected AbstractGroupData getBlankGroupData() { protected void writeNodeData(WireProperties nodeData, NBTTagCompound tagCompound) { tagCompound.setInteger("voltage", nodeData.getVoltage()); tagCompound.setInteger("amperage", nodeData.getAmperage()); - tagCompound.setInteger("loss", nodeData.getLossPerBlock()); + tagCompound.setInteger("loss", nodeData.getLoss()); + tagCompound.setInteger("meltTemperature", nodeData.getMeltTemperature()); tagCompound.setInteger("critical", nodeData.getSuperconductorCriticalTemperature()); tagCompound.setBoolean("supercond", nodeData.isSuperconductor()); } @@ -67,8 +68,9 @@ protected WireProperties readNodeData(NBTTagCompound tagCompound) { int voltage = tagCompound.getInteger("voltage"); int amperage = tagCompound.getInteger("amperage"); int lossPerBlock = tagCompound.getInteger("loss"); + int meltTemperature = tagCompound.getInteger("meltTemperature"); int critical = tagCompound.getInteger("critical"); boolean supercond = tagCompound.getBoolean("supercond"); - return new WireProperties(voltage, amperage, lossPerBlock, supercond, critical); + return new WireProperties(voltage, amperage, lossPerBlock, meltTemperature, supercond, critical); } } diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java index 07be5d453dd..a4c2af97461 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java @@ -33,6 +33,7 @@ import net.minecraft.util.text.TextFormatting; import net.minecraft.world.WorldServer; import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -51,8 +52,6 @@ public class TileEntityCable extends TileEntityMaterialPipeBase implements IDataInfoProvider { - private int meltTemp = 3000; - private final EnumMap handlers = new EnumMap<>(EnumFacing.class); private final PerTickLongCounter maxVoltageCounter = new PerTickLongCounter(); private final AveragingPerTickCounter averageVoltageCounter = new AveragingPerTickCounter(); @@ -107,7 +106,7 @@ public NodeLossResult applyHeat(int amount, boolean simulate) { double loss = 1; Consumer> destructionResult = null; - if (temperature + amount >= meltTemp) { + if (temperature + amount >= getMeltTemp()) { // cable melted destructionResult = node -> { isTicking = false; @@ -199,12 +198,12 @@ public int getTemperature() { } public int getMeltTemp() { - return meltTemp; + return this.getNodeData().getMeltTemperature(); } @SideOnly(Side.CLIENT) public void createParticle() { - particle = new GTOverheatParticle(this, meltTemp, getPipeBoxes(), getPipeType().insulationLevel >= 0); + particle = new GTOverheatParticle(this, getMeltTemp(), getPipeBoxes(), getPipeType().insulationLevel >= 0); GTParticleManager.INSTANCE.addEffect(particle); } @@ -265,13 +264,6 @@ public int getDefaultPaintingColor() { return 0x404040; } - @Override - public void setPipeData(BlockPipe pipeBlock, Insulation insulation, - Material pipeMaterial) { - super.setPipeData(pipeBlock, insulation, pipeMaterial); - updateMeltTemperature(); - } - @Override public void receiveCustomData(int discriminator, PacketBuffer buf) { if (discriminator == CABLE_TEMPERATURE) { @@ -281,15 +273,9 @@ public void receiveCustomData(int discriminator, PacketBuffer buf) { if (isParticleAlive() && discriminator == UPDATE_CONNECTIONS) { particle.updatePipeBoxes(getPipeBoxes()); } - if (discriminator == UPDATE_PIPE_MATERIAL) updateMeltTemperature(); } } - protected void updateMeltTemperature() { - this.meltTemp = this.getPipeMaterial().getBlastTemperature(); - if (this.meltTemp == 0) this.meltTemp = 1000; - } - @SideOnly(Side.CLIENT) public boolean isParticleAlive() { return particle != null && particle.isAlive(); diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java index 385ddbbb5cd..133da4d47fe 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java @@ -322,7 +322,7 @@ public ItemStack insert(NetPath.FacedNetPath { @@ -9,7 +10,7 @@ public class LaserPipeProperties implements INodeData { public static final LaserPipeProperties INSTANCE = new LaserPipeProperties(); @Override - public LaserPipeProperties getMinData(Set datas) { + public LaserPipeProperties getSumData(List datas) { return this; } } diff --git a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java index b064f7eb83a..045e376d75e 100644 --- a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java +++ b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java @@ -2,6 +2,7 @@ import gregtech.api.pipenet.INodeData; +import java.util.List; import java.util.Set; public class OpticalPipeProperties implements INodeData { @@ -9,7 +10,7 @@ public class OpticalPipeProperties implements INodeData { public static final OpticalPipeProperties INSTANCE = new OpticalPipeProperties(); @Override - public OpticalPipeProperties getMinData(Set datas) { + public OpticalPipeProperties getSumData(List datas) { return this; } } diff --git a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java index bf4624282cb..c9a2560a0d6 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java @@ -247,15 +247,17 @@ public static void addTools(Material m, float toolSpeed, float toolAttackDamage, @ZenMethod public static void addWires(Material m, int voltage, int baseAmperage, int lossPerBlock, - @Optional boolean isSuperCon, @Optional int criticalTemp) { + @Optional boolean isSuperCon, @Optional int criticalTemp, + @Optional int meltTemperature) { if (checkFrozen("add Wires to a material")) return; if (m.hasProperty(PropertyKey.WIRE)) { m.getProperty(PropertyKey.WIRE).setVoltage(voltage); m.getProperty(PropertyKey.WIRE).setAmperage(baseAmperage); m.getProperty(PropertyKey.WIRE).setLossPerBlock(lossPerBlock); + m.getProperty(PropertyKey.WIRE).setMeltTemperature(meltTemperature); m.getProperty(PropertyKey.WIRE).setSuperconductor(isSuperCon); m.getProperty(PropertyKey.WIRE).setSuperconductorCriticalTemperature(criticalTemp); } else m.setProperty(PropertyKey.WIRE, - new WireProperties(voltage, baseAmperage, lossPerBlock, isSuperCon, criticalTemp)); + new WireProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, isSuperCon, criticalTemp)); } } diff --git a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java index 83ceb1b27a7..126ca31e162 100644 --- a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java @@ -329,15 +329,21 @@ public static void addWires(Material m, int voltage, int baseAmperage, int lossP public static void addWires(Material m, int voltage, int baseAmperage, int lossPerBlock, boolean isSuperCon, int criticalTemp) { + addWires(m, voltage, baseAmperage, lossPerBlock, isSuperCon, criticalTemp, 0); + } + + public static void addWires(Material m, int voltage, int baseAmperage, int lossPerBlock, boolean isSuperCon, + int criticalTemp, int meltTemperature) { if (checkFrozen("add Wires to a material")) return; if (m.hasProperty(PropertyKey.WIRE)) { m.getProperty(PropertyKey.WIRE).setVoltage(voltage); m.getProperty(PropertyKey.WIRE).setAmperage(baseAmperage); m.getProperty(PropertyKey.WIRE).setLossPerBlock(lossPerBlock); + m.getProperty(PropertyKey.WIRE).setMeltTemperature(meltTemperature); m.getProperty(PropertyKey.WIRE).setSuperconductor(isSuperCon); m.getProperty(PropertyKey.WIRE).setSuperconductorCriticalTemperature(criticalTemp); } else m.setProperty(PropertyKey.WIRE, - new WireProperties(voltage, baseAmperage, lossPerBlock, isSuperCon, criticalTemp)); + new WireProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, isSuperCon, criticalTemp)); } public static void addCables(Material m, int voltage, int baseAmperage, int lossPerBlock) { From 2d24e7365d233c43833ef1ba1a4d155245029026 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 27 Jun 2024 20:14:06 -0600 Subject: [PATCH 073/157] spotless --- .../java/gregtech/api/pipenet/WorldPipeNetBase.java | 1 - .../alg/DynamicWeightsShortestPathsAlgorithm.java | 10 ++++++---- .../api/pipenet/graph/CustomDirectedGraph.java | 2 +- .../java/gregtech/api/pipenet/graph/ICustomGraph.java | 2 +- .../gregtech/api/unification/material/Material.java | 9 ++++++--- .../material/properties/FluidPipeProperties.java | 1 - .../material/properties/ItemPipeProperties.java | 1 - .../common/pipelike/cable/tile/TileEntityCable.java | 2 -- .../common/pipelike/laser/LaserPipeProperties.java | 1 - .../common/pipelike/optical/OpticalPipeProperties.java | 1 - 10 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java index f7ac8de73bd..6ff6ed68974 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java +++ b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java @@ -542,5 +542,4 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { * Used for reading persistent node data */ protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); - } diff --git a/src/main/java/gregtech/api/pipenet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/DynamicWeightsShortestPathsAlgorithm.java index 2c379100f24..e2fc6e52583 100644 --- a/src/main/java/gregtech/api/pipenet/alg/DynamicWeightsShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/pipenet/alg/DynamicWeightsShortestPathsAlgorithm.java @@ -19,9 +19,10 @@ import java.util.Set; import java.util.stream.Collectors; -public class DynamicWeightsShortestPathsAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> - extends DefaultManyToManyShortestPaths, E> - implements INetAlgorithm { +public class DynamicWeightsShortestPathsAlgorithm & IPipeType, NDT extends INodeData, + E extends NetEdge> + extends DefaultManyToManyShortestPaths, E> + implements INetAlgorithm { private final WorldPipeNetBase pipenet; @@ -94,7 +95,8 @@ private void calculateNext() { next = new NetPath<>(source); return; } - ManyToManyShortestPaths, E> paths = getManyToManyPaths(Collections.singleton(source), searchSpace); + ManyToManyShortestPaths, E> paths = getManyToManyPaths(Collections.singleton(source), + searchSpace); var iter = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) .map(NetPath::new).sorted(Comparator.comparingDouble(NetPath::getWeight)).iterator(); while (iter.hasNext()) { diff --git a/src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java b/src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java index 492fb2909b4..7d74bc0a203 100644 --- a/src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java +++ b/src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java @@ -14,7 +14,7 @@ public class CustomDirectedGraph & IPipeType, NDT extends INodeData, E extends NetEdge> extends SimpleDirectedWeightedGraph, E> - implements ICustomGraph { + implements ICustomGraph { private WorldPipeNetBase net = null; diff --git a/src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java b/src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java index 183915ba6ac..4715d56b31c 100644 --- a/src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java +++ b/src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java @@ -12,7 +12,7 @@ import org.jgrapht.Graph; public interface ICustomGraph & IPipeType, NDT extends INodeData, E extends NetEdge> - extends Graph, E> { + extends Graph, E> { @ApiStatus.Internal void setOwningNet(WorldPipeNetBase net); diff --git a/src/main/java/gregtech/api/unification/material/Material.java b/src/main/java/gregtech/api/unification/material/Material.java index 1532faabc24..0b2478a1ad9 100644 --- a/src/main/java/gregtech/api/unification/material/Material.java +++ b/src/main/java/gregtech/api/unification/material/Material.java @@ -1038,7 +1038,8 @@ public Builder cableProperties(long voltage, int amperage, int loss) { } public Builder cableProperties(long voltage, int amperage, int loss, int meltTemperature) { - properties.setProperty(PropertyKey.WIRE, new WireProperties((int) voltage, amperage, loss, meltTemperature)); + properties.setProperty(PropertyKey.WIRE, + new WireProperties((int) voltage, amperage, loss, meltTemperature)); return this; } @@ -1047,7 +1048,8 @@ public Builder cableProperties(long voltage, int amperage, int loss, boolean isS } public Builder cableProperties(long voltage, int amperage, int loss, int meltTemperature, boolean isSuperCon) { - properties.setProperty(PropertyKey.WIRE, new WireProperties((int) voltage, amperage, loss, meltTemperature, isSuperCon)); + properties.setProperty(PropertyKey.WIRE, + new WireProperties((int) voltage, amperage, loss, meltTemperature, isSuperCon)); return this; } @@ -1059,7 +1061,8 @@ public Builder cableProperties(long voltage, int amperage, int loss, boolean isS public Builder cableProperties(long voltage, int amperage, int loss, int meltTemperature, boolean isSuperCon, int criticalTemperature) { properties.setProperty(PropertyKey.WIRE, - new WireProperties((int) voltage, amperage, loss, meltTemperature, isSuperCon, criticalTemperature)); + new WireProperties((int) voltage, amperage, loss, meltTemperature, isSuperCon, + criticalTemperature)); return this; } diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index 6a17908333c..a7837448e9b 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -31,7 +31,6 @@ import java.util.Collection; import java.util.List; import java.util.Objects; -import java.util.Set; import java.util.function.Consumer; public class FluidPipeProperties implements IMaterialProperty, IPropertyFluidFilter, INodeData { diff --git a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java index ddc825363c4..593e5d49573 100644 --- a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java @@ -4,7 +4,6 @@ import java.util.List; import java.util.Objects; -import java.util.Set; public class ItemPipeProperties implements IMaterialProperty, INodeData { diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java index a4c2af97461..15605ec48f7 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java @@ -10,7 +10,6 @@ import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; import gregtech.api.pipenet.edge.NetFlowEdge; import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.TaskScheduler; import gregtech.api.util.TextFormattingUtil; @@ -33,7 +32,6 @@ import net.minecraft.util.text.TextFormatting; import net.minecraft.world.WorldServer; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; diff --git a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java b/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java index ca03bdf699a..c5afafcb848 100644 --- a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java +++ b/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java @@ -3,7 +3,6 @@ import gregtech.api.pipenet.INodeData; import java.util.List; -import java.util.Set; public class LaserPipeProperties implements INodeData { diff --git a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java index 045e376d75e..b123135f018 100644 --- a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java +++ b/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java @@ -3,7 +3,6 @@ import gregtech.api.pipenet.INodeData; import java.util.List; -import java.util.Set; public class OpticalPipeProperties implements INodeData { From d5f3dd7149333937f9d62f5744cc62f9dcb56d66 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 10 Jul 2024 18:54:18 -0600 Subject: [PATCH 074/157] Complete rewrite pt1 --- .../api/block/machines/BlockMachine.java | 2 +- .../api/block/machines/MachineItemBlock.java | 2 +- .../gregtech/api/cover/CoverRayTracer.java | 2 +- .../api/graphnet/AbstractGroupData.java | 10 + .../gregtech/api/graphnet/GraphNetBacker.java | 242 ++++++++ .../java/gregtech/api/graphnet/IGraphNet.java | 170 ++++++ .../{pipenet => graphnet}/INBTBuilder.java | 2 +- .../api/graphnet/MultiNetNodeHandler.java | 33 ++ .../java/gregtech/api/graphnet/NetGroup.java | 180 ++++++ .../java/gregtech/api/graphnet/NetNode.java | 151 +++++ .../DynamicWeightsShortestPathsAlgorithm.java | 110 ++++ .../api/graphnet/alg/INetAlgorithm.java | 16 + .../api/graphnet/alg/NetAlgorithmWrapper.java | 45 ++ .../api/graphnet/alg/NetPathMapper.java | 39 ++ .../graphnet/alg/ShortestPathsAlgorithm.java | 42 ++ .../api/graphnet/alg/SinglePathAlgorithm.java | 71 +++ .../alg/iter/ICacheableIterator.java | 2 +- .../alg/iter/SimpleCacheableIterator.java | 2 +- .../graphnet/edge/AbstractNetFlowEdge.java | 101 ++++ .../gregtech/api/graphnet/edge/NetEdge.java | 81 +++ .../edge/NetFlowEdge.java | 61 +- .../edge/NetFlowSharedEdge.java | 61 +- .../edge/SimulatorKey.java | 2 +- .../edge/util/FlowConsumer.java | 24 +- .../edge/util/FlowConsumerList.java | 22 +- .../graphnet/gather/GTGraphGatherables.java | 56 ++ .../graphnet/gather/GatherLogicsEvent.java | 21 + .../gather/GatherPredicatesEvent.java | 21 + .../api/graphnet/graph/GraphEdge.java | 45 ++ .../api/graphnet/graph/GraphVertex.java | 34 ++ .../api/graphnet/graph/INetGraph.java | 20 + .../api/graphnet/graph/NetDirectedGraph.java | 65 +++ .../graphnet/graph/NetUndirectedGraph.java | 65 +++ .../logic/AbstractDoubleLogicData.java | 32 + .../graphnet/logic/AbstractIntLogicData.java | 31 + .../api/graphnet/logic/ChannelCountLogic.java | 20 + .../api/graphnet/logic/INetLogicEntry.java | 22 + .../api/graphnet/logic/LossAbsoluteLogic.java | 20 + .../graphnet/logic/MultiNetCountLogic.java | 20 + .../api/graphnet/logic/NetLogicData.java | 100 ++++ .../api/graphnet/logic/ThroughputLogic.java | 20 + .../api/graphnet/logic/WeightFactorLogic.java | 21 + .../api/graphnet/path/AbstractNetPath.java | 36 ++ .../graphnet/path/GenericGraphNetPath.java | 35 ++ .../gregtech/api/graphnet/path/INetPath.java | 19 + .../pipenet/BasicWorldPipeNetPath.java | 34 ++ .../pipenet/FlowWorldPipeNetPath.java | 34 ++ .../graphnet/pipenet/IPipeNetNodeHandler.java | 12 + .../api/graphnet/pipenet/WorldPipeNet.java | 110 ++++ .../graphnet/pipenet/WorldPipeNetNode.java | 47 ++ .../pipenet/block/CableStructure.java | 11 + .../pipenet/block/IPipeStructure.java | 6 + .../api/graphnet/pipenet/block/PipeBlock.java | 96 +++ .../pipenet/block/PipeMaterialBlock.java | 144 +++++ .../pipenetold}/IBlockAppearance.java | 2 +- .../api/graphnet/pipenetold/IPipeNetData.java | 15 + .../pipenetold}/IPipeNetHandler.java | 4 +- .../api/graphnet/pipenetold/NetPath.java | 4 + .../graphnet/pipenetold/NodeLossResult.java | 20 + .../pipenetold/PipeNetNode.java} | 150 ++--- .../api/graphnet/pipenetold/PipeNetPath.java | 117 ++++ .../graphnet/pipenetold/WorldPipeNetBase.java | 419 ++++++++++++++ .../pipenetold}/WorldPipeNetComplex.java | 22 +- .../pipenetold}/WorldPipeNetSimple.java | 22 +- .../pipenetold}/block/BlockPipe.java | 18 +- .../graphnet/pipenetold/block/IPipeType.java | 14 + .../pipenetold}/block/ItemBlockPipe.java | 8 +- .../block/material/BlockMaterialPipe.java | 18 +- .../block/material/IMaterialPipeTile.java | 14 + .../block/material/IMaterialPipeType.java | 8 +- .../block/material/ItemBlockMaterialPipe.java | 8 +- .../material/TileEntityMaterialPipeBase.java | 14 +- .../block/simple/BlockSimplePipe.java | 18 +- .../longdist/BlockLongDistancePipe.java | 2 +- .../pipenetold}/longdist/ILDEndpoint.java | 2 +- .../pipenetold}/longdist/ILDNetworkPart.java | 2 +- .../longdist/LongDistanceNetwork.java | 4 +- .../longdist/LongDistancePipeType.java | 6 +- .../pipenetold}/longdist/NetworkBuilder.java | 2 +- .../predicate/FilteredEdgePredicate.java | 4 +- .../predicate/IShutteredEdgePredicate.java | 2 +- .../predicate/ShutteredEdgePredicate.java} | 13 +- .../pipenetold}/tile/IPipeTile.java | 16 +- .../tile/PipeCoverableImplementation.java | 4 +- .../pipenetold}/tile/TileEntityPipeBase.java | 36 +- .../predicate/EdgePredicateHandler.java | 86 +++ .../graphnet/predicate/IEdgePredicate.java | 33 ++ .../predicate/test}/FluidTestObject.java | 2 +- .../predicate/test/IPredicateTestObject.java | 4 + .../predicate/test}/ItemTestObject.java | 2 +- .../api/graphnet/servernet/ServerNet.java | 126 ++++ .../api/graphnet/servernet/ServerNetNode.java | 38 ++ .../api/graphnet/worldnet/WorldNet.java | 155 +++++ .../api/graphnet/worldnet/WorldNetNode.java | 46 ++ .../multiblock/MultiblockControllerBase.java | 2 +- .../api/pipenet/AbstractGroupData.java | 14 - .../java/gregtech/api/pipenet/INodeData.java | 25 - .../java/gregtech/api/pipenet/NetGroup.java | 249 -------- .../java/gregtech/api/pipenet/NetPath.java | 195 ------- .../gregtech/api/pipenet/NodeLossResult.java | 20 - .../api/pipenet/WorldPipeNetBase.java | 545 ------------------ .../DynamicWeightsShortestPathsAlgorithm.java | 119 ---- .../api/pipenet/alg/INetAlgorithm.java | 42 -- .../pipenet/alg/ShortestPathsAlgorithm.java | 44 -- .../api/pipenet/alg/SinglePathAlgorithm.java | 64 -- .../gregtech/api/pipenet/block/IPipeType.java | 14 - .../block/material/IMaterialPipeTile.java | 14 - .../api/pipenet/edge/AbstractNetFlowEdge.java | 108 ---- .../java/gregtech/api/pipenet/edge/IEdge.java | 12 - .../gregtech/api/pipenet/edge/NetEdge.java | 135 ----- .../pipenet/graph/CustomDirectedGraph.java | 56 -- .../pipenet/graph/CustomUndirectedGraph.java | 55 -- .../api/pipenet/graph/ICustomGraph.java | 22 - .../predicate/AbstractEdgePredicate.java | 63 -- .../predicate/IPredicateTestObject.java | 3 - .../properties/FluidPipeProperties.java | 40 +- .../properties/ItemPipeProperties.java | 4 +- .../properties/PipeNetProperties.java | 56 ++ .../material/properties/PropertyKey.java | 1 + .../material/properties/WireProperties.java | 4 +- .../java/gregtech/api/util/DimensionPos.java | 39 ++ .../java/gregtech/api/util/GTStringUtils.java | 2 +- .../api/util/function/TriFunction.java | 7 + .../client/particle/GTOverheatParticle.java | 2 +- .../client/renderer/pipe/CableRenderer.java | 10 +- .../renderer/pipe/FluidPipeRenderer.java | 8 +- .../renderer/pipe/ItemPipeRenderer.java | 8 +- .../renderer/pipe/LaserPipeRenderer.java | 10 +- .../renderer/pipe/OpticalPipeRenderer.java | 10 +- .../client/renderer/pipe/PipeRenderer.java | 14 +- .../client/utils/FacadeBlockAccess.java | 2 +- .../java/gregtech/common/CommonProxy.java | 20 +- .../java/gregtech/common/EventHandlers.java | 4 +- .../gregtech/common/ToolEventHandlers.java | 6 +- .../gregtech/common/blocks/BlockFrame.java | 8 +- .../gregtech/common/blocks/MetaBlocks.java | 42 +- .../blocks/properties/PropertyByte.java | 92 +++ .../common/command/CommandRecipeCheck.java | 2 +- .../gregtech/common/covers/CoverConveyor.java | 2 +- .../common/covers/CoverRoboticArm.java | 2 +- .../filter/oreglob/impl/NodeInterpreter.java | 2 +- .../filter/oreglob/impl/NodeOreGlob.java | 2 +- .../gui/widget/monitor/WidgetCoverList.java | 2 +- .../items/behaviors/ColorSprayBehaviour.java | 2 +- .../items/behaviors/TricorderBehavior.java | 4 +- .../metatileentities/MetaTileEntities.java | 4 +- .../MetaTileEntityWorldAccelerator.java | 2 +- .../MetaTileEntityMonitorScreen.java | 2 +- .../MetaTileEntityComputationHatch.java | 2 +- .../MetaTileEntityOpticalDataHatch.java | 2 +- .../MetaTileEntityLongDistanceEndpoint.java | 6 +- .../pipelike/block/CableEnergyProperties.java | 58 ++ .../pipelike/block/PipeFluidProperties.java | 4 + .../pipelike/block/PipeItemProperties.java | 4 + .../common/pipelike/net/EnergyNet.java | 42 ++ .../java/gregtech/common/pipelike/temp.java | 4 + .../cable/BlockCable.java | 16 +- .../cable/Insulation.java | 4 +- .../cable/ItemBlockCable.java | 6 +- .../cable/net/EnergyGroupData.java | 8 +- .../cable/net/EnergyNetHandler.java | 60 +- .../cable/net/WorldEnergyNet.java | 20 +- .../cable/tile/AveragingPerTickCounter.java | 2 +- .../cable/tile/PerTickLongCounter.java | 2 +- .../cable/tile/TileEntityCable.java | 24 +- .../cable/tile/TileEntityCableTickable.java | 2 +- .../fluidpipe/BlockFluidPipe.java | 24 +- .../fluidpipe/FluidPipeType.java | 4 +- .../fluidpipe/ItemBlockFluidPipe.java | 6 +- .../longdistance/LDFluidPipeType.java | 4 +- .../MetaTileEntityLDFluidEndpoint.java | 4 +- .../fluidpipe/net/FluidEdgePredicate.java | 10 +- .../fluidpipe/net/FluidNetHandler.java | 48 +- .../fluidpipe/net/WorldFluidPipeNet.java | 44 +- .../fluidpipe/tile/TileEntityFluidPipe.java | 14 +- .../tile/TileEntityFluidPipeTickable.java | 2 +- .../itempipe/BlockItemPipe.java | 16 +- .../itempipe/ItemBlockItemPipe.java | 6 +- .../itempipe/ItemPipeType.java | 4 +- .../itempipe/longdistance/LDItemPipeType.java | 4 +- .../MetaTileEntityLDItemEndpoint.java | 4 +- .../itempipe/net/ItemEdgePredicate.java | 10 +- .../itempipe/net/ItemNetHandler.java | 52 +- .../itempipe/net/WorldItemPipeNet.java | 15 +- .../itempipe/tile/TileEntityItemPipe.java | 14 +- .../tile/TileEntityItemPipeTickable.java | 2 +- .../laser/BlockLaserPipe.java | 14 +- .../laser/ItemBlockLaserPipe.java | 8 +- .../laser/LaserPipeProperties.java | 6 +- .../laser/LaserPipeType.java | 4 +- .../laser/net/LaserNetHandler.java | 22 +- .../laser/net/WorldLaserPipeNet.java | 14 +- .../laser/tile/TileEntityLaserPipe.java | 16 +- .../optical/BlockOpticalPipe.java | 14 +- .../optical/ItemBlockOpticalPipe.java | 4 +- .../optical/OpticalPipeProperties.java | 6 +- .../optical/OpticalPipeType.java | 4 +- .../optical/net/OpticalNetHandler.java | 24 +- .../optical/net/WorldOpticalPipeNet.java | 14 +- .../optical/tile/TileEntityOpticalPipe.java | 16 +- .../integration/RecipeCompatUtil.java | 2 +- .../recipe/MetaItemBracketHandler.java | 6 +- .../groovy/GroovyScriptModule.java | 6 +- .../theoneprobe/provider/LDPipeProvider.java | 4 +- .../debug/DebugPipeNetInfoProvider.java | 14 +- 205 files changed, 4584 insertions(+), 2533 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/AbstractGroupData.java create mode 100644 src/main/java/gregtech/api/graphnet/GraphNetBacker.java create mode 100644 src/main/java/gregtech/api/graphnet/IGraphNet.java rename src/main/java/gregtech/api/{pipenet => graphnet}/INBTBuilder.java (70%) create mode 100644 src/main/java/gregtech/api/graphnet/MultiNetNodeHandler.java create mode 100644 src/main/java/gregtech/api/graphnet/NetGroup.java create mode 100644 src/main/java/gregtech/api/graphnet/NetNode.java create mode 100644 src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java create mode 100644 src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java create mode 100644 src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java create mode 100644 src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java create mode 100644 src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java create mode 100644 src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java rename src/main/java/gregtech/api/{pipenet => graphnet}/alg/iter/ICacheableIterator.java (81%) rename src/main/java/gregtech/api/{pipenet => graphnet}/alg/iter/SimpleCacheableIterator.java (96%) create mode 100644 src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java create mode 100644 src/main/java/gregtech/api/graphnet/edge/NetEdge.java rename src/main/java/gregtech/api/{pipenet => graphnet}/edge/NetFlowEdge.java (63%) rename src/main/java/gregtech/api/{pipenet => graphnet}/edge/NetFlowSharedEdge.java (65%) rename src/main/java/gregtech/api/{pipenet => graphnet}/edge/SimulatorKey.java (94%) rename src/main/java/gregtech/api/{pipenet => graphnet}/edge/util/FlowConsumer.java (67%) rename src/main/java/gregtech/api/{pipenet => graphnet}/edge/util/FlowConsumerList.java (54%) create mode 100644 src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java create mode 100644 src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java create mode 100644 src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java create mode 100644 src/main/java/gregtech/api/graphnet/graph/GraphEdge.java create mode 100644 src/main/java/gregtech/api/graphnet/graph/GraphVertex.java create mode 100644 src/main/java/gregtech/api/graphnet/graph/INetGraph.java create mode 100644 src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java create mode 100644 src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/LossAbsoluteLogic.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/NetLogicData.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java create mode 100644 src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java create mode 100644 src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java create mode 100644 src/main/java/gregtech/api/graphnet/path/INetPath.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/block/CableStructure.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/block/IPipeStructure.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/block/PipeBlock.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/block/PipeMaterialBlock.java rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/IBlockAppearance.java (96%) create mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetData.java rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/IPipeNetHandler.java (89%) create mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/NetPath.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/NodeLossResult.java rename src/main/java/gregtech/api/{pipenet/NetNode.java => graphnet/pipenetold/PipeNetNode.java} (62%) create mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/PipeNetPath.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/WorldPipeNetComplex.java (82%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/WorldPipeNetSimple.java (76%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/block/BlockPipe.java (98%) create mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/block/IPipeType.java rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/block/ItemBlockPipe.java (91%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/block/material/BlockMaterialPipe.java (88%) create mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeTile.java rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/block/material/IMaterialPipeType.java (50%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/block/material/ItemBlockMaterialPipe.java (78%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/block/material/TileEntityMaterialPipeBase.java (90%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/block/simple/BlockSimplePipe.java (70%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/longdist/BlockLongDistancePipe.java (99%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/longdist/ILDEndpoint.java (97%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/longdist/ILDNetworkPart.java (94%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/longdist/LongDistanceNetwork.java (99%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/longdist/LongDistancePipeType.java (92%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/longdist/NetworkBuilder.java (99%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/predicate/FilteredEdgePredicate.java (96%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/predicate/IShutteredEdgePredicate.java (75%) rename src/main/java/gregtech/api/{pipenet/predicate/BasicEdgePredicate.java => graphnet/pipenetold/predicate/ShutteredEdgePredicate.java} (79%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/tile/IPipeTile.java (83%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/tile/PipeCoverableImplementation.java (98%) rename src/main/java/gregtech/api/{pipenet => graphnet/pipenetold}/tile/TileEntityPipeBase.java (94%) create mode 100644 src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java create mode 100644 src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java rename src/main/java/gregtech/api/{pipenet/predicate => graphnet/predicate/test}/FluidTestObject.java (95%) create mode 100644 src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java rename src/main/java/gregtech/api/{pipenet/predicate => graphnet/predicate/test}/ItemTestObject.java (95%) create mode 100644 src/main/java/gregtech/api/graphnet/servernet/ServerNet.java create mode 100644 src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java create mode 100644 src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java create mode 100644 src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java delete mode 100644 src/main/java/gregtech/api/pipenet/AbstractGroupData.java delete mode 100644 src/main/java/gregtech/api/pipenet/INodeData.java delete mode 100644 src/main/java/gregtech/api/pipenet/NetGroup.java delete mode 100644 src/main/java/gregtech/api/pipenet/NetPath.java delete mode 100644 src/main/java/gregtech/api/pipenet/NodeLossResult.java delete mode 100644 src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java delete mode 100644 src/main/java/gregtech/api/pipenet/alg/DynamicWeightsShortestPathsAlgorithm.java delete mode 100644 src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java delete mode 100644 src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java delete mode 100644 src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java delete mode 100644 src/main/java/gregtech/api/pipenet/block/IPipeType.java delete mode 100644 src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java delete mode 100644 src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java delete mode 100644 src/main/java/gregtech/api/pipenet/edge/IEdge.java delete mode 100644 src/main/java/gregtech/api/pipenet/edge/NetEdge.java delete mode 100644 src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java delete mode 100644 src/main/java/gregtech/api/pipenet/graph/CustomUndirectedGraph.java delete mode 100644 src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java delete mode 100644 src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java delete mode 100644 src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java create mode 100644 src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java create mode 100644 src/main/java/gregtech/api/util/DimensionPos.java create mode 100644 src/main/java/gregtech/api/util/function/TriFunction.java create mode 100644 src/main/java/gregtech/common/blocks/properties/PropertyByte.java create mode 100644 src/main/java/gregtech/common/pipelike/block/CableEnergyProperties.java create mode 100644 src/main/java/gregtech/common/pipelike/block/PipeFluidProperties.java create mode 100644 src/main/java/gregtech/common/pipelike/block/PipeItemProperties.java create mode 100644 src/main/java/gregtech/common/pipelike/net/EnergyNet.java create mode 100644 src/main/java/gregtech/common/pipelike/temp.java rename src/main/java/gregtech/common/{pipelike => pipelikeold}/cable/BlockCable.java (94%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/cable/Insulation.java (95%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/cable/ItemBlockCable.java (92%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/cable/net/EnergyGroupData.java (69%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/cable/net/EnergyNetHandler.java (86%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/cable/net/WorldEnergyNet.java (81%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/cable/tile/AveragingPerTickCounter.java (98%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/cable/tile/PerTickLongCounter.java (97%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/cable/tile/TileEntityCable.java (94%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/cable/tile/TileEntityCableTickable.java (87%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/fluidpipe/BlockFluidPipe.java (90%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/fluidpipe/FluidPipeType.java (95%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/fluidpipe/ItemBlockFluidPipe.java (91%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/fluidpipe/longdistance/LDFluidPipeType.java (72%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java (97%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/fluidpipe/net/FluidEdgePredicate.java (74%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/fluidpipe/net/FluidNetHandler.java (85%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/fluidpipe/net/WorldFluidPipeNet.java (63%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/fluidpipe/tile/TileEntityFluidPipe.java (94%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/fluidpipe/tile/TileEntityFluidPipeTickable.java (85%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/itempipe/BlockItemPipe.java (90%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/itempipe/ItemBlockItemPipe.java (91%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/itempipe/ItemPipeType.java (95%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/itempipe/longdistance/LDItemPipeType.java (72%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java (97%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/itempipe/net/ItemEdgePredicate.java (74%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/itempipe/net/ItemNetHandler.java (88%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/itempipe/net/WorldItemPipeNet.java (88%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/itempipe/tile/TileEntityItemPipe.java (90%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/itempipe/tile/TileEntityItemPipeTickable.java (85%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/laser/BlockLaserPipe.java (93%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/laser/ItemBlockLaserPipe.java (84%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/laser/LaserPipeProperties.java (56%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/laser/LaserPipeType.java (83%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/laser/net/LaserNetHandler.java (83%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/laser/net/WorldLaserPipeNet.java (79%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/laser/tile/TileEntityLaserPipe.java (94%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/optical/BlockOpticalPipe.java (92%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/optical/ItemBlockOpticalPipe.java (90%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/optical/OpticalPipeProperties.java (56%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/optical/OpticalPipeType.java (83%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/optical/net/OpticalNetHandler.java (86%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/optical/net/WorldOpticalPipeNet.java (79%) rename src/main/java/gregtech/common/{pipelike => pipelikeold}/optical/tile/TileEntityOpticalPipe.java (93%) diff --git a/src/main/java/gregtech/api/block/machines/BlockMachine.java b/src/main/java/gregtech/api/block/machines/BlockMachine.java index 181c670d540..bf6ad133c20 100644 --- a/src/main/java/gregtech/api/block/machines/BlockMachine.java +++ b/src/main/java/gregtech/api/block/machines/BlockMachine.java @@ -12,7 +12,7 @@ import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; -import gregtech.api.pipenet.IBlockAppearance; +import gregtech.api.graphnet.pipenetold.IBlockAppearance; import gregtech.api.util.GTUtility; import gregtech.api.util.Mods; import gregtech.client.renderer.handler.MetaTileEntityRenderer; diff --git a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java index 80bb7c71331..cd4a76b33ac 100644 --- a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java +++ b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java @@ -4,7 +4,7 @@ import gregtech.api.GregTechAPI; import gregtech.api.metatileentity.ITieredMetaTileEntity; import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.pipenet.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; import gregtech.api.util.GTUtility; import gregtech.api.util.LocalizationUtils; import gregtech.client.utils.TooltipHelper; diff --git a/src/main/java/gregtech/api/cover/CoverRayTracer.java b/src/main/java/gregtech/api/cover/CoverRayTracer.java index e8507cb7665..ef9ec827ef6 100644 --- a/src/main/java/gregtech/api/cover/CoverRayTracer.java +++ b/src/main/java/gregtech/api/cover/CoverRayTracer.java @@ -1,6 +1,6 @@ package gregtech.api.cover; -import gregtech.api.pipenet.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; import gregtech.api.util.GTUtility; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/gregtech/api/graphnet/AbstractGroupData.java b/src/main/java/gregtech/api/graphnet/AbstractGroupData.java new file mode 100644 index 00000000000..4a798ad8257 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/AbstractGroupData.java @@ -0,0 +1,10 @@ +package gregtech.api.graphnet; + +public abstract class AbstractGroupData { + + protected NetGroup group; + + public void withGroup(NetGroup group) { + this.group = group; + } +} diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java new file mode 100644 index 00000000000..7b566c7b377 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -0,0 +1,242 @@ +package gregtech.api.graphnet; + +import gregtech.api.graphnet.alg.INetAlgorithm; +import gregtech.api.graphnet.alg.NetAlgorithmWrapper; +import gregtech.api.graphnet.alg.NetPathMapper; +import gregtech.api.graphnet.alg.iter.ICacheableIterator; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.INetGraph; + +import gregtech.api.graphnet.graph.GraphVertex; + +import gregtech.api.graphnet.path.INetPath; + +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.nbt.NBTTagCompound; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.Iterator; +import java.util.function.Function; + +/** + * The bridge between JGraphT graphs and graphnet abstractions. + * Doesn't do any automatic linking, weighting, predicating, etc. Simply handles storing the JGraphT graph to disk, + * interfacing with graph algorithms, and interacting with the JGraphT graph. + */ +public final class GraphNetBacker { + + private final INetGraph pipeGraph; + private final Object2ObjectOpenHashMap vertexMap; + private final NetAlgorithmWrapper netAlgorithm; + + public GraphNetBacker(IGraphNet backedNet, Function algorithmBuilder, + INetGraph graph) { + graph.setOwningNet(this); + this.pipeGraph = graph; + this.netAlgorithm = new NetAlgorithmWrapper(backedNet, algorithmBuilder); + this.vertexMap = new Object2ObjectOpenHashMap<>(); + } + + public void addNode(NetNode node) { + GraphVertex vertex = new GraphVertex(node); + getGraph().addVertex(vertex); + this.vertexMap.put(node.getEquivalencyData(), vertex); + } + + @Nullable + public NetNode getNode(Object equivalencyData) { + GraphVertex vertex = this.vertexMap.get(equivalencyData); + return vertex == null ? null : vertex.wrapped; + } + + public boolean removeNode(@Nullable NetNode node) { + if (node != null) { + if (this.getGraph().edgesOf(node.wrapper).size() != 0) this.invalidateAlg(); + if (node.getGroupUnsafe() != null) { + node.getGroupUnsafe().splitNode(node); + } else this.removeVertex(node.wrapper); + return true; + } else return false; + } + + @ApiStatus.Internal + public void removeVertex(GraphVertex vertex) { + this.getGraph().removeVertex(vertex); + this.vertexMap.remove(vertex.wrapped.getEquivalencyData()); + } + + @Nullable + public NetEdge addEdge(NetNode source, NetNode target, double weight) { + GraphEdge graphEdge = getGraph().addEdge(source.wrapper, target.wrapper); + if (graphEdge != null) getGraph().setEdgeWeight(graphEdge, weight); + return graphEdge == null ? null : graphEdge.wrapped; + } + + @Nullable + public NetEdge getEdge(NetNode source, NetNode target) { + GraphEdge graphEdge = getGraph().getEdge(source.wrapper, target.wrapper); + return graphEdge == null ? null : graphEdge.wrapped; + } + + public boolean removeEdge(NetNode source, NetNode target) { + if (source.getGroupUnsafe() == null) { + return removeEdge(source.wrapper, target.wrapper) != null; + } else return source.getGroupUnsafe().splitEdge(source, target); + } + + @ApiStatus.Internal + public GraphEdge removeEdge(GraphVertex source, GraphVertex target) { + return this.getGraph().removeEdge(source, target); + } + + @ApiStatus.Internal + public void removeEdge(GraphEdge edge) { + this.getGraph().removeEdge(edge); + } + + public boolean dynamicWeights() { + return netAlgorithm.supportsDynamicWeights(); + } + + /** + * Note - if an error is thrown with a stacktrace descending from this method, + * most likely a bad remapper was passed in.
+ * This method should never be exposed outside the net this backer is backing due to this fragility. + */ + public > Iterator getPaths(@Nullable NetNode node, @NotNull NetPathMapper remapper) { + if (node == null) return Collections.emptyIterator(); + + Iterator> cache = node.getPathCache(); + if (cache != null) return (Iterator) cache; + + Iterator iter = this.netAlgorithm.getPathsIterator(node.wrapper, remapper); + if (iter instanceof ICacheableIterator) { + return (Iterator) node.setPathCache((ICacheableIterator) iter); + } else return iter; + } + + public void invalidateAlg() { + this.netAlgorithm.invalidate(); + } + + public INetGraph getGraph() { + return pipeGraph; + } + + // PROPOSAL FOR ALTERNATIVE STORAGE MECHANISM TO REDUCE MEMORY COSTS + // > Always loaded & nbt stored data: + // map & weak map of group ids to groups. No references to group objects exist outside of this, only references to grou ids. + // (for pipenet) pipes store a reference to their group id + // > Disk-stored data: + // contents of groups, specifically their nodes and edges. + // > Impl (for pipenet) + // When a pipe is loaded, it goes fetch its group and tells it the pipe's chunk. This chunk is added to a *set* of chunks that are 'loading' this group. + // When a chunk is unloaded, it is removed from the set of 'loading' chunks for all groups. + // When the set of 'loading' chunks for a group is empty, the group writes its data to disk and removes itself from the map and the graph but not the weak map. + // (proposal - create a graph impl that allows for weak references to vertices and edges, in order to remove need for explicit removal of group from graph?) + // When a pipe fetches its group, if the group is not found in the map, it then checks the weak map. + // If found in the weak map, the pipe's chunk is added to the 'loading' chunks and a reference to the group is added to the map and the contents are added to the graph. + // If not found in the weak map, the group is instead read from disk and initialized. + // > Benefits of this Impl + // By only loading the (potentially) large number of edges and nodes into the graph that a group contains when that group is needed, + // the number of unnecessary references in the graphnet on, say, a large server is drastically reduced. + // however, since there are necessarily more read/write actions to disk, the cpu load would increase in turn. + + public void readFromNBT(NBTTagCompound nbt) { + // construct map of node ids -> nodes, while building nodes to groups + // construct edges using map + Int2ObjectOpenHashMap groupMap = new Int2ObjectOpenHashMap<>(); + NBTTagCompound vertices = nbt.getCompoundTag("Vertices"); + int vertexCount = vertices.getInteger("Count"); + Int2ObjectOpenHashMap vertexMap = new Int2ObjectOpenHashMap<>(vertexCount); + for (int i = 0; i < vertexCount; i++) { + NBTTagCompound tag = vertices.getCompoundTag(String.valueOf(i)); + NetNode node = this.netAlgorithm.getNet().getNewNode(); + node.deserializeNBT(tag); + if (tag.hasKey("GroupID")) { + int id = tag.getInteger("GroupID"); + NetGroup group = groupMap.get(id); + if (group == null) { + group = new NetGroup(this.netAlgorithm.getNet()); + groupMap.put(id, group); + } + group.addNode(node); + } + GraphVertex vertex = new GraphVertex(node); + this.getGraph().addVertex(vertex); + vertexMap.put(i, vertex); + this.vertexMap.put(node.getEquivalencyData(), vertex); + } + + NBTTagCompound edges = nbt.getCompoundTag("Edges"); + int edgeCount = edges.getInteger("Count"); + for (int i = 0; i < edgeCount; i++) { + NBTTagCompound tag = edges.getCompoundTag(String.valueOf(i)); + GraphEdge graphEdge = this.getGraph().addEdge(vertexMap.get(tag.getInteger("SourceID")), vertexMap.get(tag.getInteger("TargetID"))); + this.getGraph().setEdgeWeight(graphEdge, tag.getDouble("Weight")); + graphEdge.wrapped.deserializeNBT(tag); + } + } + + public NBTTagCompound writeToNBT(NBTTagCompound compound) { + // map of net groups -> autogenerated ids; + // tag of autogenerated vertex ids -> node nbt & group id + // tag of autogenerated edge ids -> edge nbt & source/target ids + Object2IntOpenHashMap groupMap = new Object2IntOpenHashMap<>(); + Object2IntOpenHashMap vertexMap = new Object2IntOpenHashMap<>(); + int i = -1; + int g = 0; + NBTTagCompound vertices = new NBTTagCompound(); + for (GraphVertex graphVertex : this.getGraph().vertexSet()) { + vertexMap.put(graphVertex, i++); + NetGroup group = graphVertex.wrapped.getGroupUnsafe(); + NBTTagCompound tag = graphVertex.wrapped.serializeNBT(); + if (group != null) { + int groupID; + if (!groupMap.containsKey(group)) { + groupMap.put(group, g++); + groupID = g; + } else groupID = groupMap.getInt(group); + tag.setInteger("GroupID", groupID); + } + vertices.setTag(String.valueOf(i), tag); + } + vertices.setInteger("Count", i + 1); + compound.setTag("Vertices", vertices); + + i = -1; + NBTTagCompound edges = new NBTTagCompound(); + for (GraphEdge graphEdge : this.getGraph().edgeSet()) { + NBTTagCompound tag = graphEdge.wrapped.serializeNBT(); + tag.setInteger("SourceID", vertexMap.getInt(getSource(graphEdge))); + tag.setInteger("TargetID", vertexMap.getInt(getTarget(graphEdge))); + tag.setDouble("Weight", getWeight(graphEdge)); + edges.setTag(String.valueOf(i++), tag); + } + edges.setInteger("Count", i + 1); + compound.setTag("Edges", edges); + + return compound; + } + + private GraphVertex getSource(GraphEdge graphEdge) { + return this.getGraph().getEdgeSource(graphEdge); + } + + private GraphVertex getTarget(GraphEdge graphEdge) { + return this.getGraph().getEdgeTarget(graphEdge); + } + + private double getWeight(GraphEdge graphEdge) { + return this.getGraph().getEdgeWeight(graphEdge); + } +} diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java new file mode 100644 index 00000000000..632ca6ae617 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -0,0 +1,170 @@ +package gregtech.api.graphnet; + +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.INetGraph; + +import gregtech.api.graphnet.graph.GraphVertex; + +import gregtech.api.graphnet.logic.NetLogicData; + +import gregtech.api.graphnet.logic.WeightFactorLogic; + +import gregtech.api.graphnet.worldnet.WorldNetNode; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.traverse.BreadthFirstIterator; + +import java.util.Iterator; + +public interface IGraphNet { + + /** + * Adds a node to the graphnet. + * @param node The node to add. + */ + void addNode(@NotNull NetNode node); + + /** + * Gets the net node with the given equivalency data, if one exists. + * @param equivalencyData the equivalency data to match. + * @return the matching net node, if one exists. + */ + @Nullable + NetNode getNode(@NotNull Object equivalencyData); + + /** + * Removes a node from the graphnet. + * @param node The node to remove. + */ + void removeNode(@NotNull NetNode node); + + /** + * Links two nodes by an edge. + * @param source Source node. + * @param target Target node. + * @param bothWays If the graph is directional, passing in true will create both the forwards and backwards edge. + * @return the created edge, if it was created. Returns null if bothWays is set to true. + */ + @Nullable + @Contract("_, _, false -> _; _, _, true -> null") + NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays); + + /** + * Returns the edge linking two nodes together, if one exists. + * @param source Source node. + * @param target Target node. + * @return the linking edge, if one exists. + */ + @Nullable + NetEdge getEdge(@NotNull NetNode source, @NotNull NetNode target); + + /** + * Removes the edge linking two nodes together, if one exists. + * @param source Source node. + * @param target Target node. + * @param bothWays If the graph is directional, passing in true will remove both the forwards and backwards edge. + */ + void removeEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays); + + /** + * Gets the net graph backing this graphnet. This should NEVER be modified directly. + * @return the backing net graph + */ + @ApiStatus.Internal + default INetGraph getGraph() { + return getBacker().getGraph(); + } + + /** + * Gets the GraphNetBacker backing this graphnet. This should NEVER be used except inside the graphnet impl. + * @return the backing graphnet backer + */ + @ApiStatus.Internal + GraphNetBacker getBacker(); + + /** + * Get a blank group data for this graph.
+ * Make sure to override this if your NetGroups use data. + * + * @return The correct data variant. + */ + @Nullable + default AbstractGroupData getBlankGroupData() { + return null; + } + + /** + * Get a default node data for this graph. Generally used for immediate nbt deserialization. + * @return A default node data object. + */ + @NotNull + default NetLogicData getDefaultNodeData() { + return new NetLogicData().setLogicEntry(new WeightFactorLogic().setValue(1)); + } + + /** + * Returns whether a node exists in this graph. + * @param node the node in question. + * @return whether the node exists. + */ + default boolean containsNode(NetNode node) { + return getGraph().containsVertex(node.wrapper); + } + + /** + * Returns a breadth-first iterator through this graph, starting from the passed in node. + * @param node the node to start from. + * @return a breadth-first iterator through this graph. + */ + @NotNull + default Iterator breadthIterator(NetNode node) { + return new Iterator<>() { + + private final BreadthFirstIterator iterator = new BreadthFirstIterator<>(getGraph(), node.wrapper); + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public NetNode next() { + return iterator.next().wrapped; + } + }; + } + + /** + * @return the class all registered nodes are expected to be children of. + */ + Class getNodeClass(); + + /** + * While this is crude, it does allow for avoiding generics literally everywhere. + * The systems that make up a graphnet intertwine such that generics would be needed in basically every class. + * Basically, instead of a bunch of generics everywhere, we just instate an honor system that crashes the game if you violate it. + */ + default void nodeClassCheck(NetNode node) { + if (!(getNodeClass().isInstance(node))) + throw new IllegalArgumentException("Cannot provide a " + this.getClass().getSimpleName() + + " with a " + node.getClass().getSimpleName() + " node!"); + } + + /** + * @return a new node with no data, to be either nbt deserialized or initialized in some other way. + */ + @NotNull + NetNode getNewNode(); + + /** + * @return a new edge with no data, to be either nbt deserialized or initialized in some other way. + */ + @NotNull + default NetEdge getNewEdge() { + return new NetEdge(); + } +} diff --git a/src/main/java/gregtech/api/pipenet/INBTBuilder.java b/src/main/java/gregtech/api/graphnet/INBTBuilder.java similarity index 70% rename from src/main/java/gregtech/api/pipenet/INBTBuilder.java rename to src/main/java/gregtech/api/graphnet/INBTBuilder.java index 19381d1615d..62a358b23cb 100644 --- a/src/main/java/gregtech/api/pipenet/INBTBuilder.java +++ b/src/main/java/gregtech/api/graphnet/INBTBuilder.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet; +package gregtech.api.graphnet; @FunctionalInterface public interface INBTBuilder { diff --git a/src/main/java/gregtech/api/graphnet/MultiNetNodeHandler.java b/src/main/java/gregtech/api/graphnet/MultiNetNodeHandler.java new file mode 100644 index 00000000000..d9da128ae0f --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/MultiNetNodeHandler.java @@ -0,0 +1,33 @@ +package gregtech.api.graphnet; + +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; +import org.jetbrains.annotations.ApiStatus; + +public class MultiNetNodeHandler { + + protected final int allowedActiveNets; + protected final int timeoutDelay; + + protected final Object2LongOpenHashMap activeNets = new Object2LongOpenHashMap<>(); + + public MultiNetNodeHandler(int allowedActiveNets, int timeoutDelay) { + this.allowedActiveNets = allowedActiveNets; + this.timeoutDelay = timeoutDelay; + } + + public boolean traverse(IGraphNet net, long queryTick, boolean simulate) { + timeout(queryTick); + if (activeNets.size() < allowedActiveNets || activeNets.containsKey(net)) { + if (!simulate) activeNets.put(net, queryTick + timeoutDelay); + return true; + } else return false; + } + + private void timeout(long queryTick) { + var iter = activeNets.object2LongEntrySet().fastIterator(); + while (iter.hasNext()) { + var next = iter.next(); + if (next.getLongValue() <= queryTick) iter.remove(); + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/NetGroup.java b/src/main/java/gregtech/api/graphnet/NetGroup.java new file mode 100644 index 00000000000..33069397dda --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/NetGroup.java @@ -0,0 +1,180 @@ +package gregtech.api.graphnet; + +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public class NetGroup { + + public final IGraphNet net; + + private final Set nodes; + + private final AbstractGroupData data; + + public NetGroup(IGraphNet net) { + this(net, new ObjectOpenHashSet<>()); + } + + public NetGroup(IGraphNet net, + Set nodes) { + this.net = net; + this.data = net.getBlankGroupData(); + if (data != null) data.withGroup(this); + this.nodes = nodes; + nodes.forEach(this::onAddedToGroup); + } + + public void addNode(NetNode node) { + this.nodes.add(node); + this.onAddedToGroup(node); + } + + protected void addNodes(Collection nodes) { + this.nodes.addAll(nodes); + nodes.forEach(this::onAddedToGroup); + } + + protected void removeNode(NetNode node) { + this.nodes.remove(node); + } + + protected void removeNodes(Collection nodes) { + this.nodes.removeAll(nodes); + } + + protected void clearNodes() { + this.nodes.clear(); + } + + protected void onAddedToGroup(NetNode node) { + node.setGroup(this); + } + + /** + * Merges the groups of an edge if necessary. + * + * @param source the source node of the edge + * @param target the target node of the edge + */ + public static void mergeEdge(NetNode source, NetNode target) { + NetGroup sourceGroup = source.getGroupUnsafe(); + NetGroup targetGroup = target.getGroupUnsafe(); + if (sourceGroup == targetGroup) { + if (sourceGroup == null) { + sourceGroup = source.getGroupSafe(); + } else { + sourceGroup.clearPathCaches(); + return; + } + } + if (sourceGroup != null) { + sourceGroup.mergeNode(target); + } else { + assert targetGroup != null; + targetGroup.mergeNode(source); + } + } + + protected void mergeNode(NetNode node) { + NetGroup group = node.getGroupUnsafe(); + if (group != null) { + this.addNodes(group.getNodes()); + group.clearNodes(); + } else addNode(node); + this.clearPathCaches(); + } + + /** + * Split this group by removing a node. Automatically removes the node from the backing graph. + * + * @param source node to remove + */ + public void splitNode(NetNode source) { + if (!this.net.containsNode(source)) return; + this.clearPathCaches(); + List targets = this.net.getGraph().outgoingEdgesOf(source.wrapper).stream().map(a -> { + // handling so undirected graphs don't throw an error + if (net.getGraph().isDirected() || Objects.equals(getTarget(a).wrapped, source)) return getTarget(a).wrapped; + return getSource(a).wrapped; + }).collect(Collectors.toList()); + this.net.getBacker().removeVertex(source.wrapper); + this.removeNode(source); + while (!targets.isEmpty()) { + NetNode target = targets.remove(targets.size() - 1); + + Set targetGroup = new ObjectOpenHashSet<>(); + Iterator i = this.net.breadthIterator(target); + NetNode temp; + while (i.hasNext()) { + temp = i.next(); + targetGroup.add(temp); + // if we find a target node in our search, remove it from the list + targets.remove(temp); + } + this.removeNodes(targetGroup); + if (targetGroup.size() != 0) { + new NetGroup(this.net, targetGroup); + } + } + } + + private GraphVertex getSource(GraphEdge graphEdge) { + return this.net.getGraph().getEdgeSource(graphEdge); + } + + private GraphVertex getTarget(GraphEdge graphEdge) { + return this.net.getGraph().getEdgeTarget(graphEdge); + } + + /** + * Split this group by removing an edge. Automatically removes the edge from the graph. + * + * @param source source of the edge + * @param target target of the edge + * @return Whether the edge existed in the graph + */ + public boolean splitEdge(NetNode source, NetNode target) { + if (this.net.getBacker().removeEdge(source.wrapper, target.wrapper) != null) { + this.clearPathCaches(); + Set targetGroup = new ObjectOpenHashSet<>(); + Iterator i = this.net.breadthIterator(target); + NetNode temp; + while (i.hasNext()) { + temp = i.next(); + // if there's another complete path to the source node from the target node, there's no need to split + if (source == temp) return true; + targetGroup.add(temp); + } + this.removeNodes(targetGroup); + if (targetGroup.size() != 0) { + new NetGroup(this.net, targetGroup); + } + return true; + } + return false; + } + + /** + * For memory considerations, returns the uncloned set. Do not modify this directly. + */ + public Set getNodes() { + return nodes; + } + + public void clearPathCaches() { + this.getNodes().forEach(NetNode::clearPathCache); + } + + public AbstractGroupData getData() { + return this.data; + } +} diff --git a/src/main/java/gregtech/api/graphnet/NetNode.java b/src/main/java/gregtech/api/graphnet/NetNode.java new file mode 100644 index 00000000000..9cebda4a2ed --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/NetNode.java @@ -0,0 +1,151 @@ +package gregtech.api.graphnet; + +import gregtech.api.graphnet.alg.iter.ICacheableIterator; + +import gregtech.api.graphnet.graph.GraphVertex; + +import gregtech.api.graphnet.logic.NetLogicData; + +import gregtech.api.graphnet.path.INetPath; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.INBTSerializable; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; +import java.util.Objects; + +public abstract class NetNode implements INBTSerializable { + + /** + * For interacting with the internal graph representation ONLY, do not use or set this field otherwise. + */ + @ApiStatus.Internal + public GraphVertex wrapper; + + private boolean isActive = false; + + private final IGraphNet net; + private NetLogicData data; + private NetGroup group = null; + + @Nullable + private ICacheableIterator> pathCache = null; + + public NetNode(IGraphNet net) { + this.net = net; + } + + public IGraphNet getNet() { + return net; + } + + /** + * Determines whether the node should be treated as a valid destination of pathing algorithms + */ + public boolean isActive() { + return isActive; + } + + /** + * Sets whether the node should be treated as a valid destination of pathing algorithms + */ + public void setActive(boolean active) { + isActive = active; + } + + public void setData(NetLogicData data) { + this.data = data; + } + + public NetLogicData getData() { + return data; + } + + public boolean traverse(long queryTick, boolean simulate) { + return true; + } + + @Nullable + public Iterator> getPathCache() { + if (pathCache == null) return null; + return pathCache.newIterator(); + } + + /** + * Sets the path cache to the provided cache. Returns a new iterator from the cache for convenience. + * + * @param pathCache The new cache. + * @return The new cache. + */ + public Iterator> setPathCache(ICacheableIterator> pathCache) { + this.pathCache = pathCache; + return getPathCache(); + } + + public void clearPathCache() { + this.pathCache = null; + } + + @NotNull + public NetGroup getGroupSafe() { + if (this.group == null) { + new NetGroup(this.getNet()).addNode(this); + // addNodes automatically sets our group to the new group + } + return this.group; + } + + @Nullable + public NetGroup getGroupUnsafe() { + return this.group; + } + + public NetGroup setGroup(NetGroup group) { + this.group = group; + return group; + } + + void clearGroup() { + this.group = null; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setTag("Data", this.data.serializeNBT()); + tag.setBoolean("IsActive", this.isActive()); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + this.isActive = nbt.getBoolean("IsActive"); + this.data = this.net.getDefaultNodeData(); + this.data.deserializeNBT((NBTTagList) nbt.getTag("Data")); + } + + /** + * Used to determine if two nodes are equal, for graph purposes. + * Should not change over the lifetime of a node, except when {@link #deserializeNBT(NBTTagCompound)} is called. + * @return equivalency data. Needs to work with {@link Objects#equals(Object, Object)} + */ + public abstract Object getEquivalencyData(); + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + NetNode node = (NetNode) o; + return Objects.equals(getEquivalencyData(), node.getEquivalencyData()); + } + + @Override + public int hashCode() { + return Objects.hash(getEquivalencyData()); + } +} diff --git a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java new file mode 100644 index 00000000000..3485a574701 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java @@ -0,0 +1,110 @@ +package gregtech.api.graphnet.alg; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.alg.iter.ICacheableIterator; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jgrapht.alg.shortestpath.DefaultManyToManyShortestPaths; + +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public class DynamicWeightsShortestPathsAlgorithm extends DefaultManyToManyShortestPaths + implements INetAlgorithm { + + public DynamicWeightsShortestPathsAlgorithm(IGraphNet net) { + super(net.getGraph()); + } + + @Override + public > Iterator getPathsIterator(GraphVertex source, + NetPathMapper remapper) { + Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream().filter(NetNode::isActive) + .map(n -> n.wrapper).filter(node -> !source.equals(node)).collect(Collectors.toSet()); + return new LimitedIterator<>(source, searchSpace, remapper); + } + + @Override + public boolean supportsDynamicWeights() { + return true; + } + + protected class LimitedIterator> implements ICacheableIterator { + + private static final int MAX_ITERATIONS = 100; + + private final GraphVertex source; + private final Set searchSpace; + private final NetPathMapper remapper; + + private int iterationCount = 0; + private final ObjectArrayList visited = new ObjectArrayList<>(); + private Path next; + + public LimitedIterator(GraphVertex source, Set searchSpace, NetPathMapper remapper) { + this.source = source; + this.searchSpace = searchSpace; + this.remapper = remapper; + } + + @Override + public ICacheableIterator newCacheableIterator() { + return new LimitedIterator<>(source, searchSpace, remapper); + } + + @Override + public Iterator newIterator() { + return newCacheableIterator(); + } + + @Override + public boolean hasNext() { + if (next == null && iterationCount < MAX_ITERATIONS) calculateNext(); + return next != null; + } + + @Override + public Path next() { + if (!hasNext()) throw new NoSuchElementException(); + Path temp = next; + next = null; + return temp; + } + + private void calculateNext() { + iterationCount++; + if (iterationCount == 1) { + next = remapper.map(source); + return; + } + ManyToManyShortestPaths paths = getManyToManyPaths(Collections.singleton(source), + searchSpace); + var iter = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) + .map(remapper::map).sorted(Comparator.comparingDouble(INetPath::getWeight)).iterator(); + while (iter.hasNext()) { + var next = iter.next(); + if (isUnique(next)) { + this.next = next; + break; + } + } + if (next != null) visited.add(next); + } + + private boolean isUnique(Path path) { + for (Path other : visited) { + if (path.matches(other)) return false; + } + return true; + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java new file mode 100644 index 00000000000..acd0d22f5b2 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java @@ -0,0 +1,16 @@ +package gregtech.api.graphnet.alg; + +import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.graph.GraphVertex; + +import java.util.Iterator; + +public interface INetAlgorithm { + + > Iterator getPathsIterator(GraphVertex source, NetPathMapper remapper); + + default boolean supportsDynamicWeights() { + return false; + } + +} diff --git a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java new file mode 100644 index 00000000000..34876bd5da8 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java @@ -0,0 +1,45 @@ +package gregtech.api.graphnet.alg; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.graph.GraphVertex; + +import net.minecraftforge.fml.common.FMLCommonHandler; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; +import java.util.function.Function; + +public class NetAlgorithmWrapper { + + private final IGraphNet net; + @Nullable + private INetAlgorithm alg; + + private final Function builder; + + public NetAlgorithmWrapper(IGraphNet net, @NotNull Function builder) { + this.net = net; + this.builder = builder; + } + + public IGraphNet getNet() { + return net; + } + + public void invalidate() { + this.alg = null; + } + + public boolean supportsDynamicWeights() { + if (alg == null) alg = builder.apply(net); + return alg.supportsDynamicWeights(); + } + + public > Iterator getPathsIterator(GraphVertex source, NetPathMapper remapper) { + net.getGraph().setQueryTick(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); + if (alg == null) alg = builder.apply(net); + return alg.getPathsIterator(source, remapper); + } +} diff --git a/src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java b/src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java new file mode 100644 index 00000000000..4ba08a12257 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java @@ -0,0 +1,39 @@ +package gregtech.api.graphnet.alg; + +import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.util.function.TriFunction; + +import org.jetbrains.annotations.NotNull; +import org.jgrapht.GraphPath; + +import java.util.List; +import java.util.function.Function; + +public class NetPathMapper> { + + private final Function singlePathMapper; + private final TriFunction, List, @NotNull Double, Path> fullConstructMapper; + private final Function, Path> graphPathMapper; + + public NetPathMapper(Function singlePathMapper, + TriFunction, List, @NotNull Double, Path> fullConstructMapper, + Function, Path> graphPathMapper) { + this.singlePathMapper = singlePathMapper; + this.fullConstructMapper = fullConstructMapper; + this.graphPathMapper = graphPathMapper; + } + + public Path map(GraphVertex graphVertex) { + return singlePathMapper.apply(graphVertex); + } + + public Path map(List vertices, List graphEdges, double weight) { + return fullConstructMapper.apply(vertices, graphEdges, weight); + } + + public Path map(GraphPath graphPath) { + return graphPathMapper.apply(graphPath); + } +} diff --git a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java new file mode 100644 index 00000000000..094df3d08c3 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java @@ -0,0 +1,42 @@ +package gregtech.api.graphnet.alg; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.alg.iter.SimpleCacheableIterator; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; + +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.Set; +import java.util.stream.Collectors; + +public final class ShortestPathsAlgorithm extends CHManyToManyShortestPaths implements INetAlgorithm { + + public ShortestPathsAlgorithm(IGraphNet net) { + super(net.getGraph()); + } + + @Override + public > Iterator getPathsIterator(GraphVertex source, + NetPathMapper remapper) { + if (!graph.containsVertex(source)) { + throw new IllegalArgumentException("Graph must contain the source vertex"); + } + // if the source has no group, it has no paths other than the path to itself. + if (source.wrapped.getGroupUnsafe() == null) return Collections.singletonList(remapper.map(source)).iterator(); + + Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream() + .filter(NetNode::isActive).map(n -> n.wrapper).collect(Collectors.toSet()); + ManyToManyShortestPaths manyToManyPaths = getManyToManyPaths( + Collections.singleton(source), searchSpace); + return new SimpleCacheableIterator<>(searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)) + .map(remapper::map).sorted(Comparator.comparingDouble(INetPath::getWeight)) + .collect(Collectors.toCollection(ObjectArrayList::new))); + } +} diff --git a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java new file mode 100644 index 00000000000..c8c4c50af11 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java @@ -0,0 +1,71 @@ +package gregtech.api.graphnet.alg; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.alg.iter.SimpleCacheableIterator; + +import com.google.common.collect.ImmutableList; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +public final class SinglePathAlgorithm implements INetAlgorithm { + + private final IGraphNet net; + + public SinglePathAlgorithm(IGraphNet pipenet) { + this.net = pipenet; + } + + @Override + public > Iterator getPathsIterator(GraphVertex source, + NetPathMapper remapper) { + if (!this.net.getGraph().containsVertex(source)) { + throw new IllegalArgumentException("Graph must contain the source vertex"); + } + List graphEdges = new ObjectArrayList<>(); + List nodes = new ObjectArrayList<>(); + nodes.add(source); + GraphVertex lastNode = null; + GraphVertex node = source; + GraphEdge graphEdge; + double sumWeight = 0; + boolean valid = true; + while (valid) { + Iterator i = this.net.getGraph().outgoingEdgesOf(node).iterator(); + if (!i.hasNext()) break; // we've reached the end, exit the loop while still valid + graphEdge = i.next(); + // if we are directed, we know that the target is the target. + // if we aren't directed, we need to see if the graphEdge's source was secretly the target + boolean reversedEdge = !this.net.getGraph().isDirected() && getSource(graphEdge) == lastNode; + if (getTarget(graphEdge) == lastNode || reversedEdge) { + if (i.hasNext()) graphEdge = i.next(); + else break; // we've reached the end, exit the loop while still valid + } else if (i.hasNext()) i.next(); + if (i.hasNext()) valid = false; // third graphEdge detected - that's an invalid group + lastNode = node; + node = reversedEdge ? getSource(graphEdge) : getTarget(graphEdge); + graphEdges.add(graphEdge); + nodes.add(node); + sumWeight += getWeight(graphEdge); + } + if (!valid) return Collections.emptyIterator(); + return new SimpleCacheableIterator<>(ImmutableList.of(remapper.map(nodes, graphEdges, sumWeight))); + } + + private GraphVertex getSource(GraphEdge graphEdge) { + return this.net.getGraph().getEdgeSource(graphEdge); + } + + private GraphVertex getTarget(GraphEdge graphEdge) { + return this.net.getGraph().getEdgeTarget(graphEdge); + } + + private double getWeight(GraphEdge graphEdge) { + return this.net.getGraph().getEdgeWeight(graphEdge); + } +} diff --git a/src/main/java/gregtech/api/pipenet/alg/iter/ICacheableIterator.java b/src/main/java/gregtech/api/graphnet/alg/iter/ICacheableIterator.java similarity index 81% rename from src/main/java/gregtech/api/pipenet/alg/iter/ICacheableIterator.java rename to src/main/java/gregtech/api/graphnet/alg/iter/ICacheableIterator.java index adcf2fe6695..4b5031bfbd8 100644 --- a/src/main/java/gregtech/api/pipenet/alg/iter/ICacheableIterator.java +++ b/src/main/java/gregtech/api/graphnet/alg/iter/ICacheableIterator.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet.alg.iter; +package gregtech.api.graphnet.alg.iter; import java.util.Iterator; diff --git a/src/main/java/gregtech/api/pipenet/alg/iter/SimpleCacheableIterator.java b/src/main/java/gregtech/api/graphnet/alg/iter/SimpleCacheableIterator.java similarity index 96% rename from src/main/java/gregtech/api/pipenet/alg/iter/SimpleCacheableIterator.java rename to src/main/java/gregtech/api/graphnet/alg/iter/SimpleCacheableIterator.java index 718a0525d85..e60be5f8eb5 100644 --- a/src/main/java/gregtech/api/pipenet/alg/iter/SimpleCacheableIterator.java +++ b/src/main/java/gregtech/api/graphnet/alg/iter/SimpleCacheableIterator.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet.alg.iter; +package gregtech.api.graphnet.alg.iter; import java.util.Iterator; import java.util.function.Consumer; diff --git a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java new file mode 100644 index 00000000000..550562cfba0 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java @@ -0,0 +1,101 @@ +package gregtech.api.graphnet.edge; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.logic.ChannelCountLogic; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.WeakReference; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.function.Supplier; + +public abstract class AbstractNetFlowEdge extends NetEdge { + + private final AbstractChannelsHolder channels; + private final WeakHashMap simulatedChannels; + + public AbstractNetFlowEdge() { + this.channels = getNewHolder(null, null); + this.simulatedChannels = new WeakHashMap<>(9); + } + + @Override + public double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick, + Supplier<@NotNull Double> defaultWeight) { + if (cannotSupportChannel(channel, queryTick, simulator)) { + return defaultWeight.get() * 1000000; + } else return defaultWeight.get(); + } + + public boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick, @Nullable SimulatorKey simulator) { + return getChannels(simulator).cannotSupportChannel(channel, queryTick); + } + + protected AbstractChannelsHolder getChannels(@Nullable SimulatorKey simulator) { + if (simulator == null) return this.channels; + else { + AbstractChannelsHolder channels = simulatedChannels.get(simulator); + if (channels == null) { + channels = getNewHolder(this.channels, simulator); + simulatedChannels.put(simulator, channels); + } + return channels; + } + } + + protected int getChannelCount() { + return getData().getLogicEntryDefaultable(ChannelCountLogic.INSTANCE).getValue(); + } + + protected int getThroughput() { + return getData().getLogicEntryDefaultable(ThroughputLogic.INSTANCE).getValue(); + } + + public long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick, @Nullable SimulatorKey simulator) { + return getChannels(simulator).getFlowLimit(channel, graph, queryTick); + } + + public long getConsumedLimit(IPredicateTestObject channel, long queryTick, @Nullable SimulatorKey simulator) { + return getChannels(simulator).getConsumedLimit(channel, queryTick); + } + + public void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick, @Nullable SimulatorKey simulator) { + getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); + } + + public Set getActiveChannels(@Nullable SimulatorKey simulator, long queryTick) { + return getChannels(simulator).getActiveChannels(queryTick); + } + + protected abstract AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, + SimulatorKey simulator); + + protected abstract static class AbstractChannelsHolder { + + private final WeakReference simulator; + + public AbstractChannelsHolder(SimulatorKey simulator) { + this.simulator = new WeakReference<>(simulator); + } + + public SimulatorKey getSimulator() { + return simulator.get(); + } + + abstract void recalculateFlowLimits(long queryTick); + + abstract boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick); + + abstract long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick); + + abstract long getConsumedLimit(IPredicateTestObject channel, long queryTick); + + abstract void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick); + + abstract Set getActiveChannels(long queryTick); + } +} diff --git a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java new file mode 100644 index 00000000000..51052d40ad4 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java @@ -0,0 +1,81 @@ +package gregtech.api.graphnet.edge; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.predicate.EdgePredicateHandler; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.INBTSerializable; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +public class NetEdge implements INBTSerializable { + + /** + * For interacting with the internal graph representation ONLY, do not use or set this field otherwise. + */ + @ApiStatus.Internal + public GraphEdge wrapper; + + private EdgePredicateHandler predicateHandler; + + private NetLogicData data; + + protected NetNode getSource() { + return wrapper.getSource().wrapped; + } + + protected NetNode getTarget() { + return wrapper.getTarget().wrapped; + } + + public void setData(NetLogicData data) { + this.data = data; + } + + public NetLogicData getData() { + return this.data; + } + + public void setPredicateHandler(EdgePredicateHandler predicateHandler) { + this.predicateHandler = predicateHandler; + } + + @NotNull + public EdgePredicateHandler getPredicateHandler() { + if (predicateHandler == null) predicateHandler = new EdgePredicateHandler(); + return predicateHandler; + } + + public boolean test(IPredicateTestObject object) { + if (predicateHandler == null) return true; + else return predicateHandler.test(object); + } + + public double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick, + Supplier<@NotNull Double> defaultWeight) { + return defaultWeight.get(); + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + if (predicateHandler != null) tag.setTag("Predicate", predicateHandler.serializeNBT()); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + if (nbt.hasKey("Predicate")) { + this.predicateHandler = new EdgePredicateHandler(); + this.predicateHandler.deserializeNBT((NBTTagList) nbt.getTag("Predicate")); + } + } +} diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java similarity index 63% rename from src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java rename to src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java index a6243935a77..831aba48198 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java @@ -1,17 +1,21 @@ -package gregtech.api.pipenet.edge; +package gregtech.api.graphnet.edge; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.PipeNetNode; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; import java.util.List; import java.util.Set; -public class NetFlowEdge extends AbstractNetFlowEdge { +public class NetFlowEdge extends AbstractNetFlowEdge { private final int flowBufferTicks; @@ -27,15 +31,24 @@ public NetFlowEdge(int flowBufferTicks) { } @Override - protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, - SimulatorKey simulator) { + protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, + SimulatorKey simulator) { if (prototype instanceof ChannelsHolder holder) return new ChannelsHolder(holder, simulator); return new ChannelsHolder(simulator); } - private final class ChannelsHolder extends AbstractChannelsHolder { + @Nullable + private NetFlowEdge getInverse(IGraphNet graph) { + NetEdge edge = graph.getEdge(getTarget(), getSource()); + if (edge instanceof NetFlowEdge i && i != this) { + return i; + } + return null; + } + + private final class ChannelsHolder extends AbstractChannelsHolder { - private final Object2LongOpenHashMap map; + private final Object2LongOpenHashMap map; private long lastQueryTick; private boolean init; @@ -51,21 +64,19 @@ public ChannelsHolder(ChannelsHolder prototype, SimulatorKey simulator) { } @Override - public boolean cannotSupportChannel(Object channel, long queryTick) { + boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick) { recalculateFlowLimits(queryTick); if (map.containsKey(channel)) return map.getLong(channel) <= 0; - else return map.size() >= getMinData().getChannelMaxCount(); + else return map.size() >= getChannelCount(); } @Override - public & IPipeType, NDT extends INodeData> long getFlowLimit(Object channel, - Graph, NetFlowEdge> graph, - long queryTick) { + long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick) { if (cannotSupportChannel(channel, queryTick)) return 0; long limit = map.getLong(channel); - NetFlowEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); - if (inverse != null && inverse != NetFlowEdge.this) { + NetFlowEdge inverse = getInverse(graph); + if (inverse != null) { if (inverse.cannotSupportChannel(channel, queryTick, getSimulator())) return 0; limit += inverse.getConsumedLimit(channel, queryTick, getSimulator()); } @@ -74,24 +85,20 @@ public & IPipeType, NDT extends INodeData> long g } @Override - long getConsumedLimit(Object channel, long queryTick) { + long getConsumedLimit(IPredicateTestObject channel, long queryTick) { recalculateFlowLimits(queryTick); long limit = map.defaultReturnValue(); return limit - map.getLong(channel); } @Override - & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, - Graph, NetFlowEdge> graph, - long amount, - long queryTick) { + void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick) { if (amount == 0) return; recalculateFlowLimits(queryTick); // check against reverse edge - NetFlowEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); - if (inverse != null && inverse != NetFlowEdge.this) { + NetFlowEdge inverse = getInverse(graph); + if (inverse != null) { long inverseConsumed = inverse.getConsumedLimit(channel, queryTick, getSimulator()); if (inverseConsumed != 0) { long toFreeUp = Math.min(inverseConsumed, amount); @@ -114,7 +121,7 @@ & IPipeType, NDT extends INodeData> void consumeF @Override public void recalculateFlowLimits(long queryTick) { if (!this.init) { - this.map.defaultReturnValue((long) getMinData().getThroughput() * flowBufferTicks); + this.map.defaultReturnValue((long) getThroughput() * flowBufferTicks); this.init = true; } int time = (int) (queryTick - this.lastQueryTick); @@ -123,7 +130,7 @@ public void recalculateFlowLimits(long queryTick) { } else { List toRemove = new ObjectArrayList<>(); this.map.replaceAll((k, v) -> { - v += (long) time * getMinData().getThroughput(); + v += (long) time * getThroughput(); if (v >= map.defaultReturnValue()) toRemove.add(k); return v; }); @@ -133,7 +140,7 @@ public void recalculateFlowLimits(long queryTick) { } @Override - Set getActiveChannels(long queryTick) { + Set getActiveChannels(long queryTick) { recalculateFlowLimits(queryTick); return map.keySet(); } diff --git a/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java similarity index 65% rename from src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java rename to src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java index f7381a316f7..518b67ea32f 100644 --- a/src/main/java/gregtech/api/pipenet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java @@ -1,19 +1,23 @@ -package gregtech.api.pipenet.edge; +package gregtech.api.graphnet.edge; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.PipeNetNode; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.util.math.MathHelper; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; import java.util.List; import java.util.Set; -public class NetFlowSharedEdge extends AbstractNetFlowEdge { +public class NetFlowSharedEdge extends AbstractNetFlowEdge { private final int flowBufferTicks; @@ -29,17 +33,26 @@ public NetFlowSharedEdge(int flowBufferTicks) { } @Override - protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, - SimulatorKey simulator) { + protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, + SimulatorKey simulator) { if (prototype instanceof ChannelsHolder holder) return new ChannelsHolder(holder, simulator); return new ChannelsHolder(simulator); } - private final class ChannelsHolder extends AbstractChannelsHolder { + @Nullable + private NetFlowSharedEdge getInverse(IGraphNet graph) { + NetEdge edge = graph.getEdge(getTarget(), getSource()); + if (edge instanceof NetFlowSharedEdge i && i != this) { + return i; + } + return null; + } + + private final class ChannelsHolder extends AbstractChannelsHolder { private long maxCapacity; private long sharedCapacity; - private final Object2LongOpenHashMap map; + private final Object2LongOpenHashMap map; private long lastQueryTick; private boolean init; @@ -56,43 +69,37 @@ public ChannelsHolder(ChannelsHolder prototype, SimulatorKey simulator) { } @Override - public boolean cannotSupportChannel(Object channel, long queryTick) { + public boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick) { recalculateFlowLimits(queryTick); if (sharedCapacity <= 0) return true; - else return map.size() >= getMinData().getChannelMaxCount(); + else return map.size() >= getChannelCount(); } @Override - public & IPipeType, NDT extends INodeData> long getFlowLimit(Object channel, - Graph, NetFlowSharedEdge> graph, - long queryTick) { + long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick) { if (cannotSupportChannel(channel, queryTick)) return 0; - NetFlowSharedEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); - if (inverse != null && inverse != NetFlowSharedEdge.this) { + NetFlowSharedEdge inverse = getInverse(graph); + if (inverse != null) { if (inverse.cannotSupportChannel(channel, queryTick, getSimulator())) return 0; return sharedCapacity + inverse.getConsumedLimit(channel, queryTick, getSimulator()); } else return sharedCapacity; } @Override - long getConsumedLimit(Object channel, long queryTick) { + long getConsumedLimit(IPredicateTestObject channel, long queryTick) { recalculateFlowLimits(queryTick); return map.getLong(channel); } @Override - & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, - Graph, NetFlowSharedEdge> graph, - long amount, - long queryTick) { + void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick) { if (amount == 0) return; recalculateFlowLimits(queryTick); // check against reverse edge - NetFlowSharedEdge inverse = graph.getEdge(getCastTarget(), getCastSource()); - if (inverse != null && inverse != NetFlowSharedEdge.this) { + NetFlowSharedEdge inverse = getInverse(graph); + if (inverse != null) { long inverseConsumed = inverse.getConsumedLimit(channel, queryTick, getSimulator()); if (inverseConsumed != 0) { long toFreeUp = Math.min(inverseConsumed, amount); @@ -116,7 +123,7 @@ & IPipeType, NDT extends INodeData> void consumeF @Override public void recalculateFlowLimits(long queryTick) { if (!this.init) { - this.maxCapacity = (long) getMinData().getThroughput() * flowBufferTicks; + this.maxCapacity = (long) getThroughput() * flowBufferTicks; this.init = true; } int time = (int) (queryTick - this.lastQueryTick); @@ -124,7 +131,7 @@ public void recalculateFlowLimits(long queryTick) { this.map.clear(); } else { List toRemove = new ObjectArrayList<>(); - long regenerationPer = MathHelper.ceil((double) time * getMinData().getThroughput() / map.size()); + long regenerationPer = MathHelper.ceil((double) time * getThroughput() / map.size()); map.replaceAll((k, v) -> { v -= regenerationPer; if (v <= 0) toRemove.add(k); @@ -143,7 +150,7 @@ private void boundCapacity() { } @Override - Set getActiveChannels(long queryTick) { + Set getActiveChannels(long queryTick) { recalculateFlowLimits(queryTick); return map.keySet(); } diff --git a/src/main/java/gregtech/api/pipenet/edge/SimulatorKey.java b/src/main/java/gregtech/api/graphnet/edge/SimulatorKey.java similarity index 94% rename from src/main/java/gregtech/api/pipenet/edge/SimulatorKey.java rename to src/main/java/gregtech/api/graphnet/edge/SimulatorKey.java index ec4f8c69db9..bc3879b4a9b 100644 --- a/src/main/java/gregtech/api/pipenet/edge/SimulatorKey.java +++ b/src/main/java/gregtech/api/graphnet/edge/SimulatorKey.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet.edge; +package gregtech.api.graphnet.edge; public final class SimulatorKey { diff --git a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java b/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumer.java similarity index 67% rename from src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java rename to src/main/java/gregtech/api/graphnet/edge/util/FlowConsumer.java index 376df509d3b..1566d8eb72b 100644 --- a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumer.java +++ b/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumer.java @@ -1,22 +1,22 @@ -package gregtech.api.pipenet.edge.util; +package gregtech.api.graphnet.edge.util; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.AbstractNetFlowEdge; -import gregtech.api.pipenet.edge.SimulatorKey; -import gregtech.api.pipenet.predicate.FluidTestObject; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.PipeNetNode; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.predicate.test.FluidTestObject; import org.jgrapht.Graph; import java.util.function.Consumer; -public class FlowConsumer & IPipeType, NDT extends INodeData, - E extends AbstractNetFlowEdge> implements Consumer { +public class FlowConsumer & IPipeType, NDT extends IPipeNetData, + E extends AbstractNetFlowEdge> implements Consumer { private final E edge; private final FluidTestObject testObject; - private final Graph, E> graph; + private final Graph, E> graph; private final long flow; private final long tick; private final SimulatorKey simulatorKey; @@ -24,12 +24,12 @@ public class FlowConsumer & IPipeType, NDT extends INod private double ratio = 1; - public FlowConsumer(E edge, FluidTestObject testObject, Graph, E> graph, long flow, + public FlowConsumer(E edge, FluidTestObject testObject, Graph, E> graph, long flow, long tick, SimulatorKey simulatorKey) { this(edge, testObject, graph, flow, tick, simulatorKey, null); } - public FlowConsumer(E edge, FluidTestObject testObject, Graph, E> graph, long flow, + public FlowConsumer(E edge, FluidTestObject testObject, Graph, E> graph, long flow, long tick, SimulatorKey simulatorKey, Consumer extra) { this.edge = edge; this.testObject = testObject; diff --git a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java b/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumerList.java similarity index 54% rename from src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java rename to src/main/java/gregtech/api/graphnet/edge/util/FlowConsumerList.java index 94a99f8ff29..40bedc403b2 100644 --- a/src/main/java/gregtech/api/pipenet/edge/util/FlowConsumerList.java +++ b/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumerList.java @@ -1,26 +1,26 @@ -package gregtech.api.pipenet.edge.util; +package gregtech.api.graphnet.edge.util; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.AbstractNetFlowEdge; -import gregtech.api.pipenet.edge.SimulatorKey; -import gregtech.api.pipenet.predicate.FluidTestObject; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.PipeNetNode; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.predicate.test.FluidTestObject; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.Graph; import java.util.function.Consumer; -public class FlowConsumerList & IPipeType, NDT extends INodeData, - E extends AbstractNetFlowEdge> extends ObjectArrayList> { +public class FlowConsumerList & IPipeType, NDT extends IPipeNetData, + E extends AbstractNetFlowEdge> extends ObjectArrayList> { - public void add(E edge, FluidTestObject testObject, Graph, E> graph, long flow, + public void add(E edge, FluidTestObject testObject, Graph, E> graph, long flow, long tick, SimulatorKey simulatorKey) { this.add(new FlowConsumer<>(edge, testObject, graph, flow, tick, simulatorKey)); } - public void add(E edge, FluidTestObject testObject, Graph, E> graph, long flow, + public void add(E edge, FluidTestObject testObject, Graph, E> graph, long flow, long tick, SimulatorKey simulatorKey, Consumer extra) { this.add(new FlowConsumer<>(edge, testObject, graph, flow, tick, simulatorKey, extra)); } diff --git a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java new file mode 100644 index 00000000000..1f75dddf5cb --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java @@ -0,0 +1,56 @@ +package gregtech.api.graphnet.gather; + +import gregtech.api.GTValues; +import gregtech.api.graphnet.logic.ChannelCountLogic; +import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.LossAbsoluteLogic; +import gregtech.api.graphnet.logic.MultiNetCountLogic; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.logic.WeightFactorLogic; + +import gregtech.api.graphnet.predicate.IEdgePredicate; + +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.Map; +import java.util.function.Supplier; + +@Mod.EventBusSubscriber(modid = GTValues.MODID) +public final class GTGraphGatherables { + + private static Map>> PREDICATES_REGISTRY; + private static Map>> LOGICS_REGISTRY; + + public static Map>> getPredicatesRegistry() { + if (PREDICATES_REGISTRY == null) { + GatherPredicatesEvent predicates = new GatherPredicatesEvent(); + MinecraftForge.EVENT_BUS.post(predicates); + PREDICATES_REGISTRY = predicates.gathered; + } + return PREDICATES_REGISTRY; + } + + public static Map>> getLogicsRegistry() { + if (LOGICS_REGISTRY == null) { + GatherLogicsEvent logics = new GatherLogicsEvent(); + MinecraftForge.EVENT_BUS.post(logics); + LOGICS_REGISTRY = logics.gathered; + } + return LOGICS_REGISTRY; + } + + @SubscribeEvent + public static void gatherPredicates(GatherPredicatesEvent event) { + } + + @SubscribeEvent + public static void gatherLogics(GatherLogicsEvent event) { + event.registerSupplier(WeightFactorLogic.INSTANCE.getName(), WeightFactorLogic::new); + event.registerSupplier(ThroughputLogic.INSTANCE.getName(), ThroughputLogic::new); + event.registerSupplier(ChannelCountLogic.INSTANCE.getName(), ChannelCountLogic::new); + event.registerSupplier(MultiNetCountLogic.INSTANCE.getName(), MultiNetCountLogic::new); + event.registerSupplier(LossAbsoluteLogic.INSTANCE.getName(), LossAbsoluteLogic::new); + } +} diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java new file mode 100644 index 00000000000..99f95da6f4e --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java @@ -0,0 +1,21 @@ +package gregtech.api.graphnet.gather; + +import gregtech.api.graphnet.logic.INetLogicEntry; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraftforge.fml.common.eventhandler.Event; + +import java.util.Map; +import java.util.function.Supplier; + +public class GatherLogicsEvent extends Event { + + final Map>> gathered = new Object2ObjectOpenHashMap<>(); + + GatherLogicsEvent() {} + + public void registerSupplier(String name, Supplier> supplier) { + gathered.put(name, supplier); + } +} diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java new file mode 100644 index 00000000000..e90f4e9e46e --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java @@ -0,0 +1,21 @@ +package gregtech.api.graphnet.gather; + +import gregtech.api.graphnet.predicate.IEdgePredicate; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraftforge.fml.common.eventhandler.Event; + +import java.util.Map; +import java.util.function.Supplier; + +public class GatherPredicatesEvent extends Event { + + final Map>> gathered = new Object2ObjectOpenHashMap<>(); + + GatherPredicatesEvent() {} + + public void registerSupplier(String name, Supplier> supplier) { + gathered.put(name, supplier); + } +} diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java new file mode 100644 index 00000000000..9dd71345f5e --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java @@ -0,0 +1,45 @@ +package gregtech.api.graphnet.graph; + +import gregtech.api.graphnet.edge.NetEdge; + +import org.jetbrains.annotations.NotNull; +import org.jgrapht.graph.DefaultWeightedEdge; + +import java.util.Objects; + +public final class GraphEdge extends DefaultWeightedEdge { + + public final @NotNull NetEdge wrapped; + + public GraphEdge(@NotNull NetEdge wrapped) { + this.wrapped = wrapped; + wrapped.wrapper = this; + } + + public @NotNull NetEdge getWrapped() { + return wrapped; + } + + @Override + public GraphVertex getSource() { + return (GraphVertex) super.getSource(); + } + + @Override + public GraphVertex getTarget() { + return (GraphVertex) super.getTarget(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GraphEdge graphEdge = (GraphEdge) o; + return Objects.equals(wrapped, graphEdge.wrapped); + } + + @Override + public int hashCode() { + return Objects.hash(wrapped); + } +} diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java b/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java new file mode 100644 index 00000000000..e77a5e4a7ba --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java @@ -0,0 +1,34 @@ +package gregtech.api.graphnet.graph; + +import gregtech.api.graphnet.NetNode; + +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public final class GraphVertex { + + public final @NotNull NetNode wrapped; + + public GraphVertex(@NotNull NetNode wrapped) { + this.wrapped = wrapped; + wrapped.wrapper = this; + } + + public @NotNull NetNode getWrapped() { + return wrapped; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GraphVertex graphVertex = (GraphVertex) o; + return Objects.equals(wrapped, graphVertex.wrapped); + } + + @Override + public int hashCode() { + return Objects.hash(wrapped); + } +} diff --git a/src/main/java/gregtech/api/graphnet/graph/INetGraph.java b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java new file mode 100644 index 00000000000..7c9bd4a8cad --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java @@ -0,0 +1,20 @@ +package gregtech.api.graphnet.graph; + +import gregtech.api.graphnet.GraphNetBacker; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import org.jetbrains.annotations.ApiStatus; +import org.jgrapht.Graph; + +public interface INetGraph extends Graph { + + @ApiStatus.Internal + void setOwningNet(GraphNetBacker net); + + void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator); + + void setQueryTick(long queryTick); + + boolean isDirected(); +} diff --git a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java new file mode 100644 index 00000000000..fa3267af0d0 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java @@ -0,0 +1,65 @@ +package gregtech.api.graphnet.graph; + +import gregtech.api.graphnet.GraphNetBacker; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import org.jgrapht.graph.SimpleDirectedWeightedGraph; + +import java.util.function.Function; +import java.util.function.Supplier; + +public class NetDirectedGraph extends SimpleDirectedWeightedGraph implements INetGraph { + + private GraphNetBacker net = null; + + private IPredicateTestObject testObject; + private SimulatorKey simulator; + private long queryTick; + + public NetDirectedGraph(Supplier vertexSupplier, Supplier edgeSupplier) { + super(vertexSupplier, edgeSupplier); + } + + @Override + public void setOwningNet(GraphNetBacker net) { + if (this.net != null) + throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); + this.net = net; + } + + @Override + public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator) { + if (!net.dynamicWeights()) throw new IllegalStateException("Net does not support dynamic weights!"); + this.testObject = testObject; + this.simulator = simulator; + } + + public void setQueryTick(long queryTick) { + this.queryTick = queryTick; + } + + @Override + public boolean isDirected() { + return true; + } + + @Override + public double getEdgeWeight(GraphEdge graphEdge) { + if (!graphEdge.getSource().wrapped.traverse(queryTick, true) || + !graphEdge.getTarget().wrapped.traverse(queryTick, true)) + return Double.POSITIVE_INFINITY; + + if (net.dynamicWeights()) { + return graphEdge.wrapped.test(testObject) ? + graphEdge.wrapped.getDynamicWeight(testObject, simulator, queryTick, () -> super.getEdgeWeight(graphEdge)) : + Double.POSITIVE_INFINITY; + } else return super.getEdgeWeight(graphEdge); + } + + public static Function standardBuilder() { + return iGraphNet -> new NetDirectedGraph(() -> new GraphVertex(iGraphNet.getNewNode()), + () -> new GraphEdge(iGraphNet.getNewEdge())); + } +} diff --git a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java new file mode 100644 index 00000000000..01dc3a63330 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java @@ -0,0 +1,65 @@ +package gregtech.api.graphnet.graph; + +import gregtech.api.graphnet.GraphNetBacker; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import org.jgrapht.graph.SimpleWeightedGraph; + +import java.util.function.Function; +import java.util.function.Supplier; + +public class NetUndirectedGraph extends SimpleWeightedGraph implements INetGraph { + + private GraphNetBacker net = null; + + private IPredicateTestObject testObject; + private SimulatorKey simulator; + private long queryTick; + + public NetUndirectedGraph(Supplier vertexSupplier, Supplier edgeSupplier) { + super(vertexSupplier, edgeSupplier); + } + + @Override + public void setOwningNet(GraphNetBacker net) { + if (this.net != null) + throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); + this.net = net; + } + + @Override + public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator) { + if (!net.dynamicWeights()) throw new IllegalStateException("Net does not support dynamic weights!"); + this.testObject = testObject; + this.simulator = simulator; + } + + public void setQueryTick(long queryTick) { + this.queryTick = queryTick; + } + + @Override + public boolean isDirected() { + return false; + } + + @Override + public double getEdgeWeight(GraphEdge graphEdge) { + if (!graphEdge.getSource().wrapped.traverse(queryTick, true) || + !graphEdge.getTarget().wrapped.traverse(queryTick, true)) + return Double.POSITIVE_INFINITY; + + if (net.dynamicWeights()) { + return graphEdge.wrapped.test(testObject) ? + graphEdge.wrapped.getDynamicWeight(testObject, simulator, queryTick, () -> super.getEdgeWeight(graphEdge)) : + Double.POSITIVE_INFINITY; + } else return super.getEdgeWeight(graphEdge); + } + + public static Function standardBuilder() { + return iGraphNet -> new NetUndirectedGraph(() -> new GraphVertex(iGraphNet.getNewNode()), + () -> new GraphEdge(iGraphNet.getNewEdge())); + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java new file mode 100644 index 00000000000..efc17ed1061 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java @@ -0,0 +1,32 @@ +package gregtech.api.graphnet.logic; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagDouble; +import net.minecraft.nbt.NBTTagInt; + +import org.jetbrains.annotations.Contract; + +public abstract class AbstractDoubleLogicData> implements INetLogicEntry { + + private double value; + + @Contract("_ -> this") + public T setValue(double value) { + this.value = value; + return (T) this; + } + + public double getValue() { + return this.value; + } + + @Override + public NBTTagDouble serializeNBT() { + return new NBTTagDouble(this.value); + } + + @Override + public void deserializeNBT(NBTTagDouble nbt) { + this.value = nbt.getDouble(); + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java new file mode 100644 index 00000000000..720845a0da6 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java @@ -0,0 +1,31 @@ +package gregtech.api.graphnet.logic; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagInt; + +import org.jetbrains.annotations.Contract; + +public abstract class AbstractIntLogicData> implements INetLogicEntry { + + private int value; + + @Contract("_ -> this") + public T setValue(int value) { + this.value = value; + return (T) this; + } + + public int getValue() { + return this.value; + } + + @Override + public NBTTagInt serializeNBT() { + return new NBTTagInt(this.value); + } + + @Override + public void deserializeNBT(NBTTagInt nbt) { + this.value = nbt.getInt(); + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java b/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java new file mode 100644 index 00000000000..6d9e7ec66df --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java @@ -0,0 +1,20 @@ +package gregtech.api.graphnet.logic; + +import org.jetbrains.annotations.NotNull; + +public final class ChannelCountLogic extends AbstractIntLogicData { + + public static final ChannelCountLogic INSTANCE = new ChannelCountLogic().setValue(1); + + @Override + public @NotNull String getName() { + return "ChannelCount"; + } + + @Override + public ChannelCountLogic union(INetLogicEntry other) { + if (other instanceof ChannelCountLogic l) { + return new ChannelCountLogic().setValue(Math.min(this.getValue(), l.getValue())); + } else return new ChannelCountLogic().setValue(1); + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java new file mode 100644 index 00000000000..41ae6984fdd --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java @@ -0,0 +1,22 @@ +package gregtech.api.graphnet.logic; + +import gregtech.api.graphnet.predicate.IEdgePredicate; + +import net.minecraft.nbt.NBTBase; +import net.minecraft.util.IStringSerializable; +import net.minecraftforge.common.util.INBTSerializable; + +import org.jetbrains.annotations.Contract; + +/** + * Note - all implementers of this interface are suggested to be final, in order to avoid unexpected {@link #union(INetLogicEntry)} behavior. + */ +public interface INetLogicEntry, N extends NBTBase> extends INBTSerializable, IStringSerializable { + + default void deserializeNBTNaive(NBTBase nbt) { + deserializeNBT((N) nbt); + } + + @Contract("_ -> new") + T union(INetLogicEntry other); +} diff --git a/src/main/java/gregtech/api/graphnet/logic/LossAbsoluteLogic.java b/src/main/java/gregtech/api/graphnet/logic/LossAbsoluteLogic.java new file mode 100644 index 00000000000..37e42ef488e --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/LossAbsoluteLogic.java @@ -0,0 +1,20 @@ +package gregtech.api.graphnet.logic; + +import org.jetbrains.annotations.NotNull; + +public final class LossAbsoluteLogic extends AbstractIntLogicData { + + public static final LossAbsoluteLogic INSTANCE = new LossAbsoluteLogic().setValue(0); + + @Override + public @NotNull String getName() { + return "LossAbsolute"; + } + + @Override + public LossAbsoluteLogic union(INetLogicEntry other) { + if (other instanceof LossAbsoluteLogic l) { + return new LossAbsoluteLogic().setValue((this.getValue() + l.getValue()) / 2); + } else return new LossAbsoluteLogic().setValue(this.getValue() / 2); + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java b/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java new file mode 100644 index 00000000000..a429991a131 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java @@ -0,0 +1,20 @@ +package gregtech.api.graphnet.logic; + +import org.jetbrains.annotations.NotNull; + +public final class MultiNetCountLogic extends AbstractIntLogicData { + + public static final MultiNetCountLogic INSTANCE = new MultiNetCountLogic().setValue(1); + + @Override + public @NotNull String getName() { + return "MultiNetCount"; + } + + @Override + public MultiNetCountLogic union(INetLogicEntry other) { + if (other instanceof MultiNetCountLogic l) { + return new MultiNetCountLogic().setValue(Math.min(this.getValue(), l.getValue())); + } else return new MultiNetCountLogic().setValue(1); + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java new file mode 100644 index 00000000000..8fcbfd0f930 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -0,0 +1,100 @@ +package gregtech.api.graphnet.logic; + +import gregtech.api.graphnet.gather.GTGraphGatherables; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.INBTSerializable; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.Supplier; + +public final class NetLogicData implements INBTSerializable { + + private final Map> logicEntrySet; + + public NetLogicData() { + logicEntrySet = new Object2ObjectOpenHashMap<>(); + } + + private NetLogicData(Map> logicEntrySet) { + this.logicEntrySet = logicEntrySet; + } + + public NetLogicData mergeLogicEntry(INetLogicEntry entry) { + INetLogicEntry current = logicEntrySet.get(entry.getName()); + if (entry.getClass().isInstance(current)) { + entry = current.union(entry); + } + return setLogicEntry(entry); + } + + public NetLogicData setLogicEntry(INetLogicEntry entry) { + logicEntrySet.put(entry.getName(), entry); + return this; + } + + public NetLogicData removeLogicEntry(@NotNull INetLogicEntry key) { + logicEntrySet.remove(key.getName()); + return this; + } + + @Nullable + public > T getLogicEntryNullable(@NotNull T key) { + try { + return (T) logicEntrySet.get(key.getName()); + } catch (ClassCastException ignored) { + return null; + } + } + + @NotNull + public > T getLogicEntryDefaultable(@NotNull T key) { + try { + T returnable = (T) logicEntrySet.get(key.getName()); + return returnable == null ? key : returnable; + } catch (ClassCastException ignored) { + return key; + } + } + + public static NetLogicData union(NetLogicData sourceData, NetLogicData targetData) { + Map> newLogic = new Object2ObjectOpenHashMap<>(sourceData.logicEntrySet); + newLogic.replaceAll((k, v) -> v.union(targetData.logicEntrySet.get(k))); + targetData.logicEntrySet.forEach((key, value) -> newLogic.computeIfAbsent(key, k -> value.union(null))); + return new NetLogicData(newLogic); + } + + @Override + public NBTTagList serializeNBT() { + NBTTagList list = new NBTTagList(); + for (INetLogicEntry entry : logicEntrySet.values()) { + NBTTagCompound tag = new NBTTagCompound(); + tag.setTag("Tag", entry.serializeNBT()); + tag.setString("Name", entry.getName()); + list.appendTag(tag); + } + return list; + } + + @Override + public void deserializeNBT(NBTTagList nbt) { + for (int i = 0; i < nbt.tagCount(); i++) { + NBTTagCompound tag = nbt.getCompoundTagAt(i); + String key = tag.getString("Name"); + INetLogicEntry entry = this.logicEntrySet.get(key); + if (entry == null) entry = getSupplier(key).get(); + if (entry == null) continue; + entry.deserializeNBTNaive(tag.getTag("Tag")); + } + } + + private static Supplier> getSupplier(String identifier) { + return GTGraphGatherables.getLogicsRegistry().getOrDefault(identifier, () -> null); + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java b/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java new file mode 100644 index 00000000000..d3ee65e5003 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java @@ -0,0 +1,20 @@ +package gregtech.api.graphnet.logic; + +import org.jetbrains.annotations.NotNull; + +public final class ThroughputLogic extends AbstractIntLogicData { + + public static final ThroughputLogic INSTANCE = new ThroughputLogic().setValue(0); + + @Override + public @NotNull String getName() { + return "Throughput"; + } + + @Override + public ThroughputLogic union(INetLogicEntry other) { + if (other instanceof ThroughputLogic l) { + return new ThroughputLogic().setValue(Math.min(this.getValue(), l.getValue())); + } else return new ThroughputLogic().setValue(0); + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java new file mode 100644 index 00000000000..d64dad4db42 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java @@ -0,0 +1,21 @@ +package gregtech.api.graphnet.logic; + +import org.jetbrains.annotations.NotNull; + +public final class WeightFactorLogic extends AbstractDoubleLogicData { + + public static final WeightFactorLogic INSTANCE = new WeightFactorLogic().setValue(0.1d); + + @Override + public @NotNull String getName() { + return "WeightFactor"; + } + + @Override + public WeightFactorLogic union(INetLogicEntry other) { + if (other instanceof WeightFactorLogic l) { + return new WeightFactorLogic().setValue(this.getValue() + l.getValue()); + } else return new WeightFactorLogic().setValue(this.getValue()); + + } +} diff --git a/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java b/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java new file mode 100644 index 00000000000..15237c83c44 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java @@ -0,0 +1,36 @@ +package gregtech.api.graphnet.path; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; + +import java.util.List; + +public abstract class AbstractNetPath implements INetPath { + + protected final List nodes; + + protected final List edges; + + protected final double weight; + + public AbstractNetPath(List nodes, List edges, double weight) { + this.nodes = nodes; + this.edges = edges; + this.weight = weight; + } + + @Override + public List getOrderedNodes() { + return nodes; + } + + @Override + public List getOrderedEdges() { + return edges; + } + + @Override + public double getWeight() { + return weight; + } +} diff --git a/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java b/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java new file mode 100644 index 00000000000..217e3497315 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java @@ -0,0 +1,35 @@ +package gregtech.api.graphnet.path; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.alg.NetPathMapper; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; + +import gregtech.api.graphnet.logic.WeightFactorLogic; + +import org.jgrapht.GraphPath; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class GenericGraphNetPath extends AbstractNetPath { + + public static final NetPathMapper MAPPER = + new NetPathMapper<>(GenericGraphNetPath::new, GenericGraphNetPath::new, GenericGraphNetPath::new); + + public GenericGraphNetPath(GraphVertex vertex) { + this(Collections.singletonList(vertex), Collections.emptyList(), + vertex.wrapped.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue()); + } + + public GenericGraphNetPath(List vertices, List edges, double weight) { + super(vertices.stream().map(v -> v.wrapped).collect(Collectors.toList()), + edges.stream().map(e -> e.wrapped).collect(Collectors.toList()), weight); + } + + public GenericGraphNetPath(GraphPath path) { + this(path.getVertexList(), path.getEdgeList(), path.getWeight()); + } +} diff --git a/src/main/java/gregtech/api/graphnet/path/INetPath.java b/src/main/java/gregtech/api/graphnet/path/INetPath.java new file mode 100644 index 00000000000..4b13bed448b --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/path/INetPath.java @@ -0,0 +1,19 @@ +package gregtech.api.graphnet.path; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; + +import java.util.List; + +public interface INetPath { + List getOrderedNodes(); + + List getOrderedEdges(); + + double getWeight(); + + default boolean matches(INetPath other) { + return getWeight() == other.getWeight() && + getOrderedNodes().equals(other.getOrderedNodes()) && getOrderedEdges().equals(other.getOrderedEdges()); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java new file mode 100644 index 00000000000..3f5969e1d1f --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java @@ -0,0 +1,34 @@ +package gregtech.api.graphnet.pipenet; + +import gregtech.api.graphnet.alg.NetPathMapper; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.path.AbstractNetPath; + +import org.jgrapht.GraphPath; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class BasicWorldPipeNetPath extends AbstractNetPath { + + public static final NetPathMapper MAPPER = + new NetPathMapper<>(BasicWorldPipeNetPath::new, BasicWorldPipeNetPath::new, BasicWorldPipeNetPath::new); + + public BasicWorldPipeNetPath(GraphVertex vertex) { + this(Collections.singletonList(vertex), Collections.emptyList(), + vertex.wrapped.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue()); + } + + public BasicWorldPipeNetPath(List vertices, List edges, double weight) { + super(vertices.stream().map(v -> (WorldPipeNetNode) v.wrapped).collect(Collectors.toList()), + edges.stream().map(e -> e.wrapped).collect(Collectors.toList()), weight); + } + + public BasicWorldPipeNetPath(GraphPath path) { + this(path.getVertexList(), path.getEdgeList(), path.getWeight()); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java new file mode 100644 index 00000000000..151af50e583 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java @@ -0,0 +1,34 @@ +package gregtech.api.graphnet.pipenet; + +import gregtech.api.graphnet.alg.NetPathMapper; +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.path.AbstractNetPath; + +import org.jgrapht.GraphPath; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class FlowWorldPipeNetPath extends AbstractNetPath { + + public static final NetPathMapper MAPPER = + new NetPathMapper<>(FlowWorldPipeNetPath::new, FlowWorldPipeNetPath::new, FlowWorldPipeNetPath::new); + + public FlowWorldPipeNetPath(GraphVertex vertex) { + this(Collections.singletonList(vertex), Collections.emptyList(), + vertex.wrapped.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue()); + } + + public FlowWorldPipeNetPath(List vertices, List edges, double weight) { + super(vertices.stream().map(v -> (WorldPipeNetNode) v.wrapped).collect(Collectors.toList()), + edges.stream().map(e -> (AbstractNetFlowEdge) e.wrapped).collect(Collectors.toList()), weight); + } + + public FlowWorldPipeNetPath(GraphPath path) { + this(path.getVertexList(), path.getEdgeList(), path.getWeight()); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java new file mode 100644 index 00000000000..1f27c59adee --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java @@ -0,0 +1,12 @@ +package gregtech.api.graphnet.pipenet; + +import gregtech.api.graphnet.pipenet.block.IPipeStructure; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public interface IPipeNetNodeHandler { + void addToNets(World world, BlockPos pos, IPipeStructure structure); + + void removeFromNets(World world, BlockPos pos, IPipeStructure structure); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java new file mode 100644 index 00000000000..8f4bda742b0 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -0,0 +1,110 @@ +package gregtech.api.graphnet.pipenet; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.MultiNetNodeHandler; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.alg.INetAlgorithm; +import gregtech.api.graphnet.graph.INetGraph; +import gregtech.api.graphnet.logic.MultiNetCountLogic; +import gregtech.api.graphnet.worldnet.WorldNet; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.util.math.BlockPos; + +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.Objects; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; + +public abstract class WorldPipeNet extends WorldNet { + + public static final int MULTI_NET_TIMEOUT = 10; + + private static final Object2ObjectOpenHashMap>> dimensionNets = new Object2ObjectOpenHashMap<>(); + + public WorldPipeNet(String name, Function algorithmBuilder, + Function graphBuilder) { + super(name, algorithmBuilder, graphBuilder); + dimensionNets.compute(getDimension(), (k, v) -> { + if (v == null) v = new ObjectOpenHashSet<>(); + v.add(new WeakReference<>(this)); + return v; + }); + } + + public WorldPipeNet(String name, Function algorithmBuilder, boolean directed) { + super(name, algorithmBuilder, directed); + dimensionNets.compute(getDimension(), (k, v) -> { + if (v == null) v = new ObjectOpenHashSet<>(); + v.add(new WeakReference<>(this)); + return v; + }); + } + + @Override + public @Nullable WorldPipeNetNode getNode(@NotNull BlockPos equivalencyData) { + return (WorldPipeNetNode) getNode((Object) equivalencyData); + } + + protected Stream<@NotNull WorldPipeNet> sameDimensionNetsStream() { + ObjectArrayList> expired = new ObjectArrayList<>(); + Stream<@NotNull WorldPipeNet> returnable = dimensionNets.get(this.getDimension()).stream() + .map(ref -> { + WorldPipeNet net = ref.get(); + if (net == null) expired.add(ref); + return net; + }).filter(Objects::nonNull); + expired.forEach(dimensionNets.get(this.getDimension())::remove); + return returnable; + } + + public void synchronizeNode(WorldPipeNetNode node) { + // basically, if another net has a node in the exact same position, then we know it's the same block. + // thus, we set up a multi net node handler for the node in order to manage the overlap + // this is disk-load safe, since this method is called during nbt deserialization. + sameDimensionNetsStream().map(n -> n.getNode(node.getEquivalencyData())).filter(Objects::nonNull) + .forEach(n -> { + if (n.handler != node.handler) { + if (node.handler == null) { + // n handler is not null + node.handler = n.handler; + return; + } + } else if (n.handler == null) { + // both handlers are null + node.handler = new MultiNetNodeHandler(node.getData().getLogicEntryDefaultable( + MultiNetCountLogic.INSTANCE).getValue(), MULTI_NET_TIMEOUT); + } + // n handler does not match cast handler + n.handler = node.handler; + }); + } + + public static String getDataID(final String baseID, final World world) { + if (world == null || world.isRemote) + throw new RuntimeException("WorldPipeNets should only be created on the server!"); + int dimension = world.provider.getDimension(); + return baseID + '.' + dimension; + } + + @Override + public final Class getNodeClass() { + return WorldPipeNetNode.class; + } + + @Override + public final @NotNull WorldPipeNetNode getNewNode() { + return new WorldPipeNetNode(this); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java new file mode 100644 index 00000000000..7335b2fc56b --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java @@ -0,0 +1,47 @@ +package gregtech.api.graphnet.pipenet; + +import gregtech.api.graphnet.GraphNetBacker; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.MultiNetNodeHandler; +import gregtech.api.graphnet.worldnet.WorldNet; +import gregtech.api.graphnet.worldnet.WorldNetNode; + +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.Nullable; + +public final class WorldPipeNetNode extends WorldNetNode { + + @Nullable + MultiNetNodeHandler handler; + + public WorldPipeNetNode(WorldPipeNet net) { + super(net); + } + + @Override + public WorldPipeNet getNet() { + return (WorldPipeNet) super.getNet(); + } + + @Override + public WorldPipeNetNode setPos(BlockPos pos) { + super.setPos(pos); + this.getNet().synchronizeNode(this); + return this; + } + + @Override + public boolean traverse(long queryTick, boolean simulate) { + if (handler != null) { + return handler.traverse(this.getNet(), queryTick, simulate); + } + else return true; + } + + @Override + public BlockPos getEquivalencyData() { + return (BlockPos) super.getEquivalencyData(); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/block/CableStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/block/CableStructure.java new file mode 100644 index 00000000000..47e44b11161 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/block/CableStructure.java @@ -0,0 +1,11 @@ +package gregtech.api.graphnet.pipenet.block; + +import org.jetbrains.annotations.NotNull; + +public record CableStructure(String name, int material, int insulation, int lossMult) implements IPipeStructure { + + @Override + public @NotNull String getName() { + return this.name(); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/block/IPipeStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/block/IPipeStructure.java new file mode 100644 index 00000000000..66f8d8e3563 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/block/IPipeStructure.java @@ -0,0 +1,6 @@ +package gregtech.api.graphnet.pipenet.block; + +import net.minecraft.util.IStringSerializable; + +public interface IPipeStructure extends IStringSerializable { +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/block/PipeBlock.java new file mode 100644 index 00000000000..cdc1a7084d6 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/block/PipeBlock.java @@ -0,0 +1,96 @@ +package gregtech.api.graphnet.pipenet.block; + +import gregtech.api.block.BuiltInRenderBlock; + +import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; +import gregtech.api.util.GTUtility; +import gregtech.common.ConfigHolder; + +import net.minecraft.block.Block; +import net.minecraft.block.SoundType; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLiving; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public abstract class PipeBlock extends BuiltInRenderBlock { + + public final IPipeStructure structure; + + public PipeBlock(IPipeStructure structure) { + super(net.minecraft.block.material.Material.IRON); + this.structure = structure; + this.setDefaultState(constructDefaultState()); + + setTranslationKey("pipe" + getStructureName()); + setSoundType(SoundType.METAL); + setHardness(2.0f); + setResistance(3.0f); + setLightOpacity(0); + disableStats(); + } + + protected IBlockState constructDefaultState() { + return this.blockState.getBaseState(); + } + + @Override + public void onBlockAdded(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { + super.onBlockAdded(worldIn, pos, state); + getHandler(state).addToNets(worldIn, pos, structure); + } + + @Override + public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { + super.breakBlock(worldIn, pos, state); + getHandler(state).removeFromNets(worldIn, pos, structure); + } + + @NotNull + protected abstract IPipeNetNodeHandler getHandler(IBlockState state); + + @Override + public boolean canCreatureSpawn(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, + @NotNull EntityLiving.SpawnPlacementType type) { + return false; + } + + public String getStructureName() { + return GTUtility.lowerUnderscoreToUpperCamel(structure.getName()); + } + + @Override + public void addInformation(@NotNull ItemStack stack, @Nullable World world, @NotNull List tooltip, + @NotNull ITooltipFlag flag) { + if (ConfigHolder.misc.debug) { + tooltip.add("MetaItem Id: pipe" + getStructureName()); + } + } + + @Nullable + public static PipeBlock getPipeBlockFromItem(@NotNull ItemStack stack) { + Item item = stack.getItem(); + if (item instanceof ItemBlock) { + Block block = ((ItemBlock) item).getBlock(); + if (block instanceof PipeBlock) return (PipeBlock) block; + } + return null; + } + + @Override + protected Pair getParticleTexture(World world, BlockPos blockPos) { + return null; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/block/PipeMaterialBlock.java new file mode 100644 index 00000000000..97f095fc332 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/block/PipeMaterialBlock.java @@ -0,0 +1,144 @@ +package gregtech.api.graphnet.pipenet.block; + +import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; +import gregtech.api.items.toolitem.ToolClasses; +import gregtech.api.recipes.ModHandler; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.registry.MaterialRegistry; +import gregtech.api.util.GTUtility; +import gregtech.common.ConfigHolder; +import gregtech.common.blocks.properties.PropertyMaterial; + +import net.minecraft.block.Block; +import net.minecraft.block.SoundType; +import net.minecraft.block.state.IBlockState; + +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.List; + +public abstract class PipeMaterialBlock extends PipeBlock { + + public final MaterialRegistry registry; + public final PropertyMaterial propertyMaterial; + + public PipeMaterialBlock(IPipeStructure structure, MaterialRegistry registry, Collection materials) { + super(structure); + this.registry = registry; + this.propertyMaterial = PropertyMaterial.create("Material", materials); + } + + @Override + protected IBlockState constructDefaultState() { + return super.constructDefaultState().withProperty(propertyMaterial, propertyMaterial.getAllowedValues().get(0)); + } + + @Override + protected @NotNull IPipeNetNodeHandler getHandler(IBlockState state) { + return getHandler(state.getValue(propertyMaterial)); + } + + @NotNull + protected abstract IPipeNetNodeHandler getHandler(Material material); + + @NotNull + public ItemStack getItem(@NotNull Material material) { + return GTUtility.toItem(getDefaultState().withProperty(propertyMaterial, material)); + } + + @NotNull + public Material getGtMaterial(int meta) { + if (meta >= propertyMaterial.getAllowedValues().size()) { + meta = 0; + } + return propertyMaterial.getAllowedValues().get(meta); + } + + @NotNull + public Material getGtMaterial(@NotNull ItemStack stack) { + return getGtMaterial(stack.getMetadata()); + } + + @NotNull + public Material getGtMaterial(@NotNull IBlockState state) { + return state.getValue(propertyMaterial); + } + + @NotNull + public IBlockState getBlock(@NotNull Material material) { + return super.getDefaultState().withProperty(propertyMaterial, material); + } + + @Override + public String getHarvestTool(@NotNull IBlockState state) { + Material material = getGtMaterial(state); + if (ModHandler.isMaterialWood(material)) { + return ToolClasses.AXE; + } + return ToolClasses.WRENCH; + } + + @NotNull + @Override + public SoundType getSoundType(@NotNull IBlockState state, @NotNull World world, @NotNull BlockPos pos, + @Nullable Entity entity) { + Material material = getGtMaterial(state); + if (ModHandler.isMaterialWood(material)) { + return SoundType.WOOD; + } + return SoundType.METAL; + } + + public SoundType getSoundType(ItemStack stack) { + Material material = getGtMaterial(stack); + if (ModHandler.isMaterialWood(material)) { + return SoundType.WOOD; + } + return SoundType.METAL; + } + + @Override + public int getHarvestLevel(@NotNull IBlockState state) { + return 1; + } + + @Override + @NotNull + @SuppressWarnings("deprecation") + public net.minecraft.block.material.Material getMaterial(@NotNull IBlockState state) { + Material material = getGtMaterial(state); + if (ModHandler.isMaterialWood(material)) { + return net.minecraft.block.material.Material.WOOD; + } + return super.getMaterial(state); + } + + @Override + public void addInformation(@NotNull ItemStack stack, @Nullable World world, @NotNull List tooltip, + @NotNull ITooltipFlag flag) { + if (ConfigHolder.misc.debug) { + tooltip.add("MetaItem Id: pipe" + getStructureName() + getGtMaterial(stack).toCamelCaseString()); + } + } + + @Nullable + public static PipeMaterialBlock getPipeMaterialBlockFromItem(@NotNull ItemStack stack) { + Item item = stack.getItem(); + if (item instanceof ItemBlock) { + Block block = ((ItemBlock) item).getBlock(); + if (block instanceof PipeMaterialBlock) return (PipeMaterialBlock) block; + } + return null; + } +} diff --git a/src/main/java/gregtech/api/pipenet/IBlockAppearance.java b/src/main/java/gregtech/api/graphnet/pipenetold/IBlockAppearance.java similarity index 96% rename from src/main/java/gregtech/api/pipenet/IBlockAppearance.java rename to src/main/java/gregtech/api/graphnet/pipenetold/IBlockAppearance.java index 38f089b154e..02bac4c2521 100644 --- a/src/main/java/gregtech/api/pipenet/IBlockAppearance.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/IBlockAppearance.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet; +package gregtech.api.graphnet.pipenetold; import net.minecraft.block.state.IBlockState; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetData.java b/src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetData.java new file mode 100644 index 00000000000..5141f3a53c7 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetData.java @@ -0,0 +1,15 @@ +package gregtech.api.graphnet.pipenetold; + +import gregtech.api.graphnet.logic.NetLogicData; + +import java.util.Collections; +import java.util.List; + +public interface IPipeNetData> extends NetLogicData { + + T getSumData(List datas); + + default T getSumData(Object data) { + return getSumData(Collections.singletonList((T) data)); + } +} diff --git a/src/main/java/gregtech/api/pipenet/IPipeNetHandler.java b/src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetHandler.java similarity index 89% rename from src/main/java/gregtech/api/pipenet/IPipeNetHandler.java rename to src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetHandler.java index ef9400c3f62..45ef391e87f 100644 --- a/src/main/java/gregtech/api/pipenet/IPipeNetHandler.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetHandler.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet; +package gregtech.api.graphnet.pipenetold; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; @@ -15,7 +15,7 @@ public interface IPipeNetHandler { EnumFacing getFacing(); default Cover getCoverOnNeighbour(BlockPos pos, EnumFacing facing) { - NetNode node = getNet().getNode(pos); + PipeNetNode node = getNet().getNode(pos); if (node != null) { TileEntity tile = node.getConnnected(facing); if (tile != null) { diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/NetPath.java b/src/main/java/gregtech/api/graphnet/pipenetold/NetPath.java new file mode 100644 index 00000000000..3d4547857f9 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenetold/NetPath.java @@ -0,0 +1,4 @@ +package gregtech.api.graphnet.pipenetold; + +public class NetPath { +} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/NodeLossResult.java b/src/main/java/gregtech/api/graphnet/pipenetold/NodeLossResult.java new file mode 100644 index 00000000000..add527682d6 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenetold/NodeLossResult.java @@ -0,0 +1,20 @@ +package gregtech.api.graphnet.pipenetold; + +import net.minecraft.util.Tuple; + +import java.util.function.Consumer; + +public class NodeLossResult extends Tuple>, Double> { + + public NodeLossResult(Consumer> postAction, Double lossFunction) { + super(postAction, lossFunction); + } + + public Consumer> getPostAction() { + return this.getFirst(); + } + + public Double getLossFunction() { + return this.getSecond(); + } +} diff --git a/src/main/java/gregtech/api/pipenet/NetNode.java b/src/main/java/gregtech/api/graphnet/pipenetold/PipeNetNode.java similarity index 62% rename from src/main/java/gregtech/api/pipenet/NetNode.java rename to src/main/java/gregtech/api/graphnet/pipenetold/PipeNetNode.java index 2cabb96f2af..7eb9101e6a0 100644 --- a/src/main/java/gregtech/api/pipenet/NetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/PipeNetNode.java @@ -1,35 +1,32 @@ -package gregtech.api.pipenet; +package gregtech.api.graphnet.pipenetold; -import gregtech.api.pipenet.alg.iter.ICacheableIterator; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; -import java.util.Iterator; import java.util.Map; -import java.util.Objects; -public final class NetNode & IPipeType, - NodeDataType extends INodeData, Edge extends NetEdge> - implements INBTSerializable { +public final class PipeNetNode & IPipeType, + NodeDataType extends IPipeNetData, Edge extends NetEdge> + extends NetNode { public static final int DEFAULT_MARK = 0; - public final WorldPipeNetBase net; - - private NodeDataType data; /** * Specifies bitmask of open connections. * Open connections determine visual connections and graph edges. @@ -48,27 +45,19 @@ public final class NetNode & IPipeType> heldMTE; - private final BlockPos nodePos; - - private NetGroup group = null; + private BlockPos nodePos; - @Nullable - private ICacheableIterator> pathCache = null; - - public NetNode(NodeDataType data, IPipeTile heldMTE, - WorldPipeNetBase net) { - this.data = data; + public PipeNetNode(NodeDataType data, IPipeTile heldMTE, IGraphNet net) { + super(net); + this.setData(data); this.openConnections = 0; this.blockedConnections = 0; this.mark = 0; - this.isActive = false; this.heldMTE = new WeakReference<>(heldMTE); this.nodePos = heldMTE.getPipePos(); - this.net = net; } /** @@ -76,10 +65,10 @@ public NetNode(NodeDataType data, IPipeTile heldMT * Should never be required to reference its net, data, or position. */ @SideOnly(Side.CLIENT) - public NetNode(IPipeTile heldMTE) { + public PipeNetNode(IPipeTile heldMTE) { + super(null); this.nodePos = null; - this.net = null; - this.data = null; + this.setData(null); this.heldMTE = new WeakReference<>(heldMTE); this.openConnections = 0; this.blockedConnections = 0; @@ -89,10 +78,10 @@ public NetNode(IPipeTile heldMTE) { * Creates a dummy node for fake flow edges. * Should never be required to reference its net, mte, or position. */ - public NetNode(NodeDataType data) { + public PipeNetNode(NodeDataType data) { + super(null); this.nodePos = null; - this.net = null; - this.data = data; + this.setData(data); this.heldMTE = null; this.openConnections = 0; this.blockedConnections = 0; @@ -101,36 +90,12 @@ public NetNode(NodeDataType data) { /** * For construction during NBT reading only */ - public NetNode(NBTTagCompound tag, WorldPipeNetBase net) { - this.nodePos = BlockPos.fromLong(tag.getLong("Pos")); - deserializeNBT(tag); - this.data = net.readNodeData(tag.getCompoundTag("Data")); - this.net = net; + @ApiStatus.Internal + public PipeNetNode(IGraphNet net) { + super(net); this.heldMTE = new WeakReference<>(null); } - public NetGroup getGroupSafe() { - if (this.group == null) { - new NetGroup<>(this.net.pipeGraph, this.net).addNode(this); - // addNodes automatically sets our group to the new group - } - return this.group; - } - - @Nullable - public NetGroup getGroupUnsafe() { - return this.group; - } - - NetGroup setGroup(NetGroup group) { - this.group = group; - return group; - } - - void clearGroup() { - this.group = null; - } - public boolean hasConnecteds() { for (EnumFacing facing : EnumFacing.VALUES) { if (!isConnected(facing)) continue; @@ -179,7 +144,6 @@ void setConnected(EnumFacing facing, boolean connect) { this.openConnections &= ~(1 << facing.getIndex()); } this.getHeldMTESafe().onConnectionChange(); - this.getGroupSafe().connectionChange(this); } public int getOpenConnections() { @@ -218,6 +182,10 @@ public long getLongPos() { return nodePos.toLong(); } + public WorldPipeNetBase getNet() { + return (WorldPipeNetBase) super.getNet(); + } + public void setHeldMTE(IPipeTile heldMTE) { if (this.heldMTE.get() != heldMTE) this.heldMTE = new WeakReference<>(heldMTE); @@ -237,7 +205,7 @@ public IPipeTile getHeldMTEUnsafe() { public IPipeTile getHeldMTE() { IPipeTile te = getHeldMTEUnsafe(); if (te == null) { - te = net.castTE(net.getWorld().getTileEntity(this.nodePos)); + te = this.getNet().castTE(this.getNet().getWorld().getTileEntity(this.nodePos)); setHeldMTE(te); } return te; @@ -248,7 +216,8 @@ public IPipeTile getHeldMTE() { */ public IPipeTile getHeldMTESafe() { IPipeTile te = getHeldMTEUnsafe(); - IPipeTile properTE = net.castTE(net.getWorld().getTileEntity(this.nodePos)); + IPipeTile properTE = + this.getNet().castTE(this.getNet().getWorld().getTileEntity(this.nodePos)); if (te != properTE) { setHeldMTE(properTE); } @@ -256,68 +225,45 @@ public IPipeTile getHeldMTESafe() { } public void setData(NodeDataType data) { - this.data = data; - } - - public NodeDataType getData() { - return data; + super.setData(data); } - public boolean isActive() { - return isActive; - } - - @Nullable - public Iterator> getPathCache() { - if (pathCache == null) return null; - return pathCache.newIterator(); - } - - /** - * Sets the path cache to the provided cache. Returns a new iterator from the cache for convenience. - * - * @param pathCache The new cache. - * @return The new cache. - */ - public Iterator> setPathCache( - ICacheableIterator> pathCache) { - this.pathCache = pathCache; - return getPathCache(); + @Override + public void setData(NetLogicData data) { + try { + NodeDataType cast = (NodeDataType) data; + this.setData(cast); + } catch (ClassCastException e) { + throw new IllegalArgumentException("Cannot give a pipenet node an arbitrary data type."); + } } - public void clearPathCache() { - this.pathCache = null; + @Override + public NodeDataType getData() { + return (NodeDataType) super.getData(); } @Override public NBTTagCompound serializeNBT() { - NBTTagCompound tag = new NBTTagCompound(); + NBTTagCompound tag = super.serializeNBT(); tag.setLong("Pos", this.nodePos.toLong()); tag.setInteger("Mark", this.mark); tag.setInteger("OpenConnections", this.openConnections); tag.setInteger("BlockedConnections", this.blockedConnections); - tag.setBoolean("IsActive", this.isActive); return tag; } @Override public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt); + this.nodePos = BlockPos.fromLong(nbt.getLong("Pos")); this.mark = nbt.getInteger("Mark"); this.openConnections = nbt.getInteger("OpenConnections"); this.blockedConnections = nbt.getInteger("BlockedConnections"); - this.isActive = nbt.getBoolean("IsActive"); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - NetNode node = (NetNode) o; - return nodePos != null && Objects.equals(nodePos, node.nodePos); } @Override - public int hashCode() { - return Objects.hash(nodePos); + protected Object getEquivalencyData() { + return this.nodePos; } } diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/PipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenetold/PipeNetPath.java new file mode 100644 index 00000000000..234f349160f --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenetold/PipeNetPath.java @@ -0,0 +1,117 @@ +package gregtech.api.graphnet.pipenetold; + +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.util.FacingPos; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; + +import org.jgrapht.GraphPath; + +import java.util.*; +import java.util.stream.Collectors; + +public class PipeNetPath & IPipeType, + NodeDataType extends IPipeNetData, Edge extends NetEdge> + extends NetPath, Edge> { + + private NodeDataType data = null; + + public PipeNetPath(GraphVertex node) { + super(node); + } + + public PipeNetPath(List nodes, List graphEdges, double weight) { + super(nodes, graphEdges, weight); + } + + public PipeNetPath(GraphPath path) { + super(path); + } + + public Iterator getFacingIterator() { + return this.getTargetTEs().keySet().iterator(); + } + + public FacedPipeNetPath firstFacing() { + return this.withFacing(this.getFacingIterator().next()); + } + + public FacedPipeNetPath withFacing(EnumFacing facing) { + return new FacedPipeNetPath<>(this, facing); + } + + public Map getTargetTEs() { + return getTargetNode().getConnecteds(); + } + + public NodeDataType getSumData() { + // generate min data on-demand and cache it, rather than generating for every path always + if (this.data == null) { + this.data = getSourceNode().getData() + .getSumData(this.getNodeList().stream().map(PipeNetNode::getData).collect(Collectors.toList())); + } + return data; + } + + public static class FacedPipeNetPath & IPipeType, NDT extends IPipeNetData, + E extends NetEdge> { + + public PipeNetPath path; + + public EnumFacing facing; + + public FacedPipeNetPath(PipeNetPath path, EnumFacing facing) { + this.path = path; + this.facing = facing; + } + + public TileEntity getTargetTE() { + return path.getTargetTEs().get(facing); + } + + public List> getNodeList() { + return path.getNodeList(); + } + + public List getEdgeList() { + return path.getEdgeList(); + } + + public PipeNetNode getSourceNode() { + return path.getSourceNode(); + } + + public PipeNetNode getTargetNode() { + return path.getTargetNode(); + } + + public Map getTargetTEs() { + return path.getTargetTEs(); + } + + public double getWeight() { + return path.getWeight(); + } + + public NDT getSumData() { + return path.getSumData(); + } + + public boolean checkPredicate(IPredicateTestObject testObject) { + return path.checkPredicate(testObject); + } + + public FacingPos toFacingPos() { + return new FacingPos(path.getTargetNode().getNodePos(), this.facing); + } + + public EnumFacing oppositeFacing() { + return facing.getOpposite(); + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java b/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java new file mode 100644 index 00000000000..9477056972a --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java @@ -0,0 +1,419 @@ +package gregtech.api.graphnet.pipenetold; + +import gregtech.api.cover.Cover; +import gregtech.api.graphnet.GraphNetBacker; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetGroup; +import gregtech.api.graphnet.alg.INetAlgorithm; +import gregtech.api.graphnet.alg.iter.ICacheableIterator; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.INetGraph; +import gregtech.api.graphnet.pipenetold.predicate.ShutteredEdgePredicate; +import gregtech.api.graphnet.pipenetold.predicate.IShutteredEdgePredicate; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; +import gregtech.common.covers.CoverShutter; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.storage.WorldSavedData; +import net.minecraftforge.common.capabilities.Capability; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.WeakReference; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.function.Function; + +public abstract class WorldPipeNetBase, + PipeType extends Enum & IPipeType, Edge extends NetEdge> extends WorldSavedData + implements IGraphNet { + + + private final boolean isDirected; + + private WeakReference worldRef = new WeakReference<>(null); + protected final Map> pipeMap = new Object2ObjectOpenHashMap<>(); + + private final GraphNetBacker> backer; + + WorldPipeNetBase(String name, boolean isDirected, + Function algorithmBuilder, + INetGraph graph) { + super(name); + this.backer = new GraphNetBacker(this, algorithmBuilder, graph, this.needsDynamicWeights()); + this.isDirected = isDirected; + } + + @Override + public INetGraph getGraph() { + return this.backer.getGraph(); + } + + public final boolean isDirected() { + return isDirected; + } + + protected void markAlgInvalid() { + this.backer.invalidateAlg(); + } + + public World getWorld() { + return this.worldRef.get(); + } + + protected boolean needsDynamicWeights() { + return false; + } + + protected void setWorldAndInit(World world) { + if (world != this.worldRef.get()) { + this.worldRef = new WeakReference<>(world); + } + } + + public static String getDataID(final String baseID, final World world) { + if (world == null || world.isRemote) + throw new RuntimeException("WorldPipeNetBase should only be created on the server!"); + int dimension = world.provider.getDimension(); + return dimension == 0 ? baseID : baseID + '.' + dimension; + } + + /** + * Preferred override. Only collects a fresh TE from the server if the provided TE is invalid. + * + * @param tile The {@link TileEntityPipeBase} that paths are being requested for + * @return the ordered list of paths associated with the {@link TileEntityPipeBase} + */ + public Iterator> getPaths(TileEntityPipeBase tile) { + return getPaths(this.pipeMap.get(tile.getPipePos()), tile); + } + + /** + * Special-case override. Forces the collection of a fresh TE from the server. + * + * @param pos The {@link BlockPos} that paths are being requested for + * @return the ordered list of paths associated with the {@link BlockPos} + */ + public Iterator> getPaths(BlockPos pos) { + return getPaths(this.pipeMap.get(pos), null); + } + + public Iterator> getPaths(@Nullable PipeNetNode node, + @Nullable TileEntityPipeBase tile) { + if (node == null) return Collections.emptyIterator(); + + node.setHeldMTE(tile); + + Iterator returnable = node.getPathCache(); + if (returnable == null) { + returnable = this.backer.getPaths(node, MAPPER); + if (returnable instanceof ICacheableIterator) { + returnable = node.setPathCache((ICacheableIterator) returnable); + } + } + return (Iterator>) returnable; + } + + @Nullable + protected TileEntityPipeBase castTE(TileEntity te) { + if (te instanceof TileEntityPipeBasepipe) { + if (!getBasePipeClass().isAssignableFrom(pipe.getClass())) { + return null; + } + // noinspection unchecked + return (TileEntityPipeBase) pipe; + } + return null; + } + + public void markNodeAsOldData(PipeNetNode node) { + updateActiveNodeStatus(node); + } + + protected abstract Class> getBasePipeClass(); + + public PipeNetNode getOrCreateNode(@NotNull IPipeTile mte) { + PipeNetNode node = this.pipeMap.get(mte.getPipePos()); + if (node != null) return node; + if (!canAttachNode(mte.getNodeData())) return null; + node = new PipeNetNode<>(mte.getNodeData(), mte, this); + this.addNode(node); + return node; + } + + protected final boolean canNodesConnect(PipeNetNode source, EnumFacing nodeFacing, + PipeNetNode target) { + return areNodeBlockedConnectionsCompatible(source, nodeFacing, target) && + areMarksCompatible(source.mark, target.mark) && + areNodesCustomContactable(source.getData(), target.getData()); + } + + private static boolean areMarksCompatible(int mark1, int mark2) { + return mark1 == mark2 || mark1 == PipeNetNode.DEFAULT_MARK || mark2 == PipeNetNode.DEFAULT_MARK; + } + + private boolean areNodeBlockedConnectionsCompatible(PipeNetNode source, + EnumFacing nodeFacing, + PipeNetNode target) { + return !source.isConnected(nodeFacing) && !target.isConnected(nodeFacing.getOpposite()); + } + + protected boolean areNodesCustomContactable(NodeDataType source, NodeDataType target) { + return true; + } + + protected boolean canAttachNode(NodeDataType nodeData) { + return true; + } + + public void updateActiveConnections(BlockPos nodePos, EnumFacing side, boolean connect) { + PipeNetNode node = pipeMap.get(nodePos); + if (node == null || node.isConnected(side) == connect) return; + + node.setConnected(side, connect); + updateActiveNodeStatus(node); + + PipeNetNode nodeOffset = pipeMap.get(nodePos.offset(side)); + if (nodeOffset == null) return; + + nodeOffset.setConnected(side.getOpposite(), connect); + + if (connect) { + if (!node.isBlocked(side)) { + addEdge(nodeOffset, node, null); + this.predicateEdge(nodeOffset, node, side.getOpposite()); + if (!this.getGraph().isDirected()) return; + } + if (!nodeOffset.isBlocked(side.getOpposite())) { + addEdge(node, nodeOffset, null); + this.predicateEdge(node, nodeOffset, side); + } + } else { + removeUndirectedEdge(node, nodeOffset); + } + } + + public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean blocked) { + if (!isDirected()) return; // no such thing as blocked connections on undirected graphs. + PipeNetNode node = pipeMap.get(nodePos); + if (node == null || node.isBlocked(side) == blocked) return; + + node.setBlocked(side, blocked); + + PipeNetNode nodeOffset = pipeMap.get(nodePos.offset(side)); + if (nodeOffset == null) return; + + if (!blocked) { + addEdge(nodeOffset, node, null); + this.predicateEdge(nodeOffset, node, side); + } else { + removeEdge(nodeOffset, node); + } + } + + public void updateMark(BlockPos nodePos, int newMark) { + PipeNetNode node = pipeMap.get(nodePos); + + int oldMark = node.mark; + node.mark = newMark; + + for (EnumFacing side : EnumFacing.VALUES) { + PipeNetNode nodeOffset = pipeMap.get(nodePos.offset(side)); + if (nodeOffset == null) continue; + if (!areNodeBlockedConnectionsCompatible(node, side, nodeOffset) || + !areNodesCustomContactable(node.getData(), nodeOffset.getData())) + continue; + if (areMarksCompatible(oldMark, nodeOffset.mark) == areMarksCompatible(newMark, nodeOffset.mark)) continue; + + if (areMarksCompatible(newMark, nodeOffset.mark)) { + addEdge(node, nodeOffset, null); + this.predicateEdge(node, nodeOffset, side); + } else { + removeEdge(node, nodeOffset); + } + } + } + + protected abstract Capability[] getConnectionCapabilities(); + + public boolean hasNode(BlockPos pos) { + return pipeMap.containsKey(pos); + } + + public void addNodeSilent(PipeNetNode node) { + backer.addNode(node); + this.pipeMap.put(node.getNodePos(), node); + // we do not need to invalidate the cache, because just adding a node means it's not connected to anything. + } + + public void addNode(PipeNetNode node) { + addNodeSilent(node); + this.markDirty(); + } + + @Nullable + public PipeNetNode getNode(BlockPos pos) { + return this.pipeMap.get(pos); + } + + public void addUndirectedEdge(PipeNetNode source, + PipeNetNode target) { + this.addEdge(source, target, null); + if (this.isDirected()) this.addEdge(target, source, null); + } + + public void addEdge(PipeNetNode source, PipeNetNode target, + @Nullable IEdgePredicateOld predicate) { + addEdge(source, target, source.getData().getWeightFactor() + target.getData().getWeightFactor(), predicate); + } + + public void addUndirectedEdge(PipeNetNode source, + PipeNetNode target, + double weight) { + this.addEdge(source, target, weight, null); + if (this.isDirected()) this.addEdge(target, source, weight, null); + } + + public void addEdge(PipeNetNode source, PipeNetNode target, + double weight, + @Nullable IEdgePredicateOld predicate) { + NetEdge edge = backer.addEdge(source, target, weight); + if (edge != null) { + NetGroup.mergeEdge(source, target); + if (predicate != null) { + edge.setPredicate(predicate); + } + this.markAlgInvalid(); + this.markDirty(); + } + } + + public void predicateUndirectedEdge(BlockPos pos, EnumFacing faceToNeighbour) { + PipeNetNode source = this.pipeMap.get(pos); + PipeNetNode target = this.pipeMap.get(pos.offset(faceToNeighbour)); + if (source != null && target != null) { + this.predicateUndirectedEdge(source, target, faceToNeighbour); + } + } + + public void predicateEdge(BlockPos pos, EnumFacing faceToNeighbour) { + PipeNetNode source = this.pipeMap.get(pos); + PipeNetNode target = this.pipeMap.get(pos.offset(faceToNeighbour)); + if (source != null && target != null) + this.predicateEdge(source, target, faceToNeighbour); + } + + public void predicateUndirectedEdge(PipeNetNode source, + PipeNetNode target, + EnumFacing faceToNeighbour) { + this.predicateEdge(source, target, faceToNeighbour); + if (this.isDirected()) this.predicateEdge(target, source, faceToNeighbour.getOpposite()); + } + + public void predicateEdge(PipeNetNode source, + PipeNetNode target, + EnumFacing faceToNeighbour) { + NetEdge edge = this.backer.getEdge(source, target); + if (edge == null) return; + Cover thisCover = source.getHeldMTESafe().getCoverableImplementation().getCoverAtSide(faceToNeighbour); + Cover neighbourCover = target.getHeldMTESafe().getCoverableImplementation() + .getCoverAtSide(faceToNeighbour.getOpposite()); + IEdgePredicateOld predicate = getPredicate(thisCover, neighbourCover); + predicate.setPosInfo(source.getNodePos(), target.getNodePos()); + edge.setPredicate(predicate); + } + + protected IEdgePredicateOld getPredicate(Cover thisCover, Cover neighbourCover) { + return shutterify(new ShutteredEdgePredicate(), thisCover, neighbourCover); + } + + protected final IEdgePredicateOld shutterify(IEdgePredicateOld predicate, @Nullable Cover thisCover, + @Nullable Cover neighbourCover) { + if (predicate instanceof IShutteredEdgePredicate shutteredEdgePredicate) { + if (thisCover instanceof CoverShutter shutter) { + shutteredEdgePredicate.setShutteredSource(shutter.isWorkingEnabled()); + } + if (neighbourCover instanceof CoverShutter shutter) { + shutteredEdgePredicate.setShutteredTarget(shutter.isWorkingEnabled()); + } + } + return predicate; + } + + public void removeUndirectedEdge(PipeNetNode source, + PipeNetNode target) { + this.removeEdge(source, target); + if (isDirected()) this.removeEdge(target, source); + } + + public void removeEdge(PipeNetNode source, PipeNetNode target) { + if (backer.removeEdge(source, target)) { + this.markAlgInvalid(); + this.markDirty(); + } + } + + public void removeNode(BlockPos pos) { + this.removeNode(this.pipeMap.get(pos)); + } + + public void removeNode(@Nullable PipeNetNode node) { + if (backer.removeNode(node)) { + this.pipeMap.remove(node.getNodePos()); + this.markDirty(); + } + } + + public NetGroup getGroup(BlockPos pos) { + PipeNetNode node = this.getNode(pos); + if (node == null) return null; + if (node.getGroupSafe() != null) return node.getGroupSafe(); + return node.setGroup(new NetGroup(this)); + } + + public boolean updateActiveNodeStatus(PipeNetNode node) { + return markNodeAsActive(node, shouldNodeBeActive(node)); + } + + public boolean shouldNodeBeActive(PipeNetNode node) { + var connecteds = node.getConnecteds(); + if (connecteds != null) return connecteds.entrySet().stream().filter(entry -> { + if (entry.getValue() instanceof IPipeTile) return false; + for (Capability cap : this.getConnectionCapabilities()) { + if (entry.getValue().hasCapability(cap, entry.getKey())) return true; + } + return false; + }).toArray().length > 0; + return false; + } + + public boolean markNodeAsActive(PipeNetNode node, boolean isActive) { + if (node != null && node.isActive() != isActive) { + node.getGroupSafe().clearPathCaches(); + node.setActive(isActive); + this.markDirty(); + return true; + } + return false; + } + + @Override + public void readFromNBT(@NotNull NBTTagCompound nbt) { + backer.readFromNBT(nbt); + } + + @NotNull + @Override + public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { + return backer.writeToNBT(compound); + } +} diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java b/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetComplex.java similarity index 82% rename from src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java rename to src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetComplex.java index b6c7fd7f40a..ef8b926906e 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetComplex.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetComplex.java @@ -1,17 +1,17 @@ -package gregtech.api.pipenet; +package gregtech.api.graphnet.pipenetold; -import gregtech.api.pipenet.alg.INetAlgorithm; -import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; -import gregtech.api.pipenet.alg.SinglePathAlgorithm; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.graph.CustomDirectedGraph; -import gregtech.api.pipenet.graph.CustomUndirectedGraph; +import gregtech.api.graphnet.alg.INetAlgorithm; +import gregtech.api.graphnet.alg.ShortestPathsAlgorithm; +import gregtech.api.graphnet.alg.SinglePathAlgorithm; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.NetDirectedGraph; +import gregtech.api.graphnet.graph.NetUndirectedGraph; import java.util.function.Function; import java.util.function.Supplier; -public abstract class WorldPipeNetComplex, +public abstract class WorldPipeNetComplex, PipeType extends Enum & IPipeType, Edge extends NetEdge> extends WorldPipeNetBase { @@ -46,7 +46,7 @@ public WorldPipeNetComplex(String name, boolean isDirected, boolean isSinglePath */ public WorldPipeNetComplex(String name, boolean isDirected, Supplier edgeSupplier, Function, INetAlgorithm> algorithmBuilder) { - super(name, isDirected, algorithmBuilder, isDirected ? new CustomDirectedGraph<>(null, edgeSupplier) : - new CustomUndirectedGraph<>(null, edgeSupplier)); + super(name, isDirected, algorithmBuilder, isDirected ? new NetDirectedGraph<>(null, edgeSupplier) : + new NetUndirectedGraph(null, edgeSupplier)); } } diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java b/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetSimple.java similarity index 76% rename from src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java rename to src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetSimple.java index bbb456e6e63..203787a1ec0 100644 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetSimple.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetSimple.java @@ -1,16 +1,16 @@ -package gregtech.api.pipenet; +package gregtech.api.graphnet.pipenetold; -import gregtech.api.pipenet.alg.INetAlgorithm; -import gregtech.api.pipenet.alg.ShortestPathsAlgorithm; -import gregtech.api.pipenet.alg.SinglePathAlgorithm; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.graph.CustomDirectedGraph; -import gregtech.api.pipenet.graph.CustomUndirectedGraph; +import gregtech.api.graphnet.alg.INetAlgorithm; +import gregtech.api.graphnet.alg.ShortestPathsAlgorithm; +import gregtech.api.graphnet.alg.SinglePathAlgorithm; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.NetDirectedGraph; +import gregtech.api.graphnet.graph.NetUndirectedGraph; import java.util.function.Function; -public abstract class WorldPipeNetSimple, +public abstract class WorldPipeNetSimple, PipeType extends Enum & IPipeType> extends WorldPipeNetBase { @@ -39,7 +39,7 @@ public WorldPipeNetSimple(String name, boolean isDirected, boolean isSinglePath) */ public WorldPipeNetSimple(String name, boolean isDirected, Function, INetAlgorithm> algorithmBuilder) { - super(name, isDirected, algorithmBuilder, isDirected ? new CustomDirectedGraph<>(NetEdge.class) : - new CustomUndirectedGraph<>(NetEdge.class)); + super(name, isDirected, algorithmBuilder, isDirected ? new NetDirectedGraph<>(NetEdge.class) : + new NetUndirectedGraph(NetEdge.class)); } } diff --git a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/BlockPipe.java similarity index 98% rename from src/main/java/gregtech/api/pipenet/block/BlockPipe.java rename to src/main/java/gregtech/api/graphnet/pipenetold/block/BlockPipe.java index 3bd613757f3..d8a4a254f1f 100644 --- a/src/main/java/gregtech/api/pipenet/block/BlockPipe.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/block/BlockPipe.java @@ -1,19 +1,19 @@ -package gregtech.api.pipenet.block; +package gregtech.api.graphnet.pipenetold.block; import gregtech.api.block.BuiltInRenderBlock; import gregtech.api.cover.Cover; import gregtech.api.cover.CoverHolder; import gregtech.api.cover.CoverRayTracer; import gregtech.api.cover.IFacadeCover; +import gregtech.api.graphnet.pipenetold.IBlockAppearance; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; -import gregtech.api.pipenet.IBlockAppearance; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.WorldPipeNetBase; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.PipeCoverableImplementation; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.PipeCoverableImplementation; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.util.GTUtility; import gregtech.common.ConfigHolder; import gregtech.common.blocks.BlockFrame; @@ -65,7 +65,7 @@ @SuppressWarnings("deprecation") public abstract class BlockPipe & IPipeType, - NodeDataType extends INodeData, Edge extends NetEdge, + NodeDataType extends IPipeNetData, Edge extends NetEdge, WorldPipeNetType extends WorldPipeNetBase> extends BuiltInRenderBlock implements ITileEntityProvider, IFacadeWrapper, IBlockAppearance { diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/IPipeType.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/IPipeType.java new file mode 100644 index 00000000000..6e94ad7212a --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenetold/block/IPipeType.java @@ -0,0 +1,14 @@ +package gregtech.api.graphnet.pipenetold.block; + +import gregtech.api.graphnet.pipenetold.IPipeNetData; + +import net.minecraft.util.IStringSerializable; + +public interface IPipeType> extends IStringSerializable { + + float getThickness(); + + NodeDataType modifyProperties(NodeDataType baseProperties); + + boolean isPaintable(); +} diff --git a/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/ItemBlockPipe.java similarity index 91% rename from src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java rename to src/main/java/gregtech/api/graphnet/pipenetold/block/ItemBlockPipe.java index 8ec0406531c..4e582785284 100644 --- a/src/main/java/gregtech/api/pipenet/block/ItemBlockPipe.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/block/ItemBlockPipe.java @@ -1,7 +1,7 @@ -package gregtech.api.pipenet.block; +package gregtech.api.graphnet.pipenetold.block; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.common.ConfigHolder; import net.minecraft.block.state.IBlockState; @@ -16,7 +16,7 @@ import org.jetbrains.annotations.NotNull; public class ItemBlockPipe & IPipeType, - NodeDataType extends INodeData> extends ItemBlock { + NodeDataType extends IPipeNetData> extends ItemBlock { protected final BlockPipe blockPipe; diff --git a/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/BlockMaterialPipe.java similarity index 88% rename from src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java rename to src/main/java/gregtech/api/graphnet/pipenetold/block/material/BlockMaterialPipe.java index 6cc49be9342..8099e34b9bb 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/BlockMaterialPipe.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/BlockMaterialPipe.java @@ -1,13 +1,13 @@ -package gregtech.api.pipenet.block.material; +package gregtech.api.graphnet.pipenetold.block.material; import gregtech.api.GTValues; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.WorldPipeNetBase; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.unification.ore.OrePrefix; @@ -29,7 +29,7 @@ public abstract class BlockMaterialPipe< PipeType extends Enum & IPipeType & IMaterialPipeType, - NodeDataType extends INodeData, Edge extends NetEdge, + NodeDataType extends IPipeNetData, Edge extends NetEdge, WorldPipeNetType extends WorldPipeNetBase> extends BlockPipe { diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeTile.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeTile.java new file mode 100644 index 00000000000..37ecb30bb97 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeTile.java @@ -0,0 +1,14 @@ +package gregtech.api.graphnet.pipenetold.block.material; + +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.unification.material.Material; + +public interface IMaterialPipeTile & IPipeType, + NodeDataType extends IPipeNetData, Edge extends NetEdge> + extends IPipeTile { + + Material getPipeMaterial(); +} diff --git a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeType.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeType.java similarity index 50% rename from src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeType.java rename to src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeType.java index 018ec16785b..bb439a42992 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeType.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeType.java @@ -1,10 +1,10 @@ -package gregtech.api.pipenet.block.material; +package gregtech.api.graphnet.pipenetold.block.material; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.block.IPipeType; import gregtech.api.unification.ore.OrePrefix; -public interface IMaterialPipeType> extends IPipeType { +public interface IMaterialPipeType> extends IPipeType { /** * Determines ore prefix used for this pipe type, which gives pipe ore dictionary key diff --git a/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/ItemBlockMaterialPipe.java similarity index 78% rename from src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java rename to src/main/java/gregtech/api/graphnet/pipenetold/block/material/ItemBlockMaterialPipe.java index a348fa05379..2b31a6bf229 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/ItemBlockMaterialPipe.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/ItemBlockMaterialPipe.java @@ -1,7 +1,7 @@ -package gregtech.api.pipenet.block.material; +package gregtech.api.graphnet.pipenetold.block.material; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.block.ItemBlockPipe; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.block.ItemBlockPipe; import gregtech.api.unification.material.Material; import net.minecraft.item.ItemStack; @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; public class ItemBlockMaterialPipe & IMaterialPipeType, - NodeDataType extends INodeData> + NodeDataType extends IPipeNetData> extends ItemBlockPipe { public ItemBlockMaterialPipe(BlockMaterialPipe block) { diff --git a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/TileEntityMaterialPipeBase.java similarity index 90% rename from src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java rename to src/main/java/gregtech/api/graphnet/pipenetold/block/material/TileEntityMaterialPipeBase.java index 8d3f59f18a2..2076f07300f 100644 --- a/src/main/java/gregtech/api/pipenet/block/material/TileEntityMaterialPipeBase.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/TileEntityMaterialPipeBase.java @@ -1,10 +1,10 @@ -package gregtech.api.pipenet.block.material; +package gregtech.api.graphnet.pipenetold.block.material; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; import gregtech.api.unification.material.registry.MaterialRegistry; @@ -17,7 +17,7 @@ import static gregtech.api.capability.GregtechDataCodes.UPDATE_PIPE_MATERIAL; public abstract class TileEntityMaterialPipeBase & IMaterialPipeType, - NodeDataType extends INodeData, Edge extends NetEdge> + NodeDataType extends IPipeNetData, Edge extends NetEdge> extends TileEntityPipeBase implements IMaterialPipeTile { diff --git a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/simple/BlockSimplePipe.java similarity index 70% rename from src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java rename to src/main/java/gregtech/api/graphnet/pipenetold/block/simple/BlockSimplePipe.java index 164b60fb14f..a4eec35eff6 100644 --- a/src/main/java/gregtech/api/pipenet/block/simple/BlockSimplePipe.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/block/simple/BlockSimplePipe.java @@ -1,17 +1,17 @@ -package gregtech.api.pipenet.block.simple; +package gregtech.api.graphnet.pipenetold.block.simple; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.WorldPipeNetBase; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import net.minecraft.item.ItemStack; public abstract class BlockSimplePipe & IPipeType, - NodeDataType extends INodeData, Edge extends NetEdge, + NodeDataType extends IPipeNetData, Edge extends NetEdge, WorldPipeNetType extends WorldPipeNetBase> extends BlockPipe { diff --git a/src/main/java/gregtech/api/pipenet/longdist/BlockLongDistancePipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/BlockLongDistancePipe.java similarity index 99% rename from src/main/java/gregtech/api/pipenet/longdist/BlockLongDistancePipe.java rename to src/main/java/gregtech/api/graphnet/pipenetold/longdist/BlockLongDistancePipe.java index 2372a9792c8..804831f9721 100644 --- a/src/main/java/gregtech/api/pipenet/longdist/BlockLongDistancePipe.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/BlockLongDistancePipe.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet.longdist; +package gregtech.api.graphnet.pipenetold.longdist; import gregtech.api.items.toolitem.ToolClasses; import gregtech.common.creativetab.GTCreativeTabs; diff --git a/src/main/java/gregtech/api/pipenet/longdist/ILDEndpoint.java b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDEndpoint.java similarity index 97% rename from src/main/java/gregtech/api/pipenet/longdist/ILDEndpoint.java rename to src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDEndpoint.java index 8b7e506faa7..42628428f9c 100644 --- a/src/main/java/gregtech/api/pipenet/longdist/ILDEndpoint.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDEndpoint.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet.longdist; +package gregtech.api.graphnet.pipenetold.longdist; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.interfaces.INeighborCache; diff --git a/src/main/java/gregtech/api/pipenet/longdist/ILDNetworkPart.java b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDNetworkPart.java similarity index 94% rename from src/main/java/gregtech/api/pipenet/longdist/ILDNetworkPart.java rename to src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDNetworkPart.java index 2e68fc04ec6..8bf2d86e273 100644 --- a/src/main/java/gregtech/api/pipenet/longdist/ILDNetworkPart.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDNetworkPart.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet.longdist; +package gregtech.api.graphnet.pipenetold.longdist; import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistanceNetwork.java similarity index 99% rename from src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java rename to src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistanceNetwork.java index 898df301336..fe42a1478e0 100644 --- a/src/main/java/gregtech/api/pipenet/longdist/LongDistanceNetwork.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistanceNetwork.java @@ -1,6 +1,6 @@ -package gregtech.api.pipenet.longdist; +package gregtech.api.graphnet.pipenetold.longdist; -import gregtech.api.pipenet.WorldPipeNetBase; +import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/api/pipenet/longdist/LongDistancePipeType.java b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistancePipeType.java similarity index 92% rename from src/main/java/gregtech/api/pipenet/longdist/LongDistancePipeType.java rename to src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistancePipeType.java index 61b3c615380..ca630fe787e 100644 --- a/src/main/java/gregtech/api/pipenet/longdist/LongDistancePipeType.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistancePipeType.java @@ -1,7 +1,7 @@ -package gregtech.api.pipenet.longdist; +package gregtech.api.graphnet.pipenetold.longdist; -import gregtech.common.pipelike.fluidpipe.longdistance.LDFluidPipeType; -import gregtech.common.pipelike.itempipe.longdistance.LDItemPipeType; +import gregtech.common.pipelikeold.fluidpipe.longdistance.LDFluidPipeType; +import gregtech.common.pipelikeold.itempipe.longdistance.LDItemPipeType; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; diff --git a/src/main/java/gregtech/api/pipenet/longdist/NetworkBuilder.java b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/NetworkBuilder.java similarity index 99% rename from src/main/java/gregtech/api/pipenet/longdist/NetworkBuilder.java rename to src/main/java/gregtech/api/graphnet/pipenetold/longdist/NetworkBuilder.java index 2eb375b5c23..e122da098f0 100644 --- a/src/main/java/gregtech/api/pipenet/longdist/NetworkBuilder.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/NetworkBuilder.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet.longdist; +package gregtech.api.graphnet.pipenetold.longdist; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; diff --git a/src/main/java/gregtech/api/pipenet/predicate/FilteredEdgePredicate.java b/src/main/java/gregtech/api/graphnet/pipenetold/predicate/FilteredEdgePredicate.java similarity index 96% rename from src/main/java/gregtech/api/pipenet/predicate/FilteredEdgePredicate.java rename to src/main/java/gregtech/api/graphnet/pipenetold/predicate/FilteredEdgePredicate.java index 25d15a08bd1..1493a11fdc0 100644 --- a/src/main/java/gregtech/api/pipenet/predicate/FilteredEdgePredicate.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/predicate/FilteredEdgePredicate.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet.predicate; +package gregtech.api.graphnet.pipenetold.predicate; import gregtech.api.util.IDirtyNotifiable; import gregtech.common.covers.filter.BaseFilterContainer; @@ -8,7 +8,7 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -public abstract class FilteredEdgePredicate> extends AbstractEdgePredicate +public abstract class FilteredEdgePredicate> extends IEdgePredicateOld implements IShutteredEdgePredicate { protected static final IDirtyNotifiable DECOY = () -> {}; diff --git a/src/main/java/gregtech/api/pipenet/predicate/IShutteredEdgePredicate.java b/src/main/java/gregtech/api/graphnet/pipenetold/predicate/IShutteredEdgePredicate.java similarity index 75% rename from src/main/java/gregtech/api/pipenet/predicate/IShutteredEdgePredicate.java rename to src/main/java/gregtech/api/graphnet/pipenetold/predicate/IShutteredEdgePredicate.java index d68ea3369e1..d14316f2861 100644 --- a/src/main/java/gregtech/api/pipenet/predicate/IShutteredEdgePredicate.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/predicate/IShutteredEdgePredicate.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet.predicate; +package gregtech.api.graphnet.pipenetold.predicate; public interface IShutteredEdgePredicate { diff --git a/src/main/java/gregtech/api/pipenet/predicate/BasicEdgePredicate.java b/src/main/java/gregtech/api/graphnet/pipenetold/predicate/ShutteredEdgePredicate.java similarity index 79% rename from src/main/java/gregtech/api/pipenet/predicate/BasicEdgePredicate.java rename to src/main/java/gregtech/api/graphnet/pipenetold/predicate/ShutteredEdgePredicate.java index cbd09fba42d..8987bd7450e 100644 --- a/src/main/java/gregtech/api/pipenet/predicate/BasicEdgePredicate.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/predicate/ShutteredEdgePredicate.java @@ -1,16 +1,15 @@ -package gregtech.api.pipenet.predicate; +package gregtech.api.graphnet.pipenetold.predicate; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTTagCompound; import org.jetbrains.annotations.NotNull; -public class BasicEdgePredicate extends AbstractEdgePredicate implements IShutteredEdgePredicate { - - private final static String KEY = "Basic"; +public class ShutteredEdgePredicate extends IEdgePredicateOld + implements IShutteredEdgePredicate { - static { - PREDICATE_SUPPLIERS.put(KEY, BasicEdgePredicate::new); - } + public final static String KEY = "Basic"; protected boolean shutteredSource; protected boolean shutteredTarget; diff --git a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java b/src/main/java/gregtech/api/graphnet/pipenetold/tile/IPipeTile.java similarity index 83% rename from src/main/java/gregtech/api/pipenet/tile/IPipeTile.java rename to src/main/java/gregtech/api/graphnet/pipenetold/tile/IPipeTile.java index c58403b4815..1613131bfc1 100644 --- a/src/main/java/gregtech/api/pipenet/tile/IPipeTile.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/tile/IPipeTile.java @@ -1,11 +1,11 @@ -package gregtech.api.pipenet.tile; +package gregtech.api.graphnet.pipenetold.tile; +import gregtech.api.graphnet.pipenetold.PipeNetNode; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.metatileentity.interfaces.INeighborCache; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.IPipeNetData; import gregtech.api.unification.material.Material; import net.minecraft.network.PacketBuffer; @@ -20,7 +20,7 @@ import java.util.function.Consumer; public interface IPipeTile & IPipeType, - NodeDataType extends INodeData, Edge extends NetEdge> extends INeighborCache { + NodeDataType extends IPipeNetData, Edge extends NetEdge> extends INeighborCache { World getPipeWorld(); @@ -81,7 +81,7 @@ default boolean canHaveBlockedFaces() { NodeDataType getNodeData(); - NetNode getNode(); + PipeNetNode getNode(); @Nullable TileEntity getNonPipeNeighbour(EnumFacing facing); diff --git a/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java b/src/main/java/gregtech/api/graphnet/pipenetold/tile/PipeCoverableImplementation.java similarity index 98% rename from src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java rename to src/main/java/gregtech/api/graphnet/pipenetold/tile/PipeCoverableImplementation.java index 30a6a6c4ceb..6dfc4a65a8c 100644 --- a/src/main/java/gregtech/api/pipenet/tile/PipeCoverableImplementation.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/tile/PipeCoverableImplementation.java @@ -1,9 +1,9 @@ -package gregtech.api.pipenet.tile; +package gregtech.api.graphnet.pipenetold.tile; import gregtech.api.cover.Cover; import gregtech.api.cover.CoverHolder; import gregtech.api.cover.CoverSaveHandler; -import gregtech.api.pipenet.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; import gregtech.api.util.GTUtility; import gregtech.common.ConfigHolder; diff --git a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java similarity index 94% rename from src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java rename to src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java index c622a7502b5..8488aa98c99 100644 --- a/src/main/java/gregtech/api/pipenet/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java @@ -1,16 +1,16 @@ -package gregtech.api.pipenet.tile; +package gregtech.api.graphnet.pipenetold.tile; import gregtech.api.GregTechAPI; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.PipeNetNode; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.metatileentity.NeighborCacheTileEntityBase; import gregtech.api.metatileentity.SyncedTileEntityBase; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.WorldPipeNetBase; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; import gregtech.api.unification.material.Material; import net.minecraft.block.Block; @@ -37,7 +37,7 @@ import static gregtech.api.capability.GregtechDataCodes.*; public abstract class TileEntityPipeBase & IPipeType, - NodeDataType extends INodeData, Edge extends NetEdge> extends NeighborCacheTileEntityBase + NodeDataType extends IPipeNetData, Edge extends NetEdge> extends NeighborCacheTileEntityBase implements IPipeTile { protected final PipeCoverableImplementation coverableImplementation = new PipeCoverableImplementation(this); @@ -52,7 +52,7 @@ public abstract class TileEntityPipeBase & IPipe /** * Our node stores connection data and NodeData data */ - protected @Nullable NetNode netNode; + protected @Nullable PipeNetNode pipeNetNode; private BlockPipe pipeBlock; private PipeType pipeType = getPipeTypeClass().getEnumConstants()[0]; @Nullable @@ -81,8 +81,8 @@ public void setPipeData(BlockPipe pipeBlock, Pi public void transferDataFrom(IPipeTile tileEntity) { this.pipeType = tileEntity.getPipeType(); this.paintingColor = tileEntity.getPaintingColor(); - this.netNode = tileEntity.getNode(); - this.netNode.setData(getPipeBlock().createProperties(this)); + this.pipeNetNode = tileEntity.getNode(); + this.pipeNetNode.setData(getPipeBlock().createProperties(this)); if (tileEntity instanceof SyncedTileEntityBase pipeBase) { addPacketsFrom(pipeBase); } @@ -91,13 +91,13 @@ public void transferDataFrom(IPipeTile tileEntity) } @Override - public NetNode getNode() { - if (netNode == null) { + public PipeNetNode getNode() { + if (pipeNetNode == null) { if (this.getPipeWorld().isRemote) - netNode = new NetNode<>(this); - else netNode = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()).getOrCreateNode(this); + pipeNetNode = new PipeNetNode<>(this); + else pipeNetNode = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()).getOrCreateNode(this); } - return netNode; + return pipeNetNode; } @Override @@ -322,7 +322,7 @@ public PipeType getPipeType() { @Override public NodeDataType getNodeData() { // the only thing standing between this and a stack overflow error - if (this.netNode == null) return getPipeBlock().createProperties(this); + if (this.pipeNetNode == null) return getPipeBlock().createProperties(this); if (this.getNode().getData() == null) { this.getNode().setData(getPipeBlock().createProperties(this)); @@ -473,7 +473,7 @@ protected void doOldNetSetup() { // something to do with removing the tile entities that the chunk is iterating over to load WorldPipeNetBase net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); for (EnumFacing facing : EnumFacing.VALUES) { - NetNode nodeOffset = net.getNode(this.getPipePos().offset(facing)); + PipeNetNode nodeOffset = net.getNode(this.getPipePos().offset(facing)); if (nodeOffset == null) continue; if (net.isDirected()) { // offset node might've been read before us, so we have to cover for it. diff --git a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java new file mode 100644 index 00000000000..e6bb6659889 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java @@ -0,0 +1,86 @@ +package gregtech.api.graphnet.predicate; + +import gregtech.api.graphnet.gather.GTGraphGatherables; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.common.util.INBTSerializable; + +import java.util.Map; +import java.util.function.Predicate; +import java.util.function.Supplier; + +public final class EdgePredicateHandler implements INBTSerializable, Predicate { + + private final Map> predicateSet; + + public EdgePredicateHandler() { + predicateSet = new Object2ObjectOpenHashMap<>(); + } + + private EdgePredicateHandler(Map> predicateSet) { + this.predicateSet = predicateSet; + } + + public EdgePredicateHandler mergePredicate(IEdgePredicate predicate) { + IEdgePredicate current = predicateSet.get(predicate.getName()); + if (predicate.getClass().isInstance(current)) { + predicate = current.union(predicate); + } + return setPredicate(predicate); + } + + public EdgePredicateHandler setPredicate(IEdgePredicate predicate) { + predicateSet.put(predicate.getName(), predicate); + return this; + } + + public EdgePredicateHandler removePredicate(IEdgePredicate key) { + predicateSet.remove(key.getName()); + return this; + } + + @Override + public boolean test(IPredicateTestObject iPredicateTestObject) { + // TODO predicate 'categories' or 'affinities' that determine order of operations with and-y and or-y behavior? + boolean result = false; + for (IEdgePredicate predicate : predicateSet.values()) { + boolean test = predicate.test(iPredicateTestObject); + if (predicate.andy() && !test) return false; + else result |= test; + } + return result; + } + + @Override + public NBTTagList serializeNBT() { + NBTTagList list = new NBTTagList(); + for (IEdgePredicate entry : predicateSet.values()) { + NBTTagCompound tag = new NBTTagCompound(); + tag.setTag("Tag", entry.serializeNBT()); + tag.setString("Name", entry.getName()); + list.appendTag(tag); + } + return list; + } + + @Override + public void deserializeNBT(NBTTagList nbt) { + for (int i = 0; i < nbt.tagCount(); i++) { + NBTTagCompound tag = nbt.getCompoundTagAt(i); + String key = tag.getString("Name"); + IEdgePredicate entry = this.predicateSet.get(key); + if (entry == null) entry = getSupplier(key).get(); + if (entry == null) continue; + entry.deserializeNBTNaive(tag.getTag("Tag")); + } + } + + private static Supplier> getSupplier(String identifier) { + return GTGraphGatherables.getPredicatesRegistry().getOrDefault(identifier, () -> null); + } +} diff --git a/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java b/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java new file mode 100644 index 00000000000..ff15d4e48cf --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java @@ -0,0 +1,33 @@ +package gregtech.api.graphnet.predicate; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import net.minecraft.nbt.NBTBase; +import net.minecraft.util.IStringSerializable; +import net.minecraftforge.common.util.INBTSerializable; + +import org.jetbrains.annotations.Contract; + +/** + * Note - all implementers of this interface are suggested to be final, in order to avoid unexpected {@link #union(IEdgePredicate)} behavior. + */ +public interface IEdgePredicate, N extends NBTBase> extends INBTSerializable, IStringSerializable { + + default void deserializeNBTNaive(NBTBase nbt) { + deserializeNBT((N) nbt); + } + + /** + * Whether this predicate should behave in "and" fashion with other predicates.

+ * For example, if a predicate handler has 2 and-y predicates and 3 or-y predicates, + * the effective result of evaluation will be:
(andy1) && (andy2) && (ory1 || ory2 || ory3) + */ + default boolean andy() { + return false; + } + + boolean test(IPredicateTestObject object); + + @Contract("_ -> new") + T union(IEdgePredicate other); +} diff --git a/src/main/java/gregtech/api/pipenet/predicate/FluidTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java similarity index 95% rename from src/main/java/gregtech/api/pipenet/predicate/FluidTestObject.java rename to src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java index c03d260a3e6..87ca1818007 100644 --- a/src/main/java/gregtech/api/pipenet/predicate/FluidTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet.predicate; +package gregtech.api.graphnet.predicate.test; import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fluids.Fluid; diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java new file mode 100644 index 00000000000..77d9bf7061a --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java @@ -0,0 +1,4 @@ +package gregtech.api.graphnet.predicate.test; + +public interface IPredicateTestObject { +} diff --git a/src/main/java/gregtech/api/pipenet/predicate/ItemTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java similarity index 95% rename from src/main/java/gregtech/api/pipenet/predicate/ItemTestObject.java rename to src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java index f39450aedbd..4e1661a6e85 100644 --- a/src/main/java/gregtech/api/pipenet/predicate/ItemTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java @@ -1,4 +1,4 @@ -package gregtech.api.pipenet.predicate; +package gregtech.api.graphnet.predicate.test; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java new file mode 100644 index 00000000000..bfcf07f82ad --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java @@ -0,0 +1,126 @@ +package gregtech.api.graphnet.servernet; + +import gregtech.api.graphnet.GraphNetBacker; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.alg.INetAlgorithm; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.INetGraph; +import gregtech.api.graphnet.graph.NetDirectedGraph; +import gregtech.api.graphnet.graph.NetUndirectedGraph; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.WeightFactorLogic; + +import gregtech.api.util.DimensionPos; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.storage.WorldSavedData; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Function; + +/** + * Unused demonstration net that would allow for edges bridging dimensions inside the graph representation. + */ +@SuppressWarnings("unused") +public abstract class ServerNet extends WorldSavedData implements IGraphNet { + + protected final GraphNetBacker backer; + + public ServerNet(String name, Function algorithmBuilder, + Function graphBuilder, boolean dynamicWeights) { + super(name); + this.backer = new GraphNetBacker(this, algorithmBuilder, graphBuilder.apply(this), dynamicWeights); + } + + public ServerNet(String name, Function algorithmBuilder, + boolean directed, boolean dynamicWeights) { + this(name, algorithmBuilder, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), dynamicWeights); + } + + @Override + public void addNode(@NotNull NetNode node) { + nodeClassCheck(node); + this.backer.addNode(node); + } + + public @Nullable ServerNetNode getNode(@NotNull DimensionPos equivalencyData) { + return (ServerNetNode) getNode((Object) equivalencyData); + } + + @Override + public @Nullable NetNode getNode(@NotNull Object equivalencyData) { + return backer.getNode(equivalencyData); + } + + @Override + public void removeNode(@NotNull NetNode node) { + nodeClassCheck(node); + this.backer.removeNode(node); + } + + @Override + public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays) { + nodeClassCheck(source); + nodeClassCheck(target); + double weight = source.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue() + + target.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue(); + NetEdge edge = backer.addEdge(source, target, weight); + if (edge != null) initializeEdge(source, target, edge); + if (bothWays) { + if (this.getGraph().isDirected()) { + edge = backer.addEdge(target, source, weight); + if (edge != null) initializeEdge(target, source, edge); + } + return null; + } else return edge; + } + + @Override + public @Nullable NetEdge getEdge(@NotNull NetNode source, @NotNull NetNode target) { + nodeClassCheck(source); + nodeClassCheck(target); + return backer.getEdge(source, target); + } + + @Override + public void removeEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays) { + nodeClassCheck(source); + nodeClassCheck(target); + this.backer.removeEdge(source, target); + if (bothWays && this.getGraph().isDirected()) { + this.backer.removeEdge(target, source); + } + } + + protected void initializeEdge(@NotNull NetNode source, @NotNull NetNode target, @NotNull NetEdge edge) { + edge.setData(NetLogicData.union(source.getData(), target.getData())); + } + + @Override + public void readFromNBT(@NotNull NBTTagCompound nbt) { + backer.readFromNBT(nbt); + } + + @Override + public @NotNull NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { + return backer.writeToNBT(compound); + } + + @Override + public GraphNetBacker getBacker() { + return backer; + } + + @Override + public Class getNodeClass() { + return ServerNetNode.class; + } + + @Override + public @NotNull ServerNetNode getNewNode() { + return new ServerNetNode(this); + } +} diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java new file mode 100644 index 00000000000..79af7d4b2f1 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java @@ -0,0 +1,38 @@ +package gregtech.api.graphnet.servernet; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetNode; + +import gregtech.api.util.DimensionPos; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; + +public class ServerNetNode extends NetNode { + + private DimensionPos pos; + + public ServerNetNode(IGraphNet net) { + super(net); + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = super.serializeNBT(); + tag.setLong("Pos", pos.getPos().toLong()); + tag.setInteger("Dim", pos.getDimension()); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt); + BlockPos pos = BlockPos.fromLong(nbt.getLong("Pos")); + this.pos = new DimensionPos(pos, nbt.getInteger("Dim")); + } + + @Override + public Object getEquivalencyData() { + return pos; + } +} diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java new file mode 100644 index 00000000000..e1732d94412 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -0,0 +1,155 @@ +package gregtech.api.graphnet.worldnet; + +import gregtech.api.graphnet.path.GenericGraphNetPath; +import gregtech.api.graphnet.GraphNetBacker; +import gregtech.api.graphnet.IGraphNet; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.alg.INetAlgorithm; + +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.INetGraph; + +import gregtech.api.graphnet.graph.NetDirectedGraph; +import gregtech.api.graphnet.graph.NetUndirectedGraph; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.WeightFactorLogic; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.storage.WorldSavedData; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; +import java.util.function.Function; + +public abstract class WorldNet extends WorldSavedData implements IGraphNet { + + protected final GraphNetBacker backer; + private World world; + + public WorldNet(String name, Function algorithmBuilder, + Function graphBuilder) { + super(name); + this.backer = new GraphNetBacker(this, algorithmBuilder, graphBuilder.apply(this)); + } + + public WorldNet(String name, Function algorithmBuilder, + boolean directed) { + this(name, algorithmBuilder, + directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder()); + } + + public void setWorld(World world) { + this.world = world; + } + + public World getWorld() { + return world; + } + + public Iterator getGenericPaths(WorldNetNode node) { + return backer.getPaths(node, GenericGraphNetPath.MAPPER); + } + + @NotNull + public WorldNetNode getOrCreateNode(@NotNull BlockPos pos) { + WorldNetNode node = getNode(pos); + if (node != null) return node; + node = getNewNode(); + node.setPos(pos); + addNode(node); + return node; + } + + @Override + public void addNode(@NotNull NetNode node) { + nodeClassCheck(node); + this.backer.addNode(node); + } + + public @Nullable WorldNetNode getNode(@NotNull BlockPos equivalencyData) { + return (WorldNetNode) getNode((Object) equivalencyData); + } + + @Override + public @Nullable NetNode getNode(@NotNull Object equivalencyData) { + return backer.getNode(equivalencyData); + } + + @Override + public void removeNode(@NotNull NetNode node) { + nodeClassCheck(node); + this.backer.removeNode(node); + } + + @Override + public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays) { + nodeClassCheck(source); + nodeClassCheck(target); + double weight = source.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue() + + target.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue(); + NetEdge edge = backer.addEdge(source, target, weight); + if (edge != null) initializeEdge(source, target, edge); + if (bothWays) { + if (this.getGraph().isDirected()) { + edge = backer.addEdge(target, source, weight); + if (edge != null) initializeEdge(target, source, edge); + } + return null; + } else return edge; + } + + @Override + public @Nullable NetEdge getEdge(@NotNull NetNode source, @NotNull NetNode target) { + nodeClassCheck(source); + nodeClassCheck(target); + return backer.getEdge(source, target); + } + + @Override + public void removeEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays) { + nodeClassCheck(source); + nodeClassCheck(target); + this.backer.removeEdge(source, target); + if (bothWays && this.getGraph().isDirected()) { + this.backer.removeEdge(target, source); + } + } + + protected void initializeEdge(@NotNull NetNode source, @NotNull NetNode target, @NotNull NetEdge edge) { + edge.setData(NetLogicData.union(source.getData(), target.getData())); + } + + protected int getDimension() { + return world.provider.getDimension(); + } + + @Override + public void readFromNBT(@NotNull NBTTagCompound nbt) { + backer.readFromNBT(nbt); + } + + @Override + public @NotNull NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { + return backer.writeToNBT(compound); + } + + @Override + public GraphNetBacker getBacker() { + return backer; + } + + @Override + public Class getNodeClass() { + return WorldNetNode.class; + } + + @Override + public @NotNull WorldNetNode getNewNode() { + return new WorldNetNode(this); + } +} diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java new file mode 100644 index 00000000000..e539e80b0d6 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java @@ -0,0 +1,46 @@ +package gregtech.api.graphnet.worldnet; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetNode; + +import gregtech.api.graphnet.pipenet.WorldPipeNet; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; + +public class WorldNetNode extends NetNode { + + private BlockPos pos; + + public WorldNetNode(WorldNet net) { + super(net); + } + + @Override + public WorldNet getNet() { + return (WorldNet) super.getNet(); + } + + public WorldNetNode setPos(BlockPos pos) { + this.pos = pos; + return this; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = super.serializeNBT(); + tag.setLong("Pos", pos.toLong()); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt); + this.setPos(BlockPos.fromLong(nbt.getLong("Pos"))); + } + + @Override + public Object getEquivalencyData() { + return pos; + } +} diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java index c24c471ae58..b90673cdfef 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java @@ -9,7 +9,7 @@ import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.pattern.*; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.Material; import gregtech.api.util.BlockInfo; import gregtech.api.util.GTLog; diff --git a/src/main/java/gregtech/api/pipenet/AbstractGroupData.java b/src/main/java/gregtech/api/pipenet/AbstractGroupData.java deleted file mode 100644 index b3ba32072f2..00000000000 --- a/src/main/java/gregtech/api/pipenet/AbstractGroupData.java +++ /dev/null @@ -1,14 +0,0 @@ -package gregtech.api.pipenet; - -import gregtech.api.pipenet.block.IPipeType; - -public abstract class AbstractGroupData & IPipeType, - NodeDataType extends INodeData> { - - protected NetGroup group; - - public AbstractGroupData withGroup(NetGroup group) { - this.group = group; - return this; - } -} diff --git a/src/main/java/gregtech/api/pipenet/INodeData.java b/src/main/java/gregtech/api/pipenet/INodeData.java deleted file mode 100644 index 7ed17c339cf..00000000000 --- a/src/main/java/gregtech/api/pipenet/INodeData.java +++ /dev/null @@ -1,25 +0,0 @@ -package gregtech.api.pipenet; - -import java.util.Collections; -import java.util.List; - -public interface INodeData> { - - default int getChannelMaxCount() { - return 1; - } - - default double getWeightFactor() { - return 1; - } - - default int getThroughput() { - return 1; - } - - T getSumData(List datas); - - default T getSumData(Object data) { - return getSumData(Collections.singletonList((T) data)); - } -} diff --git a/src/main/java/gregtech/api/pipenet/NetGroup.java b/src/main/java/gregtech/api/pipenet/NetGroup.java deleted file mode 100644 index 8edfc178fd4..00000000000 --- a/src/main/java/gregtech/api/pipenet/NetGroup.java +++ /dev/null @@ -1,249 +0,0 @@ -package gregtech.api.pipenet; - -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.common.util.INBTSerializable; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jgrapht.Graph; -import org.jgrapht.traverse.BreadthFirstIterator; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -public class NetGroup & IPipeType, - NodeDataType extends INodeData, - Edge extends NetEdge> implements INBTSerializable { - - public final WorldPipeNetBase net; - - private final Graph, Edge> graph; - - private final Set> nodes; - - private final AbstractGroupData data; - - public NetGroup(Graph, Edge> graph, - WorldPipeNetBase net) { - this(graph, net, new ObjectOpenHashSet<>()); - } - - public NetGroup(Graph, Edge> graph, - WorldPipeNetBase net, - Set> nodes) { - this.graph = graph; - this.net = net; - this.data = net.getBlankGroupData(); - if (data != null) data.withGroup(this); - this.nodes = nodes; - nodes.forEach(this::onAddedToGroup); - } - - protected void addNode(NetNode node) { - this.nodes.add(node); - this.onAddedToGroup(node); - } - - protected void addNodes(Collection> nodes) { - this.nodes.addAll(nodes); - nodes.forEach(this::onAddedToGroup); - } - - protected void removeNode(NetNode node) { - this.nodes.remove(node); - } - - protected void removeNodes(Collection> nodes) { - this.nodes.removeAll(nodes); - } - - protected void clearNodes() { - this.nodes.clear(); - } - - protected void onAddedToGroup(NetNode node) { - node.setGroup(this); - } - - public void connectionChange(NetNode node) { - // TODO simplify path search by only checking nodes that have connections - // use net's connection capabilities - } - - /** - * Merges the groups of an edge if necessary. - * - * @param source the source node of the edge - * @param target the target node of the edge - */ - public static & IPipeType, - NDT extends INodeData, E extends NetEdge> void mergeEdge( - NetNode source, - NetNode target) { - NetGroup sourceGroup = source.getGroupUnsafe(); - NetGroup targetGroup = target.getGroupUnsafe(); - if (sourceGroup == targetGroup) { - if (sourceGroup == null) { - sourceGroup = source.getGroupSafe(); - } else { - sourceGroup.clearPathCaches(); - return; - } - } - if (sourceGroup != null) { - sourceGroup.mergeNode(target); - } else { - assert targetGroup != null; - targetGroup.mergeNode(source); - } - } - - protected void mergeNode(NetNode node) { - NetGroup group = node.getGroupUnsafe(); - if (group != null) { - this.addNodes(group.getNodes()); - group.clearNodes(); - } else addNode(node); - this.clearPathCaches(); - } - - /** - * Split this group by removing a node. Automatically removes the node from the graph. - * - * @param source node to remove - * @return Whether the node existed in the graph - */ - public boolean splitNode(NetNode source) { - if (this.graph.containsVertex(source)) { - this.clearPathCaches(); - List> targets = graph.outgoingEdgesOf(source).stream().map(a -> { - // handling so undirected graphs don't throw an error - if (net.isDirected() || a.getTarget().getNodePos() != source.getNodePos()) return a.getTarget(); - return a.getSource(); - }).collect(Collectors.toList()); - this.graph.removeVertex(source); - this.removeNode(source); - while (!targets.isEmpty()) { - // get the last target; if this throws a cast exception, something is very wrong with the graph. - @SuppressWarnings("unchecked") - NetNode target = (NetNode) targets - .remove(targets.size() - 1); - - Set> targetGroup = new ObjectOpenHashSet<>(); - BreadthFirstIterator, Edge> i = new BreadthFirstIterator<>(graph, - target); - NetNode temp; - while (i.hasNext()) { - temp = i.next(); - targetGroup.add(temp); - // if we find a target node in our search, remove it from the list - targets.remove(temp); - } - this.removeNodes(targetGroup); - if (targetGroup.size() != 0) { - new NetGroup<>(this.graph, this.net, targetGroup); - } - } - return true; - } - return false; - } - - /** - * Split this group by removing an edge. Automatically removes the edge from the graph. - * - * @param source source of the edge - * @param target target of the edge - * @return Whether the edge existed in the graph - */ - public boolean splitEdge(NetNode source, - NetNode target) { - if (graph.removeEdge(source, target) != null) { - this.clearPathCaches(); - Set> targetGroup = new ObjectOpenHashSet<>(); - BreadthFirstIterator, Edge> i = new BreadthFirstIterator<>(graph, - target); - NetNode temp; - while (i.hasNext()) { - temp = i.next(); - // if there's a another complete path to the source node from the target node, there's no need to split - if (source == temp) return true; - targetGroup.add(temp); - } - this.removeNodes(targetGroup); - if (targetGroup.size() != 0) { - new NetGroup<>(this.graph, this.net, targetGroup); - } - return true; - } - return false; - } - - /** - * For memory considerations, returns the uncloned set. Do not modify this directly. - */ - public Set> getNodes() { - return nodes; - } - - protected void clearPathCaches() { - this.getNodes().forEach(NetNode::clearPathCache); - } - - public Graph, Edge> getGraph() { - return graph; - } - - public AbstractGroupData getData() { - return this.data; - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tag = new NBTTagCompound(); - int i = 0; - for (NetNode node : this.nodes) { - tag.setLong(String.valueOf(i), node.getLongPos()); - i++; - } - tag.setInteger("NodeCount", i); - return tag; - } - - /** - * Use {@link NBTBuilder} instead, this does nothing. - */ - @Override - @Deprecated - public void deserializeNBT(NBTTagCompound nbt) {} - - public static final class NBTBuilder & IPipeType, - NodeDataType extends INodeData, E extends NetEdge> implements INBTBuilder { - - private final Set> nodes; - private final Graph, E> graph; - private final WorldPipeNetBase net; - - public NBTBuilder(Map> longPosMap, NBTTagCompound tag, - Graph, E> graph, - WorldPipeNetBase net) { - nodes = new ObjectOpenHashSet<>(); - for (int i = 0; i < tag.getInteger("NodeCount"); i++) { - NetNode node = longPosMap.get(tag.getLong(String.valueOf(i))); - nodes.add(node); - } - this.graph = graph; - this.net = net; - } - - @Override - public void build() { - NetGroup g = new NetGroup<>(graph, net, nodes); - } - } -} diff --git a/src/main/java/gregtech/api/pipenet/NetPath.java b/src/main/java/gregtech/api/pipenet/NetPath.java deleted file mode 100644 index 13d365292cc..00000000000 --- a/src/main/java/gregtech/api/pipenet/NetPath.java +++ /dev/null @@ -1,195 +0,0 @@ -package gregtech.api.pipenet; - -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.predicate.IPredicateTestObject; -import gregtech.api.util.FacingPos; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jgrapht.Graph; -import org.jgrapht.GraphPath; - -import java.util.*; -import java.util.stream.Collectors; - -public class NetPath & IPipeType, - NodeDataType extends INodeData, Edge extends NetEdge> { - - private List> nodeList; - private List edgeList; - - private NetNode sourceNode; - - private NetNode targetNode; - - private double weight; - - private NodeDataType data = null; - - /** - * Generates a loop NetPath for a node - * - * @param node the node to - */ - public NetPath(NetNode node) { - this.sourceNode = node; - this.targetNode = node; - this.nodeList = Collections.singletonList(node); - this.weight = node.getData().getWeightFactor(); - this.edgeList = new ObjectArrayList<>(0); - assert this.nodeList.size() == this.edgeList.size() + 1; - } - - /** - * Generates a NetPath from an ordered list of nodes, edges, and a weight. - * - * @param nodes List of nodes. - * @param edges List of edges. - * @param weight Sum weight of the path. - */ - public NetPath(List> nodes, List edges, double weight) { - this.sourceNode = nodes.get(0); - this.targetNode = nodes.get(nodes.size() - 1); - this.nodeList = nodes; - this.weight = weight; - this.edgeList = edges; - assert this.nodeList.size() == this.edgeList.size() + 1; - } - - /** - * Generates a NetPath from a GraphPath - * - * @param path the GraphPath - */ - public NetPath(GraphPath, Edge> path) { - this.sourceNode = path.getStartVertex(); - this.targetNode = path.getEndVertex(); - this.nodeList = path.getVertexList(); - // convert weight to the true value of the involved nodes - this.weight = (path.getWeight() + sourceNode.getData().getWeightFactor() + - targetNode.getData().getWeightFactor()) / 2; - - Graph, Edge> g = path.getGraph(); - this.edgeList = new ObjectArrayList<>(path.getEdgeList()); - assert this.nodeList.size() == this.edgeList.size() + 1; - } - - protected NetPath() {} - - public List> getNodeList() { - return nodeList; - } - - public List getEdgeList() { - return edgeList; - } - - public NetNode getSourceNode() { - return sourceNode; - } - - public NetNode getTargetNode() { - return targetNode; - } - - public Iterator getFacingIterator() { - return this.getTargetTEs().keySet().iterator(); - } - - public FacedNetPath firstFacing() { - return this.withFacing(this.getFacingIterator().next()); - } - - public FacedNetPath withFacing(EnumFacing facing) { - return new FacedNetPath<>(this, facing); - } - - public Map getTargetTEs() { - return targetNode.getConnecteds(); - } - - public double getWeight() { - return weight; - } - - public NodeDataType getSumData() { - // generate min data on-demand and cache it, rather than generating for every path always - if (this.data == null) { - this.data = sourceNode.getData() - .getSumData(this.nodeList.stream().map(NetNode::getData).collect(Collectors.toList())); - } - return data; - } - - public boolean checkPredicate(IPredicateTestObject testObject) { - for (NetEdge edge : this.edgeList) { - if (!edge.getPredicate().test(testObject)) return false; - } - return true; - } - - public boolean matches(NetPath other) { - // if the edge list and node list match content and order, then we definitely match. - return Objects.equals(nodeList, other.nodeList) && Objects.equals(edgeList, other.edgeList); - } - - public static class FacedNetPath & IPipeType, NDT extends INodeData, - E extends NetEdge> { - - public NetPath path; - - public EnumFacing facing; - - public FacedNetPath(NetPath path, EnumFacing facing) { - this.path = path; - this.facing = facing; - } - - public TileEntity getTargetTE() { - return path.getTargetTEs().get(facing); - } - - public List> getNodeList() { - return path.getNodeList(); - } - - public List getEdgeList() { - return path.getEdgeList(); - } - - public NetNode getSourceNode() { - return path.getSourceNode(); - } - - public NetNode getTargetNode() { - return path.getTargetNode(); - } - - public Map getTargetTEs() { - return path.getTargetTEs(); - } - - public double getWeight() { - return path.getWeight(); - } - - public NDT getSumData() { - return path.getSumData(); - } - - public boolean checkPredicate(IPredicateTestObject testObject) { - return path.checkPredicate(testObject); - } - - public FacingPos toFacingPos() { - return new FacingPos(path.getTargetNode().getNodePos(), this.facing); - } - - public EnumFacing oppositeFacing() { - return facing.getOpposite(); - } - } -} diff --git a/src/main/java/gregtech/api/pipenet/NodeLossResult.java b/src/main/java/gregtech/api/pipenet/NodeLossResult.java deleted file mode 100644 index 79fdb6ed062..00000000000 --- a/src/main/java/gregtech/api/pipenet/NodeLossResult.java +++ /dev/null @@ -1,20 +0,0 @@ -package gregtech.api.pipenet; - -import net.minecraft.util.Tuple; - -import java.util.function.Consumer; - -public class NodeLossResult extends Tuple>, Double> { - - public NodeLossResult(Consumer> postAction, Double lossFunction) { - super(postAction, lossFunction); - } - - public Consumer> getPostAction() { - return this.getFirst(); - } - - public Double getLossFunction() { - return this.getSecond(); - } -} diff --git a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java b/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java deleted file mode 100644 index 6ff6ed68974..00000000000 --- a/src/main/java/gregtech/api/pipenet/WorldPipeNetBase.java +++ /dev/null @@ -1,545 +0,0 @@ -package gregtech.api.pipenet; - -import gregtech.api.cover.Cover; -import gregtech.api.pipenet.alg.INetAlgorithm; -import gregtech.api.pipenet.alg.iter.ICacheableIterator; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.graph.ICustomGraph; -import gregtech.api.pipenet.predicate.AbstractEdgePredicate; -import gregtech.api.pipenet.predicate.BasicEdgePredicate; -import gregtech.api.pipenet.predicate.IShutteredEdgePredicate; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; -import gregtech.common.covers.CoverShutter; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.storage.WorldSavedData; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.Constants; - -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -public abstract class WorldPipeNetBase, - PipeType extends Enum & IPipeType, Edge extends NetEdge> extends WorldSavedData { - - private final boolean isDirected; - private final Function, INetAlgorithm> algorithmBuilder; - - private Set builders = null; - - private WeakReference worldRef = new WeakReference<>(null); - protected final ICustomGraph pipeGraph; - protected final Map> pipeMap = new Object2ObjectOpenHashMap<>(); - - private final INetAlgorithm.NetAlgorithmWrapper netAlgorithm; - - private boolean validAlgorithmInstance = false; - - WorldPipeNetBase(String name, boolean isDirected, - Function, INetAlgorithm> algorithmBuilder, - ICustomGraph graph) { - super(name); - graph.setOwningNet(this); - this.pipeGraph = graph; - this.netAlgorithm = new INetAlgorithm.NetAlgorithmWrapper<>(); - this.isDirected = isDirected; - this.algorithmBuilder = algorithmBuilder; - } - - public ICustomGraph getGraph() { - return this.pipeGraph; - } - - public final boolean isDirected() { - return isDirected; - } - - protected void markAlgInvalid() { - this.validAlgorithmInstance = false; - } - - protected void markAlgValid() { - this.validAlgorithmInstance = true; - } - - protected boolean hasValidAlg() { - return this.validAlgorithmInstance; - } - - public World getWorld() { - return this.worldRef.get(); - } - - public final boolean usesDynamicWeights() { - if (!needsDynamicWeights()) return false; - if (!this.hasValidAlg()) this.rebuildNetAlgorithm(); - return this.netAlgorithm.supportsDynamicWeights(); - } - - protected boolean needsDynamicWeights() { - return false; - } - - protected void setWorldAndInit(World world) { - if (world != this.worldRef.get()) { - this.worldRef = new WeakReference<>(world); - onWorldSet(); - // some builders have to wait for world set, so we wait until then to build them. - if (this.builders != null) this.builders.forEach(INBTBuilder::build); - } - } - - public static String getDataID(final String baseID, final World world) { - if (world == null || world.isRemote) - throw new RuntimeException("WorldPipeNetBase should only be created on the server!"); - int dimension = world.provider.getDimension(); - return dimension == 0 ? baseID : baseID + '.' + dimension; - } - - protected void onWorldSet() { - this.rebuildNetAlgorithm(); - } - - /** - * Preferred override. Only collects a fresh TE from the server if the provided TE is invalid. - * - * @param tile The {@link TileEntityPipeBase} that paths are being requested for - * @return the ordered list of paths associated with the {@link TileEntityPipeBase} - */ - public Iterator> getPaths(TileEntityPipeBase tile) { - return getPaths(this.pipeMap.get(tile.getPipePos()), tile); - } - - /** - * Special-case override. Forces the collection of a fresh TE from the server. - * - * @param pos The {@link BlockPos} that paths are being requested for - * @return the ordered list of paths associated with the {@link BlockPos} - */ - public Iterator> getPaths(BlockPos pos) { - return getPaths(this.pipeMap.get(pos), null); - } - - public Iterator> getPaths(@Nullable NetNode node, - @Nullable TileEntityPipeBase tile) { - if (node == null) return Collections.emptyIterator(); - - node.setHeldMTE(tile); - - if (!this.hasValidAlg()) this.rebuildNetAlgorithm(); - - Iterator> cache = node.getPathCache(); - if (cache != null) return cache; - - Iterator> iter = this.netAlgorithm.getPathsIterator(node); - if (iter instanceof ICacheableIterator) { - return node.setPathCache((ICacheableIterator>) iter); - } else return iter; - } - - /** - * Verification removes paths ending in unloaded TEs, - * paths that don't connect to anything, - * and all paths if the source TE is unloaded. - */ - protected List> verifyList(List> list, - NetNode source) { - if (!verifyNode(source)) return new ObjectArrayList<>(); - return list.stream().filter(a -> verifyNode(a.getTargetNode()) && a.getWeight() != Double.POSITIVE_INFINITY) - .collect(Collectors.toList()); - } - - protected boolean verifyNode(NetNode node) { - node.getHeldMTESafe(); - return node.hasConnecteds(); - } - - @Nullable - protected TileEntityPipeBase castTE(TileEntity te) { - if (te instanceof TileEntityPipeBasepipe) { - if (!getBasePipeClass().isAssignableFrom(pipe.getClass())) { - return null; - } - // noinspection unchecked - return (TileEntityPipeBase) pipe; - } - return null; - } - - public void markNodeAsOldData(NetNode node) { - updateActiveNodeStatus(node); - } - - protected abstract Class> getBasePipeClass(); - - /** - * Make sure to override this if your NetGroups use data. - * - * @return The correct data variant - */ - protected AbstractGroupData getBlankGroupData() { - return null; - } - - public NetNode getOrCreateNode(@NotNull IPipeTile mte) { - NetNode node = this.pipeMap.get(mte.getPipePos()); - if (node != null) return node; - if (!canAttachNode(mte.getNodeData())) return null; - node = new NetNode<>(mte.getNodeData(), mte, this); - this.addNode(node); - return node; - } - - protected final boolean canNodesConnect(NetNode source, EnumFacing nodeFacing, - NetNode target) { - return areNodeBlockedConnectionsCompatible(source, nodeFacing, target) && - areMarksCompatible(source.mark, target.mark) && - areNodesCustomContactable(source.getData(), target.getData()); - } - - private static boolean areMarksCompatible(int mark1, int mark2) { - return mark1 == mark2 || mark1 == NetNode.DEFAULT_MARK || mark2 == NetNode.DEFAULT_MARK; - } - - private boolean areNodeBlockedConnectionsCompatible(NetNode source, - EnumFacing nodeFacing, - NetNode target) { - return !source.isConnected(nodeFacing) && !target.isConnected(nodeFacing.getOpposite()); - } - - protected boolean areNodesCustomContactable(NodeDataType source, NodeDataType target) { - return true; - } - - protected boolean canAttachNode(NodeDataType nodeData) { - return true; - } - - public void updateActiveConnections(BlockPos nodePos, EnumFacing side, boolean connect) { - NetNode node = pipeMap.get(nodePos); - if (node == null || node.isConnected(side) == connect) return; - - node.setConnected(side, connect); - updateActiveNodeStatus(node); - - NetNode nodeOffset = pipeMap.get(nodePos.offset(side)); - if (nodeOffset == null) return; - - nodeOffset.setConnected(side.getOpposite(), connect); - - if (connect) { - if (!node.isBlocked(side)) { - addEdge(nodeOffset, node, null); - this.predicateEdge(nodeOffset, node, side.getOpposite()); - if (!this.isDirected()) return; - } - if (!nodeOffset.isBlocked(side.getOpposite())) { - addEdge(node, nodeOffset, null); - this.predicateEdge(node, nodeOffset, side); - } - } else { - removeUndirectedEdge(node, nodeOffset); - } - } - - public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean blocked) { - if (!isDirected()) return; // no such thing as blocked connections on undirected graphs. - NetNode node = pipeMap.get(nodePos); - if (node == null || node.isBlocked(side) == blocked) return; - - node.setBlocked(side, blocked); - - NetNode nodeOffset = pipeMap.get(nodePos.offset(side)); - if (nodeOffset == null) return; - - if (!blocked) { - addEdge(nodeOffset, node, null); - this.predicateEdge(nodeOffset, node, side); - } else { - removeEdge(nodeOffset, node); - } - } - - public void updateMark(BlockPos nodePos, int newMark) { - NetNode node = pipeMap.get(nodePos); - - int oldMark = node.mark; - node.mark = newMark; - - for (EnumFacing side : EnumFacing.VALUES) { - NetNode nodeOffset = pipeMap.get(nodePos.offset(side)); - if (nodeOffset == null) continue; - if (!areNodeBlockedConnectionsCompatible(node, side, nodeOffset) || - !areNodesCustomContactable(node.getData(), nodeOffset.getData())) - continue; - if (areMarksCompatible(oldMark, nodeOffset.mark) == areMarksCompatible(newMark, nodeOffset.mark)) continue; - - if (areMarksCompatible(newMark, nodeOffset.mark)) { - addEdge(node, nodeOffset, null); - this.predicateEdge(node, nodeOffset, side); - } else { - removeEdge(node, nodeOffset); - } - } - } - - protected abstract Capability[] getConnectionCapabilities(); - - public boolean hasNode(BlockPos pos) { - return pipeMap.containsKey(pos); - } - - public void addNodeSilent(NetNode node) { - pipeGraph.addVertex(node); - this.pipeMap.put(node.getNodePos(), node); - // we do not need to invalidate the cache, because just adding a node means it's not connected to anything. - } - - public void addNode(NetNode node) { - addNodeSilent(node); - this.markDirty(); - } - - @Nullable - public NetNode getNode(BlockPos pos) { - return this.pipeMap.get(pos); - } - - public void addUndirectedEdge(NetNode source, - NetNode target) { - this.addEdge(source, target, null); - if (this.isDirected()) this.addEdge(target, source, null); - } - - public void addEdge(NetNode source, NetNode target, - @Nullable AbstractEdgePredicate predicate) { - addEdge(source, target, source.getData().getWeightFactor() + target.getData().getWeightFactor(), predicate); - } - - public void addUndirectedEdge(NetNode source, - NetNode target, - double weight) { - this.addEdge(source, target, weight, null); - if (this.isDirected()) this.addEdge(target, source, weight, null); - } - - public void addEdge(NetNode source, NetNode target, - double weight, - @Nullable AbstractEdgePredicate predicate) { - if (pipeGraph.addEdge(source, target) != null) { - NetGroup.mergeEdge(source, target); - pipeGraph.setEdgeWeight(source, target, weight); - if (predicate != null) { - pipeGraph.getEdge(source, target).setPredicate(predicate); - } - this.markAlgInvalid(); - this.markDirty(); - } - } - - public void predicateUndirectedEdge(BlockPos pos, EnumFacing faceToNeighbour) { - NetNode source = this.pipeMap.get(pos); - NetNode target = this.pipeMap.get(pos.offset(faceToNeighbour)); - if (source != null && target != null) { - this.predicateUndirectedEdge(source, target, faceToNeighbour); - } - } - - public void predicateEdge(BlockPos pos, EnumFacing faceToNeighbour) { - NetNode source = this.pipeMap.get(pos); - NetNode target = this.pipeMap.get(pos.offset(faceToNeighbour)); - if (source != null && target != null) - this.predicateEdge(source, target, faceToNeighbour); - } - - public void predicateUndirectedEdge(NetNode source, - NetNode target, - EnumFacing faceToNeighbour) { - this.predicateEdge(source, target, faceToNeighbour); - if (this.isDirected()) this.predicateEdge(target, source, faceToNeighbour.getOpposite()); - } - - public void predicateEdge(NetNode source, - NetNode target, - EnumFacing faceToNeighbour) { - if (!this.pipeGraph.containsEdge(source, target)) return; - Cover thisCover = source.getHeldMTESafe().getCoverableImplementation().getCoverAtSide(faceToNeighbour); - Cover neighbourCover = target.getHeldMTESafe().getCoverableImplementation() - .getCoverAtSide(faceToNeighbour.getOpposite()); - AbstractEdgePredicate predicate = getPredicate(thisCover, neighbourCover); - predicate.setPosInfo(source.getNodePos(), target.getNodePos()); - Edge edge = this.pipeGraph.getEdge(source, target); - edge.setPredicate(predicate); - } - - protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbourCover) { - return shutterify(new BasicEdgePredicate(), thisCover, neighbourCover); - } - - protected final AbstractEdgePredicate shutterify(AbstractEdgePredicate predicate, @Nullable Cover thisCover, - @Nullable Cover neighbourCover) { - if (predicate instanceof IShutteredEdgePredicate shutteredEdgePredicate) { - if (thisCover instanceof CoverShutter shutter) { - shutteredEdgePredicate.setShutteredSource(shutter.isWorkingEnabled()); - } - if (neighbourCover instanceof CoverShutter shutter) { - shutteredEdgePredicate.setShutteredTarget(shutter.isWorkingEnabled()); - } - } - return predicate; - } - - public void removeUndirectedEdge(NetNode source, - NetNode target) { - this.removeEdge(source, target); - if (isDirected()) this.removeEdge(target, source); - } - - public void removeEdge(NetNode source, NetNode target) { - if (source.getGroupSafe() != null && source.getGroupSafe().splitEdge(source, target)) { - this.markAlgInvalid(); - this.markDirty(); - } - } - - public void removeNode(BlockPos pos) { - this.removeNode(this.pipeMap.get(pos)); - } - - public void removeNode(@Nullable NetNode node) { - if (node != null) { - if (this.pipeGraph.edgesOf(node).size() != 0) this.markAlgInvalid(); - if (node.getGroupUnsafe() != null) { - node.getGroupUnsafe().splitNode(node); - } else this.pipeGraph.removeVertex(node); - this.pipeMap.remove(node.getNodePos()); - this.markDirty(); - } - } - - public NetGroup getGroup(BlockPos pos) { - NetNode node = this.getNode(pos); - if (node == null) return null; - if (node.getGroupSafe() != null) return node.getGroupSafe(); - return node.setGroup(new NetGroup<>(this.pipeGraph, this)); - } - - public boolean updateActiveNodeStatus(NetNode node) { - return markNodeAsActive(node, shouldNodeBeActive(node)); - } - - public boolean shouldNodeBeActive(NetNode node) { - var connecteds = node.getConnecteds(); - if (connecteds != null) return connecteds.entrySet().stream().filter(entry -> { - if (entry.getValue() instanceof IPipeTile) return false; - for (Capability cap : this.getConnectionCapabilities()) { - if (entry.getValue().hasCapability(cap, entry.getKey())) return true; - } - return false; - }).toArray().length > 0; - return false; - } - - public boolean markNodeAsActive(NetNode node, boolean isActive) { - if (node != null && node.isActive != isActive) { - node.getGroupSafe().clearPathCaches(); - node.isActive = isActive; - this.markDirty(); - return true; - } - return false; - } - - protected void rebuildNetAlgorithm() { - this.netAlgorithm.setAlg(algorithmBuilder.apply(this)); - this.markAlgValid(); - } - - @Override - public void readFromNBT(NBTTagCompound nbt) { - if (!nbt.hasKey("NetEdges")) { - return; - } - this.builders = new ObjectOpenHashSet<>(); - NBTTagList allPipeNodes = nbt.getTagList("PipeNodes", Constants.NBT.TAG_COMPOUND); - Map> longPosMap = new Long2ObjectOpenHashMap<>(); - for (int i = 0; i < allPipeNodes.tagCount(); i++) { - NBTTagCompound pNodeTag = allPipeNodes.getCompoundTagAt(i); - NetNode node = new NetNode<>(pNodeTag, this); - longPosMap.put(node.getLongPos(), node); - this.addNodeSilent(node); - } - NBTTagList allNetEdges = nbt.getTagList("NetEdges", Constants.NBT.TAG_COMPOUND); - for (int i = 0; i < allNetEdges.tagCount(); i++) { - NBTTagCompound gEdgeTag = allNetEdges.getCompoundTagAt(i); - this.builders.add(new NetEdge.NBTBuilder<>(longPosMap, gEdgeTag, this::addEdge)); - } - NBTTagList allNetGroups = nbt.getTagList("NetGroups", Constants.NBT.TAG_COMPOUND); - for (int i = 0; i < allNetGroups.tagCount(); i++) { - NBTTagCompound gTag = allNetGroups.getCompoundTagAt(i); - this.builders.add(new NetGroup.NBTBuilder<>(longPosMap, gTag, this.pipeGraph, this)); - } - } - - @NotNull - @Override - public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { - NBTTagList allPipeNodes = new NBTTagList(); - Set> groups = new ObjectOpenHashSet<>(); - for (NetNode node : pipeGraph.vertexSet()) { - if (node.getGroupUnsafe() != null) groups.add(node.getGroupUnsafe()); - NBTTagCompound nodeTag = node.serializeNBT(); - NBTTagCompound dataTag = new NBTTagCompound(); - writeNodeData(node.getData(), dataTag); - nodeTag.setTag("Data", dataTag); - allPipeNodes.appendTag(nodeTag); - } - compound.setTag("PipeNodes", allPipeNodes); - - NBTTagList allNetEdges = new NBTTagList(); - for (Edge edge : pipeGraph.edgeSet()) { - allNetEdges.appendTag(edge.serializeNBT()); - } - compound.setTag("NetEdges", allNetEdges); - - NBTTagList allNetGroups = new NBTTagList(); - for (NetGroup group : groups) { - allNetGroups.appendTag(group.serializeNBT()); - } - compound.setTag("NetGroups", allNetGroups); - - return compound; - } - - /** - * Serializes node data into specified tag compound - * Used for writing persistent node data - */ - protected abstract void writeNodeData(NodeDataType nodeData, NBTTagCompound tagCompound); - - /** - * Deserializes node data from specified tag compound - * Used for reading persistent node data - */ - protected abstract NodeDataType readNodeData(NBTTagCompound tagCompound); -} diff --git a/src/main/java/gregtech/api/pipenet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/DynamicWeightsShortestPathsAlgorithm.java deleted file mode 100644 index e2fc6e52583..00000000000 --- a/src/main/java/gregtech/api/pipenet/alg/DynamicWeightsShortestPathsAlgorithm.java +++ /dev/null @@ -1,119 +0,0 @@ -package gregtech.api.pipenet.alg; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.WorldPipeNetBase; -import gregtech.api.pipenet.alg.iter.ICacheableIterator; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jgrapht.alg.shortestpath.DefaultManyToManyShortestPaths; - -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -public class DynamicWeightsShortestPathsAlgorithm & IPipeType, NDT extends INodeData, - E extends NetEdge> - extends DefaultManyToManyShortestPaths, E> - implements INetAlgorithm { - - private final WorldPipeNetBase pipenet; - - public DynamicWeightsShortestPathsAlgorithm(WorldPipeNetBase pipenet) { - super(pipenet.getGraph()); - this.pipenet = pipenet; - } - - @Override - public Iterator> getPathsIterator(NetNode source) { - Set> searchSpace = source.getGroupSafe().getNodes().stream() - .filter(NetNode::isActive).filter(node -> !source.equals(node)).collect(Collectors.toSet()); - return new LimitedIterator(source, searchSpace); - } - - @Override - public boolean supportsDynamicWeights() { - return true; - } - - protected class LimitedIterator implements ICacheableIterator> { - - private static final int MAX_ITERATIONS = 100; - - private final NetNode source; - private final Set> searchSpace; - - private int iterationCount = 0; - private final ObjectArrayList> visited = new ObjectArrayList<>(); - private NetPath next; - - public LimitedIterator(NetNode source, Set> searchSpace) { - this.source = source; - this.searchSpace = searchSpace; - } - - public LimitedIterator(NetNode source, Set> searchSpace, - ManyToManyShortestPaths, E> manyToManyShortestPaths) { - this.source = source; - this.searchSpace = searchSpace; - } - - @Override - public ICacheableIterator> newCacheableIterator() { - return new LimitedIterator(source, searchSpace); - } - - @Override - public Iterator> newIterator() { - return newCacheableIterator(); - } - - @Override - public boolean hasNext() { - if (next == null && iterationCount < MAX_ITERATIONS) calculateNext(); - return next != null; - } - - @Override - public NetPath next() { - if (!hasNext()) throw new NoSuchElementException(); - NetPath temp = next; - next = null; - return temp; - } - - private void calculateNext() { - iterationCount++; - if (iterationCount == 1) { - next = new NetPath<>(source); - return; - } - ManyToManyShortestPaths, E> paths = getManyToManyPaths(Collections.singleton(source), - searchSpace); - var iter = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) - .map(NetPath::new).sorted(Comparator.comparingDouble(NetPath::getWeight)).iterator(); - while (iter.hasNext()) { - var next = iter.next(); - if (isUnique(next)) { - this.next = next; - break; - } - } - if (next != null) visited.add(next); - } - - private boolean isUnique(NetPath path) { - for (NetPath other : visited) { - if (path.matches(other)) return false; - } - return true; - } - } -} diff --git a/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java deleted file mode 100644 index 05cd29665b8..00000000000 --- a/src/main/java/gregtech/api/pipenet/alg/INetAlgorithm.java +++ /dev/null @@ -1,42 +0,0 @@ -package gregtech.api.pipenet.alg; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; - -import java.util.Iterator; - -public interface INetAlgorithm & IPipeType, NDT extends INodeData, E extends NetEdge> { - - Iterator> getPathsIterator(NetNode source); - - default boolean supportsDynamicWeights() { - return false; - } - - class NetAlgorithmWrapper & IPipeType, - NodeDataType extends INodeData, E extends NetEdge> { - - INetAlgorithm alg; - - public void setAlg(INetAlgorithm alg) { - this.alg = alg; - } - - public INetAlgorithm getAlg() { - return alg; - } - - public boolean supportsDynamicWeights() { - if (alg == null) return false; - return alg.supportsDynamicWeights(); - } - - public Iterator> getPathsIterator(NetNode source) { - if (alg == null) return null; - return alg.getPathsIterator(source); - } - } -} diff --git a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java deleted file mode 100644 index 09b992e9a27..00000000000 --- a/src/main/java/gregtech/api/pipenet/alg/ShortestPathsAlgorithm.java +++ /dev/null @@ -1,44 +0,0 @@ -package gregtech.api.pipenet.alg; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.WorldPipeNetBase; -import gregtech.api.pipenet.alg.iter.SimpleCacheableIterator; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; - -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.Set; -import java.util.stream.Collectors; - -public final class ShortestPathsAlgorithm & IPipeType, - NDT extends INodeData, E extends NetEdge> extends CHManyToManyShortestPaths, E> - implements INetAlgorithm { - - public ShortestPathsAlgorithm(WorldPipeNetBase pipenet) { - super(pipenet.getGraph()); - } - - @Override - public Iterator> getPathsIterator(NetNode source) { - if (!graph.containsVertex(source)) { - throw new IllegalArgumentException("Graph must contain the source vertex"); - } - // if the source has no group, it has no paths other than the path to itself. - if (source.getGroupUnsafe() == null) return Collections.singletonList(new NetPath<>(source)).iterator(); - - Set> searchSpace = source.getGroupSafe().getNodes().stream() - .filter(NetNode::isActive).collect(Collectors.toSet()); - ManyToManyShortestPaths, E> manyToManyPaths = getManyToManyPaths( - Collections.singleton(source), searchSpace); - return new SimpleCacheableIterator<>(searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)) - .map(NetPath::new).sorted(Comparator.comparingDouble(NetPath::getWeight)) - .collect(Collectors.toCollection(ObjectArrayList::new))); - } -} diff --git a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java deleted file mode 100644 index f0420188d8c..00000000000 --- a/src/main/java/gregtech/api/pipenet/alg/SinglePathAlgorithm.java +++ /dev/null @@ -1,64 +0,0 @@ -package gregtech.api.pipenet.alg; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.WorldPipeNetBase; -import gregtech.api.pipenet.alg.iter.SimpleCacheableIterator; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; - -import com.google.common.collect.ImmutableList; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jgrapht.Graph; - -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -public final class SinglePathAlgorithm & IPipeType, NDT extends INodeData, - E extends NetEdge> implements INetAlgorithm { - - private final Graph, E> graph; - private final boolean isDirected; - - public SinglePathAlgorithm(WorldPipeNetBase pipenet) { - this.graph = pipenet.getGraph(); - this.isDirected = pipenet.isDirected(); - } - - @Override - public Iterator> getPathsIterator(NetNode source) { - if (!this.graph.containsVertex(source)) { - throw new IllegalArgumentException("Graph must contain the source vertex"); - } - List edges = new ObjectArrayList<>(); - List> nodes = new ObjectArrayList<>(); - nodes.add(source); - NetNode lastNode = null; - NetNode node = source; - E edge; - double sumWeight = source.getData().getWeightFactor(); - boolean valid = true; - while (valid) { - Iterator i = this.graph.outgoingEdgesOf(node).iterator(); - if (!i.hasNext()) break; // we've reached the end, exit the loop while still valid - edge = i.next(); - // if we are directed, we know that the target is the target. - // if we aren't directed, we need to see if the edge's source was secretly the target - boolean reversedEdge = !isDirected && edge.getSource() == lastNode; - if (edge.getTarget() == lastNode || reversedEdge) { - if (i.hasNext()) edge = i.next(); - else break; // we've reached the end, exit the loop while still valid - } else if (i.hasNext()) i.next(); - if (i.hasNext()) valid = false; // third edge detected - that's an invalid group - lastNode = node; - node = reversedEdge ? edge.getCastSource() : edge.getCastTarget(); - edges.add(edge); - nodes.add(node); - sumWeight += node.getData().getWeightFactor(); - } - if (!valid) return Collections.emptyIterator(); - return new SimpleCacheableIterator<>(ImmutableList.of(new NetPath<>(nodes, edges, sumWeight))); - } -} diff --git a/src/main/java/gregtech/api/pipenet/block/IPipeType.java b/src/main/java/gregtech/api/pipenet/block/IPipeType.java deleted file mode 100644 index baff9640dc6..00000000000 --- a/src/main/java/gregtech/api/pipenet/block/IPipeType.java +++ /dev/null @@ -1,14 +0,0 @@ -package gregtech.api.pipenet.block; - -import gregtech.api.pipenet.INodeData; - -import net.minecraft.util.IStringSerializable; - -public interface IPipeType> extends IStringSerializable { - - float getThickness(); - - NodeDataType modifyProperties(NodeDataType baseProperties); - - boolean isPaintable(); -} diff --git a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java b/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java deleted file mode 100644 index 85c2838d466..00000000000 --- a/src/main/java/gregtech/api/pipenet/block/material/IMaterialPipeTile.java +++ /dev/null @@ -1,14 +0,0 @@ -package gregtech.api.pipenet.block.material; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.unification.material.Material; - -public interface IMaterialPipeTile & IPipeType, - NodeDataType extends INodeData, Edge extends NetEdge> - extends IPipeTile { - - Material getPipeMaterial(); -} diff --git a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java deleted file mode 100644 index 06b51bba366..00000000000 --- a/src/main/java/gregtech/api/pipenet/edge/AbstractNetFlowEdge.java +++ /dev/null @@ -1,108 +0,0 @@ -package gregtech.api.pipenet.edge; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.predicate.IPredicateTestObject; - -import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; - -import java.lang.ref.WeakReference; -import java.util.Set; -import java.util.WeakHashMap; - -public abstract class AbstractNetFlowEdge> extends NetEdge { - - private final AbstractChannelsHolder channels; - private final WeakHashMap> simulatedChannels; - - public AbstractNetFlowEdge() { - this.channels = getNewHolder(null, null); - this.simulatedChannels = new WeakHashMap<>(9); - } - - @Override - public double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick) { - if (!cannotSupportChannel(channel, queryTick, simulator)) { - return getWeight(); - } - return getWeight() * 1000000; - } - - public boolean cannotSupportChannel(Object channel, long queryTick, @Nullable SimulatorKey simulator) { - return getChannels(simulator).cannotSupportChannel(channel, queryTick); - } - - protected AbstractChannelsHolder getChannels(@Nullable SimulatorKey simulator) { - if (simulator == null) return this.channels; - else { - AbstractChannelsHolder channels = simulatedChannels.get(simulator); - if (channels == null) { - channels = getNewHolder(this.channels, simulator); - simulatedChannels.put(simulator, channels); - } - return channels; - } - } - - public & IPipeType, NDT extends INodeData> long getFlowLimit( - Object channel, - Graph, E> graph, - long queryTick, - @Nullable SimulatorKey simulator) { - return getChannels(simulator).getFlowLimit(channel, graph, queryTick); - } - - public long getConsumedLimit(Object channel, long queryTick, @Nullable SimulatorKey simulator) { - return getChannels(simulator).getConsumedLimit(channel, queryTick); - } - - public & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, - Graph, E> graph, - long amount, - long queryTick, - @Nullable SimulatorKey simulator) { - getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); - } - - public Set getActiveChannels(@Nullable SimulatorKey simulator, long queryTick) { - return getChannels(simulator).getActiveChannels(queryTick); - } - - protected abstract AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, - SimulatorKey simulator); - - protected abstract static class AbstractChannelsHolder> { - - private final WeakReference simulator; - - public AbstractChannelsHolder(SimulatorKey simulator) { - this.simulator = new WeakReference<>(simulator); - } - - public SimulatorKey getSimulator() { - return simulator.get(); - } - - abstract void recalculateFlowLimits(long queryTick); - - abstract boolean cannotSupportChannel(Object channel, long queryTick); - - abstract & IPipeType, NDT extends INodeData> long getFlowLimit( - Object channel, - Graph, E> graph, - long queryTick); - - abstract long getConsumedLimit(Object channel, long queryTick); - - abstract & IPipeType, NDT extends INodeData> void consumeFlowLimit( - Object channel, - Graph, E> graph, - long amount, - long queryTick); - - abstract Set getActiveChannels(long queryTick); - } -} diff --git a/src/main/java/gregtech/api/pipenet/edge/IEdge.java b/src/main/java/gregtech/api/pipenet/edge/IEdge.java deleted file mode 100644 index 885f6f3419d..00000000000 --- a/src/main/java/gregtech/api/pipenet/edge/IEdge.java +++ /dev/null @@ -1,12 +0,0 @@ -package gregtech.api.pipenet.edge; - -import gregtech.api.pipenet.predicate.IPredicateTestObject; - -public interface IEdge { - - V getSource(); - - V getTarget(); - - double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick); -} diff --git a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java b/src/main/java/gregtech/api/pipenet/edge/NetEdge.java deleted file mode 100644 index 3f3e65e92b5..00000000000 --- a/src/main/java/gregtech/api/pipenet/edge/NetEdge.java +++ /dev/null @@ -1,135 +0,0 @@ -package gregtech.api.pipenet.edge; - -import gregtech.api.pipenet.INBTBuilder; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.predicate.AbstractEdgePredicate; -import gregtech.api.pipenet.predicate.IPredicateTestObject; -import gregtech.api.util.function.QuadConsumer; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.common.util.INBTSerializable; - -import org.jgrapht.graph.DefaultWeightedEdge; - -import java.util.Map; -import java.util.function.Predicate; - -public class NetEdge extends DefaultWeightedEdge implements INBTSerializable, IEdge> { - - private AbstractEdgePredicate predicate; - private boolean invertedPredicate; - - private INodeData> minData; - - /** - * Most basic NetEdge that provides predicate handling & NBT storage capability - */ - @SuppressWarnings("unused") // used via reflection - public NetEdge() {} - - public void setPredicate(AbstractEdgePredicate predicate) { - this.predicate = predicate; - this.invertedPredicate = predicate.getSourcePos() != this.getSource().getNodePos(); - } - - public Predicate getPredicate() { - // if we don't have a predicate, just assume that we're good. - if (predicate == null) return (a) -> true; - return predicate; - } - - public INodeData> getMinData() { - if (this.minData == null) - this.minData = this.getCastSource().getData().getSumData(this.getCastTarget().getData()); - return this.minData; - } - - public boolean isPredicateInverted() { - return invertedPredicate; - } - - @Override - public NetNode getSource() { - return (NetNode) super.getSource(); - } - - @Override - public NetNode getTarget() { - return (NetNode) super.getTarget(); - } - - @SuppressWarnings("unchecked") - public & IPipeType, NDT extends INodeData, - E extends NetEdge> NetNode getCastSource() { - return (NetNode) getSource(); - } - - @SuppressWarnings("unchecked") - public & IPipeType, NDT extends INodeData, - E extends NetEdge> NetNode getCastTarget() { - return (NetNode) getTarget(); - } - - @Override - protected final double getWeight() { - return super.getWeight(); - } - - public double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick) { - return getWeight(); - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tag = new NBTTagCompound(); - tag.setLong("SourceLongPos", getSource().getLongPos()); - tag.setLong("TargetLongPos", getTarget().getLongPos()); - tag.setDouble("Weight", getWeight()); - if (predicate != null) tag.setTag("Predicate", AbstractEdgePredicate.toNBT(predicate)); - tag.setBoolean("InvertedPredicate", isPredicateInverted()); - return tag; - } - - /** - * Use {@link NBTBuilder} instead, this does nothing. - */ - @Override - @Deprecated - public void deserializeNBT(NBTTagCompound nbt) {} - - public static final class NBTBuilder & IPipeType, - NodeDataType extends INodeData, E extends NetEdge> implements INBTBuilder { - - private final NetNode node1; - private final NetNode node2; - private final AbstractEdgePredicate predicate; - private final double weight; - private final boolean buildable; - - private final QuadConsumer, NetNode, Double, AbstractEdgePredicate> edgeProducer; - - public NBTBuilder(Map> longPosMap, NBTTagCompound tag, - QuadConsumer, NetNode, Double, AbstractEdgePredicate> edgeProducer) { - this.node1 = longPosMap.get(tag.getLong("SourceLongPos")); - this.node2 = longPosMap.get(tag.getLong("TargetLongPos")); - this.weight = tag.getDouble("Weight"); - this.predicate = AbstractEdgePredicate.nbtPredicate(tag.getCompoundTag("Predicate")); - if (predicate != null) { - if (tag.getBoolean("InvertedPredicate")) - this.predicate.setPosInfo(this.node2.getNodePos(), this.node1.getNodePos()); - else this.predicate.setPosInfo(this.node1.getNodePos(), this.node2.getNodePos()); - } - this.edgeProducer = edgeProducer; - this.buildable = node1 != null && node2 != null; - } - - @Override - public void build() { - if (buildable) { - edgeProducer.accept(node1, node2, weight, predicate); - } - } - } -} diff --git a/src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java b/src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java deleted file mode 100644 index 7d74bc0a203..00000000000 --- a/src/main/java/gregtech/api/pipenet/graph/CustomDirectedGraph.java +++ /dev/null @@ -1,56 +0,0 @@ -package gregtech.api.pipenet.graph; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.WorldPipeNetBase; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.edge.SimulatorKey; -import gregtech.api.pipenet.predicate.IPredicateTestObject; - -import org.jgrapht.graph.SimpleDirectedWeightedGraph; - -import java.util.function.Supplier; - -public class CustomDirectedGraph & IPipeType, NDT extends INodeData, - E extends NetEdge> extends SimpleDirectedWeightedGraph, E> - implements ICustomGraph { - - private WorldPipeNetBase net = null; - - private IPredicateTestObject testObject; - private SimulatorKey simulator; - private long queryTick; - - @Override - public void setOwningNet(WorldPipeNetBase net) { - if (this.net != null) - throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); - this.net = net; - } - - @Override - public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, - long queryTick) { - if (!net.usesDynamicWeights()) throw new IllegalStateException("Net does not support dynamic weights!"); - this.testObject = testObject; - this.simulator = simulator; - this.queryTick = queryTick; - } - - public CustomDirectedGraph(Class edgeClass) { - super(edgeClass); - } - - public CustomDirectedGraph(Supplier> vertexSupplier, Supplier edgeSupplier) { - super(vertexSupplier, edgeSupplier); - } - - @Override - public double getEdgeWeight(E edge) { - if (net.usesDynamicWeights()) { - return edge.getPredicate().test(testObject) ? edge.getDynamicWeight(testObject, simulator, queryTick) : - Double.POSITIVE_INFINITY; - } else return super.getEdgeWeight(edge); - } -} diff --git a/src/main/java/gregtech/api/pipenet/graph/CustomUndirectedGraph.java b/src/main/java/gregtech/api/pipenet/graph/CustomUndirectedGraph.java deleted file mode 100644 index 4777a6d7228..00000000000 --- a/src/main/java/gregtech/api/pipenet/graph/CustomUndirectedGraph.java +++ /dev/null @@ -1,55 +0,0 @@ -package gregtech.api.pipenet.graph; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.WorldPipeNetBase; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.edge.SimulatorKey; -import gregtech.api.pipenet.predicate.IPredicateTestObject; - -import org.jgrapht.graph.SimpleWeightedGraph; - -import java.util.function.Supplier; - -public class CustomUndirectedGraph & IPipeType, NDT extends INodeData, - E extends NetEdge> extends SimpleWeightedGraph, E> implements ICustomGraph { - - private WorldPipeNetBase net = null; - - private IPredicateTestObject testObject; - private SimulatorKey simulator; - private long queryTick; - - @Override - public void setOwningNet(WorldPipeNetBase net) { - if (this.net != null) - throw new IllegalStateException("Tried to set the owning net of an already initialized graph!"); - this.net = net; - } - - @Override - public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, - long queryTick) { - if (!net.usesDynamicWeights()) throw new IllegalStateException("Net does not support dynamic weights!"); - this.testObject = testObject; - this.simulator = simulator; - this.queryTick = queryTick; - } - - public CustomUndirectedGraph(Class edgeClass) { - super(edgeClass); - } - - public CustomUndirectedGraph(Supplier> vertexSupplier, Supplier edgeSupplier) { - super(vertexSupplier, edgeSupplier); - } - - @Override - public double getEdgeWeight(E edge) { - if (net.usesDynamicWeights()) { - return edge.getPredicate().test(testObject) ? edge.getDynamicWeight(testObject, simulator, queryTick) : - Double.POSITIVE_INFINITY; - } else return super.getEdgeWeight(edge); - } -} diff --git a/src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java b/src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java deleted file mode 100644 index 4715d56b31c..00000000000 --- a/src/main/java/gregtech/api/pipenet/graph/ICustomGraph.java +++ /dev/null @@ -1,22 +0,0 @@ -package gregtech.api.pipenet.graph; - -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.WorldPipeNetBase; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.edge.SimulatorKey; -import gregtech.api.pipenet.predicate.IPredicateTestObject; - -import org.jetbrains.annotations.ApiStatus; -import org.jgrapht.Graph; - -public interface ICustomGraph & IPipeType, NDT extends INodeData, E extends NetEdge> - extends Graph, E> { - - @ApiStatus.Internal - void setOwningNet(WorldPipeNetBase net); - - void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, - long queryTick); -} diff --git a/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java b/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java deleted file mode 100644 index e14f63c226c..00000000000 --- a/src/main/java/gregtech/api/pipenet/predicate/AbstractEdgePredicate.java +++ /dev/null @@ -1,63 +0,0 @@ -package gregtech.api.pipenet.predicate; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.math.BlockPos; -import net.minecraftforge.common.util.INBTSerializable; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; -import java.util.function.Predicate; -import java.util.function.Supplier; - -public abstract class AbstractEdgePredicate> implements - Predicate, INBTSerializable { - - protected static final Map>> PREDICATE_SUPPLIERS = new Object2ObjectOpenHashMap<>(); - - protected BlockPos sourcePos; - protected BlockPos targetPos; - - public void setPosInfo(BlockPos sourcePos, BlockPos targetPos) { - this.sourcePos = sourcePos; - this.targetPos = targetPos; - } - - protected abstract String predicateName(); - - public BlockPos getSourcePos() { - return sourcePos; - } - - public BlockPos getTargetPos() { - return targetPos; - } - - private static Supplier> getSupplier(String identifier) { - return PREDICATE_SUPPLIERS.getOrDefault(identifier, () -> null); - } - - @Nullable - public static AbstractEdgePredicate newPredicate(String identifier) { - return getSupplier(identifier).get(); - } - - @Nullable - public static AbstractEdgePredicate nbtPredicate(@NotNull NBTTagCompound nbt) { - AbstractEdgePredicate predicate = getSupplier(nbt.getString("Type")).get(); - if (predicate != null) { - predicate.deserializeNBT(nbt.getCompoundTag("Data")); - return predicate; - } - return null; - } - - public static @NotNull NBTTagCompound toNBT(@NotNull AbstractEdgePredicate predicate) { - NBTTagCompound tag = new NBTTagCompound(); - tag.setString("Type", predicate.predicateName()); - tag.setTag("Data", predicate.serializeNBT()); - return tag; - } -} diff --git a/src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java b/src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java deleted file mode 100644 index aa1f794a982..00000000000 --- a/src/main/java/gregtech/api/pipenet/predicate/IPredicateTestObject.java +++ /dev/null @@ -1,3 +0,0 @@ -package gregtech.api.pipenet.predicate; - -public interface IPredicateTestObject {} diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java index a7837448e9b..22d0ed7646d 100644 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java @@ -7,13 +7,14 @@ import gregtech.api.fluids.attribute.AttributedFluid; import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.fluids.attribute.FluidAttributes; -import gregtech.api.pipenet.INodeData; -import gregtech.api.pipenet.NodeLossResult; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.IPipeNetData; +import gregtech.api.graphnet.pipenetold.NodeLossResult; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.util.EntityDamageUtil; -import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; +import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; @@ -33,12 +34,13 @@ import java.util.Objects; import java.util.function.Consumer; -public class FluidPipeProperties implements IMaterialProperty, IPropertyFluidFilter, INodeData { +public class FluidPipeProperties implements IMaterialProperty, IPropertyFluidFilter, + IPipeNetData { private final Object2BooleanMap containmentPredicate = new Object2BooleanOpenHashMap<>(); private int throughput; - private final int tanks; + private int tanks; private int maxFluidTemperature; private boolean gasProof; @@ -52,7 +54,7 @@ public FluidPipeProperties(int maxFluidTemperature, int throughput, boolean gasP /** * Should only be called from - * {@link gregtech.common.pipelike.fluidpipe.FluidPipeType#modifyProperties(FluidPipeProperties)} + * {@link gregtech.common.pipelikeold.fluidpipe.FluidPipeType#modifyProperties(FluidPipeProperties)} */ public FluidPipeProperties(int maxFluidTemperature, int throughput, boolean gasProof, boolean acidProof, boolean cryoProof, boolean plasmaProof, int tanks) { @@ -326,6 +328,30 @@ public FluidPipeProperties getSumData(List datas) { return new FluidPipeProperties(maxFluidTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof); } + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tagCompound = new NBTTagCompound(); + tagCompound.setInteger("max_temperature", this.getMaxFluidTemperature()); + tagCompound.setInteger("throughput", this.getThroughput()); + tagCompound.setBoolean("gas_proof", this.isGasProof()); + tagCompound.setBoolean("acid_proof", this.isAcidProof()); + tagCompound.setBoolean("cryo_proof", this.isCryoProof()); + tagCompound.setBoolean("plasma_proof", this.isPlasmaProof()); + tagCompound.setInteger("channels", this.getTanks()); + return tagCompound; + } + + @Override + public void deserializeNBT(NBTTagCompound tagCompound) { + maxFluidTemperature = tagCompound.getInteger("max_temperature"); + throughput = tagCompound.getInteger("throughput"); + gasProof = tagCompound.getBoolean("gas_proof"); + if (tagCompound.getBoolean("acid_proof")) setCanContain(FluidAttributes.ACID, true); + cryoProof = tagCompound.getBoolean("cryo_proof"); + plasmaProof = tagCompound.getBoolean("plasma_proof"); + tanks = tagCompound.getInteger("channels"); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java index 593e5d49573..22e4fbcc448 100644 --- a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java @@ -1,11 +1,11 @@ package gregtech.api.unification.material.properties; -import gregtech.api.pipenet.INodeData; +import gregtech.api.graphnet.pipenetold.IPipeNetData; import java.util.List; import java.util.Objects; -public class ItemPipeProperties implements IMaterialProperty, INodeData { +public class ItemPipeProperties implements IMaterialProperty, IPipeNetData { /** * Items will try to take the path with the lowest priority diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java new file mode 100644 index 00000000000..607ab104044 --- /dev/null +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -0,0 +1,56 @@ +package gregtech.api.unification.material.properties; + +import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; + +import gregtech.api.graphnet.pipenet.block.IPipeStructure; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.util.Map; + +public class PipeNetProperties implements IMaterialProperty, IPipeNetNodeHandler { + + protected final Map properties = new Object2ObjectOpenHashMap<>(); + + public void setProperty(IPipeNetMaterialProperty property) { + this.properties.put(property.getName(), property); + } + + public void removeProperty(String propertyName) { + this.properties.remove(propertyName); + } + + @Override + public void addToNets(World world, BlockPos pos, IPipeStructure structure) { + for (IPipeNetMaterialProperty p : properties.values()) { + if (p.supportedStructure(structure)) p.addToNet(world, pos, structure); + } + } + + @Override + public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) { + for (IPipeNetMaterialProperty p : properties.values()) { + if (p.supportedStructure(structure)) p.removeFromNet(world, pos); + } + } + + @Override + public void verifyProperty(MaterialProperties properties) { + for (IPipeNetMaterialProperty p : this.properties.values()) { + p.verifyProperty(properties); + } + } + + public interface IPipeNetMaterialProperty extends IMaterialProperty, IStringSerializable { + + void addToNet(World world, BlockPos pos, IPipeStructure structure); + + void removeFromNet(World world, BlockPos pos); + + boolean supportedStructure(IPipeStructure structure); + } +} diff --git a/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java b/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java index 5dc2234a40e..0b783a3c776 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java +++ b/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java @@ -4,6 +4,7 @@ public class PropertyKey { public static final PropertyKey BLAST = new PropertyKey<>("blast", BlastProperty.class); public static final PropertyKey DUST = new PropertyKey<>("dust", DustProperty.class); + public static final PropertyKey PIPENET_PROPERTIES = new PropertyKey<>("net_pipe", PipeNetProperties.class); public static final PropertyKey FLUID_PIPE = new PropertyKey<>("fluid_pipe", FluidPipeProperties.class); public static final PropertyKey FLUID = new PropertyKey<>("fluid", FluidProperty.class); diff --git a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java index 660383072be..9d5b310d97f 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java @@ -3,7 +3,7 @@ import gregtech.api.GTValues; import gregtech.api.fluids.FluidBuilder; import gregtech.api.fluids.store.FluidStorageKeys; -import gregtech.api.pipenet.INodeData; +import gregtech.api.graphnet.pipenetold.IPipeNetData; import gregtech.api.unification.material.Material; import net.minecraftforge.fluids.Fluid; @@ -13,7 +13,7 @@ import static gregtech.api.unification.material.info.MaterialFlags.GENERATE_FOIL; -public class WireProperties implements IMaterialProperty, INodeData { +public class WireProperties implements IMaterialProperty, IPipeNetData { private int voltage; private int amperage; diff --git a/src/main/java/gregtech/api/util/DimensionPos.java b/src/main/java/gregtech/api/util/DimensionPos.java new file mode 100644 index 00000000000..056e572aa32 --- /dev/null +++ b/src/main/java/gregtech/api/util/DimensionPos.java @@ -0,0 +1,39 @@ +package gregtech.api.util; + +import net.minecraft.util.math.BlockPos; + +import java.util.Objects; + +public class DimensionPos { + + private final BlockPos pos; + private final int dimension; + private final int hashCode; + + public DimensionPos(BlockPos pos, int dimension) { + this.pos = pos; + this.dimension = dimension; + this.hashCode = Objects.hash(pos, dimension); + } + + public int getDimension() { + return dimension; + } + + public BlockPos getPos() { + return pos; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DimensionPos dimensionPos = (DimensionPos) o; + return GTUtility.arePosEqual(pos, dimensionPos.getPos()) && dimension == dimensionPos.getDimension(); + } + + @Override + public int hashCode() { + return hashCode; + } +} diff --git a/src/main/java/gregtech/api/util/GTStringUtils.java b/src/main/java/gregtech/api/util/GTStringUtils.java index fdfbe1a999e..6e7649dca2e 100644 --- a/src/main/java/gregtech/api/util/GTStringUtils.java +++ b/src/main/java/gregtech/api/util/GTStringUtils.java @@ -4,7 +4,7 @@ import gregtech.api.items.materialitem.MetaPrefixItem; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.pipenet.block.material.BlockMaterialPipe; +import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; import gregtech.api.recipes.ingredients.IntCircuitIngredient; import gregtech.api.unification.material.Material; import gregtech.api.unification.ore.OrePrefix; diff --git a/src/main/java/gregtech/api/util/function/TriFunction.java b/src/main/java/gregtech/api/util/function/TriFunction.java new file mode 100644 index 00000000000..9c3a1cb7d02 --- /dev/null +++ b/src/main/java/gregtech/api/util/function/TriFunction.java @@ -0,0 +1,7 @@ +package gregtech.api.util.function; + +@FunctionalInterface +public interface TriFunction { + + R apply(P p, S s, T t); +} diff --git a/src/main/java/gregtech/client/particle/GTOverheatParticle.java b/src/main/java/gregtech/client/particle/GTOverheatParticle.java index 8736b628798..614a2b47f21 100644 --- a/src/main/java/gregtech/client/particle/GTOverheatParticle.java +++ b/src/main/java/gregtech/client/particle/GTOverheatParticle.java @@ -8,7 +8,7 @@ import gregtech.client.utils.RenderBufferHelper; import gregtech.client.utils.RenderUtil; import gregtech.common.ConfigHolder; -import gregtech.common.pipelike.cable.tile.TileEntityCable; +import gregtech.common.pipelikeold.cable.tile.TileEntityCable; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; diff --git a/src/main/java/gregtech/client/renderer/pipe/CableRenderer.java b/src/main/java/gregtech/client/renderer/pipe/CableRenderer.java index ce2ec2b9d59..c45630f99c7 100644 --- a/src/main/java/gregtech/client/renderer/pipe/CableRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/CableRenderer.java @@ -1,12 +1,12 @@ package gregtech.client.renderer.pipe; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.Material; import gregtech.api.util.GTUtility; -import gregtech.common.pipelike.cable.Insulation; +import gregtech.common.pipelikeold.cable.Insulation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; diff --git a/src/main/java/gregtech/client/renderer/pipe/FluidPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipe/FluidPipeRenderer.java index 91df50b0d47..a7a78c63d8a 100644 --- a/src/main/java/gregtech/client/renderer/pipe/FluidPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/FluidPipeRenderer.java @@ -1,13 +1,13 @@ package gregtech.client.renderer.pipe; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.recipes.ModHandler; import gregtech.api.unification.material.Material; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; -import gregtech.common.pipelike.fluidpipe.FluidPipeType; +import gregtech.common.pipelikeold.fluidpipe.FluidPipeType; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; diff --git a/src/main/java/gregtech/client/renderer/pipe/ItemPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipe/ItemPipeRenderer.java index 9e4df421227..f803229ae14 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ItemPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/ItemPipeRenderer.java @@ -1,12 +1,12 @@ package gregtech.client.renderer.pipe; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.Material; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; -import gregtech.common.pipelike.itempipe.ItemPipeType; +import gregtech.common.pipelikeold.itempipe.ItemPipeType; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; diff --git a/src/main/java/gregtech/client/renderer/pipe/LaserPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipe/LaserPipeRenderer.java index f67beda6a1d..37f7c5b73c0 100644 --- a/src/main/java/gregtech/client/renderer/pipe/LaserPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/LaserPipeRenderer.java @@ -1,15 +1,15 @@ package gregtech.client.renderer.pipe; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.Material; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; import gregtech.client.utils.BloomEffectUtil; import gregtech.common.ConfigHolder; -import gregtech.common.pipelike.laser.LaserPipeType; -import gregtech.common.pipelike.laser.tile.TileEntityLaserPipe; +import gregtech.common.pipelikeold.laser.LaserPipeType; +import gregtech.common.pipelikeold.laser.tile.TileEntityLaserPipe; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; diff --git a/src/main/java/gregtech/client/renderer/pipe/OpticalPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipe/OpticalPipeRenderer.java index 5eae9211e3d..ddd4da6264e 100644 --- a/src/main/java/gregtech/client/renderer/pipe/OpticalPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/OpticalPipeRenderer.java @@ -1,14 +1,14 @@ package gregtech.client.renderer.pipe; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.Material; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; import gregtech.common.ConfigHolder; -import gregtech.common.pipelike.optical.OpticalPipeType; -import gregtech.common.pipelike.optical.tile.TileEntityOpticalPipe; +import gregtech.common.pipelikeold.optical.OpticalPipeType; +import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java b/src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java index f046a76f876..673dcb037c6 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java @@ -1,13 +1,13 @@ package gregtech.client.renderer.pipe; import gregtech.api.cover.CoverHolder; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.IPipeType; -import gregtech.api.pipenet.block.ItemBlockPipe; -import gregtech.api.pipenet.block.material.BlockMaterialPipe; -import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.pipenetold.block.ItemBlockPipe; +import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; +import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.info.MaterialIconType; import gregtech.api.util.GTUtility; diff --git a/src/main/java/gregtech/client/utils/FacadeBlockAccess.java b/src/main/java/gregtech/client/utils/FacadeBlockAccess.java index 8aea61ce848..879b446bddd 100644 --- a/src/main/java/gregtech/client/utils/FacadeBlockAccess.java +++ b/src/main/java/gregtech/client/utils/FacadeBlockAccess.java @@ -1,6 +1,6 @@ package gregtech.client.utils; -import gregtech.api.pipenet.IBlockAppearance; +import gregtech.api.graphnet.pipenetold.IBlockAppearance; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index 3c474d5edc9..5908f048f41 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -24,16 +24,16 @@ import gregtech.common.blocks.*; import gregtech.common.items.MetaItems; import gregtech.common.items.ToolItems; -import gregtech.common.pipelike.cable.BlockCable; -import gregtech.common.pipelike.cable.ItemBlockCable; -import gregtech.common.pipelike.fluidpipe.BlockFluidPipe; -import gregtech.common.pipelike.fluidpipe.ItemBlockFluidPipe; -import gregtech.common.pipelike.itempipe.BlockItemPipe; -import gregtech.common.pipelike.itempipe.ItemBlockItemPipe; -import gregtech.common.pipelike.laser.BlockLaserPipe; -import gregtech.common.pipelike.laser.ItemBlockLaserPipe; -import gregtech.common.pipelike.optical.BlockOpticalPipe; -import gregtech.common.pipelike.optical.ItemBlockOpticalPipe; +import gregtech.common.pipelikeold.cable.BlockCable; +import gregtech.common.pipelikeold.cable.ItemBlockCable; +import gregtech.common.pipelikeold.fluidpipe.BlockFluidPipe; +import gregtech.common.pipelikeold.fluidpipe.ItemBlockFluidPipe; +import gregtech.common.pipelikeold.itempipe.BlockItemPipe; +import gregtech.common.pipelikeold.itempipe.ItemBlockItemPipe; +import gregtech.common.pipelikeold.laser.BlockLaserPipe; +import gregtech.common.pipelikeold.laser.ItemBlockLaserPipe; +import gregtech.common.pipelikeold.optical.BlockOpticalPipe; +import gregtech.common.pipelikeold.optical.ItemBlockOpticalPipe; import gregtech.integration.groovy.GroovyScriptModule; import gregtech.loaders.MaterialInfoLoader; import gregtech.loaders.OreDictionaryLoader; diff --git a/src/main/java/gregtech/common/EventHandlers.java b/src/main/java/gregtech/common/EventHandlers.java index 9d2db26a6fe..f4869c33c9d 100644 --- a/src/main/java/gregtech/common/EventHandlers.java +++ b/src/main/java/gregtech/common/EventHandlers.java @@ -6,8 +6,8 @@ import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.pipenet.longdist.LongDistanceNetwork; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.longdist.LongDistanceNetwork; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.Materials; import gregtech.api.util.BlockUtility; import gregtech.api.util.CapesRegistry; diff --git a/src/main/java/gregtech/common/ToolEventHandlers.java b/src/main/java/gregtech/common/ToolEventHandlers.java index 141b7a14a17..305bd503437 100644 --- a/src/main/java/gregtech/common/ToolEventHandlers.java +++ b/src/main/java/gregtech/common/ToolEventHandlers.java @@ -14,9 +14,9 @@ import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.util.GTUtility; import gregtech.api.util.TaskScheduler; import gregtech.common.items.tool.rotation.CustomBlockRotations; diff --git a/src/main/java/gregtech/common/blocks/BlockFrame.java b/src/main/java/gregtech/common/blocks/BlockFrame.java index bc727d38e50..6fb87bfe308 100644 --- a/src/main/java/gregtech/common/blocks/BlockFrame.java +++ b/src/main/java/gregtech/common/blocks/BlockFrame.java @@ -2,10 +2,10 @@ import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.ItemBlockPipe; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.ItemBlockPipe; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.recipes.ModHandler; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.info.MaterialIconType; diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 1cacda968e6..0b63d47b6b7 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -3,7 +3,7 @@ import gregtech.api.GregTechAPI; import gregtech.api.block.machines.BlockMachine; import gregtech.api.metatileentity.MetaTileEntityHolder; -import gregtech.api.pipenet.longdist.BlockLongDistancePipe; +import gregtech.api.graphnet.pipenetold.longdist.BlockLongDistancePipe; import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; @@ -38,26 +38,26 @@ import gregtech.common.blocks.wood.BlockRubberSapling; import gregtech.common.blocks.wood.BlockWoodenDoor; import gregtech.common.items.MetaItems; -import gregtech.common.pipelike.cable.BlockCable; -import gregtech.common.pipelike.cable.Insulation; -import gregtech.common.pipelike.cable.tile.TileEntityCable; -import gregtech.common.pipelike.cable.tile.TileEntityCableTickable; -import gregtech.common.pipelike.fluidpipe.BlockFluidPipe; -import gregtech.common.pipelike.fluidpipe.FluidPipeType; -import gregtech.common.pipelike.fluidpipe.longdistance.LDFluidPipeType; -import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; -import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipeTickable; -import gregtech.common.pipelike.itempipe.BlockItemPipe; -import gregtech.common.pipelike.itempipe.ItemPipeType; -import gregtech.common.pipelike.itempipe.longdistance.LDItemPipeType; -import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; -import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipeTickable; -import gregtech.common.pipelike.laser.BlockLaserPipe; -import gregtech.common.pipelike.laser.LaserPipeType; -import gregtech.common.pipelike.laser.tile.TileEntityLaserPipe; -import gregtech.common.pipelike.optical.BlockOpticalPipe; -import gregtech.common.pipelike.optical.OpticalPipeType; -import gregtech.common.pipelike.optical.tile.TileEntityOpticalPipe; +import gregtech.common.pipelikeold.cable.BlockCable; +import gregtech.common.pipelikeold.cable.Insulation; +import gregtech.common.pipelikeold.cable.tile.TileEntityCable; +import gregtech.common.pipelikeold.cable.tile.TileEntityCableTickable; +import gregtech.common.pipelikeold.fluidpipe.BlockFluidPipe; +import gregtech.common.pipelikeold.fluidpipe.FluidPipeType; +import gregtech.common.pipelikeold.fluidpipe.longdistance.LDFluidPipeType; +import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; +import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipeTickable; +import gregtech.common.pipelikeold.itempipe.BlockItemPipe; +import gregtech.common.pipelikeold.itempipe.ItemPipeType; +import gregtech.common.pipelikeold.itempipe.longdistance.LDItemPipeType; +import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipe; +import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipeTickable; +import gregtech.common.pipelikeold.laser.BlockLaserPipe; +import gregtech.common.pipelikeold.laser.LaserPipeType; +import gregtech.common.pipelikeold.laser.tile.TileEntityLaserPipe; +import gregtech.common.pipelikeold.optical.BlockOpticalPipe; +import gregtech.common.pipelikeold.optical.OpticalPipeType; +import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.block.Block; import net.minecraft.block.BlockFence; diff --git a/src/main/java/gregtech/common/blocks/properties/PropertyByte.java b/src/main/java/gregtech/common/blocks/properties/PropertyByte.java new file mode 100644 index 00000000000..3042eaca500 --- /dev/null +++ b/src/main/java/gregtech/common/blocks/properties/PropertyByte.java @@ -0,0 +1,92 @@ +package gregtech.common.blocks.properties; + + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.block.properties.PropertyHelper; +import net.minecraft.block.properties.PropertyInteger; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Set; + +public class PropertyByte extends PropertyHelper { + private final ImmutableSet allowedValues; + + protected PropertyByte(String name, byte min, byte max) { + super(name, Byte.class); + + if (min < 0) { + throw new IllegalArgumentException("Min value of " + name + " must be 0 or greater"); + } + else if (max <= min) { + throw new IllegalArgumentException("Max value of " + name + " must be greater than min (" + min + ")"); + } + else { + Set set = new ObjectOpenHashSet<>(); + + for (byte i = min; i <= max; ++i) + { + set.add(i); + } + + this.allowedValues = ImmutableSet.copyOf(set); + } + } + + @Override + public @NotNull Collection getAllowedValues() + { + return this.allowedValues; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + else if (other instanceof PropertyByte propertyByte && super.equals(other)) { + return this.allowedValues.equals(propertyByte.allowedValues); + } + else + { + return false; + } + } + + @Override + public int hashCode() + { + return 31 * super.hashCode() + this.allowedValues.hashCode(); + } + + @Contract("_, _, _ -> new") + public static @NotNull PropertyByte create(String name, byte min, byte max) + { + return new PropertyByte(name, min, max); + } + + @SuppressWarnings("Guava") + @Override + public @NotNull Optional parseValue(@NotNull String value) { + try { + Byte val = Byte.valueOf(value); + return this.allowedValues.contains(val) ? Optional.of(val) : Optional.absent(); + } catch (NumberFormatException var3) { + return Optional.absent(); + } + } + + /** + * Get the name for the given value. + */ + @Override + public @NotNull String getName(Byte value) + { + return value.toString(); + } +} diff --git a/src/main/java/gregtech/common/command/CommandRecipeCheck.java b/src/main/java/gregtech/common/command/CommandRecipeCheck.java index 9aff5b7c070..a7bb61663f0 100644 --- a/src/main/java/gregtech/common/command/CommandRecipeCheck.java +++ b/src/main/java/gregtech/common/command/CommandRecipeCheck.java @@ -5,7 +5,7 @@ import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.metaitem.MetaItem.MetaValueItem; import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.pipenet.block.material.BlockMaterialPipe; +import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.chance.output.impl.ChancedFluidOutput; diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 127c852fb83..20bf62d9cad 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -15,7 +15,7 @@ import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; import gregtech.common.covers.filter.ItemFilterContainer; -import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; +import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipe; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 883fe18f9ec..fa3139006d3 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -6,7 +6,7 @@ import gregtech.api.mui.GTGuiTextures; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.SmartItemFilter; -import gregtech.common.pipelike.itempipe.net.ItemNetHandler; +import gregtech.common.pipelikeold.itempipe.net.ItemNetHandler; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java index 4ee96e5418a..10b6d46675c 100644 --- a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java +++ b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java @@ -9,7 +9,7 @@ import java.util.List; /** - * NetNode-based, state-based evaluator for oreGlob. + * WorldPipeNetNode-based, state-based evaluator for oreGlob. *

* OreGlob nodes are evaluated by simulating match for each possible branch of states. * Each state corresponds to index of character the next match will start. All matches diff --git a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java index f06aef71fb8..ae357edf28f 100644 --- a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java +++ b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java @@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; /** - * NetNode-based implementation of oreglob. + * WorldPipeNetNode-based implementation of oreglob. */ public final class NodeOreGlob extends OreGlob { diff --git a/src/main/java/gregtech/common/gui/widget/monitor/WidgetCoverList.java b/src/main/java/gregtech/common/gui/widget/monitor/WidgetCoverList.java index 5706c8a6787..f8bc247c0bd 100644 --- a/src/main/java/gregtech/common/gui/widget/monitor/WidgetCoverList.java +++ b/src/main/java/gregtech/common/gui/widget/monitor/WidgetCoverList.java @@ -6,7 +6,7 @@ import gregtech.api.gui.widgets.ScrollableListWidget; import gregtech.api.gui.widgets.SlotWidget; import gregtech.api.gui.widgets.WidgetGroup; -import gregtech.api.pipenet.tile.PipeCoverableImplementation; +import gregtech.api.graphnet.pipenetold.tile.PipeCoverableImplementation; import gregtech.api.util.GTLog; import gregtech.api.util.Position; import gregtech.api.util.Size; diff --git a/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java index 629fdd24c1c..1949724c0fd 100644 --- a/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java @@ -3,7 +3,7 @@ import gregtech.api.items.metaitem.stats.IItemDurabilityManager; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.util.GradientUtil; import gregtech.api.util.Mods; import gregtech.core.sound.GTSoundEvents; diff --git a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java index 204139a5680..cb62eda55ea 100644 --- a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java @@ -9,13 +9,13 @@ import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.util.GTUtility; import gregtech.api.util.LocalizationUtils; import gregtech.api.util.TextFormattingUtil; import gregtech.api.worldgen.bedrockFluids.BedrockFluidVeinHandler; import gregtech.common.ConfigHolder; -import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; +import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; import gregtech.core.sound.GTSoundEvents; import net.minecraft.block.Block; diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java index 9f01ef182e5..4f8201e52d6 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java @@ -126,8 +126,8 @@ import gregtech.common.metatileentities.storage.MetaTileEntityQuantumChest; import gregtech.common.metatileentities.storage.MetaTileEntityQuantumTank; import gregtech.common.metatileentities.storage.MetaTileEntityWorkbench; -import gregtech.common.pipelike.fluidpipe.longdistance.MetaTileEntityLDFluidEndpoint; -import gregtech.common.pipelike.itempipe.longdistance.MetaTileEntityLDItemEndpoint; +import gregtech.common.pipelikeold.fluidpipe.longdistance.MetaTileEntityLDFluidEndpoint; +import gregtech.common.pipelikeold.itempipe.longdistance.MetaTileEntityLDItemEndpoint; import gregtech.integration.jei.multiblock.MultiblockInfoCategory; import net.minecraft.util.ResourceLocation; diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityWorldAccelerator.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityWorldAccelerator.java index 861cdd4c9e9..723c2d1cc2f 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityWorldAccelerator.java +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityWorldAccelerator.java @@ -8,7 +8,7 @@ import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.TieredMetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.util.GTLog; import gregtech.client.renderer.texture.Textures; import gregtech.common.ConfigHolder; diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java index cf920b2105c..2df02b2c251 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java @@ -15,7 +15,7 @@ import gregtech.api.metatileentity.MetaTileEntityUIFactory; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.util.FacingPos; import gregtech.api.util.GTLog; import gregtech.client.utils.RenderUtil; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java index b54f74f4ad6..6d250a712e5 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java @@ -11,7 +11,7 @@ import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.util.GTLog; import gregtech.client.renderer.texture.Textures; -import gregtech.common.pipelike.optical.tile.TileEntityOpticalPipe; +import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java index 054cbccfd19..ba1d589b12e 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java @@ -12,7 +12,7 @@ import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; import gregtech.api.recipes.Recipe; import gregtech.client.renderer.texture.Textures; -import gregtech.common.pipelike.optical.tile.TileEntityOpticalPipe; +import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java index 600092ddb2b..31886adb0f6 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java @@ -2,9 +2,9 @@ import gregtech.api.metatileentity.IDataInfoProvider; import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.pipenet.longdist.ILDEndpoint; -import gregtech.api.pipenet.longdist.LongDistanceNetwork; -import gregtech.api.pipenet.longdist.LongDistancePipeType; +import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; +import gregtech.api.graphnet.pipenetold.longdist.LongDistanceNetwork; +import gregtech.api.graphnet.pipenetold.longdist.LongDistancePipeType; import gregtech.common.ConfigHolder; import net.minecraft.client.resources.I18n; diff --git a/src/main/java/gregtech/common/pipelike/block/CableEnergyProperties.java b/src/main/java/gregtech/common/pipelike/block/CableEnergyProperties.java new file mode 100644 index 00000000000..888745cf99c --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/CableEnergyProperties.java @@ -0,0 +1,58 @@ +package gregtech.common.pipelike.block; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.logic.LossAbsoluteLogic; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.pipenet.block.CableStructure; +import gregtech.api.graphnet.pipenet.block.IPipeStructure; +import gregtech.api.unification.material.properties.MaterialProperties; +import gregtech.api.unification.material.properties.PipeNetProperties; + +import gregtech.common.pipelike.net.EnergyNet; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; + +public class CableEnergyProperties implements PipeNetProperties.IPipeNetMaterialProperty { + + private final long voltageLimit; + private final long amperageLimit; + private final int temperatureLimit; + private final int lossPerAmp; + + public CableEnergyProperties(long voltageLimit, long amperageLimit, int temperatureLimit, int lossPerAmp) { + this.voltageLimit = voltageLimit; + this.amperageLimit = amperageLimit; + this.temperatureLimit = temperatureLimit; + this.lossPerAmp = lossPerAmp; + } + + @Override + public @NotNull String getName() { + return "cableEnergy"; + } + + @Override + public void verifyProperty(MaterialProperties properties) {} + + @Override + public void addToNet(World world, BlockPos pos, IPipeStructure structure) { + assert structure instanceof CableStructure; + NetLogicData newData = EnergyNet.getWorldNet(world).getOrCreateNode(pos).getData(); + newData.setLogicEntry(new LossAbsoluteLogic().setValue(lossPerAmp)); + } + + @Override + public void removeFromNet(World world, BlockPos pos) { + EnergyNet net = EnergyNet.getWorldNet(world); + NetNode node = net.getNode(pos); + if (node != null) net.removeNode(node); + } + + @Override + public boolean supportedStructure(IPipeStructure structure) { + return structure.getClass() == CableStructure.class; + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/PipeFluidProperties.java b/src/main/java/gregtech/common/pipelike/block/PipeFluidProperties.java new file mode 100644 index 00000000000..0df7f293cc3 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/PipeFluidProperties.java @@ -0,0 +1,4 @@ +package gregtech.common.pipelike.block; + +public class PipeFluidProperties { +} diff --git a/src/main/java/gregtech/common/pipelike/block/PipeItemProperties.java b/src/main/java/gregtech/common/pipelike/block/PipeItemProperties.java new file mode 100644 index 00000000000..496507d8ddd --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/PipeItemProperties.java @@ -0,0 +1,4 @@ +package gregtech.common.pipelike.block; + +public class PipeItemProperties { +} diff --git a/src/main/java/gregtech/common/pipelike/net/EnergyNet.java b/src/main/java/gregtech/common/pipelike/net/EnergyNet.java new file mode 100644 index 00000000000..5eb6459d983 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/EnergyNet.java @@ -0,0 +1,42 @@ +package gregtech.common.pipelike.net; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNet; + +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; + +public final class EnergyNet extends WorldPipeNet { + + private static final String DATA_ID_BASE = "gregtech.energy_net"; + + public static EnergyNet getWorldNet(World world) { + final String DATA_ID = getDataID(DATA_ID_BASE, world); + EnergyNet net = (EnergyNet) world.loadData(EnergyNet.class, DATA_ID); + if (net == null) { + net = new EnergyNet(DATA_ID); + world.setData(DATA_ID, net); + } + return net; + } + + public EnergyNet(String name) { + super(name, DynamicWeightsShortestPathsAlgorithm::new, false); + } + + public Iterator getPaths(NetNode node) { + return backer.getPaths(node, FlowWorldPipeNetPath.MAPPER); + } + + @Override + public @NotNull NetEdge getNewEdge() { + return new NetFlowEdge(1); + } +} diff --git a/src/main/java/gregtech/common/pipelike/temp.java b/src/main/java/gregtech/common/pipelike/temp.java new file mode 100644 index 00000000000..676bd7e2c5d --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/temp.java @@ -0,0 +1,4 @@ +package gregtech.common.pipelike; + +public class temp { +} diff --git a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java b/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java similarity index 94% rename from src/main/java/gregtech/common/pipelike/cable/BlockCable.java rename to src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java index 723512f528b..2e37fe4e6ca 100644 --- a/src/main/java/gregtech/common/pipelike/cable/BlockCable.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java @@ -1,13 +1,13 @@ -package gregtech.common.pipelike.cable; +package gregtech.common.pipelikeold.cable; import gregtech.api.capability.GregtechCapabilities; import gregtech.api.damagesources.DamageSources; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; -import gregtech.api.pipenet.block.material.BlockMaterialPipe; -import gregtech.api.pipenet.edge.NetFlowEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.unification.material.registry.MaterialRegistry; @@ -15,9 +15,9 @@ import gregtech.client.renderer.pipe.CableRenderer; import gregtech.client.renderer.pipe.PipeRenderer; import gregtech.common.creativetab.GTCreativeTabs; -import gregtech.common.pipelike.cable.net.WorldEnergyNet; -import gregtech.common.pipelike.cable.tile.TileEntityCable; -import gregtech.common.pipelike.cable.tile.TileEntityCableTickable; +import gregtech.common.pipelikeold.cable.net.WorldEnergyNet; +import gregtech.common.pipelikeold.cable.tile.TileEntityCable; +import gregtech.common.pipelikeold.cable.tile.TileEntityCableTickable; import gregtech.core.advancement.AdvancementTriggers; import net.minecraft.block.ITileEntityProvider; diff --git a/src/main/java/gregtech/common/pipelike/cable/Insulation.java b/src/main/java/gregtech/common/pipelikeold/cable/Insulation.java similarity index 95% rename from src/main/java/gregtech/common/pipelike/cable/Insulation.java rename to src/main/java/gregtech/common/pipelikeold/cable/Insulation.java index 5739ad1a3d4..4ecdb939a6c 100644 --- a/src/main/java/gregtech/common/pipelike/cable/Insulation.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/Insulation.java @@ -1,6 +1,6 @@ -package gregtech.common.pipelike.cable; +package gregtech.common.pipelikeold.cable; -import gregtech.api.pipenet.block.material.IMaterialPipeType; +import gregtech.api.graphnet.pipenetold.block.material.IMaterialPipeType; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.unification.ore.OrePrefix; diff --git a/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java b/src/main/java/gregtech/common/pipelikeold/cable/ItemBlockCable.java similarity index 92% rename from src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java rename to src/main/java/gregtech/common/pipelikeold/cable/ItemBlockCable.java index 9f8458796ad..3b03a0e14ef 100644 --- a/src/main/java/gregtech/common/pipelike/cable/ItemBlockCable.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/ItemBlockCable.java @@ -1,8 +1,8 @@ -package gregtech.common.pipelike.cable; +package gregtech.common.pipelikeold.cable; import gregtech.api.GTValues; -import gregtech.api.pipenet.block.material.BlockMaterialPipe; -import gregtech.api.pipenet.block.material.ItemBlockMaterialPipe; +import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; +import gregtech.api.graphnet.pipenetold.block.material.ItemBlockMaterialPipe; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.GTUtility; import gregtech.client.utils.TooltipHelper; diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyGroupData.java b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java similarity index 69% rename from src/main/java/gregtech/common/pipelike/cable/net/EnergyGroupData.java rename to src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java index 34e1c6bec83..2ebae018f96 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java @@ -1,12 +1,10 @@ -package gregtech.common.pipelike.cable.net; +package gregtech.common.pipelikeold.cable.net; -import gregtech.api.pipenet.AbstractGroupData; -import gregtech.api.unification.material.properties.WireProperties; -import gregtech.common.pipelike.cable.Insulation; +import gregtech.api.graphnet.AbstractGroupData; import net.minecraft.world.World; -public class EnergyGroupData extends AbstractGroupData { +public class EnergyGroupData extends AbstractGroupData { private long lastEnergyFluxPerSec; private long energyFluxPerSec; diff --git a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java similarity index 86% rename from src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java rename to src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java index 961b21aca75..d1f62cb9fc2 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java @@ -1,21 +1,21 @@ -package gregtech.common.pipelike.cable.net; +package gregtech.common.pipelikeold.cable.net; import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IEnergyContainer; -import gregtech.api.pipenet.AbstractGroupData; -import gregtech.api.pipenet.IPipeNetHandler; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.NodeLossResult; -import gregtech.api.pipenet.edge.NetFlowEdge; -import gregtech.api.pipenet.edge.SimulatorKey; -import gregtech.api.pipenet.edge.util.FlowConsumerList; +import gregtech.api.graphnet.AbstractGroupData; +import gregtech.api.graphnet.pipenetold.IPipeNetHandler; +import gregtech.api.graphnet.pipenetold.PipeNetNode; +import gregtech.api.graphnet.pipenetold.PipeNetPath; +import gregtech.api.graphnet.pipenetold.NodeLossResult; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.edge.util.FlowConsumerList; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.FacingPos; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; -import gregtech.common.pipelike.cable.Insulation; -import gregtech.common.pipelike.cable.tile.TileEntityCable; +import gregtech.common.pipelikeold.cable.Insulation; +import gregtech.common.pipelikeold.cable.tile.TileEntityCable; import net.minecraft.util.EnumFacing; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -34,14 +34,14 @@ public class EnergyNetHandler implements IEnergyContainer, IPipeNetHandler { - protected static final NetNode FAKE_SOURCE = new NetNode<>( + protected static final PipeNetNode FAKE_SOURCE = new PipeNetNode<>( new WireProperties(Integer.MAX_VALUE, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, false)); private final WorldEnergyNet net; private boolean transfer; private final TileEntityCable cable; private final EnumFacing facing; - private final Map, NodeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); + private final Map, NodeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); private Object2LongOpenHashMap destSimulationCache; private final NetFlowEdge inputEdge; @@ -52,12 +52,12 @@ public EnergyNetHandler(WorldEnergyNet net, TileEntityCable cable, EnumFacing fa this.inputEdge = new NetFlowEdge(1) { @Override - public NetNode getSource() { + public PipeNetNode getSource() { return FAKE_SOURCE; } @Override - public NetNode getTarget() { + public PipeNetNode getTarget() { return EnergyNetHandler.this.cable.getNode(); } }; @@ -75,14 +75,14 @@ public EnumFacing getFacing() { @Override public long getInputPerSec() { - AbstractGroupData data = net.getGroup(cable.getPipePos()).getData(); + AbstractGroupData data = net.getGroup(cable.getPipePos()).getData(); if (!(data instanceof EnergyGroupData e)) return 0; return e.getEnergyFluxPerSec(); } @Override public long getOutputPerSec() { - AbstractGroupData data = net.getGroup(cable.getPipePos()).getData(); + AbstractGroupData data = net.getGroup(cable.getPipePos()).getData(); if (!(data instanceof EnergyGroupData e)) return 0; return e.getEnergyFluxPerSec(); } @@ -106,7 +106,7 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage SimulatorKey simulator = simulate ? SimulatorKey.getNewSimulatorInstance() : null; destSimulationCache = simulate ? new Object2LongOpenHashMap<>() : null; - this.getNet().getGraph().prepareForDynamicWeightAlgorithmRun(null, simulator, queryTick); + this.getNet().getGraph().prepareForDynamicWeightAlgorithmRun(null, simulator); long amperesUsed = distributionRespectCapacity(side, voltage, amperage, queryTick, this.getNet().getPaths(cable), simulator); if (amperesUsed < amperage) { @@ -125,18 +125,18 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage } private long distributionRespectCapacity(EnumFacing side, long voltage, long amperage, long queryTick, - Iterator> paths, + Iterator> paths, SimulatorKey simulator) { long availableAmperage = amperage; mainloop: while (paths.hasNext()) { - NetPath path = paths.next(); + PipeNetPath path = paths.next(); // skip paths where loss exceeds available voltage if (path.getSumData().getLoss() > voltage) continue; Iterator iterator = path.getFacingIterator(); boolean pathDestThis = path.getTargetNode().getNodePos().equals(this.cable.getPipePos()); while (iterator.hasNext()) { - NetPath.FacedNetPath facedPath = path + PipeNetPath.FacedPipeNetPath facedPath = path .withFacing(iterator.next()); if (pathDestThis && facedPath.facing == side) { // do not distribute power back into our source @@ -148,7 +148,7 @@ private long distributionRespectCapacity(EnumFacing side, long voltage, long amp if (dest == null || dest == this) continue; if (!dest.inputsEnergy(facedPath.oppositeFacing()) || dest.getEnergyCanBeInserted() <= 0) continue; - List> nodeList = facedPath.getNodeList(); + List> nodeList = facedPath.getNodeList(); DoubleList voltageCaps = new DoubleArrayList(); long pathAmperage = availableAmperage; @@ -156,7 +156,7 @@ private long distributionRespectCapacity(EnumFacing side, long voltage, long amp FlowConsumerList flowLimitConsumers = new FlowConsumerList<>(); for (int j = 0; j < nodeList.size(); j++) { NetFlowEdge edge = j == 0 ? inputEdge : edgeList.get(j - 1); - NetNode target = nodeList.get(j); + PipeNetNode target = nodeList.get(j); // amperage capping long max = Math.min(pathAmperage, edge.getFlowLimit(null, this.net.getGraph(), queryTick, simulator)); @@ -197,20 +197,20 @@ private long distributionRespectCapacity(EnumFacing side, long voltage, long amp } private long distributionIgnoreCapacity(EnumFacing side, long voltage, long amperage, long queryTick, - Iterator> paths, + Iterator> paths, SimulatorKey simulator) { Object2LongOpenHashMap localDestSimulationCache = new Object2LongOpenHashMap<>(); long availableAmperage = amperage; mainloop: while (paths.hasNext()) { - NetPath path = paths.next(); + PipeNetPath path = paths.next(); // skip paths where loss exceeds available voltage if (path.getSumData().getLoss() > voltage) continue; Iterator iterator = path.getFacingIterator(); boolean pathDestThis = path.getTargetNode().getNodePos().equals(this.cable.getPipePos()); while (iterator.hasNext()) { - NetPath.FacedNetPath facedPath = path + PipeNetPath.FacedPipeNetPath facedPath = path .withFacing(iterator.next()); if (pathDestThis && facedPath.facing == side) { // do not distribute power back into our source @@ -222,7 +222,7 @@ private long distributionIgnoreCapacity(EnumFacing side, long voltage, long ampe if (dest == null || dest == this) continue; if (!dest.inputsEnergy(facedPath.oppositeFacing()) || dest.getEnergyCanBeInserted() <= 0) continue; - List> nodeList = facedPath.getNodeList(); + List> nodeList = facedPath.getNodeList(); DoubleList voltageCaps = new DoubleArrayList(); long pathAmperage = availableAmperage; @@ -231,7 +231,7 @@ private long distributionIgnoreCapacity(EnumFacing side, long voltage, long ampe List> amperageLossHeat = new ObjectArrayList<>(); for (int j = 0; j < nodeList.size(); j++) { NetFlowEdge edge = j == 0 ? inputEdge : edgeList.get(j - 1); - NetNode target = nodeList.get(j); + PipeNetNode target = nodeList.get(j); // amperage capping long flowLimit = edge.getFlowLimit(null, this.net.getGraph(), queryTick, simulator); long finalPathAmperage = pathAmperage; @@ -299,7 +299,7 @@ private long getSimulatedAccepted(Object2LongOpenHashMap destSimulati private boolean calculateVoltageLoss(long voltage, SimulatorKey simulator, DoubleList voltageCaps, long pathAmperage, - NetNode target) { + PipeNetNode target) { // TODO undo loss & heating on backflow if (target.getData().getVoltage() < voltage) { int heat = calculateHeat(pathAmperage, voltage, target.getData().getVoltage()); @@ -361,7 +361,7 @@ public boolean isOneProbeHidden() { return true; } - protected NodeLossResult getOrGenerateLossResult(NetNode node, + protected NodeLossResult getOrGenerateLossResult(PipeNetNode node, int heat, boolean simulate) { var cachedResult = this.lossResultCache.get(node); if (cachedResult == null) { diff --git a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelikeold/cable/net/WorldEnergyNet.java similarity index 81% rename from src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java rename to src/main/java/gregtech/common/pipelikeold/cable/net/WorldEnergyNet.java index 38581010589..f4a00f48f5f 100644 --- a/src/main/java/gregtech/common/pipelike/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/net/WorldEnergyNet.java @@ -1,14 +1,14 @@ -package gregtech.common.pipelike.cable.net; +package gregtech.common.pipelikeold.cable.net; import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.pipenet.AbstractGroupData; -import gregtech.api.pipenet.WorldPipeNetComplex; -import gregtech.api.pipenet.alg.DynamicWeightsShortestPathsAlgorithm; -import gregtech.api.pipenet.edge.NetFlowEdge; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.AbstractGroupData; +import gregtech.api.graphnet.pipenetold.WorldPipeNetComplex; +import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.properties.WireProperties; -import gregtech.common.pipelike.cable.Insulation; -import gregtech.common.pipelike.cable.tile.TileEntityCable; +import gregtech.common.pipelikeold.cable.Insulation; +import gregtech.common.pipelikeold.cable.tile.TileEntityCable; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; @@ -49,12 +49,12 @@ protected Class> ge } @Override - protected AbstractGroupData getBlankGroupData() { + public AbstractGroupData getBlankGroupData() { return new EnergyGroupData(); } @Override - protected void writeNodeData(WireProperties nodeData, NBTTagCompound tagCompound) { + public void writeNodeData(WireProperties nodeData, NBTTagCompound tagCompound) { tagCompound.setInteger("voltage", nodeData.getVoltage()); tagCompound.setInteger("amperage", nodeData.getAmperage()); tagCompound.setInteger("loss", nodeData.getLoss()); diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/AveragingPerTickCounter.java b/src/main/java/gregtech/common/pipelikeold/cable/tile/AveragingPerTickCounter.java similarity index 98% rename from src/main/java/gregtech/common/pipelike/cable/tile/AveragingPerTickCounter.java rename to src/main/java/gregtech/common/pipelikeold/cable/tile/AveragingPerTickCounter.java index f9691274b89..0dd33aa769f 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/AveragingPerTickCounter.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/tile/AveragingPerTickCounter.java @@ -1,4 +1,4 @@ -package gregtech.common.pipelike.cable.tile; +package gregtech.common.pipelikeold.cable.tile; import net.minecraft.world.World; diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/PerTickLongCounter.java b/src/main/java/gregtech/common/pipelikeold/cable/tile/PerTickLongCounter.java similarity index 97% rename from src/main/java/gregtech/common/pipelike/cable/tile/PerTickLongCounter.java rename to src/main/java/gregtech/common/pipelikeold/cable/tile/PerTickLongCounter.java index e2fe2e9102e..11c9a571471 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/PerTickLongCounter.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/tile/PerTickLongCounter.java @@ -1,4 +1,4 @@ -package gregtech.common.pipelike.cable.tile; +package gregtech.common.pipelikeold.cable.tile; import net.minecraft.world.World; diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCable.java similarity index 94% rename from src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java rename to src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCable.java index 15605ec48f7..8768892d834 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCable.java @@ -1,25 +1,25 @@ -package gregtech.common.pipelike.cable.tile; +package gregtech.common.pipelikeold.cable.tile; import gregtech.api.GTValues; import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IEnergyContainer; import gregtech.api.metatileentity.IDataInfoProvider; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.NodeLossResult; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; -import gregtech.api.pipenet.edge.NetFlowEdge; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.PipeNetNode; +import gregtech.api.graphnet.pipenetold.NodeLossResult; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.TaskScheduler; import gregtech.api.util.TextFormattingUtil; import gregtech.client.particle.GTOverheatParticle; import gregtech.client.particle.GTParticleManager; import gregtech.common.blocks.MetaBlocks; -import gregtech.common.pipelike.cable.BlockCable; -import gregtech.common.pipelike.cable.Insulation; -import gregtech.common.pipelike.cable.net.EnergyNetHandler; -import gregtech.common.pipelike.cable.net.WorldEnergyNet; +import gregtech.common.pipelikeold.cable.BlockCable; +import gregtech.common.pipelikeold.cable.Insulation; +import gregtech.common.pipelikeold.cable.net.EnergyNetHandler; +import gregtech.common.pipelikeold.cable.net.WorldEnergyNet; import net.minecraft.init.Blocks; import net.minecraft.nbt.NBTTagCompound; @@ -102,7 +102,7 @@ public void onLoad() { public NodeLossResult applyHeat(int amount, boolean simulate) { double loss = 1; - Consumer> destructionResult = null; + Consumer> destructionResult = null; if (temperature + amount >= getMeltTemp()) { // cable melted diff --git a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCableTickable.java b/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCableTickable.java similarity index 87% rename from src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCableTickable.java rename to src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCableTickable.java index 29b9592cdb3..b07b3ca4117 100644 --- a/src/main/java/gregtech/common/pipelike/cable/tile/TileEntityCableTickable.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCableTickable.java @@ -1,4 +1,4 @@ -package gregtech.common.pipelike.cable.tile; +package gregtech.common.pipelikeold.cable.tile; import net.minecraft.util.ITickable; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java similarity index 90% rename from src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java rename to src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java index 96673e4268d..902212116cf 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/BlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java @@ -1,13 +1,13 @@ -package gregtech.common.pipelike.fluidpipe; +package gregtech.common.pipelikeold.fluidpipe; import gregtech.api.fluids.FluidConstants; import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.block.material.BlockMaterialPipe; -import gregtech.api.pipenet.edge.NetFlowEdge; -import gregtech.api.pipenet.predicate.FluidTestObject; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.PipeNetNode; +import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.unification.material.registry.MaterialRegistry; @@ -15,9 +15,9 @@ import gregtech.client.renderer.pipe.FluidPipeRenderer; import gregtech.client.renderer.pipe.PipeRenderer; import gregtech.common.creativetab.GTCreativeTabs; -import gregtech.common.pipelike.fluidpipe.net.WorldFluidPipeNet; -import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; -import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipeTickable; +import gregtech.common.pipelikeold.fluidpipe.net.WorldFluidPipeNet; +import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; +import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipeTickable; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -142,8 +142,8 @@ public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @No TileEntityFluidPipe pipe = (TileEntityFluidPipe) getPipeTileEntity(worldIn, pos); if (pipe.getFrameMaterial() == null && pipe.getOffsetTimer() % 10 == 0) { if (entityIn instanceof EntityLivingBase living) { - NetNode node = pipe.getNode(); - var net = node.getGroupSafe().net; + PipeNetNode node = pipe.getNode(); + var net = node.getNet(); Set fluids = new ObjectOpenHashSet<>(); for (NetFlowEdge edge : net.getGraph().edgesOf(node)) { for (Object obj : edge.getActiveChannels(null, diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/FluidPipeType.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/FluidPipeType.java similarity index 95% rename from src/main/java/gregtech/common/pipelike/fluidpipe/FluidPipeType.java rename to src/main/java/gregtech/common/pipelikeold/fluidpipe/FluidPipeType.java index 2a99c200680..8f85d012d03 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/FluidPipeType.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/FluidPipeType.java @@ -1,6 +1,6 @@ -package gregtech.common.pipelike.fluidpipe; +package gregtech.common.pipelikeold.fluidpipe; -import gregtech.api.pipenet.block.material.IMaterialPipeType; +import gregtech.api.graphnet.pipenetold.block.material.IMaterialPipeType; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.unification.ore.OrePrefix; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/ItemBlockFluidPipe.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/ItemBlockFluidPipe.java similarity index 91% rename from src/main/java/gregtech/common/pipelike/fluidpipe/ItemBlockFluidPipe.java rename to src/main/java/gregtech/common/pipelikeold/fluidpipe/ItemBlockFluidPipe.java index 1dfc763b283..4072b809931 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/ItemBlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/ItemBlockFluidPipe.java @@ -1,7 +1,7 @@ -package gregtech.common.pipelike.fluidpipe; +package gregtech.common.pipelikeold.fluidpipe; -import gregtech.api.pipenet.block.material.BlockMaterialPipe; -import gregtech.api.pipenet.block.material.ItemBlockMaterialPipe; +import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; +import gregtech.api.graphnet.pipenetold.block.material.ItemBlockMaterialPipe; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.client.utils.TooltipHelper; import gregtech.common.ConfigHolder; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/longdistance/LDFluidPipeType.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/LDFluidPipeType.java similarity index 72% rename from src/main/java/gregtech/common/pipelike/fluidpipe/longdistance/LDFluidPipeType.java rename to src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/LDFluidPipeType.java index 05d9b91f407..43ad21d7cea 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/longdistance/LDFluidPipeType.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/LDFluidPipeType.java @@ -1,6 +1,6 @@ -package gregtech.common.pipelike.fluidpipe.longdistance; +package gregtech.common.pipelikeold.fluidpipe.longdistance; -import gregtech.api.pipenet.longdist.LongDistancePipeType; +import gregtech.api.graphnet.pipenetold.longdist.LongDistancePipeType; import gregtech.common.ConfigHolder; public class LDFluidPipeType extends LongDistancePipeType { diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java similarity index 97% rename from src/main/java/gregtech/common/pipelike/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java rename to src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java index 55ddb9d3ba1..20934ea5f73 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java @@ -1,11 +1,11 @@ -package gregtech.common.pipelike.fluidpipe.longdistance; +package gregtech.common.pipelikeold.fluidpipe.longdistance; import gregtech.api.GTValues; import gregtech.api.capability.impl.FluidHandlerDelegate; import gregtech.api.gui.ModularUI; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.pipenet.longdist.ILDEndpoint; +import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; import gregtech.common.metatileentities.storage.MetaTileEntityLongDistanceEndpoint; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidEdgePredicate.java similarity index 74% rename from src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java rename to src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidEdgePredicate.java index b6c5fadc148..d5fbc9e3e02 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/FluidEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidEdgePredicate.java @@ -1,8 +1,8 @@ -package gregtech.common.pipelike.fluidpipe.net; +package gregtech.common.pipelikeold.fluidpipe.net; -import gregtech.api.pipenet.predicate.FilteredEdgePredicate; -import gregtech.api.pipenet.predicate.FluidTestObject; -import gregtech.api.pipenet.predicate.IPredicateTestObject; +import gregtech.api.graphnet.pipenetold.predicate.FilteredEdgePredicate; +import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.FluidFilterContainer; @@ -15,7 +15,7 @@ public class FluidEdgePredicate extends FilteredEdgePredicate FAKE_SOURCE = new NetNode<>( + protected static final PipeNetNode FAKE_SOURCE = new PipeNetNode<>( new FluidPipeProperties(Integer.MAX_VALUE, Integer.MAX_VALUE, true, true, true, true, Integer.MAX_VALUE)); private static final IFluidTankProperties[] EMPTY = new IFluidTankProperties[0]; @@ -44,7 +44,7 @@ public class FluidNetHandler implements IFluidHandler, IPipeNetHandler { private SimulatorKey simulatorKey; private FluidStack lastFillResource; - private final Map, NodeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); + private final Map, NodeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); private final NetFlowEdge inputEdge; @@ -55,12 +55,12 @@ public FluidNetHandler(WorldFluidPipeNet net, TileEntityFluidPipe pipe, EnumFaci this.inputEdge = new NetFlowEdge(1) { @Override - public NetNode getSource() { + public PipeNetNode getSource() { return FAKE_SOURCE; } @Override - public NetNode getTarget() { + public PipeNetNode getTarget() { return FluidNetHandler.this.pipe.getNode(); } }; @@ -102,14 +102,14 @@ public int fill(FluidStack resource, boolean doFill) { FluidStack helper = resource.copy(); if (!doFill) this.simulatorKey = SimulatorKey.getNewSimulatorInstance(); else this.simulatorKey = null; - this.getNet().getGraph().prepareForDynamicWeightAlgorithmRun(testObject, simulatorKey, queryTick); + this.getNet().getGraph().prepareForDynamicWeightAlgorithmRun(testObject, simulatorKey); mainloop: - for (Iterator> iter = this.getNet() + for (Iterator> iter = this.getNet() .getPaths(pipe); iter.hasNext();) { - NetPath path = iter.next(); + PipeNetPath path = iter.next(); for (Iterator it = path.getFacingIterator(); it.hasNext();) { EnumFacing facing = it.next(); - NetPath.FacedNetPath routePath = path + PipeNetPath.FacedPipeNetPath routePath = path .withFacing(facing); helper.amount -= this.fill(routePath, testObject, queryTick, helper, doFill); if (helper.amount <= 0) break mainloop; @@ -123,7 +123,7 @@ public int fill(FluidStack resource, boolean doFill) { return resource.amount - helper.amount; } - public int fill(NetPath.FacedNetPath routePath, + public int fill(PipeNetPath.FacedPipeNetPath routePath, FluidTestObject testObject, long tick, FluidStack resource, boolean doFill) { if (routePath.getTargetNode().getNodePos().equals(this.pipe.getPos()) && routePath.facing == this.facing) { return 0; @@ -165,7 +165,7 @@ public int fill(NetPath.FacedNetPath routePath, + public int fillOverRegulator(PipeNetPath.FacedPipeNetPath routePath, IFluidHandler handler, FluidTestObject testObject, long tick, CoverFluidRegulator regulator, FluidStack resource, int allowed, boolean doFill) { var matched = regulator.getFluidFilterContainer().match(resource); @@ -205,7 +205,7 @@ public int fillOverRegulator(NetPath.FacedNetPath routePath, + private int fill(PipeNetPath.FacedPipeNetPath routePath, IFluidHandler handler, FluidTestObject testObject, long tick, FluidStack resource, int allowed, boolean doFill) { FluidStack helper = new FluidStack(resource, allowed); @@ -213,7 +213,7 @@ private int fill(NetPath.FacedNetPath> nodeList = routePath.getNodeList(); + List> nodeList = routePath.getNodeList(); List edgeList = routePath.getEdgeList(); FlowConsumerList flowLimitConsumers = new FlowConsumerList<>(); @@ -277,7 +277,7 @@ public FluidStack drain(int maxDrain, boolean doDrain) { return null; } - protected NodeLossResult getOrGenerateLossResult(NetNode node, + protected NodeLossResult getOrGenerateLossResult(PipeNetNode node, FluidStack resource) { var cachedResult = this.lossResultCache.get(node); if (cachedResult == null) { diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/WorldFluidPipeNet.java similarity index 63% rename from src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java rename to src/main/java/gregtech/common/pipelikeold/fluidpipe/net/WorldFluidPipeNet.java index 6bebb251ee6..5d8cafa410f 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/WorldFluidPipeNet.java @@ -1,24 +1,25 @@ -package gregtech.common.pipelike.fluidpipe.net; +package gregtech.common.pipelikeold.fluidpipe.net; import gregtech.api.cover.Cover; -import gregtech.api.pipenet.WorldPipeNetComplex; -import gregtech.api.pipenet.alg.DynamicWeightsShortestPathsAlgorithm; -import gregtech.api.pipenet.edge.NetFlowEdge; -import gregtech.api.pipenet.predicate.AbstractEdgePredicate; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.pipenetold.WorldPipeNetComplex; +import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.covers.CoverFluidFilter; import gregtech.common.covers.CoverPump; import gregtech.common.covers.FluidFilterMode; import gregtech.common.covers.ManualImportExportMode; -import gregtech.common.pipelike.fluidpipe.FluidPipeType; -import gregtech.common.pipelike.fluidpipe.tile.TileEntityFluidPipe; +import gregtech.common.pipelikeold.fluidpipe.FluidPipeType; +import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import org.jetbrains.annotations.NotNull; + public class WorldFluidPipeNet extends WorldPipeNetComplex { // TODO handle fluids in old fluid pipes @@ -56,7 +57,7 @@ protected Class getPredicate(Cover thisCover, Cover neighbourCover) { + protected IEdgePredicateOld getPredicate(Cover thisCover, Cover neighbourCover) { FluidEdgePredicate predicate = new FluidEdgePredicate(); if (thisCover instanceof CoverFluidFilter filter && filter.getFilterMode() != FluidFilterMode.FILTER_FILL) { @@ -85,26 +86,7 @@ protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbour } @Override - protected void writeNodeData(FluidPipeProperties nodeData, NBTTagCompound tagCompound) { - tagCompound.setInteger("max_temperature", nodeData.getMaxFluidTemperature()); - tagCompound.setInteger("throughput", nodeData.getThroughput()); - tagCompound.setBoolean("gas_proof", nodeData.isGasProof()); - tagCompound.setBoolean("acid_proof", nodeData.isAcidProof()); - tagCompound.setBoolean("cryo_proof", nodeData.isCryoProof()); - tagCompound.setBoolean("plasma_proof", nodeData.isPlasmaProof()); - tagCompound.setInteger("channels", nodeData.getTanks()); - } - - @Override - protected FluidPipeProperties readNodeData(NBTTagCompound tagCompound) { - int maxTemperature = tagCompound.getInteger("max_temperature"); - int throughput = tagCompound.getInteger("throughput"); - boolean gasProof = tagCompound.getBoolean("gas_proof"); - boolean acidProof = tagCompound.getBoolean("acid_proof"); - boolean cryoProof = tagCompound.getBoolean("cryo_proof"); - boolean plasmaProof = tagCompound.getBoolean("plasma_proof"); - int channels = tagCompound.getInteger("channels"); - return new FluidPipeProperties(maxTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof, - channels); + public @NotNull NetLogicData getDefaultNodeData() { + return new FluidPipeProperties(); } } diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipe.java similarity index 94% rename from src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java rename to src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipe.java index 210c0d3cb09..f5087554440 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipe.java @@ -1,14 +1,14 @@ -package gregtech.common.pipelike.fluidpipe.tile; +package gregtech.common.pipelikeold.fluidpipe.tile; import gregtech.api.GTValues; -import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; -import gregtech.api.pipenet.edge.NetFlowEdge; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.util.TaskScheduler; -import gregtech.common.pipelike.fluidpipe.FluidPipeType; -import gregtech.common.pipelike.fluidpipe.net.FluidNetHandler; -import gregtech.common.pipelike.fluidpipe.net.WorldFluidPipeNet; +import gregtech.common.pipelikeold.fluidpipe.FluidPipeType; +import gregtech.common.pipelikeold.fluidpipe.net.FluidNetHandler; +import gregtech.common.pipelikeold.fluidpipe.net.WorldFluidPipeNet; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; diff --git a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipeTickable.java similarity index 85% rename from src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java rename to src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipeTickable.java index fbfedad51ba..dbf86ed6867 100644 --- a/src/main/java/gregtech/common/pipelike/fluidpipe/tile/TileEntityFluidPipeTickable.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipeTickable.java @@ -1,4 +1,4 @@ -package gregtech.common.pipelike.fluidpipe.tile; +package gregtech.common.pipelikeold.fluidpipe.tile; import net.minecraft.util.ITickable; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/BlockItemPipe.java b/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java similarity index 90% rename from src/main/java/gregtech/common/pipelike/itempipe/BlockItemPipe.java rename to src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java index 8a6698fe8b9..4488683e40c 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/BlockItemPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java @@ -1,19 +1,19 @@ -package gregtech.common.pipelike.itempipe; +package gregtech.common.pipelikeold.itempipe; import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.pipenet.block.material.BlockMaterialPipe; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.client.renderer.pipe.ItemPipeRenderer; import gregtech.client.renderer.pipe.PipeRenderer; import gregtech.common.creativetab.GTCreativeTabs; -import gregtech.common.pipelike.itempipe.net.WorldItemPipeNet; -import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; -import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipeTickable; +import gregtech.common.pipelikeold.itempipe.net.WorldItemPipeNet; +import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipe; +import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipeTickable; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/ItemBlockItemPipe.java b/src/main/java/gregtech/common/pipelikeold/itempipe/ItemBlockItemPipe.java similarity index 91% rename from src/main/java/gregtech/common/pipelike/itempipe/ItemBlockItemPipe.java rename to src/main/java/gregtech/common/pipelikeold/itempipe/ItemBlockItemPipe.java index 6246de9d6d6..2f88ae6269c 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/ItemBlockItemPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/ItemBlockItemPipe.java @@ -1,7 +1,7 @@ -package gregtech.common.pipelike.itempipe; +package gregtech.common.pipelikeold.itempipe; -import gregtech.api.pipenet.block.material.BlockMaterialPipe; -import gregtech.api.pipenet.block.material.ItemBlockMaterialPipe; +import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; +import gregtech.api.graphnet.pipenetold.block.material.ItemBlockMaterialPipe; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.client.utils.TooltipHelper; import gregtech.common.ConfigHolder; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/ItemPipeType.java b/src/main/java/gregtech/common/pipelikeold/itempipe/ItemPipeType.java similarity index 95% rename from src/main/java/gregtech/common/pipelike/itempipe/ItemPipeType.java rename to src/main/java/gregtech/common/pipelikeold/itempipe/ItemPipeType.java index cfbdcecb3f3..9b129f97d47 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/ItemPipeType.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/ItemPipeType.java @@ -1,6 +1,6 @@ -package gregtech.common.pipelike.itempipe; +package gregtech.common.pipelikeold.itempipe; -import gregtech.api.pipenet.block.material.IMaterialPipeType; +import gregtech.api.graphnet.pipenetold.block.material.IMaterialPipeType; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.unification.ore.OrePrefix; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/longdistance/LDItemPipeType.java b/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/LDItemPipeType.java similarity index 72% rename from src/main/java/gregtech/common/pipelike/itempipe/longdistance/LDItemPipeType.java rename to src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/LDItemPipeType.java index 4bf089b74c9..3062fe568c7 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/longdistance/LDItemPipeType.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/LDItemPipeType.java @@ -1,6 +1,6 @@ -package gregtech.common.pipelike.itempipe.longdistance; +package gregtech.common.pipelikeold.itempipe.longdistance; -import gregtech.api.pipenet.longdist.LongDistancePipeType; +import gregtech.api.graphnet.pipenetold.longdist.LongDistancePipeType; import gregtech.common.ConfigHolder; public class LDItemPipeType extends LongDistancePipeType { diff --git a/src/main/java/gregtech/common/pipelike/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java b/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java similarity index 97% rename from src/main/java/gregtech/common/pipelike/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java rename to src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java index e062224904b..c3095875c49 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java @@ -1,11 +1,11 @@ -package gregtech.common.pipelike.itempipe.longdistance; +package gregtech.common.pipelikeold.itempipe.longdistance; import gregtech.api.GTValues; import gregtech.api.capability.impl.ItemHandlerDelegate; import gregtech.api.gui.ModularUI; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.pipenet.longdist.ILDEndpoint; +import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; import gregtech.common.metatileentities.storage.MetaTileEntityLongDistanceEndpoint; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java b/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemEdgePredicate.java similarity index 74% rename from src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java rename to src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemEdgePredicate.java index 2df16f164c4..fa5cec2d130 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemEdgePredicate.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemEdgePredicate.java @@ -1,8 +1,8 @@ -package gregtech.common.pipelike.itempipe.net; +package gregtech.common.pipelikeold.itempipe.net; -import gregtech.api.pipenet.predicate.FilteredEdgePredicate; -import gregtech.api.pipenet.predicate.IPredicateTestObject; -import gregtech.api.pipenet.predicate.ItemTestObject; +import gregtech.api.graphnet.pipenetold.predicate.FilteredEdgePredicate; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.ItemFilterContainer; @@ -15,7 +15,7 @@ public class ItemEdgePredicate extends FilteredEdgePredicate private final static String KEY = "Item"; static { - PREDICATE_SUPPLIERS.put(KEY, ItemEdgePredicate::new); + REGISTRY.put(KEY, ItemEdgePredicate::new); } @Override diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemNetHandler.java similarity index 88% rename from src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java rename to src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemNetHandler.java index 133da4d47fe..891b28b3d50 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemNetHandler.java @@ -1,10 +1,10 @@ -package gregtech.common.pipelike.itempipe.net; +package gregtech.common.pipelikeold.itempipe.net; import gregtech.api.cover.Cover; -import gregtech.api.pipenet.IPipeNetHandler; -import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.predicate.ItemTestObject; +import gregtech.api.graphnet.pipenetold.IPipeNetHandler; +import gregtech.api.graphnet.pipenetold.PipeNetPath; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.util.FacingPos; import gregtech.api.util.GTTransferUtils; @@ -14,8 +14,8 @@ import gregtech.common.covers.CoverRoboticArm; import gregtech.common.covers.DistributionMode; import gregtech.common.covers.ItemFilterMode; -import gregtech.common.pipelike.itempipe.ItemPipeType; -import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; +import gregtech.common.pipelikeold.itempipe.ItemPipeType; +import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipe; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; @@ -116,8 +116,8 @@ public static boolean checkImportCover(Cover cover, boolean onPipe, ItemStack st } public ItemStack insertFirst(ItemStack stack, boolean simulate) { - for (Iterator> it = net.getPaths(pipe); it.hasNext();) { - NetPath inv = it.next(); + for (Iterator> it = net.getPaths(pipe); it.hasNext();) { + PipeNetPath inv = it.next(); stack = insert(inv.firstFacing(), stack, simulate); if (stack.isEmpty()) return ItemStack.EMPTY; @@ -126,9 +126,9 @@ public ItemStack insertFirst(ItemStack stack, boolean simulate) { } public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean global) { - Iterator> routePaths = net.getPaths(pipe); + Iterator> routePaths = net.getPaths(pipe); if (!routePaths.hasNext()) return stack; - List> routePathsCopy = new ObjectArrayList<>(); + List> routePathsCopy = new ObjectArrayList<>(); routePaths.forEachRemaining(routePathsCopy::add); if (global) { @@ -151,19 +151,19 @@ public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean glo * @param simulate simulate * @return remainder */ - private ItemStack insertToHandlers(List> copy, ItemStack stack, + private ItemStack insertToHandlers(List> copy, ItemStack stack, boolean simulate) { - Iterator> routePathIterator = copy.listIterator(); + Iterator> routePathIterator = copy.listIterator(); int inserted = 0; int count = stack.getCount(); int c = count / copy.size(); int m = c == 0 ? count % copy.size() : 0; mainloop: while (routePathIterator.hasNext()) { - NetPath routePath = routePathIterator.next(); + PipeNetPath routePath = routePathIterator.next(); Iterator iterator = routePath.getFacingIterator(); while (iterator.hasNext()) { - NetPath.FacedNetPath facedNetPath = routePath + PipeNetPath.FacedPipeNetPath facedPipeNetPath = routePath .withFacing(iterator.next()); int amount = c; if (m > 0) { @@ -174,7 +174,7 @@ private ItemStack insertToHandlers(List> copy, + private ItemStack insertToHandlersEnhanced(List> copy, ItemStack stack, boolean simulate) { List transferred = new ArrayList<>(); IntList steps = new IntArrayList(); @@ -200,10 +200,10 @@ private ItemStack insertToHandlersEnhanced(List inv : copy) { + for (PipeNetPath inv : copy) { Iterator iterator = inv.getFacingIterator(); while (iterator.hasNext()) { - NetPath.FacedNetPath faceInv = inv + PipeNetPath.FacedPipeNetPath faceInv = inv .withFacing(iterator.next()); simStack = stack.copy(); int ins = stack.getCount() - insert(faceInv, simStack, true, true).getCount(); @@ -311,12 +311,12 @@ private ItemStack insertToHandlersEnhanced(List routePath, ItemStack stack, + public ItemStack insert(PipeNetPath.FacedPipeNetPath routePath, ItemStack stack, boolean simulate) { return insert(routePath, stack, simulate, false); } - public ItemStack insert(NetPath.FacedNetPath routePath, ItemStack stack, + public ItemStack insert(PipeNetPath.FacedPipeNetPath routePath, ItemStack stack, boolean simulate, boolean ignoreLimit) { if (routePath.getTargetNode().getNodePos() == this.pipe.getPos() && routePath.facing == this.facing) { return stack; @@ -468,7 +468,7 @@ public int getSlotLimit(int i) { return 64; } - private void transferTo(NetPath.FacedNetPath routePath, boolean simulate, + private void transferTo(PipeNetPath.FacedPipeNetPath routePath, boolean simulate, int amount) { if (simulate) simulatedTransfersGlobalRoundRobin.merge(routePath.toFacingPos(), amount, Integer::sum); @@ -476,13 +476,13 @@ private void transferTo(NetPath.FacedNetPath routePath, + private boolean contains(PipeNetPath.FacedPipeNetPath routePath, boolean simulate) { return simulate ? simulatedTransfersGlobalRoundRobin.containsKey(routePath.toFacingPos()) : pipe.getTransferred().containsKey(routePath.toFacingPos()); } - private int didTransferTo(NetPath.FacedNetPath routePath, + private int didTransferTo(PipeNetPath.FacedPipeNetPath routePath, boolean simulate) { if (simulate) return simulatedTransfersGlobalRoundRobin.getInt(routePath.toFacingPos()); @@ -504,12 +504,12 @@ private void decrementBy(int amount) { private static class EnhancedRoundRobinData { - private final NetPath.FacedNetPath routePath; + private final PipeNetPath.FacedPipeNetPath routePath; private final int maxInsertable; private int transferred; private int toTransfer = 0; - private EnhancedRoundRobinData(NetPath.FacedNetPath routePath, + private EnhancedRoundRobinData(PipeNetPath.FacedPipeNetPath routePath, int maxInsertable, int transferred) { this.maxInsertable = maxInsertable; this.transferred = transferred; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelikeold/itempipe/net/WorldItemPipeNet.java similarity index 88% rename from src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java rename to src/main/java/gregtech/common/pipelikeold/itempipe/net/WorldItemPipeNet.java index 84c62ae5e72..7fbd7688beb 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/net/WorldItemPipeNet.java @@ -1,17 +1,16 @@ -package gregtech.common.pipelike.itempipe.net; +package gregtech.common.pipelikeold.itempipe.net; import gregtech.api.cover.Cover; -import gregtech.api.pipenet.WorldPipeNetSimple; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.predicate.AbstractEdgePredicate; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.WorldPipeNetSimple; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.common.covers.CoverConveyor; import gregtech.common.covers.CoverItemFilter; import gregtech.common.covers.ItemFilterMode; import gregtech.common.covers.ManualImportExportMode; -import gregtech.common.pipelike.itempipe.ItemPipeType; -import gregtech.common.pipelike.itempipe.tile.TileEntityItemPipe; +import gregtech.common.pipelikeold.itempipe.ItemPipeType; +import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipe; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; @@ -47,7 +46,7 @@ protected Class> } @Override - protected AbstractEdgePredicate getPredicate(Cover thisCover, Cover neighbourCover) { + protected IEdgePredicateOld getPredicate(Cover thisCover, Cover neighbourCover) { ItemEdgePredicate predicate = new ItemEdgePredicate(); if (thisCover instanceof CoverItemFilter filter && filter.getFilterMode() != ItemFilterMode.FILTER_INSERT) { diff --git a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java b/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipe.java similarity index 90% rename from src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java rename to src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipe.java index 78abaa5271c..86a9548066c 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipe.java @@ -1,13 +1,13 @@ -package gregtech.common.pipelike.itempipe.tile; +package gregtech.common.pipelikeold.itempipe.tile; -import gregtech.api.pipenet.block.material.TileEntityMaterialPipeBase; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.util.FacingPos; -import gregtech.common.pipelike.itempipe.ItemPipeType; -import gregtech.common.pipelike.itempipe.net.ItemNetHandler; -import gregtech.common.pipelike.itempipe.net.WorldItemPipeNet; +import gregtech.common.pipelikeold.itempipe.ItemPipeType; +import gregtech.common.pipelikeold.itempipe.net.ItemNetHandler; +import gregtech.common.pipelikeold.itempipe.net.WorldItemPipeNet; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; diff --git a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipeTickable.java b/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipeTickable.java similarity index 85% rename from src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipeTickable.java rename to src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipeTickable.java index 90d7b64e101..8771867385f 100644 --- a/src/main/java/gregtech/common/pipelike/itempipe/tile/TileEntityItemPipeTickable.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipeTickable.java @@ -1,4 +1,4 @@ -package gregtech.common.pipelike.itempipe.tile; +package gregtech.common.pipelikeold.itempipe.tile; import net.minecraft.util.ITickable; diff --git a/src/main/java/gregtech/common/pipelike/laser/BlockLaserPipe.java b/src/main/java/gregtech/common/pipelikeold/laser/BlockLaserPipe.java similarity index 93% rename from src/main/java/gregtech/common/pipelike/laser/BlockLaserPipe.java rename to src/main/java/gregtech/common/pipelikeold/laser/BlockLaserPipe.java index 855bff71cad..93342f9a892 100644 --- a/src/main/java/gregtech/common/pipelike/laser/BlockLaserPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/laser/BlockLaserPipe.java @@ -1,17 +1,17 @@ -package gregtech.common.pipelike.laser; +package gregtech.common.pipelikeold.laser; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.client.renderer.pipe.LaserPipeRenderer; import gregtech.client.utils.BloomEffectUtil; import gregtech.common.creativetab.GTCreativeTabs; -import gregtech.common.pipelike.laser.net.WorldLaserPipeNet; -import gregtech.common.pipelike.laser.tile.TileEntityLaserPipe; +import gregtech.common.pipelikeold.laser.net.WorldLaserPipeNet; +import gregtech.common.pipelikeold.laser.tile.TileEntityLaserPipe; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; diff --git a/src/main/java/gregtech/common/pipelike/laser/ItemBlockLaserPipe.java b/src/main/java/gregtech/common/pipelikeold/laser/ItemBlockLaserPipe.java similarity index 84% rename from src/main/java/gregtech/common/pipelike/laser/ItemBlockLaserPipe.java rename to src/main/java/gregtech/common/pipelikeold/laser/ItemBlockLaserPipe.java index 3f1faaf893a..d265c7b7bf3 100644 --- a/src/main/java/gregtech/common/pipelike/laser/ItemBlockLaserPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/laser/ItemBlockLaserPipe.java @@ -1,8 +1,8 @@ -package gregtech.common.pipelike.laser; +package gregtech.common.pipelikeold.laser; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.block.ItemBlockPipe; -import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.block.ItemBlockPipe; +import gregtech.api.graphnet.edge.NetEdge; import gregtech.client.utils.TooltipHelper; import net.minecraft.client.resources.I18n; diff --git a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java b/src/main/java/gregtech/common/pipelikeold/laser/LaserPipeProperties.java similarity index 56% rename from src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java rename to src/main/java/gregtech/common/pipelikeold/laser/LaserPipeProperties.java index c5afafcb848..9aa983f2787 100644 --- a/src/main/java/gregtech/common/pipelike/laser/LaserPipeProperties.java +++ b/src/main/java/gregtech/common/pipelikeold/laser/LaserPipeProperties.java @@ -1,10 +1,10 @@ -package gregtech.common.pipelike.laser; +package gregtech.common.pipelikeold.laser; -import gregtech.api.pipenet.INodeData; +import gregtech.api.graphnet.pipenetold.IPipeNetData; import java.util.List; -public class LaserPipeProperties implements INodeData { +public class LaserPipeProperties implements IPipeNetData { public static final LaserPipeProperties INSTANCE = new LaserPipeProperties(); diff --git a/src/main/java/gregtech/common/pipelike/laser/LaserPipeType.java b/src/main/java/gregtech/common/pipelikeold/laser/LaserPipeType.java similarity index 83% rename from src/main/java/gregtech/common/pipelike/laser/LaserPipeType.java rename to src/main/java/gregtech/common/pipelikeold/laser/LaserPipeType.java index 13cf1398b9b..fba892a5ea8 100644 --- a/src/main/java/gregtech/common/pipelike/laser/LaserPipeType.java +++ b/src/main/java/gregtech/common/pipelikeold/laser/LaserPipeType.java @@ -1,6 +1,6 @@ -package gregtech.common.pipelike.laser; +package gregtech.common.pipelikeold.laser; -import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.graphnet.pipenetold.block.IPipeType; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java b/src/main/java/gregtech/common/pipelikeold/laser/net/LaserNetHandler.java similarity index 83% rename from src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java rename to src/main/java/gregtech/common/pipelikeold/laser/net/LaserNetHandler.java index b0f327e642a..15b5382714b 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/laser/net/LaserNetHandler.java @@ -1,15 +1,15 @@ -package gregtech.common.pipelike.laser.net; +package gregtech.common.pipelikeold.laser.net; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserContainer; -import gregtech.api.pipenet.IPipeNetHandler; -import gregtech.api.pipenet.NetGroup; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.common.pipelike.laser.LaserPipeProperties; -import gregtech.common.pipelike.laser.LaserPipeType; -import gregtech.common.pipelike.laser.tile.TileEntityLaserPipe; +import gregtech.api.graphnet.pipenetold.IPipeNetHandler; +import gregtech.api.graphnet.NetGroup; +import gregtech.api.graphnet.pipenetold.PipeNetNode; +import gregtech.api.graphnet.pipenetold.PipeNetPath; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.common.pipelikeold.laser.LaserPipeProperties; +import gregtech.common.pipelikeold.laser.LaserPipeType; +import gregtech.common.pipelikeold.laser.tile.TileEntityLaserPipe; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; @@ -46,7 +46,7 @@ private void setPipesActive() { NetGroup group = getNet().getNode(this.pipe.getPipePos()) .getGroupSafe(); if (group != null) { - for (NetNode node : group.getNodes()) { + for (PipeNetNode node : group.getNodes()) { if (node.getHeldMTE() instanceof TileEntityLaserPipe laserPipe) { laserPipe.setActive(true, 100); } @@ -60,7 +60,7 @@ private ILaserContainer getInnerContainer() { return null; } - Iterator> data = net.getPaths(this.pipe); + Iterator> data = net.getPaths(this.pipe); if (data == null || !data.hasNext()) return null; Map connecteds = data.next().getTargetTEs(); if (data.hasNext()) return null; diff --git a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java b/src/main/java/gregtech/common/pipelikeold/laser/net/WorldLaserPipeNet.java similarity index 79% rename from src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java rename to src/main/java/gregtech/common/pipelikeold/laser/net/WorldLaserPipeNet.java index c7172679809..bdf8c87832f 100644 --- a/src/main/java/gregtech/common/pipelike/laser/net/WorldLaserPipeNet.java +++ b/src/main/java/gregtech/common/pipelikeold/laser/net/WorldLaserPipeNet.java @@ -1,12 +1,12 @@ -package gregtech.common.pipelike.laser.net; +package gregtech.common.pipelikeold.laser.net; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.pipenet.WorldPipeNetSimple; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.common.pipelike.laser.LaserPipeProperties; -import gregtech.common.pipelike.laser.LaserPipeType; -import gregtech.common.pipelike.laser.tile.TileEntityLaserPipe; +import gregtech.api.graphnet.pipenetold.WorldPipeNetSimple; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.common.pipelikeold.laser.LaserPipeProperties; +import gregtech.common.pipelikeold.laser.LaserPipeType; +import gregtech.common.pipelikeold.laser.tile.TileEntityLaserPipe; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; diff --git a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java b/src/main/java/gregtech/common/pipelikeold/laser/tile/TileEntityLaserPipe.java similarity index 94% rename from src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java rename to src/main/java/gregtech/common/pipelikeold/laser/tile/TileEntityLaserPipe.java index 89d597893c1..15275d1b9b3 100644 --- a/src/main/java/gregtech/common/pipelike/laser/tile/TileEntityLaserPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/laser/tile/TileEntityLaserPipe.java @@ -1,16 +1,16 @@ -package gregtech.common.pipelike.laser.tile; +package gregtech.common.pipelikeold.laser.tile; import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserContainer; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.util.TaskScheduler; -import gregtech.common.pipelike.laser.LaserPipeProperties; -import gregtech.common.pipelike.laser.LaserPipeType; -import gregtech.common.pipelike.laser.net.LaserNetHandler; -import gregtech.common.pipelike.laser.net.WorldLaserPipeNet; +import gregtech.common.pipelikeold.laser.LaserPipeProperties; +import gregtech.common.pipelikeold.laser.LaserPipeType; +import gregtech.common.pipelikeold.laser.net.LaserNetHandler; +import gregtech.common.pipelikeold.laser.net.WorldLaserPipeNet; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; diff --git a/src/main/java/gregtech/common/pipelike/optical/BlockOpticalPipe.java b/src/main/java/gregtech/common/pipelikeold/optical/BlockOpticalPipe.java similarity index 92% rename from src/main/java/gregtech/common/pipelike/optical/BlockOpticalPipe.java rename to src/main/java/gregtech/common/pipelikeold/optical/BlockOpticalPipe.java index d87803e3f9f..8dc1f64b2c3 100644 --- a/src/main/java/gregtech/common/pipelike/optical/BlockOpticalPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/optical/BlockOpticalPipe.java @@ -1,16 +1,16 @@ -package gregtech.common.pipelike.optical; +package gregtech.common.pipelikeold.optical; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.client.renderer.pipe.OpticalPipeRenderer; import gregtech.common.creativetab.GTCreativeTabs; -import gregtech.common.pipelike.optical.net.WorldOpticalPipeNet; -import gregtech.common.pipelike.optical.tile.TileEntityOpticalPipe; +import gregtech.common.pipelikeold.optical.net.WorldOpticalPipeNet; +import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; diff --git a/src/main/java/gregtech/common/pipelike/optical/ItemBlockOpticalPipe.java b/src/main/java/gregtech/common/pipelikeold/optical/ItemBlockOpticalPipe.java similarity index 90% rename from src/main/java/gregtech/common/pipelike/optical/ItemBlockOpticalPipe.java rename to src/main/java/gregtech/common/pipelikeold/optical/ItemBlockOpticalPipe.java index 9269423dedd..ca3be9c45ac 100644 --- a/src/main/java/gregtech/common/pipelike/optical/ItemBlockOpticalPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/optical/ItemBlockOpticalPipe.java @@ -1,6 +1,6 @@ -package gregtech.common.pipelike.optical; +package gregtech.common.pipelikeold.optical; -import gregtech.api.pipenet.block.ItemBlockPipe; +import gregtech.api.graphnet.pipenetold.block.ItemBlockPipe; import gregtech.client.utils.TooltipHelper; import net.minecraft.client.resources.I18n; diff --git a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java b/src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeProperties.java similarity index 56% rename from src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java rename to src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeProperties.java index b123135f018..9f61ce9247c 100644 --- a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeProperties.java +++ b/src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeProperties.java @@ -1,10 +1,10 @@ -package gregtech.common.pipelike.optical; +package gregtech.common.pipelikeold.optical; -import gregtech.api.pipenet.INodeData; +import gregtech.api.graphnet.pipenetold.IPipeNetData; import java.util.List; -public class OpticalPipeProperties implements INodeData { +public class OpticalPipeProperties implements IPipeNetData { public static final OpticalPipeProperties INSTANCE = new OpticalPipeProperties(); diff --git a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeType.java b/src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeType.java similarity index 83% rename from src/main/java/gregtech/common/pipelike/optical/OpticalPipeType.java rename to src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeType.java index 18f02a3530c..cf0c9958221 100644 --- a/src/main/java/gregtech/common/pipelike/optical/OpticalPipeType.java +++ b/src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeType.java @@ -1,6 +1,6 @@ -package gregtech.common.pipelike.optical; +package gregtech.common.pipelikeold.optical; -import gregtech.api.pipenet.block.IPipeType; +import gregtech.api.graphnet.pipenetold.block.IPipeType; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelikeold/optical/net/OpticalNetHandler.java similarity index 86% rename from src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java rename to src/main/java/gregtech/common/pipelikeold/optical/net/OpticalNetHandler.java index 1b25fbab57a..22fc06a8275 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/optical/net/OpticalNetHandler.java @@ -1,18 +1,18 @@ -package gregtech.common.pipelike.optical.net; +package gregtech.common.pipelikeold.optical.net; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IDataAccessHatch; import gregtech.api.capability.IOpticalComputationProvider; import gregtech.api.capability.IOpticalDataAccessHatch; -import gregtech.api.pipenet.IPipeNetHandler; -import gregtech.api.pipenet.NetGroup; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.NetPath; -import gregtech.api.pipenet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.IPipeNetHandler; +import gregtech.api.graphnet.NetGroup; +import gregtech.api.graphnet.pipenetold.PipeNetNode; +import gregtech.api.graphnet.pipenetold.PipeNetPath; +import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.recipes.Recipe; -import gregtech.common.pipelike.optical.OpticalPipeProperties; -import gregtech.common.pipelike.optical.OpticalPipeType; -import gregtech.common.pipelike.optical.tile.TileEntityOpticalPipe; +import gregtech.common.pipelikeold.optical.OpticalPipeProperties; +import gregtech.common.pipelikeold.optical.OpticalPipeType; +import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; @@ -81,7 +81,7 @@ private void setPipesActive() { NetGroup group = getNet().getNode(this.pipe.getPipePos()) .getGroupSafe(); if (group != null) { - for (NetNode node : group.getNodes()) { + for (PipeNetNode node : group.getNodes()) { if (node.getHeldMTE() instanceof TileEntityOpticalPipe opticalPipe) { opticalPipe.setActive(true, 100); } @@ -96,7 +96,7 @@ private boolean isNetInvalidForTraversal() { private boolean traverseRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { if (isNetInvalidForTraversal()) return false; - Iterator> inv = net.getPaths(this.pipe); + Iterator> inv = net.getPaths(this.pipe); if (inv == null || !inv.hasNext()) return false; Map connecteds = inv.next().getTargetTEs(); if (inv.hasNext()) return false; @@ -135,7 +135,7 @@ private boolean traverseCanBridge(@NotNull Collection seen) { if (isNetInvalidForTraversal()) return null; - Iterator> inv = net.getPaths(this.pipe); + Iterator> inv = net.getPaths(this.pipe); if (inv == null || !inv.hasNext()) return null; Map connecteds = inv.next().getTargetTEs(); if (inv.hasNext()) return null; diff --git a/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java b/src/main/java/gregtech/common/pipelikeold/optical/net/WorldOpticalPipeNet.java similarity index 79% rename from src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java rename to src/main/java/gregtech/common/pipelikeold/optical/net/WorldOpticalPipeNet.java index 38424ad1aeb..d3026f83050 100644 --- a/src/main/java/gregtech/common/pipelike/optical/net/WorldOpticalPipeNet.java +++ b/src/main/java/gregtech/common/pipelikeold/optical/net/WorldOpticalPipeNet.java @@ -1,12 +1,12 @@ -package gregtech.common.pipelike.optical.net; +package gregtech.common.pipelikeold.optical.net; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.pipenet.WorldPipeNetSimple; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.common.pipelike.optical.OpticalPipeProperties; -import gregtech.common.pipelike.optical.OpticalPipeType; -import gregtech.common.pipelike.optical.tile.TileEntityOpticalPipe; +import gregtech.api.graphnet.pipenetold.WorldPipeNetSimple; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.common.pipelikeold.optical.OpticalPipeProperties; +import gregtech.common.pipelikeold.optical.OpticalPipeType; +import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; diff --git a/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java b/src/main/java/gregtech/common/pipelikeold/optical/tile/TileEntityOpticalPipe.java similarity index 93% rename from src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java rename to src/main/java/gregtech/common/pipelikeold/optical/tile/TileEntityOpticalPipe.java index 445166738d1..494caefe1b6 100644 --- a/src/main/java/gregtech/common/pipelike/optical/tile/TileEntityOpticalPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/optical/tile/TileEntityOpticalPipe.java @@ -1,18 +1,18 @@ -package gregtech.common.pipelike.optical.tile; +package gregtech.common.pipelikeold.optical.tile; import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IDataAccessHatch; import gregtech.api.capability.IOpticalComputationProvider; -import gregtech.api.pipenet.edge.NetEdge; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.recipes.Recipe; import gregtech.api.util.TaskScheduler; -import gregtech.common.pipelike.optical.OpticalPipeProperties; -import gregtech.common.pipelike.optical.OpticalPipeType; -import gregtech.common.pipelike.optical.net.OpticalNetHandler; -import gregtech.common.pipelike.optical.net.WorldOpticalPipeNet; +import gregtech.common.pipelikeold.optical.OpticalPipeProperties; +import gregtech.common.pipelikeold.optical.OpticalPipeType; +import gregtech.common.pipelikeold.optical.net.OpticalNetHandler; +import gregtech.common.pipelikeold.optical.net.WorldOpticalPipeNet; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; diff --git a/src/main/java/gregtech/integration/RecipeCompatUtil.java b/src/main/java/gregtech/integration/RecipeCompatUtil.java index e18d156a004..a20e9965e2f 100644 --- a/src/main/java/gregtech/integration/RecipeCompatUtil.java +++ b/src/main/java/gregtech/integration/RecipeCompatUtil.java @@ -5,7 +5,7 @@ import gregtech.api.block.machines.MachineItemBlock; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.pipenet.block.material.BlockMaterialPipe; +import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; import gregtech.api.util.GTUtility; diff --git a/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java b/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java index c47733d6a0c..ddaab23ccdc 100644 --- a/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java +++ b/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java @@ -8,9 +8,9 @@ import gregtech.common.blocks.BlockCompressed; import gregtech.common.blocks.BlockFrame; import gregtech.common.blocks.MetaBlocks; -import gregtech.common.pipelike.cable.BlockCable; -import gregtech.common.pipelike.fluidpipe.BlockFluidPipe; -import gregtech.common.pipelike.itempipe.BlockItemPipe; +import gregtech.common.pipelikeold.cable.BlockCable; +import gregtech.common.pipelikeold.fluidpipe.BlockFluidPipe; +import gregtech.common.pipelikeold.itempipe.BlockItemPipe; import gregtech.integration.groovy.GroovyScriptModule; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java index ab61bfb9e0a..53ae11ccf4d 100644 --- a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java +++ b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java @@ -20,9 +20,9 @@ import gregtech.common.blocks.BlockCompressed; import gregtech.common.blocks.BlockFrame; import gregtech.common.blocks.MetaBlocks; -import gregtech.common.pipelike.cable.BlockCable; -import gregtech.common.pipelike.fluidpipe.BlockFluidPipe; -import gregtech.common.pipelike.itempipe.BlockItemPipe; +import gregtech.common.pipelikeold.cable.BlockCable; +import gregtech.common.pipelikeold.fluidpipe.BlockFluidPipe; +import gregtech.common.pipelikeold.itempipe.BlockItemPipe; import gregtech.integration.IntegrationSubmodule; import gregtech.modules.GregTechModules; diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java index 0ee16199774..a5c9a83c64b 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java @@ -3,8 +3,8 @@ import gregtech.api.GTValues; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.pipenet.longdist.ILDEndpoint; -import gregtech.api.pipenet.longdist.LongDistanceNetwork; +import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; +import gregtech.api.graphnet.pipenetold.longdist.LongDistanceNetwork; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java index f6c34615e96..e1150fc9fcf 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java @@ -1,12 +1,12 @@ package gregtech.integration.theoneprobe.provider.debug; +import gregtech.api.graphnet.pipenetold.PipeNetNode; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.pipenet.NetNode; -import gregtech.api.pipenet.WorldPipeNetBase; -import gregtech.api.pipenet.block.BlockPipe; -import gregtech.api.pipenet.tile.IPipeTile; -import gregtech.api.pipenet.tile.TileEntityPipeBase; +import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenetold.tile.IPipeTile; +import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.common.ConfigHolder; import net.minecraft.block.state.IBlockState; @@ -50,9 +50,9 @@ public void addProbeInfo(@NotNull ProbeMode mode, @NotNull IProbeInfo probeInfo, WorldPipeNetBase pipeNet = blockPipe.getWorldPipeNet(world); if (pipeNet != null) { probeInfo.text("Net: " + pipeNet.hashCode()); - probeInfo.text("NetNode Info: "); + probeInfo.text("WorldPipeNetNode Info: "); StringBuilder builder = new StringBuilder(); - NetNode node = pipeNet.getNode(data.getPos()); + PipeNetNode node = pipeNet.getNode(data.getPos()); if (node != null) { builder.append("{") .append("active: ").append(node.isActive) From 59309cb092620e5422fa98a7c608514088aaf759 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 12 Jul 2024 21:42:41 -0600 Subject: [PATCH 075/157] Complete rewrite pt2 --- .../api/capability/GregtechDataCodes.java | 3 +- .../api/graphnet/AbstractGroupData.java | 4 +- .../gregtech/api/graphnet/GraphNetBacker.java | 9 +- .../java/gregtech/api/graphnet/IGraphNet.java | 10 +- .../api/graphnet/alg/NetAlgorithmWrapper.java | 7 +- .../graphnet/edge/AbstractNetFlowEdge.java | 15 +- .../api/graphnet/edge/SimulatorKey.java | 1 - .../api/graphnet/edge/util/FlowConsumer.java | 61 ++- .../graphnet/edge/util/FlowConsumerList.java | 58 ++- .../graphnet/gather/GTGraphGatherables.java | 23 +- .../graphnet/gather/GatherLogicsEvent.java | 4 +- .../gather/GatherMaterialStructuresEvent.java | 24 + .../api/graphnet/graph/INetGraph.java | 4 +- .../api/graphnet/graph/NetDirectedGraph.java | 16 +- .../graphnet/graph/NetUndirectedGraph.java | 16 +- .../logic/AbstractDoubleLogicData.java | 22 +- .../graphnet/logic/AbstractIntLogicData.java | 21 +- .../graphnet/logic/AbstractLongLogicData.java | 46 ++ .../api/graphnet/logic/ChannelCountLogic.java | 9 +- .../api/graphnet/logic/INetLogicEntry.java | 41 +- .../api/graphnet/logic/LossAbsoluteLogic.java | 20 - .../graphnet/logic/MultiNetCountLogic.java | 9 +- .../api/graphnet/logic/NetLogicData.java | 87 +++- .../api/graphnet/logic/TemperatureLogic.java | 232 +++++++++ .../logic/TemperatureRestorationFunction.java | 98 ++++ .../api/graphnet/logic/ThroughputLogic.java | 13 +- .../api/graphnet/logic/WeightFactorLogic.java | 11 +- .../api/graphnet/path/AbstractNetPath.java | 40 ++ .../graphnet/path/GenericGraphNetPath.java | 9 + .../gregtech/api/graphnet/path/INetPath.java | 8 + .../pipenet/BasicWorldPipeNetPath.java | 9 + .../pipenet/FlowWorldPipeNetPath.java | 9 + .../graphnet/pipenet/IPipeNetNodeHandler.java | 8 +- .../api/graphnet/pipenet/NodeLossResult.java | 33 ++ .../api/graphnet/pipenet/WorldPipeNet.java | 14 + .../graphnet/pipenet/WorldPipeNetNode.java | 6 + .../pipenet/block/CableStructure.java | 11 - .../pipenet/block/IPipeStructure.java | 6 - .../api/graphnet/pipenet/block/PipeBlock.java | 96 ---- .../graphnet/pipenet/physical/IBurnable.java | 22 + .../physical/IPipeCapabilityObject.java | 14 + .../physical/IPipeMaterialStructure.java | 8 + .../pipenet/physical/IPipeStructure.java | 16 + .../pipenet/physical/ItemPipeBlock.java | 38 ++ .../graphnet/pipenet/physical/PipeBlock.java | 218 +++++++++ .../physical/PipeCapabilityWrapper.java | 28 ++ .../pipenet/physical/PipeCoverHolder.java | 306 ++++++++++++ .../PipeMaterialBlock.java | 95 +++- .../pipenet/physical/PipeTileEntity.java | 448 ++++++++++++++++++ .../pipenetold/tile/TileEntityPipeBase.java | 4 +- .../predicate/test/IPredicateTestObject.java | 1 + .../traverse/AbstractTraverseData.java | 44 ++ .../api/graphnet/traverse/ITraverseData.java | 47 ++ .../graphnet/traverse/TraverseHelpers.java | 149 ++++++ .../api/graphnet/worldnet/WorldNet.java | 11 +- .../properties/PipeNetProperties.java | 34 +- .../blocks/properties/PropertyShort.java | 91 ++++ .../pipelike/block/CableEnergyProperties.java | 58 --- .../pipelike/block/PipeFluidProperties.java | 4 - .../pipelike/block/PipeItemProperties.java | 4 - .../pipelike/block/cable/CableBlock.java | 48 ++ .../block/cable/CableEnergyProperties.java | 139 ++++++ .../pipelike/block/cable/CableStructure.java | 63 +++ .../block/pipe/PipeFluidProperties.java | 4 + .../block/pipe/PipeItemProperties.java | 4 + .../common/pipelike/net/EnergyNet.java | 42 -- .../net/energy/EnergyCapabilityObject.java | 171 +++++++ .../net/energy/EnergyTraverseData.java | 152 ++++++ .../net/energy/LossAbsoluteLogic.java | 28 ++ .../net/energy/SuperconductorLogic.java | 24 + .../net/energy/VoltageLimitLogic.java | 28 ++ .../pipelike/net/energy/WorldEnergyNet.java | 64 +++ .../java/gregtech/common/pipelike/temp.java | 4 - .../cable/net/EnergyGroupData.java | 19 +- .../cable/net/EnergyNetHandler.java | 2 +- .../fluidpipe/net/FluidNetHandler.java | 2 +- 76 files changed, 3160 insertions(+), 387 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/gather/GatherMaterialStructuresEvent.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java delete mode 100644 src/main/java/gregtech/api/graphnet/logic/LossAbsoluteLogic.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/TemperatureLogic.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/TemperatureRestorationFunction.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/block/CableStructure.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/block/IPipeStructure.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/block/PipeBlock.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeMaterialStructure.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/ItemPipeBlock.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/PipeBlock.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCapabilityWrapper.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCoverHolder.java rename src/main/java/gregtech/api/graphnet/pipenet/{block => physical}/PipeMaterialBlock.java (54%) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/PipeTileEntity.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java create mode 100644 src/main/java/gregtech/common/blocks/properties/PropertyShort.java delete mode 100644 src/main/java/gregtech/common/pipelike/block/CableEnergyProperties.java delete mode 100644 src/main/java/gregtech/common/pipelike/block/PipeFluidProperties.java delete mode 100644 src/main/java/gregtech/common/pipelike/block/PipeItemProperties.java create mode 100644 src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java create mode 100644 src/main/java/gregtech/common/pipelike/block/cable/CableEnergyProperties.java create mode 100644 src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java create mode 100644 src/main/java/gregtech/common/pipelike/block/pipe/PipeFluidProperties.java create mode 100644 src/main/java/gregtech/common/pipelike/block/pipe/PipeItemProperties.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/EnergyNet.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/LossAbsoluteLogic.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java delete mode 100644 src/main/java/gregtech/common/pipelike/temp.java diff --git a/src/main/java/gregtech/api/capability/GregtechDataCodes.java b/src/main/java/gregtech/api/capability/GregtechDataCodes.java index 225e12e4f74..38a459c13f6 100644 --- a/src/main/java/gregtech/api/capability/GregtechDataCodes.java +++ b/src/main/java/gregtech/api/capability/GregtechDataCodes.java @@ -58,7 +58,7 @@ public static int assignId() { public static final int UPDATE_FACADE_STACK = assignId(); // Pipe implementation update codes - public static final int UPDATE_INSULATION_COLOR = assignId(); + public static final int UPDATE_PAINT = assignId(); public static final int UPDATE_CONNECTIONS = assignId(); public static final int SYNC_COVER_IMPLEMENTATION = assignId(); public static final int UPDATE_PIPE_TYPE = assignId(); @@ -71,6 +71,7 @@ public static int assignId() { public static final int PIPE_OPTICAL_ACTIVE = assignId(); public static final int PIPE_LASER_ACTIVE = assignId(); public static final int CABLE_TEMPERATURE = assignId(); + public static final int UPDATE_PIPE_LOGIC = assignId(); // Multiblock implementation update codes public static final int SYNC_CONTROLLER = assignId(); diff --git a/src/main/java/gregtech/api/graphnet/AbstractGroupData.java b/src/main/java/gregtech/api/graphnet/AbstractGroupData.java index 4a798ad8257..4cb51981b7c 100644 --- a/src/main/java/gregtech/api/graphnet/AbstractGroupData.java +++ b/src/main/java/gregtech/api/graphnet/AbstractGroupData.java @@ -2,9 +2,9 @@ public abstract class AbstractGroupData { - protected NetGroup group; + protected NetGroup group; - public void withGroup(NetGroup group) { + public void withGroup(NetGroup group) { this.group = group; } } diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index 7b566c7b377..fb58301b781 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -5,6 +5,7 @@ import gregtech.api.graphnet.alg.NetPathMapper; import gregtech.api.graphnet.alg.iter.ICacheableIterator; import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.INetGraph; @@ -12,6 +13,8 @@ import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -104,7 +107,7 @@ public void removeEdge(GraphEdge edge) { } public boolean dynamicWeights() { - return netAlgorithm.supportsDynamicWeights(); + return netAlgorithm.getNet().usesDynamicWeights() && netAlgorithm.supportsDynamicWeights(); } /** @@ -112,13 +115,13 @@ public boolean dynamicWeights() { * most likely a bad remapper was passed in.
* This method should never be exposed outside the net this backer is backing due to this fragility. */ - public > Iterator getPaths(@Nullable NetNode node, @NotNull NetPathMapper remapper) { + public > Iterator getPaths(@Nullable NetNode node, @NotNull NetPathMapper remapper, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { if (node == null) return Collections.emptyIterator(); Iterator> cache = node.getPathCache(); if (cache != null) return (Iterator) cache; - Iterator iter = this.netAlgorithm.getPathsIterator(node.wrapper, remapper); + Iterator iter = this.netAlgorithm.getPathsIterator(node.wrapper, remapper, testObject, simulator, queryTick); if (iter instanceof ICacheableIterator) { return (Iterator) node.setPathCache((ICacheableIterator) iter); } else return iter; diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index 632ca6ae617..d7b9a6c43d2 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -22,6 +22,14 @@ public interface IGraphNet { + /** + * Controls whether dynamic weight lookup will be used. + * If the algorithm does not support dynamic weights, this will be ignored. + */ + default boolean usesDynamicWeights() { + return true; + } + /** * Adds a node to the graphnet. * @param node The node to add. @@ -103,7 +111,7 @@ default AbstractGroupData getBlankGroupData() { */ @NotNull default NetLogicData getDefaultNodeData() { - return new NetLogicData().setLogicEntry(new WeightFactorLogic().setValue(1)); + return new NetLogicData().setLogicEntry(WeightFactorLogic.INSTANCE.getWith(1)); } /** diff --git a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java index 34876bd5da8..876fa011e29 100644 --- a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java +++ b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java @@ -1,9 +1,12 @@ package gregtech.api.graphnet.alg; import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.path.INetPath; import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,8 +40,8 @@ public boolean supportsDynamicWeights() { return alg.supportsDynamicWeights(); } - public > Iterator getPathsIterator(GraphVertex source, NetPathMapper remapper) { - net.getGraph().setQueryTick(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); + public > Iterator getPathsIterator(GraphVertex source, NetPathMapper remapper, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + net.getGraph().prepareForAlgorithmRun(testObject, simulator, queryTick); if (alg == null) alg = builder.apply(net); return alg.getPathsIterator(source, remapper); } diff --git a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java index 550562cfba0..d0a4b16fb94 100644 --- a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java @@ -32,7 +32,8 @@ public double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simula } public boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick, @Nullable SimulatorKey simulator) { - return getChannels(simulator).cannotSupportChannel(channel, queryTick); + if (!this.test(channel)) return false; + else return getChannels(simulator).cannotSupportChannel(channel, queryTick); } protected AbstractChannelsHolder getChannels(@Nullable SimulatorKey simulator) { @@ -51,20 +52,24 @@ protected int getChannelCount() { return getData().getLogicEntryDefaultable(ChannelCountLogic.INSTANCE).getValue(); } - protected int getThroughput() { + protected long getThroughput() { return getData().getLogicEntryDefaultable(ThroughputLogic.INSTANCE).getValue(); } public long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick, @Nullable SimulatorKey simulator) { - return getChannels(simulator).getFlowLimit(channel, graph, queryTick); + if (!this.test(channel)) return 0; + else return getChannels(simulator).getFlowLimit(channel, graph, queryTick); } public long getConsumedLimit(IPredicateTestObject channel, long queryTick, @Nullable SimulatorKey simulator) { - return getChannels(simulator).getConsumedLimit(channel, queryTick); + if (!this.test(channel)) return 0; + else return getChannels(simulator).getConsumedLimit(channel, queryTick); } public void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick, @Nullable SimulatorKey simulator) { - getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); + if (this.test(channel)) { + getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); + } } public Set getActiveChannels(@Nullable SimulatorKey simulator, long queryTick) { diff --git a/src/main/java/gregtech/api/graphnet/edge/SimulatorKey.java b/src/main/java/gregtech/api/graphnet/edge/SimulatorKey.java index bc3879b4a9b..6d14d29849f 100644 --- a/src/main/java/gregtech/api/graphnet/edge/SimulatorKey.java +++ b/src/main/java/gregtech/api/graphnet/edge/SimulatorKey.java @@ -20,7 +20,6 @@ public static SimulatorKey getNewSimulatorInstance() { @Override public int hashCode() { - // enforcing hash uniqueness improves weak map performance return id; } } diff --git a/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumer.java b/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumer.java index 1566d8eb72b..35189c5bdd9 100644 --- a/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumer.java +++ b/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumer.java @@ -1,35 +1,30 @@ package gregtech.api.graphnet.edge.util; -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.PipeNetNode; -import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.predicate.test.FluidTestObject; -import org.jgrapht.Graph; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import java.util.function.Consumer; +import java.util.function.UnaryOperator; -public class FlowConsumer & IPipeType, NDT extends IPipeNetData, - E extends AbstractNetFlowEdge> implements Consumer { +public class FlowConsumer { - private final E edge; - private final FluidTestObject testObject; - private final Graph, E> graph; - private final long flow; + private final AbstractNetFlowEdge edge; + private final IPredicateTestObject testObject; + private final IGraphNet graph; + private double flow; private final long tick; private final SimulatorKey simulatorKey; private final Consumer extra; - private double ratio = 1; - - public FlowConsumer(E edge, FluidTestObject testObject, Graph, E> graph, long flow, + public FlowConsumer(AbstractNetFlowEdge edge, IPredicateTestObject testObject, IGraphNet graph, long flow, long tick, SimulatorKey simulatorKey) { this(edge, testObject, graph, flow, tick, simulatorKey, null); } - public FlowConsumer(E edge, FluidTestObject testObject, Graph, E> graph, long flow, + public FlowConsumer(AbstractNetFlowEdge edge, IPredicateTestObject testObject, IGraphNet graph, long flow, long tick, SimulatorKey simulatorKey, Consumer extra) { this.edge = edge; this.testObject = testObject; @@ -41,13 +36,37 @@ public FlowConsumer(E edge, FluidTestObject testObject, Graph modification) { + this.flow = modification.apply(this.flow); + } + + public void finalRatio(Double finalRatio) { + modifyRatio(finalRatio); + consume(); + } + + public void finalReduction(Long finalReduction) { + modifyReduction(finalReduction); + consume(); + } + + public void finalArbitrary(UnaryOperator modification) { + modifyArbitrary(modification); + consume(); } - @Override - public void accept(Double finalRatio) { - long consumption = (long) (finalRatio * ratio * flow); - edge.consumeFlowLimit(testObject, graph, consumption, tick, simulatorKey); - if (extra != null) extra.accept(consumption); + public void consume() { + long consumption = (long) Math.ceil(this.flow); + if (consumption > 0) { + edge.consumeFlowLimit(testObject, graph, consumption, tick, simulatorKey); + if (extra != null) extra.accept(consumption); + } } } diff --git a/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumerList.java b/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumerList.java index 40bedc403b2..51fa3f926f1 100644 --- a/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumerList.java +++ b/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumerList.java @@ -1,39 +1,67 @@ package gregtech.api.graphnet.edge.util; -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.PipeNetNode; -import gregtech.api.graphnet.pipenetold.block.IPipeType; +import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.predicate.test.FluidTestObject; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jgrapht.Graph; import java.util.function.Consumer; +import java.util.function.UnaryOperator; -public class FlowConsumerList & IPipeType, NDT extends IPipeNetData, - E extends AbstractNetFlowEdge> extends ObjectArrayList> { +public class FlowConsumerList extends ObjectArrayList { - public void add(E edge, FluidTestObject testObject, Graph, E> graph, long flow, + public void add(AbstractNetFlowEdge edge, IPredicateTestObject testObject, IGraphNet graph, long flow, long tick, SimulatorKey simulatorKey) { - this.add(new FlowConsumer<>(edge, testObject, graph, flow, tick, simulatorKey)); + this.add(new FlowConsumer(edge, testObject, graph, flow, tick, simulatorKey)); } - public void add(E edge, FluidTestObject testObject, Graph, E> graph, long flow, + public void add(AbstractNetFlowEdge edge, IPredicateTestObject testObject, IGraphNet graph, long flow, long tick, SimulatorKey simulatorKey, Consumer extra) { - this.add(new FlowConsumer<>(edge, testObject, graph, flow, tick, simulatorKey, extra)); + this.add(new FlowConsumer(edge, testObject, graph, flow, tick, simulatorKey, extra)); } public void modifyRatios(double ratio) { - for (FlowConsumer consumer : this) { + for (FlowConsumer consumer : this) { consumer.modifyRatio(ratio); } } - public void doConsumption(double ratio) { - for (FlowConsumer consumer : this) { - consumer.accept(ratio); + public void modifyReductions(long reduction) { + for (FlowConsumer consumer : this) { + consumer.modifyReduction(reduction); + } + } + + public void modifyArbitrary(UnaryOperator modifier) { + for (FlowConsumer consumer : this) { + consumer.modifyArbitrary(modifier); + } + } + + public void doConsumption(double finalRatio) { + for (FlowConsumer consumer : this) { + consumer.finalRatio(finalRatio); + } + } + + public void doConsumption(long finalReduction) { + for (FlowConsumer consumer : this) { + consumer.finalReduction(finalReduction); + } + } + + public void doConsumption(UnaryOperator finalModifier) { + for (FlowConsumer consumer : this) { + consumer.finalArbitrary(finalModifier); + } + } + + public void doConsumption() { + for (FlowConsumer consumer : this) { + consumer.consume(); } } } diff --git a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java index 1f75dddf5cb..4ece50d3fec 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java +++ b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java @@ -3,13 +3,17 @@ import gregtech.api.GTValues; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.INetLogicEntry; -import gregtech.api.graphnet.logic.LossAbsoluteLogic; +import gregtech.api.graphnet.logic.TemperatureLogic; +import gregtech.common.pipelike.block.cable.CableStructure; +import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; import gregtech.api.graphnet.logic.MultiNetCountLogic; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.predicate.IEdgePredicate; +import gregtech.common.pipelike.net.energy.VoltageLimitLogic; + import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -47,10 +51,17 @@ public static void gatherPredicates(GatherPredicatesEvent event) { @SubscribeEvent public static void gatherLogics(GatherLogicsEvent event) { - event.registerSupplier(WeightFactorLogic.INSTANCE.getName(), WeightFactorLogic::new); - event.registerSupplier(ThroughputLogic.INSTANCE.getName(), ThroughputLogic::new); - event.registerSupplier(ChannelCountLogic.INSTANCE.getName(), ChannelCountLogic::new); - event.registerSupplier(MultiNetCountLogic.INSTANCE.getName(), MultiNetCountLogic::new); - event.registerSupplier(LossAbsoluteLogic.INSTANCE.getName(), LossAbsoluteLogic::new); + event.registerLogic(WeightFactorLogic.INSTANCE); + event.registerLogic(ThroughputLogic.INSTANCE); + event.registerLogic(ChannelCountLogic.INSTANCE); + event.registerLogic(MultiNetCountLogic.INSTANCE); + event.registerLogic(LossAbsoluteLogic.INSTANCE); + event.registerLogic(VoltageLimitLogic.INSTANCE); + event.registerLogic(TemperatureLogic.INSTANCE); + } + + @SubscribeEvent + public static void gatherMaterialStructures(GatherMaterialStructuresEvent event) { + CableStructure.registerDefaultStructures(event::registerMaterialStructure); } } diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java index 99f95da6f4e..d54042b0327 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java +++ b/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java @@ -15,7 +15,7 @@ public class GatherLogicsEvent extends Event { GatherLogicsEvent() {} - public void registerSupplier(String name, Supplier> supplier) { - gathered.put(name, supplier); + public void registerLogic(INetLogicEntry logic) { + gathered.put(logic.getName(), logic::getNew); } } diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherMaterialStructuresEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherMaterialStructuresEvent.java new file mode 100644 index 00000000000..c9ed5634b5e --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/gather/GatherMaterialStructuresEvent.java @@ -0,0 +1,24 @@ +package gregtech.api.graphnet.gather; + +import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraftforge.fml.common.eventhandler.Event; + +import java.util.Set; + +public class GatherMaterialStructuresEvent extends Event { + + final Set gathered = new ObjectOpenHashSet<>(); + + GatherMaterialStructuresEvent() {} + + public void registerMaterialStructure(IPipeMaterialStructure materialStructure) { + gathered.add(materialStructure); + } + + public Set getGathered() { + return gathered; + } +} diff --git a/src/main/java/gregtech/api/graphnet/graph/INetGraph.java b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java index 7c9bd4a8cad..8a244c5b277 100644 --- a/src/main/java/gregtech/api/graphnet/graph/INetGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java @@ -12,9 +12,7 @@ public interface INetGraph extends Graph { @ApiStatus.Internal void setOwningNet(GraphNetBacker net); - void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator); - - void setQueryTick(long queryTick); + void prepareForAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, long queryTick); boolean isDirected(); } diff --git a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java index fa3267af0d0..0a8ff118cc0 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java @@ -30,13 +30,9 @@ public void setOwningNet(GraphNetBacker net) { } @Override - public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator) { - if (!net.dynamicWeights()) throw new IllegalStateException("Net does not support dynamic weights!"); + public void prepareForAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, long queryTick) { this.testObject = testObject; this.simulator = simulator; - } - - public void setQueryTick(long queryTick) { this.queryTick = queryTick; } @@ -51,11 +47,11 @@ public double getEdgeWeight(GraphEdge graphEdge) { !graphEdge.getTarget().wrapped.traverse(queryTick, true)) return Double.POSITIVE_INFINITY; - if (net.dynamicWeights()) { - return graphEdge.wrapped.test(testObject) ? - graphEdge.wrapped.getDynamicWeight(testObject, simulator, queryTick, () -> super.getEdgeWeight(graphEdge)) : - Double.POSITIVE_INFINITY; - } else return super.getEdgeWeight(graphEdge); + if (graphEdge.wrapped.test(testObject)) { + if (net.dynamicWeights()) { + return graphEdge.wrapped.getDynamicWeight(testObject, simulator, queryTick, () -> super.getEdgeWeight(graphEdge)); + } else return super.getEdgeWeight(graphEdge); + } else return Double.POSITIVE_INFINITY; } public static Function standardBuilder() { diff --git a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java index 01dc3a63330..f0ecf7b4529 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java @@ -30,13 +30,9 @@ public void setOwningNet(GraphNetBacker net) { } @Override - public void prepareForDynamicWeightAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator) { - if (!net.dynamicWeights()) throw new IllegalStateException("Net does not support dynamic weights!"); + public void prepareForAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, long queryTick) { this.testObject = testObject; this.simulator = simulator; - } - - public void setQueryTick(long queryTick) { this.queryTick = queryTick; } @@ -51,11 +47,11 @@ public double getEdgeWeight(GraphEdge graphEdge) { !graphEdge.getTarget().wrapped.traverse(queryTick, true)) return Double.POSITIVE_INFINITY; - if (net.dynamicWeights()) { - return graphEdge.wrapped.test(testObject) ? - graphEdge.wrapped.getDynamicWeight(testObject, simulator, queryTick, () -> super.getEdgeWeight(graphEdge)) : - Double.POSITIVE_INFINITY; - } else return super.getEdgeWeight(graphEdge); + if (graphEdge.wrapped.test(testObject)) { + if (net.dynamicWeights()) { + return graphEdge.wrapped.getDynamicWeight(testObject, simulator, queryTick, () -> super.getEdgeWeight(graphEdge)); + } else return super.getEdgeWeight(graphEdge); + } else return Double.POSITIVE_INFINITY; } public static Function standardBuilder() { diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java index efc17ed1061..d285ac1d39a 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java @@ -1,17 +1,17 @@ package gregtech.api.graphnet.logic; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagDouble; -import net.minecraft.nbt.NBTTagInt; - -import org.jetbrains.annotations.Contract; +import net.minecraft.network.PacketBuffer; public abstract class AbstractDoubleLogicData> implements INetLogicEntry { private double value; - @Contract("_ -> this") - public T setValue(double value) { + public T getWith(double value) { + return getNew().setValue(value); + } + + protected T setValue(double value) { this.value = value; return (T) this; } @@ -29,4 +29,14 @@ public NBTTagDouble serializeNBT() { public void deserializeNBT(NBTTagDouble nbt) { this.value = nbt.getDouble(); } + + @Override + public void encode(PacketBuffer buf, boolean fullChange) { + buf.writeDouble(value); + } + + @Override + public void decode(PacketBuffer buf, boolean fullChange) { + this.value = buf.readDouble(); + } } diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java index 720845a0da6..d1ff2c58ef9 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java @@ -1,16 +1,17 @@ package gregtech.api.graphnet.logic; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagInt; - -import org.jetbrains.annotations.Contract; +import net.minecraft.network.PacketBuffer; public abstract class AbstractIntLogicData> implements INetLogicEntry { private int value; - @Contract("_ -> this") - public T setValue(int value) { + public T getWith(int value) { + return getNew().setValue(value); + } + + protected T setValue(int value) { this.value = value; return (T) this; } @@ -28,4 +29,14 @@ public NBTTagInt serializeNBT() { public void deserializeNBT(NBTTagInt nbt) { this.value = nbt.getInt(); } + + @Override + public void encode(PacketBuffer buf, boolean fullChange) { + buf.writeVarInt(this.value); + } + + @Override + public void decode(PacketBuffer buf, boolean fullChange) { + this.value = buf.readVarInt(); + } } diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java new file mode 100644 index 00000000000..bd4cc825d29 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java @@ -0,0 +1,46 @@ +package gregtech.api.graphnet.logic; + +import net.minecraft.nbt.NBTTagLong; + +import net.minecraft.network.PacketBuffer; + +import org.jetbrains.annotations.Contract; + +public abstract class AbstractLongLogicData> implements INetLogicEntry { + + private long value; + + public T getWith(long value) { + return getNew().setValue(value); + } + + @Contract("_ -> this") + public T setValue(long value) { + this.value = value; + return (T) this; + } + + public long getValue() { + return this.value; + } + + @Override + public NBTTagLong serializeNBT() { + return new NBTTagLong(this.value); + } + + @Override + public void deserializeNBT(NBTTagLong nbt) { + this.value = nbt.getLong(); + } + + @Override + public void encode(PacketBuffer buf, boolean fullChange) { + buf.writeVarLong(this.value); + } + + @Override + public void decode(PacketBuffer buf, boolean fullChange) { + this.value = buf.readVarLong(); + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java b/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java index 6d9e7ec66df..a33c86448e5 100644 --- a/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java @@ -11,10 +11,15 @@ public final class ChannelCountLogic extends AbstractIntLogicData other) { if (other instanceof ChannelCountLogic l) { - return new ChannelCountLogic().setValue(Math.min(this.getValue(), l.getValue())); - } else return new ChannelCountLogic().setValue(1); + return this.getValue() < l.getValue() ? this : l; + } else return this; } } diff --git a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java index 41ae6984fdd..4cb66c61280 100644 --- a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java +++ b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java @@ -2,21 +2,56 @@ import gregtech.api.graphnet.predicate.IEdgePredicate; +import gregtech.api.network.IPacket; + import net.minecraft.nbt.NBTBase; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; /** * Note - all implementers of this interface are suggested to be final, in order to avoid unexpected {@link #union(INetLogicEntry)} behavior. */ -public interface INetLogicEntry, N extends NBTBase> extends INBTSerializable, IStringSerializable { +public interface INetLogicEntry, N extends NBTBase> extends INBTSerializable, + IStringSerializable, + IPacket { default void deserializeNBTNaive(NBTBase nbt) { deserializeNBT((N) nbt); } - @Contract("_ -> new") - T union(INetLogicEntry other); + /** + * Returns null if the operation is not supported. + */ + @Nullable + default T union(INetLogicEntry other) { + return null; + } + + default void registerToNetLogicData(NetLogicData data) {} + + T getNew(); + + default void encode(PacketBuffer buf) { + encode(buf, true); + } + + /** + * @param fullChange allows for less-full buffers to be sent and received. + * Useful for logics that can be partially modified, see {@link TemperatureLogic} + */ + void encode(PacketBuffer buf, boolean fullChange); + + default void decode(PacketBuffer buf) { + decode(buf, true); + } + + /** + * @param fullChange allows for less-full buffers to be sent and received. + * Useful for logics that can be partially modified, see {@link TemperatureLogic} + */ + void decode(PacketBuffer buf, boolean fullChange); } diff --git a/src/main/java/gregtech/api/graphnet/logic/LossAbsoluteLogic.java b/src/main/java/gregtech/api/graphnet/logic/LossAbsoluteLogic.java deleted file mode 100644 index 37e42ef488e..00000000000 --- a/src/main/java/gregtech/api/graphnet/logic/LossAbsoluteLogic.java +++ /dev/null @@ -1,20 +0,0 @@ -package gregtech.api.graphnet.logic; - -import org.jetbrains.annotations.NotNull; - -public final class LossAbsoluteLogic extends AbstractIntLogicData { - - public static final LossAbsoluteLogic INSTANCE = new LossAbsoluteLogic().setValue(0); - - @Override - public @NotNull String getName() { - return "LossAbsolute"; - } - - @Override - public LossAbsoluteLogic union(INetLogicEntry other) { - if (other instanceof LossAbsoluteLogic l) { - return new LossAbsoluteLogic().setValue((this.getValue() + l.getValue()) / 2); - } else return new LossAbsoluteLogic().setValue(this.getValue() / 2); - } -} diff --git a/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java b/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java index a429991a131..cbd9370546c 100644 --- a/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java @@ -11,10 +11,15 @@ public final class MultiNetCountLogic extends AbstractIntLogicData other) { if (other instanceof MultiNetCountLogic l) { - return new MultiNetCountLogic().setValue(Math.min(this.getValue(), l.getValue())); - } else return new MultiNetCountLogic().setValue(1); + return this.getValue() < l.getValue() ? this : l; + } else return this; } } diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index 8fcbfd0f930..42b3e464db5 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -2,48 +2,80 @@ import gregtech.api.graphnet.gather.GTGraphGatherables; +import gregtech.api.util.IDirtyNotifiable; + +import gregtech.api.util.function.TriConsumer; + import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraftforge.common.util.INBTSerializable; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.Map; +import java.util.Set; +import java.util.function.BiConsumer; import java.util.function.Supplier; public final class NetLogicData implements INBTSerializable { - private final Map> logicEntrySet; + // TODO caching logic on simple logics to reduce amount of reduntant creation? + private final Object2ObjectOpenHashMap> logicEntrySet; + + private final Set listeners = new ObjectOpenHashSet<>(); public NetLogicData() { - logicEntrySet = new Object2ObjectOpenHashMap<>(); + logicEntrySet = new Object2ObjectOpenHashMap<>(4); } - private NetLogicData(Map> logicEntrySet) { + private NetLogicData(Object2ObjectOpenHashMap> logicEntrySet) { this.logicEntrySet = logicEntrySet; } + /** + * If the {@link INetLogicEntry#union(INetLogicEntry)} operation is not supported for this entry, + * nothing happens if an entry is already present. + */ public NetLogicData mergeLogicEntry(INetLogicEntry entry) { INetLogicEntry current = logicEntrySet.get(entry.getName()); + if (current == null) return setLogicEntry(entry); + if (entry.getClass().isInstance(current)) { entry = current.union(entry); + if (entry == null) return this; } return setLogicEntry(entry); } public NetLogicData setLogicEntry(INetLogicEntry entry) { + entry.registerToNetLogicData(this); logicEntrySet.put(entry.getName(), entry); + this.markLogicEntryAsUpdated(entry, true); return this; } public NetLogicData removeLogicEntry(@NotNull INetLogicEntry key) { - logicEntrySet.remove(key.getName()); + return removeLogicEntry(key.getName()); + } + + public NetLogicData removeLogicEntry(@NotNull String key) { + INetLogicEntry entry = logicEntrySet.remove(key); + if (entry != null) this.listeners.forEach(l -> l.markChanged(entry, true, true)); + logicEntrySet.trim(); return this; } + public void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChange) { + this.listeners.forEach(l -> l.markChanged(entry, false, fullChange)); + } + @Nullable public > T getLogicEntryNullable(@NotNull T key) { try { @@ -63,13 +95,36 @@ public NetLogicData removeLogicEntry(@NotNull INetLogicEntry key) { } } - public static NetLogicData union(NetLogicData sourceData, NetLogicData targetData) { - Map> newLogic = new Object2ObjectOpenHashMap<>(sourceData.logicEntrySet); - newLogic.replaceAll((k, v) -> v.union(targetData.logicEntrySet.get(k))); - targetData.logicEntrySet.forEach((key, value) -> newLogic.computeIfAbsent(key, k -> value.union(null))); + @Contract("_, _ -> new") + public static @NotNull NetLogicData union(@NotNull NetLogicData sourceData, @Nullable NetLogicData targetData) { + Object2ObjectOpenHashMap> newLogic = + new Object2ObjectOpenHashMap<>(sourceData.logicEntrySet); + if (targetData != null) { + for (String key : newLogic.keySet()) { + newLogic.computeIfPresent(key, (k, v) -> v.union(targetData.logicEntrySet.get(k))); + } + targetData.logicEntrySet.forEach((key, value) -> newLogic.computeIfAbsent(key, k -> value.union(null))); + } + return new NetLogicData(newLogic); + } + + @Contract("_, _ -> new") + public static @NotNull NetLogicData union(@NotNull NetLogicData first, @NotNull NetLogicData... others) { + Object2ObjectOpenHashMap> newLogic = + new Object2ObjectOpenHashMap<>(first.logicEntrySet); + for (NetLogicData other : others) { + for (String key : newLogic.keySet()) { + newLogic.computeIfPresent(key, (k, v) -> v.union(other.logicEntrySet.get(k))); + } + other.logicEntrySet.forEach((key, value) -> newLogic.computeIfAbsent(key, k -> value.union(null))); + } return new NetLogicData(newLogic); } + public void addListener(LogicDataListener listener) { + this.listeners.add(listener); + } + @Override public NBTTagList serializeNBT() { NBTTagList list = new NBTTagList(); @@ -97,4 +152,20 @@ public void deserializeNBT(NBTTagList nbt) { private static Supplier> getSupplier(String identifier) { return GTGraphGatherables.getLogicsRegistry().getOrDefault(identifier, () -> null); } + + public final class LogicDataListener { + private final TriConsumer, Boolean, Boolean> listener; + + public LogicDataListener(TriConsumer, Boolean, Boolean> listener) { + this.listener = listener; + } + + private void markChanged(INetLogicEntry updatedEntry, boolean removed, boolean fullChange) { + this.listener.accept(updatedEntry, removed, fullChange); + } + + public void invalidate() { + listeners.remove(this); + } + } } diff --git a/src/main/java/gregtech/api/graphnet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/logic/TemperatureLogic.java new file mode 100644 index 00000000000..62ef7a7657a --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/TemperatureLogic.java @@ -0,0 +1,232 @@ +package gregtech.api.graphnet.logic; + +import gregtech.api.graphnet.pipenet.NodeLossResult; + +import gregtech.api.graphnet.pipenet.physical.IBurnable; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.nbt.NBTTagCompound; + +import net.minecraft.network.PacketBuffer; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class TemperatureLogic implements INetLogicEntry { + + public static final TemperatureLogic INSTANCE = new TemperatureLogic(); + + public static final int DEFAULT_TEMPERATURE = 293; + + @Nullable + private NetLogicData owner; + + private int temperatureMaximum; + private @Nullable Integer partialBurnTemperature; + private int temperatureMinimum; + private float energy; + private int thermalMass; + + private TemperatureRestorationFunction temperatureRestorationFunction; + private float restorationSpeedFactor; + private long lastRestorationTick; + + private TemperatureLogic() {} + + public TemperatureLogic getWith(TemperatureRestorationFunction temperatureRestorationFunction, float restorationSpeedFactor, int temperatureMaximum) { + return getWith(temperatureRestorationFunction, restorationSpeedFactor, temperatureMaximum, null); + } + + public TemperatureLogic getWith(TemperatureRestorationFunction temperatureRestorationFunction, float restorationSpeedFactor, int temperatureMaximum, @Nullable Integer partialBurnTemperature) { + return getWith(temperatureRestorationFunction, restorationSpeedFactor, temperatureMaximum, partialBurnTemperature, 1); + } + + public TemperatureLogic getWith(TemperatureRestorationFunction temperatureRestorationFunction, float restorationSpeedFactor, int temperatureMaximum, @Nullable Integer partialBurnTemperature, int temperatureMinimum) { + return getWith(temperatureRestorationFunction, restorationSpeedFactor, temperatureMaximum, partialBurnTemperature, temperatureMinimum, 1000); + } + + public TemperatureLogic getWith(TemperatureRestorationFunction temperatureRestorationFunction, float restorationSpeedFactor, int temperatureMaximum, @Nullable Integer partialBurnTemperature, int temperatureMinimum, int thermalMass) { + return getNew() + .setTemperatureRestorationFunction(temperatureRestorationFunction) + .setRestorationSpeedFactor(restorationSpeedFactor) + .setTemperatureMaximum(temperatureMaximum) + .setPartialBurnTemperature(partialBurnTemperature) + .setTemperatureMinimum(temperatureMinimum) + .setThermalMass(thermalMass); + } + + public TemperatureLogic getNew() { + return new TemperatureLogic(); + } + + public boolean aboveMax(long tick) { + return this.getTemperature(tick) > this.temperatureMaximum; + } + + public boolean belowMin(long tick) { + return this.getTemperature(tick) < this.temperatureMinimum; + } + + @Nullable + public NodeLossResult getLossResult(long tick) { + if (aboveMax(tick)) { + return new NodeLossResult(n -> { + World world = n.getNet().getWorld(); + BlockPos pos = n.getEquivalencyData(); + IBlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof IBurnable burnable) { + burnable.fullyBurn(state, world, pos); + } else { + world.setBlockToAir(pos); + } + }, l -> 0L); + } else if (partialBurnTemperature != null && getTemperature(tick) > partialBurnTemperature) { + return new NodeLossResult(n -> { + World world = n.getNet().getWorld(); + BlockPos pos = n.getEquivalencyData(); + IBlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof IBurnable burnable) { + burnable.partialBurn(state, world, pos); + } + }, l -> (long) (l * 0.5)); + } else { + return null; + } + } + + public void applyThermalEnergy(float energy, long tick) { + restoreTemperature(tick); + // since the decay logic is synced and deterministic, + // the only time client and server will desync is on external changes. + if (this.owner != null) this.owner.markLogicEntryAsUpdated(this, false); + this.energy += energy; + } + + public int getTemperature(long tick) { + restoreTemperature(tick); + return (int) (this.energy / this.thermalMass) + DEFAULT_TEMPERATURE; + } + + private void restoreTemperature(long tick) { + long timePassed = lastRestorationTick - tick; + this.lastRestorationTick = tick; + float energy = this.energy; + if (timePassed != 0) { + if (timePassed >= Integer.MAX_VALUE || timePassed < 0) { + this.energy = 0; + } else this.energy = temperatureRestorationFunction + .restoreTemperature(energy, restorationSpeedFactor, (int) timePassed); + } + } + + public TemperatureLogic setTemperatureRestorationFunction(TemperatureRestorationFunction temperatureRestorationFunction) { + this.temperatureRestorationFunction = temperatureRestorationFunction; + return this; + } + + public TemperatureRestorationFunction getTemperatureRestorationFunction() { + return temperatureRestorationFunction; + } + + public TemperatureLogic setRestorationSpeedFactor(float restorationSpeedFactor) { + this.restorationSpeedFactor = restorationSpeedFactor; + return this; + } + + public float getRestorationSpeedFactor() { + return restorationSpeedFactor; + } + + public TemperatureLogic setTemperatureMaximum(int temperatureMaximum) { + this.temperatureMaximum = temperatureMaximum; + return this; + } + + public int getTemperatureMaximum() { + return temperatureMaximum; + } + + public TemperatureLogic setPartialBurnTemperature(@Nullable Integer partialBurnTemperature) { + this.partialBurnTemperature = partialBurnTemperature; + return this; + } + + public @Nullable Integer getPartialBurnTemperature() { + return partialBurnTemperature; + } + + public TemperatureLogic setTemperatureMinimum(int temperatureMinimum) { + this.temperatureMinimum = temperatureMinimum; + return this; + } + + public int getTemperatureMinimum() { + return temperatureMinimum; + } + + public TemperatureLogic setThermalMass(int thermalMass) { + this.thermalMass = thermalMass; + return this; + } + + public int getThermalMass() { + return thermalMass; + } + + @Override + public @NotNull String getName() { + return "Temperature"; + } + + @Override + public void registerToNetLogicData(NetLogicData data) { + this.owner = data; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setFloat("ThermalEnergy", this.energy); + tag.setInteger("TemperatureMax", this.temperatureMaximum); + tag.setInteger("TemperatureMin", this.temperatureMinimum); + tag.setInteger("ThermalMass", this.thermalMass); + tag.setInteger("RestorationFunction", temperatureRestorationFunction.ordinal()); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + this.energy = nbt.getFloat("ThermalEnergy"); + this.temperatureMaximum = nbt.getInteger("TemperatureMax"); + this.temperatureMinimum = nbt.getInteger("TemperatureMin"); + this.thermalMass = nbt.getInteger("ThermalMass"); + this.temperatureRestorationFunction = + TemperatureRestorationFunction.values()[nbt.getInteger("RestorationFunction")]; + } + + @Override + public void encode(PacketBuffer buf, boolean fullChange) { + buf.writeFloat(this.energy); + if (fullChange) { + buf.writeVarInt(this.temperatureMaximum); + buf.writeVarInt(this.temperatureMinimum); + buf.writeVarInt(this.thermalMass); + buf.writeVarInt(this.temperatureRestorationFunction.ordinal()); + } + } + + @Override + public void decode(PacketBuffer buf, boolean fullChange) { + this.energy = buf.readFloat(); + if (fullChange) { + this.temperatureMaximum = buf.readVarInt(); + this.temperatureMinimum = buf.readVarInt(); + this.thermalMass = buf.readVarInt(); + this.temperatureRestorationFunction = + TemperatureRestorationFunction.values()[buf.readVarInt()]; + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/TemperatureRestorationFunction.java b/src/main/java/gregtech/api/graphnet/logic/TemperatureRestorationFunction.java new file mode 100644 index 00000000000..c25afa4f12a --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/TemperatureRestorationFunction.java @@ -0,0 +1,98 @@ +package gregtech.api.graphnet.logic; + +/** + * A bunch of loss functions. By the power of Wolfram Alpha. + * Demonstration Graph + */ +public enum TemperatureRestorationFunction { + // DO NOT REORDER FUNCTIONS, THE ORDER IS USED FOR NBT SERIALIZATION + /** + * 100 thermal energy is lost every tick, modified by restoration speed factor. + *
A constant rate. + */ + ARITHMETIC { + @Override + public float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed) { + float initialThermalEnergy = thermalEnergy; + thermalEnergy -= b(thermalEnergy, restorationSpeedFactor); + if (thermalEnergy < initialThermalEnergy) return 0; + return tolerate(thermalEnergy); + } + }, + /** + * 10% of thermal energy is lost every tick, modified by restoration speed factor. + *
Faster than {@link TemperatureRestorationFunction#ARITHMETIC} at large values, but slower at small values. + */ + GEOMETRIC { + @Override + public float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed) { + thermalEnergy *= Math.pow(a(restorationSpeedFactor), timePassed); + return tolerate(thermalEnergy); + } + }, + /** + * thermal energy is raised to the power of 1 - 0.02 every tick, modified by restoration speed factor. + *
Faster than {@link TemperatureRestorationFunction#GEOMETRIC} at large values, but incredibly slow at small values. + */ + POWER { + @Override + public float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed) { + thermalEnergy = (float) (Math.signum(thermalEnergy) * + Math.pow(Math.abs(thermalEnergy), Math.pow(c(restorationSpeedFactor), timePassed))); + return tolerate(thermalEnergy); + } + }, + /** + * 10% of thermal energy is lost, then 100 more, every tick, both values modified by restoration speed factor. + *
Slightly faster than {@link TemperatureRestorationFunction#GEOMETRIC} at large values, + * slightly faster than {@link TemperatureRestorationFunction#ARITHMETIC} at small values. + */ + GEOMETRIC_ARITHMETIC { + @Override + public float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed) { + float initialThermalEnergy = thermalEnergy; + + float a = a(restorationSpeedFactor); + float b = b(thermalEnergy, restorationSpeedFactor); + thermalEnergy = (float) ((b - Math.pow(a, timePassed) * + (-a * thermalEnergy + b + thermalEnergy)) / (a - 1)); + + if (thermalEnergy < initialThermalEnergy) return 0; + return tolerate(thermalEnergy); + } + }, + /** + * thermal energy is raised to the power of 1 - 0.02, then 10% more is lost, every tick, both values modified by restoration speed factor. + *
Slightly faster than {@link TemperatureRestorationFunction#POWER} at large values, + * slightly faster than {@link TemperatureRestorationFunction#GEOMETRIC} at small values. + */ + POWER_GEOMETRIC { + @Override + public float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed) { + float c = c(restorationSpeedFactor); + thermalEnergy = (float) (Math.pow(a(restorationSpeedFactor), (Math.pow(c, timePassed) - 1) / (c - 1)) * + Math.pow(Math.abs(thermalEnergy), Math.pow(c, timePassed)) * Math.signum(thermalEnergy)); + return tolerate(thermalEnergy); + } + }; + + public static final float TOLERANCE = 0.1f; + + protected float tolerate(float value) { + return Math.abs(value) < TOLERANCE ? 0 : value; + } + + protected float a(float restorationSpeedFactor) { + return 1 - 0.1f * restorationSpeedFactor; + } + + protected float b(float thermalEnergy, float restorationSpeedFactor) { + return Math.signum(thermalEnergy) * 100 * restorationSpeedFactor; + } + + protected float c(float restorationSpeedFactor) { + return 1 - 0.02f * restorationSpeedFactor; + } + + public abstract float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed); +} diff --git a/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java b/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java index d3ee65e5003..020645598e0 100644 --- a/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java @@ -2,19 +2,26 @@ import org.jetbrains.annotations.NotNull; -public final class ThroughputLogic extends AbstractIntLogicData { +public final class ThroughputLogic extends AbstractLongLogicData { public static final ThroughputLogic INSTANCE = new ThroughputLogic().setValue(0); + private ThroughputLogic() {} + @Override public @NotNull String getName() { return "Throughput"; } + @Override + public ThroughputLogic getNew() { + return new ThroughputLogic(); + } + @Override public ThroughputLogic union(INetLogicEntry other) { if (other instanceof ThroughputLogic l) { - return new ThroughputLogic().setValue(Math.min(this.getValue(), l.getValue())); - } else return new ThroughputLogic().setValue(0); + return this.getValue() < l.getValue() ? this : l; + } else return this; } } diff --git a/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java index d64dad4db42..29992672985 100644 --- a/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java @@ -6,16 +6,23 @@ public final class WeightFactorLogic extends AbstractDoubleLogicData other) { if (other instanceof WeightFactorLogic l) { - return new WeightFactorLogic().setValue(this.getValue() + l.getValue()); - } else return new WeightFactorLogic().setValue(this.getValue()); + return getWith(this.getValue() + l.getValue()); + } else return this; } } diff --git a/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java b/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java index 15237c83c44..94057a7d8db 100644 --- a/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java @@ -2,7 +2,11 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.logic.NetLogicData; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; import java.util.List; public abstract class AbstractNetPath implements INetPath { @@ -13,6 +17,9 @@ public abstract class AbstractNetPath impl protected final double weight; + protected NetLogicData unifiedNodeData; + protected NetLogicData unifiedEdgeData; + public AbstractNetPath(List nodes, List edges, double weight) { this.nodes = nodes; this.edges = edges; @@ -33,4 +40,37 @@ public List getOrderedEdges() { public double getWeight() { return weight; } + + @Override + public NetLogicData getUnifiedNodeData() { + if (unifiedNodeData == null) { + if (nodes.size() == 1) { + unifiedNodeData = nodes.get(0).getData(); + } else if (nodes.size() == 2) { + unifiedNodeData = NetLogicData.union(nodes.get(0).getData(), nodes.get(1).getData()); + } else { + unifiedNodeData = NetLogicData.union(nodes.get(0).getData(), + nodes.subList(1, nodes.size()).stream().map(NetNode::getData).toArray(NetLogicData[]::new)); + } + } + return unifiedNodeData; + } + + @Override + @Nullable + public NetLogicData getUnifiedEdgeData() { + if (unifiedEdgeData == null) { + if (edges.size() == 0) { + return null; + } else if (edges.size() == 1) { + unifiedEdgeData = edges.get(0).getData(); + } else if (edges.size() == 2) { + unifiedEdgeData = NetLogicData.union(edges.get(0).getData(), edges.get(1).getData()); + } else { + unifiedEdgeData = NetLogicData.union(edges.get(0).getData(), + edges.subList(1, edges.size()).stream().map(NetEdge::getData).toArray(NetLogicData[]::new)); + } + } + return unifiedEdgeData; + } } diff --git a/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java b/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java index 217e3497315..247937ab70c 100644 --- a/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java @@ -3,14 +3,19 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.alg.NetPathMapper; import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import org.jetbrains.annotations.Nullable; import org.jgrapht.GraphPath; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; @@ -32,4 +37,8 @@ public GenericGraphNetPath(List vertices, List edges, do public GenericGraphNetPath(GraphPath path) { this(path.getVertexList(), path.getEdgeList(), path.getWeight()); } + + public interface Provider { + Iterator getPaths(NetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick); + } } diff --git a/src/main/java/gregtech/api/graphnet/path/INetPath.java b/src/main/java/gregtech/api/graphnet/path/INetPath.java index 4b13bed448b..5cdf3fb1cfa 100644 --- a/src/main/java/gregtech/api/graphnet/path/INetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/INetPath.java @@ -2,6 +2,9 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.logic.NetLogicData; + +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -16,4 +19,9 @@ default boolean matches(INetPath other) { return getWeight() == other.getWeight() && getOrderedNodes().equals(other.getOrderedNodes()) && getOrderedEdges().equals(other.getOrderedEdges()); } + + NetLogicData getUnifiedNodeData(); + + @Nullable + NetLogicData getUnifiedEdgeData(); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java index 3f5969e1d1f..aa6dbd42e15 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java @@ -2,14 +2,19 @@ import gregtech.api.graphnet.alg.NetPathMapper; import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.path.AbstractNetPath; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import org.jetbrains.annotations.Nullable; import org.jgrapht.GraphPath; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; @@ -31,4 +36,8 @@ public BasicWorldPipeNetPath(List vertices, List edges, public BasicWorldPipeNetPath(GraphPath path) { this(path.getVertexList(), path.getEdgeList(), path.getWeight()); } + + public interface Provider { + Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick); + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java index 151af50e583..629d9ef5b2f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java @@ -2,14 +2,19 @@ import gregtech.api.graphnet.alg.NetPathMapper; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.path.AbstractNetPath; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import org.jetbrains.annotations.Nullable; import org.jgrapht.GraphPath; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; @@ -31,4 +36,8 @@ public FlowWorldPipeNetPath(List vertices, List edges, d public FlowWorldPipeNetPath(GraphPath path) { this(path.getVertexList(), path.getEdgeList(), path.getWeight()); } + + public interface Provider { + Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick); + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java index 1f27c59adee..c4aa9f505d5 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java @@ -1,12 +1,18 @@ package gregtech.api.graphnet.pipenet; -import gregtech.api.graphnet.pipenet.block.IPipeStructure; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import java.util.Collection; +import java.util.Map; + public interface IPipeNetNodeHandler { void addToNets(World world, BlockPos pos, IPipeStructure structure); + Collection getFromNets(World world, BlockPos pos, IPipeStructure structure); + void removeFromNets(World world, BlockPos pos, IPipeStructure structure); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java new file mode 100644 index 00000000000..7d000ffdcc8 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java @@ -0,0 +1,33 @@ +package gregtech.api.graphnet.pipenet; + +import net.minecraft.util.Tuple; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Consumer; +import java.util.function.UnaryOperator; + +public final class NodeLossResult { + + private final @Nullable Consumer postAction; + private final @NotNull UnaryOperator lossFunction; + + public NodeLossResult(@Nullable Consumer postAction, @NotNull UnaryOperator lossFunction) { + this.postAction = postAction; + this.lossFunction = lossFunction; + } + + public boolean hasPostAction() { + return postAction != null; + } + + public void triggerPostAction(WorldPipeNetNode node) { + if (postAction == null) return; + this.postAction.accept(node); + } + + public long applyLossFunction(long value) { + return this.lossFunction.apply(value); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 8f4bda742b0..7f5700c50dd 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -6,8 +6,11 @@ import gregtech.api.graphnet.alg.INetAlgorithm; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.logic.MultiNetCountLogic; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.worldnet.WorldNet; +import gregtech.api.graphnet.worldnet.WorldNetNode; + import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -17,6 +20,8 @@ import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,6 +57,15 @@ public WorldPipeNet(String name, Function algorithmBui }); } + public abstract Capability[] getTargetCapabilities(); + + public abstract IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node); + + @Override + public @NotNull WorldPipeNetNode getOrCreateNode(@NotNull BlockPos pos) { + return (WorldPipeNetNode) super.getOrCreateNode(pos); + } + @Override public @Nullable WorldPipeNetNode getNode(@NotNull BlockPos equivalencyData) { return (WorldPipeNetNode) getNode((Object) equivalencyData); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java index 7335b2fc56b..4adc6834564 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java @@ -3,6 +3,7 @@ import gregtech.api.graphnet.GraphNetBacker; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.MultiNetNodeHandler; +import gregtech.api.graphnet.pipenet.physical.PipeTileEntity; import gregtech.api.graphnet.worldnet.WorldNet; import gregtech.api.graphnet.worldnet.WorldNetNode; @@ -20,6 +21,11 @@ public WorldPipeNetNode(WorldPipeNet net) { super(net); } + public PipeTileEntity getTileEntity() { + // should this be cached? It's only ever used for active nodes when they are being targeted by a path traversal. + return (PipeTileEntity) getNet().getWorld().getTileEntity(getEquivalencyData()); + } + @Override public WorldPipeNet getNet() { return (WorldPipeNet) super.getNet(); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/block/CableStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/block/CableStructure.java deleted file mode 100644 index 47e44b11161..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/block/CableStructure.java +++ /dev/null @@ -1,11 +0,0 @@ -package gregtech.api.graphnet.pipenet.block; - -import org.jetbrains.annotations.NotNull; - -public record CableStructure(String name, int material, int insulation, int lossMult) implements IPipeStructure { - - @Override - public @NotNull String getName() { - return this.name(); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/block/IPipeStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/block/IPipeStructure.java deleted file mode 100644 index 66f8d8e3563..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/block/IPipeStructure.java +++ /dev/null @@ -1,6 +0,0 @@ -package gregtech.api.graphnet.pipenet.block; - -import net.minecraft.util.IStringSerializable; - -public interface IPipeStructure extends IStringSerializable { -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/block/PipeBlock.java deleted file mode 100644 index cdc1a7084d6..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/block/PipeBlock.java +++ /dev/null @@ -1,96 +0,0 @@ -package gregtech.api.graphnet.pipenet.block; - -import gregtech.api.block.BuiltInRenderBlock; - -import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; -import gregtech.api.util.GTUtility; -import gregtech.common.ConfigHolder; - -import net.minecraft.block.Block; -import net.minecraft.block.SoundType; -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.entity.EntityLiving; -import net.minecraft.item.Item; -import net.minecraft.item.ItemBlock; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; - -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public abstract class PipeBlock extends BuiltInRenderBlock { - - public final IPipeStructure structure; - - public PipeBlock(IPipeStructure structure) { - super(net.minecraft.block.material.Material.IRON); - this.structure = structure; - this.setDefaultState(constructDefaultState()); - - setTranslationKey("pipe" + getStructureName()); - setSoundType(SoundType.METAL); - setHardness(2.0f); - setResistance(3.0f); - setLightOpacity(0); - disableStats(); - } - - protected IBlockState constructDefaultState() { - return this.blockState.getBaseState(); - } - - @Override - public void onBlockAdded(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { - super.onBlockAdded(worldIn, pos, state); - getHandler(state).addToNets(worldIn, pos, structure); - } - - @Override - public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { - super.breakBlock(worldIn, pos, state); - getHandler(state).removeFromNets(worldIn, pos, structure); - } - - @NotNull - protected abstract IPipeNetNodeHandler getHandler(IBlockState state); - - @Override - public boolean canCreatureSpawn(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, - @NotNull EntityLiving.SpawnPlacementType type) { - return false; - } - - public String getStructureName() { - return GTUtility.lowerUnderscoreToUpperCamel(structure.getName()); - } - - @Override - public void addInformation(@NotNull ItemStack stack, @Nullable World world, @NotNull List tooltip, - @NotNull ITooltipFlag flag) { - if (ConfigHolder.misc.debug) { - tooltip.add("MetaItem Id: pipe" + getStructureName()); - } - } - - @Nullable - public static PipeBlock getPipeBlockFromItem(@NotNull ItemStack stack) { - Item item = stack.getItem(); - if (item instanceof ItemBlock) { - Block block = ((ItemBlock) item).getBlock(); - if (block instanceof PipeBlock) return (PipeBlock) block; - } - return null; - } - - @Override - protected Pair getParticleTexture(World world, BlockPos blockPos) { - return null; - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java new file mode 100644 index 00000000000..cd8cf7c46c2 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java @@ -0,0 +1,22 @@ +package gregtech.api.graphnet.pipenet.physical; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +public interface IBurnable { + + /** + * Called when the block should be partially burned.
+ * Allows for partial burns with reference to temperature logic, used in insulated cables for example. + */ + default void partialBurn(IBlockState state, World world, BlockPos pos) {} + + /** + * Called when the block should be fully burned. + */ + default void fullyBurn(IBlockState state, World world, BlockPos pos) { + world.setBlockToAir(pos); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java new file mode 100644 index 00000000000..551c18a9cd0 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java @@ -0,0 +1,14 @@ +package gregtech.api.graphnet.pipenet.physical; + +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.Capability; + +import org.jetbrains.annotations.Nullable; + +public interface IPipeCapabilityObject { + void setTile(PipeTileEntity tile); + + Capability[] getCapabilities(); + + T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeMaterialStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeMaterialStructure.java new file mode 100644 index 00000000000..3ffef9599e9 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeMaterialStructure.java @@ -0,0 +1,8 @@ +package gregtech.api.graphnet.pipenet.physical; + +import gregtech.api.unification.ore.OrePrefix; + +public interface IPipeMaterialStructure extends IPipeStructure { + + OrePrefix getOrePrefix(); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java new file mode 100644 index 00000000000..8b2ca66bcdd --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java @@ -0,0 +1,16 @@ +package gregtech.api.graphnet.pipenet.physical; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.IStringSerializable; + +public interface IPipeStructure extends IStringSerializable { + float getRenderThickness(); + + /** + * Allows for controlling what sides can be connected to based on current connections, + * such as in the case of optical and laser pipes. + */ + default boolean canConnectTo(EnumFacing side, byte connectionMask) { + return true; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/ItemPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/ItemPipeBlock.java new file mode 100644 index 00000000000..4c2a72780fc --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/ItemPipeBlock.java @@ -0,0 +1,38 @@ +package gregtech.api.graphnet.pipenet.physical; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; + +public class ItemPipeBlock extends ItemBlock { + + public ItemPipeBlock(PipeBlock block) { + super(block); + } + + @Override + public @NotNull PipeBlock getBlock() { + return (PipeBlock) super.getBlock(); + } + + @Override + public boolean placeBlockAt(@NotNull ItemStack stack, @NotNull EntityPlayer player, @NotNull World world, @NotNull BlockPos pos, @NotNull EnumFacing side, + float hitX, float hitY, float hitZ, @NotNull IBlockState newState) { + if (super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, newState)) { + PipeTileEntity tile = getBlock().getTileEntity(world, pos); + // TODO set pipe color based on offhand here + if (tile != null) { + getBlock().doPlacementLogic(tile, side.getOpposite()); + } + return true; + } else return false; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeBlock.java new file mode 100644 index 00000000000..8e05ee78c02 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeBlock.java @@ -0,0 +1,218 @@ +package gregtech.api.graphnet.pipenet.physical; + +import gregtech.api.block.BuiltInRenderBlock; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; +import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.util.GTUtility; +import gregtech.common.ConfigHolder; + +import gregtech.common.blocks.properties.PropertyByte; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.block.Block; +import net.minecraft.block.SoundType; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.NonNullList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; + +public abstract class PipeBlock extends BuiltInRenderBlock { + + private final IPipeStructure structure; + + public PipeBlock(IPipeStructure structure) { + super(net.minecraft.block.material.Material.IRON); + this.structure = structure; + setTranslationKey(getStructureName()); + setSoundType(SoundType.METAL); + setHardness(2.0f); + setResistance(3.0f); + setLightOpacity(0); + disableStats(); + } + + public IPipeStructure getStructure() { + return structure; + } + + public void doPlacementLogic(PipeTileEntity tile, EnumFacing placedBlockSearchSide) { + for (EnumFacing facing : EnumFacing.VALUES) { + TileEntity otherr = tile.getNeighbor(facing); + if (otherr instanceof PipeTileEntity other) { + // first check -- connect to matching mark pipes if side matches or config allows. + if (tile.getPaintingColor() == other.getPaintingColor() && (facing == placedBlockSearchSide || + !ConfigHolder.machines.gt6StylePipesCables)) { + connectTiles(tile, other, facing); + continue; + } + // second check -- connect to pipes with an open connection, no matter the mark status. + if (tile.isOpen(facing.getOpposite())) { + connectTiles(tile, other, facing); + } + } else if (facing == placedBlockSearchSide) { + // if the placed on tile supports one of our capabilities, connect to it. + tile.updateActiveStatus(facing, true); + } + } + } + + public void connectTiles(@NotNull PipeTileEntity tile1, @NotNull PipeTileEntity tile2, EnumFacing facingFrom1To2) { + // abort connection if either tile refuses it. + if (!tile1.canConnectTo(facingFrom1To2) || !tile2.canConnectTo(facingFrom1To2.getOpposite())) return; + + tile1.setOpen(facingFrom1To2); + tile2.setOpen(facingFrom1To2.getOpposite()); + if (tile1.getWorld().isRemote) return; + + boolean blocked1 = tile1.isBlocked(facingFrom1To2); + boolean blocked2 = tile2.isBlocked(facingFrom1To2.getOpposite()); + + Map tile2Nodes = new Object2ObjectOpenHashMap<>(); + for (WorldPipeNetNode tile : getNodesForTile(tile2)) { + tile2Nodes.put(tile.getNet(), tile); + } + + for (WorldPipeNetNode node : getNodesForTile(tile1)) { + WorldPipeNet net = node.getNet(); + WorldPipeNetNode other = tile2Nodes.get(net); + if (other == null) continue; + if (!blocked1 && !blocked2) { + net.addEdge(node, other, true); + } else if (net.getGraph().isDirected()) { + if (!blocked1) net.addEdge(other, node, false); + else if (!blocked2) net.addEdge(node, other, false); + } + } + } + + final Collection getNodesForTile(PipeTileEntity tile) { + assert !tile.getWorld().isRemote; + return tile.getBlockType().getHandler(tile.getBlockState()).getFromNets(tile.getWorld(), tile.getPos(), tile.getBlockType().getStructure()); + } + + @Override + public void onBlockAdded(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { + super.onBlockAdded(worldIn, pos, state); + if (!worldIn.isRemote) getHandler(worldIn.getBlockState(pos)).addToNets(worldIn, pos, getStructure()); + } + + @Override + public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { + super.breakBlock(worldIn, pos, state); + if (!worldIn.isRemote) getHandler(state).removeFromNets(worldIn, pos, getStructure()); + } + + @NotNull + protected abstract IPipeNetNodeHandler getHandler(IBlockState state); + + @Override + public boolean canCreatureSpawn(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, + @NotNull EntityLiving.SpawnPlacementType type) { + return false; + } + + public String getStructureName() { + return GTUtility.lowerUnderscoreToUpperCamel(getStructure().getName()); + } + + @Override + public void addInformation(@NotNull ItemStack stack, @Nullable World world, @NotNull List tooltip, + @NotNull ITooltipFlag flag) { + if (ConfigHolder.misc.debug) { + tooltip.add("MetaItem Id: " + getStructureName()); + } + } + + @Nullable + public static PipeBlock getPipeBlockFromItem(@NotNull ItemStack stack) { + Item item = stack.getItem(); + if (item instanceof ItemBlock p) { + Block block = p.getBlock(); + if (block instanceof PipeBlock pipe) { + return pipe; + } + } + return null; + } + + // tile entity // + + @Override + public boolean hasTileEntity(@NotNull IBlockState state) { + return true; + } + + @Nullable + public PipeTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { + TileEntity tile = world.getTileEntity(pos); + if (tile instanceof PipeTileEntity pipe) return pipe; + else return null; + } + + @Override + @NotNull + public PipeTileEntity createTileEntity(@NotNull World world, @NotNull IBlockState state) { + return new PipeTileEntity(this); + } + + @Override + public void onNeighborChange(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull BlockPos neighbor) { + super.onNeighborChange(world, pos, neighbor); + EnumFacing facing = GTUtility.getFacingToNeighbor(pos, neighbor); + if (facing == null) return; + PipeTileEntity tile = getTileEntity(world, pos); + if (tile != null) tile.onNeighborChanged(facing); + } + + // cover compatibility annoyance // + + @SuppressWarnings("deprecation") + @Override + public void neighborChanged(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos, @NotNull Block blockIn, @NotNull BlockPos fromPos) { + PipeTileEntity tile = getTileEntity(worldIn, pos); + if (tile != null) tile.getCoverHolder().updateInputRedstoneSignals(); + } + + @Override + public boolean shouldCheckWeakPower(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull EnumFacing side) { + // The check in World::getRedstonePower in the vanilla code base is reversed. Setting this to false will + // actually cause getWeakPower to be called, rather than prevent it. + return false; + } + + @SuppressWarnings("deprecation") + @Override + public int getWeakPower(@NotNull IBlockState blockState, @NotNull IBlockAccess blockAccess, @NotNull BlockPos pos, @NotNull EnumFacing side) { + PipeTileEntity tile = getTileEntity(blockAccess, pos); + return tile != null ? tile.getCoverHolder().getOutputRedstoneSignal(side) : 0; + } + + @Override + public boolean canConnectRedstone(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, EnumFacing side) { + PipeTileEntity tile = getTileEntity(world, pos); + return tile != null && tile.getCoverHolder().canConnectRedstone(side); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCapabilityWrapper.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCapabilityWrapper.java new file mode 100644 index 00000000000..65044da1deb --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCapabilityWrapper.java @@ -0,0 +1,28 @@ +package gregtech.api.graphnet.pipenet.physical; + +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.Capability; + +import java.util.EnumSet; + +public class PipeCapabilityWrapper { + + private byte activeMask; + public final Capability[] capabilities; + + public PipeCapabilityWrapper(Capability[] capabilities) { + this.capabilities = capabilities; + } + + public void setActive(EnumFacing facing) { + this.activeMask |= 1 << facing.ordinal(); + } + + public void setIdle(EnumFacing facing) { + this.activeMask &= ~(1 << facing.ordinal()); + } + + public boolean isActive(EnumFacing facing) { + return (this.activeMask & 1 << facing.ordinal()) > 0; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCoverHolder.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCoverHolder.java new file mode 100644 index 00000000000..cb9633e60d3 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCoverHolder.java @@ -0,0 +1,306 @@ +package gregtech.api.graphnet.pipenet.physical; + +import gregtech.api.cover.Cover; +import gregtech.api.cover.CoverHolder; +import gregtech.api.cover.CoverSaveHandler; +import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.util.GTUtility; +import gregtech.common.ConfigHolder; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; + +import net.minecraftforge.common.util.INBTSerializable; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.function.Consumer; + +import static gregtech.api.capability.GregtechDataCodes.*; +import static gregtech.api.capability.GregtechDataCodes.UPDATE_COVER_DATA_PIPE; + +public class PipeCoverHolder implements CoverHolder, ITickable, INBTSerializable { + + private final PipeTileEntity holder; + private final EnumMap covers = new EnumMap<>(EnumFacing.class); + private final EnumSet tickingCovers = EnumSet.noneOf(EnumFacing.class); + private final int[] sidedRedstoneInput = new int[6]; + + public PipeCoverHolder(PipeTileEntity holder) { + this.holder = holder; + } + + protected final void addCoverSilent(@NotNull EnumFacing side, @NotNull Cover cover) { + if (cover instanceof ITickable && !holder.isTicking()) { + holder.addTicker(this); + tickingCovers.add(side); + return; + } + // we checked before if the side already has a cover + this.covers.put(side, cover); + } + + @Override + public final void addCover(@NotNull EnumFacing side, @NotNull Cover cover) { + addCoverSilent(side, cover); + if (!getWorld().isRemote) { + // do not sync or handle logic on client side + CoverSaveHandler.writeCoverPlacement(this, COVER_ATTACHED_PIPE, side, cover); + if (cover.shouldAutoConnectToPipes()) { + if (holder.canConnectTo(side)) holder.setOpen(side); + } + } + + holder.notifyBlockUpdate(); + holder.markAsDirty(); + } + + @Override + public final void removeCover(@NotNull EnumFacing side) { + Cover cover = getCoverAtSide(side); + if (cover == null) return; + + if (cover instanceof ITickable) { + tickingCovers.remove(side); + if (tickingCovers.isEmpty()) holder.removeTicker(this); + } + + dropCover(side); + covers.remove(side); + writeCustomData(COVER_REMOVED_PIPE, buffer -> buffer.writeByte(side.getIndex())); + if (cover.shouldAutoConnectToPipes()) { + PipeTileEntity other; + if (holder.isOpen(side) && (other = holder.getPipeNeighbor(side)) != null && !other.isOpen(side.getOpposite())) + holder.setClosed(side); + } + holder.notifyBlockUpdate(); + holder.markAsDirty(); + } + + @Override + public @NotNull ItemStack getStackForm() { + return holder.getDrop(); + } + + public void onLoad() { + for (EnumFacing side : EnumFacing.VALUES) { + this.sidedRedstoneInput[side.getIndex()] = GTUtility.getRedstonePower(getWorld(), getPos(), side); + } + } + + @Override + public final int getInputRedstoneSignal(@NotNull EnumFacing side, boolean ignoreCover) { + if (!ignoreCover && getCoverAtSide(side) != null) { + return 0; // covers block input redstone signal for machine + } + return sidedRedstoneInput[side.getIndex()]; + } + + public void updateInputRedstoneSignals() { + for (EnumFacing side : EnumFacing.VALUES) { + int redstoneValue = GTUtility.getRedstonePower(getWorld(), getPos(), side); + int currentValue = sidedRedstoneInput[side.getIndex()]; + if (redstoneValue != currentValue) { + this.sidedRedstoneInput[side.getIndex()] = redstoneValue; + Cover cover = getCoverAtSide(side); + if (cover != null) { + cover.onRedstoneInputSignalChange(redstoneValue); + } + } + } + } + + @Override + public void notifyBlockUpdate() { + holder.notifyBlockUpdate(); + } + + @Override + public void scheduleRenderUpdate() { + BlockPos pos = getPos(); + getWorld().markBlockRangeForRenderUpdate( + pos.getX() - 1, pos.getY() - 1, pos.getZ() - 1, + pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1); + } + + @Override + public double getCoverPlateThickness() { + float thickness = holder.getBlockType().getStructure().getRenderThickness(); + // no cover plate for pipes >= 1 block thick + if (thickness >= 1) return 0; + + // If the available space for the cover is less than the regular cover plate thickness, use that + + // need to divide by 2 because thickness is centered on the block, so the space is half on each side of the pipe + return Math.min(1.0 / 16.0, (1.0 - thickness) / 2); + } + + @Override + public boolean shouldRenderCoverBackSides() { + return false; + } + + @Override + public int getPaintingColorForRendering() { + return ConfigHolder.client.defaultPaintingColor; + } + + @Override + public boolean canPlaceCoverOnSide(@NotNull EnumFacing side) { + return holder.canConnectTo(side); + } + + @Override + public final boolean acceptsCovers() { + return covers.size() < EnumFacing.VALUES.length; + } + + public boolean canConnectRedstone(@Nullable EnumFacing side) { + // so far null side means either upwards or downwards redstone wire connection + // so check both top cover and bottom cover + if (side == null) { + return canConnectRedstone(EnumFacing.UP) || + canConnectRedstone(EnumFacing.DOWN); + } + Cover cover = getCoverAtSide(side); + return cover != null && cover.canConnectRedstone(); + } + + public int getOutputRedstoneSignal(@Nullable EnumFacing side) { + if (side == null) { + return getHighestOutputRedstoneSignal(); + } + Cover cover = getCoverAtSide(side); + return cover == null ? 0 : cover.getRedstoneSignalOutput(); + } + + public int getHighestOutputRedstoneSignal() { + int highestSignal = 0; + for (EnumFacing side : EnumFacing.VALUES) { + Cover cover = getCoverAtSide(side); + if (cover == null) continue; + highestSignal = Math.max(highestSignal, cover.getRedstoneSignalOutput()); + } + return highestSignal; + } + + @Override + public void update() { + if (!getWorld().isRemote) { + updateCovers(); + } + } + + @Override + public void writeCoverData(@NotNull Cover cover, int discriminator, @NotNull Consumer<@NotNull PacketBuffer> buf) { + writeCustomData(UPDATE_COVER_DATA_PIPE, buffer -> { + buffer.writeByte(cover.getAttachedSide().getIndex()); + buffer.writeVarInt(discriminator); + buf.accept(buffer); + }); + } + + public void writeInitialSyncData(PacketBuffer buf) { + CoverSaveHandler.writeInitialSyncData(buf, this); + } + + public void readInitialSyncData(PacketBuffer buf) { + CoverSaveHandler.receiveInitialSyncData(buf, this); + } + + @Override + public void writeCustomData(int dataId, @NotNull Consumer writer) { + holder.writeCustomData(dataId, writer); + } + + public void readCustomData(int dataId, PacketBuffer buf) { + if (dataId == COVER_ATTACHED_PIPE) { + CoverSaveHandler.readCoverPlacement(buf, this); + } else if (dataId == COVER_REMOVED_PIPE) { + // cover removed event + EnumFacing placementSide = EnumFacing.VALUES[buf.readByte()]; + this.covers.remove(placementSide); + holder.scheduleRenderUpdate(); + } else if (dataId == UPDATE_COVER_DATA_PIPE) { + // cover custom data received + EnumFacing coverSide = EnumFacing.VALUES[buf.readByte()]; + Cover cover = getCoverAtSide(coverSide); + int internalId = buf.readVarInt(); + if (cover != null) { + cover.readCustomData(internalId, buf); + } + } + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + CoverSaveHandler.writeCoverNBT(tag, this); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + CoverSaveHandler.readCoverNBT(nbt, this, this::addCoverSilent); + } + + @Override + public World getWorld() { + return holder.getWorld(); + } + + @Override + public BlockPos getPos() { + return holder.getPos(); + } + + public TileEntity getTileEntityHere() { + return holder; + } + + @Override + public @Nullable TileEntity getNeighbor(@NotNull EnumFacing facing) { + return holder.getNeighbor(facing); + } + + @Override + public long getOffsetTimer() { + return holder.getOffsetTimer(); + } + + @Nullable + @Override + public Cover getCoverAtSide(@NotNull EnumFacing side) { + return covers.get(side); + } + + @Override + public boolean hasAnyCover() { + return !covers.isEmpty(); + } + + @Override + public void markDirty() { + holder.markAsDirty(); + } + + @Override + public boolean isValid() { + return !holder.isInvalid(); + } + + @Override + public T getCapability(@NotNull Capability capability, EnumFacing side) { + return holder.getCapability(capability, side); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeMaterialBlock.java similarity index 54% rename from src/main/java/gregtech/api/graphnet/pipenet/block/PipeMaterialBlock.java rename to src/main/java/gregtech/api/graphnet/pipenet/physical/PipeMaterialBlock.java index 97f095fc332..41a6d8e9859 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeMaterialBlock.java @@ -1,25 +1,35 @@ -package gregtech.api.graphnet.pipenet.block; +package gregtech.api.graphnet.pipenet.physical; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.recipes.ModHandler; import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.Materials; +import gregtech.api.unification.material.info.MaterialFlags; +import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.registry.MaterialRegistry; +import gregtech.api.unification.ore.OrePrefix; import gregtech.api.util.GTUtility; import gregtech.common.ConfigHolder; import gregtech.common.blocks.properties.PropertyMaterial; import net.minecraft.block.Block; import net.minecraft.block.SoundType; +import net.minecraft.block.material.MapColor; +import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; @@ -27,31 +37,31 @@ import java.util.Collection; import java.util.List; +import java.util.Random; public abstract class PipeMaterialBlock extends PipeBlock { public final MaterialRegistry registry; public final PropertyMaterial propertyMaterial; - public PipeMaterialBlock(IPipeStructure structure, MaterialRegistry registry, Collection materials) { + public PipeMaterialBlock(IPipeMaterialStructure structure, MaterialRegistry registry, Collection materials) { super(structure); this.registry = registry; this.propertyMaterial = PropertyMaterial.create("Material", materials); + this.setDefaultState(this.blockState.getBaseState().withProperty(propertyMaterial, propertyMaterial.getAllowedValues().get(0))); } @Override - protected IBlockState constructDefaultState() { - return super.constructDefaultState().withProperty(propertyMaterial, propertyMaterial.getAllowedValues().get(0)); + public IPipeMaterialStructure getStructure() { + return (IPipeMaterialStructure) super.getStructure(); } + @NotNull @Override - protected @NotNull IPipeNetNodeHandler getHandler(IBlockState state) { - return getHandler(state.getValue(propertyMaterial)); + protected BlockStateContainer createBlockState() { + return new BlockStateContainer(this, propertyMaterial); } - @NotNull - protected abstract IPipeNetNodeHandler getHandler(Material material); - @NotNull public ItemStack getItem(@NotNull Material material) { return GTUtility.toItem(getDefaultState().withProperty(propertyMaterial, material)); @@ -77,7 +87,66 @@ public Material getGtMaterial(@NotNull IBlockState state) { @NotNull public IBlockState getBlock(@NotNull Material material) { - return super.getDefaultState().withProperty(propertyMaterial, material); + return getDefaultState().withProperty(propertyMaterial, material); + } + + @NotNull + @Override + @SuppressWarnings("deprecation") + public IBlockState getStateFromMeta(int meta) { + return getDefaultState().withProperty(propertyMaterial, getGtMaterial(meta)); + } + + @Override + public int getMetaFromState(@NotNull IBlockState state) { + return propertyMaterial.getAllowedValues().indexOf(state.getValue(propertyMaterial)); + } + + @Override + public int damageDropped(@NotNull IBlockState state) { + return getMetaFromState(state); + } + + @Override + public void getSubBlocks(@NotNull CreativeTabs tab, @NotNull NonNullList list) { + for (IBlockState state : blockState.getValidStates()) { + if (getGtMaterial(state) != Materials.NULL) { + list.add(GTUtility.toItem(state)); + } + } + } + + @NotNull + @Override + @SuppressWarnings("deprecation") + public MapColor getMapColor(@NotNull IBlockState state, @NotNull IBlockAccess worldIn, @NotNull BlockPos pos) { + return getMaterial(state).getMaterialMapColor(); + } + + @Override + public int getFlammability(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull EnumFacing face) { + Material material = getGtMaterial(world.getBlockState(pos)); + if (material.hasFlag(MaterialFlags.FLAMMABLE)) { + return 20; // flammability of things like Wood Planks + } + return super.getFlammability(world, pos, face); + } + + @Override + public int getFireSpreadSpeed(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull EnumFacing face) { + Material material = getGtMaterial(world.getBlockState(pos)); + if (material.hasFlag(MaterialFlags.FLAMMABLE)) { + return 5; // encouragement of things like Wood Planks + } + return super.getFireSpreadSpeed(world, pos, face); + } + + public OrePrefix getPrefix() { + return getStructure().getOrePrefix(); + } + @Override + protected @NotNull IPipeNetNodeHandler getHandler(IBlockState state) { + return state.getValue(propertyMaterial).getProperty(PropertyKey.PIPENET_PROPERTIES); } @Override @@ -110,6 +179,10 @@ public SoundType getSoundType(ItemStack stack) { @Override public int getHarvestLevel(@NotNull IBlockState state) { + Material material = getGtMaterial(state); + if (material.hasProperty(PropertyKey.DUST)) { + return material.getBlockHarvestLevel(); + } return 1; } @@ -128,7 +201,7 @@ public net.minecraft.block.material.Material getMaterial(@NotNull IBlockState st public void addInformation(@NotNull ItemStack stack, @Nullable World world, @NotNull List tooltip, @NotNull ITooltipFlag flag) { if (ConfigHolder.misc.debug) { - tooltip.add("MetaItem Id: pipe" + getStructureName() + getGtMaterial(stack).toCamelCaseString()); + tooltip.add("MetaItem Id: " + getStructureName() + getGtMaterial(stack).toCamelCaseString()); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeTileEntity.java new file mode 100644 index 00000000000..1a903970e17 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeTileEntity.java @@ -0,0 +1,448 @@ +package gregtech.api.graphnet.pipenet.physical; + +import gregtech.api.GregTechAPI; +import gregtech.api.capability.GregtechDataCodes; +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.cover.Cover; +import gregtech.api.graphnet.gather.GTGraphGatherables; +import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.metatileentity.NeighborCacheTileEntityBase; + +import gregtech.api.unification.material.Material; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.util.EnumMap; +import java.util.Map; +import java.util.Set; + +import static gregtech.api.capability.GregtechDataCodes.UPDATE_PAINT; + +public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITickable { + + private final Object2ObjectOpenHashMap netLogicDatas = new Object2ObjectOpenHashMap<>(); + private final ObjectOpenHashSet listeners = new ObjectOpenHashSet<>(); + + private final PipeBlock block; + + // information that is only required for determining graph topology should be stored on the tile entity level, + // while information interacted with during graph traversal should be stored on the NetLogicData level. + + private byte connectionMask; + private byte blockedMask; + private int paintingColor; + + + private Material frameMaterial; + + private final Set tickers = new ObjectOpenHashSet<>(); + + protected final PipeCoverHolder covers = new PipeCoverHolder(this); + private final Object2ObjectOpenHashMap, IPipeCapabilityObject> capabilities = new Object2ObjectOpenHashMap<>(); + private final Object2ObjectOpenHashMap netCapabilities = new Object2ObjectOpenHashMap<>(); + + private final int offset = (int) (Math.random() * 20); + + public PipeTileEntity(PipeBlock block) { + this.block = block; + } + + @Nullable + public PipeTileEntity getPipeNeighbor(EnumFacing facing) { + TileEntity tile = getNeighbor(facing); + if (tile instanceof PipeTileEntity pipe) return pipe; + else return null; + } + + public ItemStack getDrop() { + return new ItemStack(getBlockType(), 1, getBlockType().damageDropped(getBlockState())); + } + + public long getOffsetTimer() { + return FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter() + offset; + } + + // mask // + + public boolean canConnectTo(EnumFacing facing) { + return this.getBlockType().getStructure().canConnectTo(facing, connectionMask); + } + + public void setOpen(EnumFacing facing) { + this.connectionMask |= 1 << facing.ordinal(); + updateActiveStatus(facing, false); + } + + public void setClosed(EnumFacing facing) { + this.connectionMask &= ~(1 << facing.ordinal()); + updateActiveStatus(facing, false); + } + + public boolean isOpen(EnumFacing facing) { + return (this.connectionMask & 1 << facing.ordinal()) > 0; + } + + public void setBlocked(EnumFacing facing) { + this.blockedMask |= 1 << facing.ordinal(); + } + + public void setUnblocked(EnumFacing facing) { + this.blockedMask &= ~(1 << facing.ordinal()); + } + + public boolean isBlocked(EnumFacing facing) { + return (this.blockedMask & 1 << facing.ordinal()) > 0; + } + + // paint // + + public int getPaintingColor() { + return isPainted() ? paintingColor : getDefaultPaintingColor(); + } + + public void setPaintingColor(int paintingColor) { + this.paintingColor = paintingColor; + if (!getWorld().isRemote) { + writeCustomData(UPDATE_PAINT, buffer -> buffer.writeInt(paintingColor)); + markDirty(); + } + } + + public boolean isPainted() { + return this.paintingColor != -1; + } + + public int getDefaultPaintingColor() { + return 0xFFFFFF; + } + + // frame // + + public void setFrameMaterial(Material frameMaterial) { + this.frameMaterial = frameMaterial; + } + + public Material getFrameMaterial() { + return frameMaterial; + } + + // ticking // + + public void addTicker(ITickable ticker) { + this.tickers.add(ticker); + //noinspection ConstantValue + if (getWorld() != null) getWorld().tickableTileEntities.add(this); + } + + @Override + public void update() { + this.tickers.forEach(ITickable::update); + } + + @Override + public void onLoad() { + super.onLoad(); + // since we're an instance of ITickable, we're automatically added to the tickable list just before this exact moment. + // it would theoretically be a micro optimization to just pop the last tile from the tickable list, but that's not guaranteed. + if (!this.isTicking()) this.getWorld().tickableTileEntities.remove(this); + } + + public void removeTicker(ITickable ticker) { + this.tickers.remove(this); + //noinspection ConstantValue + if (!this.isTicking() && getWorld() != null) getWorld().tickableTileEntities.remove(this); + } + + public boolean isTicking() { + return !tickers.isEmpty(); + } + + // cover // + + public PipeCoverHolder getCoverHolder() { + return covers; + } + + // activeness // + + @Override + public void onNeighborChanged(@NotNull EnumFacing facing) { + super.onNeighborChanged(facing); + updateActiveStatus(facing, false); + } + + /** + * Returns a map of facings to tile entities that should have at least one of the required capabilities. + * @param node the node for this tile entity. Used to identify the capabilities to match. + * @return a map of facings to tile entities. + */ + public EnumMap getTargetsWithCapabilities(WorldPipeNetNode node) { + PipeCapabilityWrapper wrapper = netCapabilities.get(node); + EnumMap caps = new EnumMap<>(EnumFacing.class); + if (wrapper == null) return caps; + + for (EnumFacing facing : EnumFacing.VALUES) { + if (wrapper.isActive(facing)) { + TileEntity tile = getNeighbor(facing); + if (tile == null || tile instanceof PipeTileEntity) updateActiveStatus(facing, false); + else caps.put(facing, tile); + } + } + return caps; + } + + public void updateActiveStatus(@Nullable EnumFacing facing, boolean canOpenConnection) { + if (facing == null) { + for (EnumFacing side : EnumFacing.VALUES) { + updateActiveStatus(side, canOpenConnection); + } + return; + } + if (!this.isOpen(facing) && !canOpenConnection) { + setAllIdle(facing); + return; + } + + TileEntity tile = getNeighbor(facing); + if (tile == null || tile instanceof PipeTileEntity) { + setAllIdle(facing); + return; + } + + boolean oneActive = false; + for (var netCapability : netCapabilities.entrySet()) { + boolean oneMatch = false; + for (Capability cap : netCapability.getValue().capabilities) { + if (tile.hasCapability(cap, facing.getOpposite())) { + oneMatch = true; + oneActive = true; + break; + } + } + netCapability.getKey().setActive(oneMatch); + } + if (oneActive) this.setOpen(facing); + } + + private void setAllIdle(EnumFacing facing) { + for (var netCapability : netCapabilities.entrySet()) { + netCapability.getValue().setIdle(facing); + netCapability.getKey().setActive(false); + } + } + + // capability // + + private void addCapabilities(IPipeCapabilityObject[] capabilities) { + for (IPipeCapabilityObject capabilityObject : capabilities) { + capabilityObject.setTile(this); + for (Capability capability : capabilityObject.getCapabilities()) { + this.capabilities.put(capability, capabilityObject); + } + } + } + + @Override + public boolean hasCapability(@NotNull Capability capability, EnumFacing facing) { + return getCapability(capability, facing) != null; + } + + @Override + public T getCapability(@NotNull Capability capability, @Nullable EnumFacing facing) { + if (capability == GregtechTileCapabilities.CAPABILITY_COVER_HOLDER) { + return GregtechTileCapabilities.CAPABILITY_COVER_HOLDER.cast(getCoverHolder()); + } + T pipeCapability = capabilities.get(capability).getCapabilityForSide(capability, facing); + if (pipeCapability == null) pipeCapability = super.getCapability(capability, facing); + + Cover cover = facing == null ? null : getCoverHolder().getCoverAtSide(facing); + if (cover == null) { + if (facing == null || isOpen(facing)) { + return pipeCapability; + } + return null; + } + + T coverCapability = cover.getCapability(capability, pipeCapability); + if (coverCapability == pipeCapability) { + if (isOpen(facing)) { + return pipeCapability; + } + return null; + } + return coverCapability; + } + + // data sync management // + + public NetLogicData getNetLogicData(String netName) { + return netLogicDatas.get(netName); + } + + @Override + public @NotNull PipeBlock getBlockType() { + return block; + } + + @Override + public void setWorld(@NotNull World worldIn) { + if (worldIn == this.getWorld()) return; + super.setWorld(worldIn); + if (!worldIn.isRemote) { + this.netLogicDatas.clear(); + this.capabilities.clear(); + this.netCapabilities.clear(); + this.listeners.forEach(NetLogicData.LogicDataListener::invalidate); + this.listeners.clear(); + for (WorldPipeNetNode node : getBlockType().getNodesForTile(this)) { + this.addCapabilities(node.getNet().getNewCapabilityObjects(node)); + this.netCapabilities.put(node, new PipeCapabilityWrapper(node.getNet().getTargetCapabilities())); + String netName = node.getNet().mapName; + netLogicDatas.put(netName, node.getData()); + var listener = node.getData().new LogicDataListener((e, r, f) -> + writeCustomData(GregtechDataCodes.UPDATE_PIPE_LOGIC, buf -> { + buf.writeString(netName); + buf.writeString(e.getName()); + buf.writeBoolean(r); + buf.writeBoolean(f); + if (!r) { + e.encode(buf); + } + })); + this.listeners.add(listener); + node.getData().addListener(listener); + } + this.netLogicDatas.trim(); + this.listeners.trim(); + this.capabilities.trim(); + this.netCapabilities.trim(); + } + } + + @Override + public @NotNull NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { + super.writeToNBT(compound); + compound.setByte("ConnectionMask", connectionMask); + compound.setByte("BlockedMask", blockedMask); + compound.setInteger("Paint", paintingColor); + compound.setString("Frame", frameMaterial.getRegistryName()); + compound.setTag("Covers", getCoverHolder().serializeNBT()); + return compound; + } + + @Override + public void readFromNBT(@NotNull NBTTagCompound compound) { + super.readFromNBT(compound); + connectionMask = compound.getByte("ConnectionMask"); + blockedMask = compound.getByte("BlockedMask"); + paintingColor = compound.getInteger("Paint"); + this.frameMaterial = GregTechAPI.materialManager.getMaterial(compound.getString("Frame")); + this.getCoverHolder().deserializeNBT(compound.getCompoundTag("Covers")); + } + + @Override + public void writeInitialSyncData(@NotNull PacketBuffer buf) { + NBTTagCompound tag = new NBTTagCompound(); + for (Map.Entry entry : netLogicDatas.entrySet()) { + tag.setTag(entry.getKey(), entry.getValue().serializeNBT()); + } + buf.writeCompoundTag(tag); + } + + @Override + public void receiveInitialSyncData(@NotNull PacketBuffer buf) { + if (world.isRemote) { + netLogicDatas.clear(); + try { + NBTTagCompound logics = buf.readCompoundTag(); + if (logics == null) return; + for (String name : logics.getKeySet()) { + NetLogicData data = new NetLogicData(); + data.deserializeNBT((NBTTagList) logics.getTag("LogicData")); + netLogicDatas.put(name, data); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + @Override + public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { + if (discriminator == GregtechDataCodes.UPDATE_PIPE_LOGIC) { + // extra check just to make sure we don't affect actual net data with our writes + if (world.isRemote) { + String netName = buf.readString(255); + String identifier = buf.readString(255); + boolean removed = buf.readBoolean(); + boolean fullChange = buf.readBoolean(); + if (removed) { + this.netLogicDatas.computeIfPresent(netName, (k, v) -> v.removeLogicEntry(identifier)); + } else { + INetLogicEntry logic = GTGraphGatherables.getLogicsRegistry() + .getOrDefault(identifier, () -> null).get(); + logic.decode(buf, fullChange); + this.netLogicDatas.compute(netName, (k, v) -> { + if (v == null) v = new NetLogicData(); + v.setLogicEntry(logic); + return v; + }); + } + } + } else { + this.getCoverHolder().readCustomData(discriminator, buf); + } + } + + // misc overrides // + + @Override + public World world() { + return getWorld(); + } + + @Override + public BlockPos pos() { + return getPos(); + } + + @Override + public void notifyBlockUpdate() { + getWorld().notifyNeighborsOfStateChange(getPos(), getBlockType(), true); + } + + + @SuppressWarnings("ConstantConditions") // yes this CAN actually be null + @Override + public void markDirty() { + if (getWorld() != null && getPos() != null) { + getWorld().markChunkDirty(getPos(), this); + } + } + + @Override + public void markAsDirty() { + markDirty(); + // this most notably gets called when the covers of a pipe get updated, aka the edge predicates need syncing. + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java index 8488aa98c99..1b63c7f8bc6 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java @@ -247,7 +247,7 @@ public void setPaintingColor(int paintingColor) { this.paintingColor = paintingColor; if (!getWorld().isRemote) { getPipeBlock().getWorldPipeNet(getWorld()).updateMark(getPos(), getCableMark()); - writeCustomData(UPDATE_INSULATION_COLOR, buffer -> buffer.writeInt(paintingColor)); + writeCustomData(UPDATE_PAINT, buffer -> buffer.writeInt(paintingColor)); markDirty(); } } @@ -545,7 +545,7 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { this.tickingPipe.receiveCustomData(discriminator, buf); return; } - if (discriminator == UPDATE_INSULATION_COLOR) { + if (discriminator == UPDATE_PAINT) { this.paintingColor = buf.readInt(); } else if (discriminator == UPDATE_CONNECTIONS) { this.getNode().setOpenConnections(buf.readVarInt()); diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java index 77d9bf7061a..41767edd54f 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java @@ -1,4 +1,5 @@ package gregtech.api.graphnet.predicate.test; public interface IPredicateTestObject { + IPredicateTestObject INSTANCE = new IPredicateTestObject() {}; } diff --git a/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java new file mode 100644 index 00000000000..7d5fd615b55 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java @@ -0,0 +1,44 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import org.jetbrains.annotations.Nullable; + +public abstract class AbstractTraverseData> implements ITraverseData { + + private final IGraphNet net; + private final IPredicateTestObject testObject; + private final SimulatorKey simulator; + private final long queryTick; + + public AbstractTraverseData(IGraphNet net, IPredicateTestObject testObject, SimulatorKey simulator, long queryTick) { + this.net = net; + this.testObject = testObject; + this.simulator = simulator; + this.queryTick = queryTick; + } + + @Override + public IGraphNet getGraphNet() { + return net; + } + + @Override + public IPredicateTestObject getTestObject() { + return testObject; + } + + @Override + public @Nullable SimulatorKey getSimulatorKey() { + return simulator; + } + + @Override + public long getQueryTick() { + return queryTick; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java new file mode 100644 index 00000000000..3294e6c183b --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java @@ -0,0 +1,47 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import org.jetbrains.annotations.Nullable; + +public interface ITraverseData> { + + IGraphNet getGraphNet(); + + IPredicateTestObject getTestObject(); + + @Nullable SimulatorKey getSimulatorKey(); + + long getQueryTick(); + + /** + * Called before walking the next path. Should reset per-path logics to prepare. + * @param path the next path + * @return whether the path should be skipped + */ + boolean prepareForPathWalk(P path); + + /** + * Reports that the traverse is traversing to a node, for additional logic to be run. + * + * @param node the node being traversed + * @param flowReachingNode the flow that has reached this node. + * @return the flow continuing onward after loss is applied. + */ + long traverseToNode(N node, long flowReachingNode); + + /** + * Reports that the traverse has finished a path walk, for finalization. + * + * @param destination the active node the path terminated at. + * @param flowReachingDestination the flow that reached the destination + * @return the amount of flow that should be consumed, before walking the next path. + */ + long finalizeAtDestination(N destination, long flowReachingDestination); +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java new file mode 100644 index 00000000000..ad9dfd55878 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -0,0 +1,149 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.edge.util.FlowConsumerList; +import gregtech.api.graphnet.path.INetPath; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +public final class TraverseHelpers { + + private TraverseHelpers() {} + + /** + * Provides logic for traversing a flow net in a 'flood' manner; + * specifically, find the lowest weight path, fill it to capacity, find the next lowest weight path, etc. + * Requires dynamic weights to function properly. + * + * @param data the traversal data. + * @param paths the paths to traverse. + * @param flowIn the flow to traverse with. + * @return the consumed flow. + */ + public static , D extends ITraverseData> long traverseFlood( + @NotNull D data, + @NotNull Iterator

paths, + long flowIn) { + long availableFlow = flowIn; + pathloop: + while (paths.hasNext()) { + long pathFlowIn = availableFlow; + long pathFlow = availableFlow; + P path = paths.next(); + if (data.prepareForPathWalk(path)) continue; + + List nodes = path.getOrderedNodes(); + List edges = path.getOrderedEdges(); + FlowConsumerList flowConsumers = new FlowConsumerList(); + assert nodes.size() == edges.size() + 1; + + N targetNode = nodes.get(0); + pathFlow = data.traverseToNode(targetNode, pathFlow); + + for (int i = 0; i < edges.size(); i++) { + E edge = edges.get(i); + targetNode = nodes.get(i + 1); + long flowLimit = edge.getFlowLimit(data.getTestObject(), data.getGraphNet(), data.getQueryTick(), data.getSimulatorKey()); + if (flowLimit < pathFlow) { + double ratio = (double) flowLimit / pathFlow; + flowConsumers.modifyRatios(ratio); + pathFlowIn *= ratio; + pathFlow = flowLimit; + } + flowConsumers.add(edge, data.getTestObject(), data.getGraphNet(), pathFlow, data.getQueryTick(), data.getSimulatorKey()); + pathFlow = data.traverseToNode(targetNode, pathFlow); + + if (pathFlow <= 0) continue pathloop; + } + long accepted = data.finalizeAtDestination(targetNode, pathFlow); + double ratio = (double) accepted / pathFlow; + flowConsumers.doConsumption(ratio); + availableFlow -= pathFlowIn * ratio; + + if (availableFlow <= 0) break; + } + + return flowIn - availableFlow; + } + + /** + * Provides logic for traversing a net that simply finds the lowest weight path that it can traverse, + * and then traverses it. Optionally supports flow, in which case overflows will be reported + * and paths will be iterated over until flow or paths are exhausted. + * + * @param data the traversal data. + * @param paths the paths to traverse. + * @param overflowListener will be provided with a node and incoming overflow once a path is walked + * and the final overflows are calculated. If null, no overflow logic will be calculated. + * @param flowIn the flow to traverse with. + * @return the consumed flow. + */ + public static , D extends ITraverseData> long traverseDumb( + @NotNull D data, + @NotNull Iterator

paths, + @Nullable BiConsumer overflowListener, + long flowIn) { + long availableFlow = flowIn; + pathloop: + while (paths.hasNext()) { + long pathFlowIn = availableFlow; + long pathFlow = availableFlow; + P path = paths.next(); + if (data.prepareForPathWalk(path)) continue; + + List nodes = path.getOrderedNodes(); + List edges = path.getOrderedEdges(); + + FlowConsumerList flowConsumers = overflowListener == null ? null : new FlowConsumerList(); + List> overflowReporters = overflowListener == null ? null : new ObjectArrayList<>(); + assert nodes.size() == edges.size() + 1; + + N targetNode = nodes.get(0); + pathFlow = data.traverseToNode(targetNode, pathFlow); + + for (int i = 0; i < edges.size(); i++) { + E edge = edges.get(i); + targetNode = nodes.get(i + 1); + if (overflowListener != null && edge instanceof AbstractNetFlowEdge flowEdge) { + long flowLimit = flowEdge.getFlowLimit(data.getTestObject(), data.getGraphNet(), data.getQueryTick(), data.getSimulatorKey()); + if (flowLimit < pathFlow) { + long overflow = pathFlow - flowLimit; + N finalTargetNode = targetNode; + overflowReporters.add(reduction -> { + long finalOverflow = overflow - reduction; + if (finalOverflow > 0) overflowListener.accept(finalTargetNode, finalOverflow); + }); + pathFlow = flowLimit; + } + flowConsumers.add(flowEdge, data.getTestObject(), data.getGraphNet(), pathFlow, data.getQueryTick(), data.getSimulatorKey()); + } + pathFlow = data.traverseToNode(targetNode, pathFlow); + + if (pathFlow <= 0) continue pathloop; + } + long accepted = data.finalizeAtDestination(targetNode, pathFlow); + long unaccepted = pathFlow - accepted; + if (overflowListener != null) { + flowConsumers.doConsumption(unaccepted); + overflowReporters.forEach((c) -> c.accept(unaccepted)); + } + availableFlow -= pathFlowIn - unaccepted; + + if (availableFlow <= 0) break; + } + + return flowIn - availableFlow; + } +} diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java index e1732d94412..7cdbc5573cf 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -1,5 +1,6 @@ package gregtech.api.graphnet.worldnet; +import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.path.GenericGraphNetPath; import gregtech.api.graphnet.GraphNetBacker; import gregtech.api.graphnet.IGraphNet; @@ -15,6 +16,8 @@ import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -26,7 +29,7 @@ import java.util.Iterator; import java.util.function.Function; -public abstract class WorldNet extends WorldSavedData implements IGraphNet { +public abstract class WorldNet extends WorldSavedData implements IGraphNet, GenericGraphNetPath.Provider { protected final GraphNetBacker backer; private World world; @@ -51,8 +54,10 @@ public World getWorld() { return world; } - public Iterator getGenericPaths(WorldNetNode node) { - return backer.getPaths(node, GenericGraphNetPath.MAPPER); + @Override + public Iterator getPaths(NetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + nodeClassCheck(node); + return backer.getPaths(node, GenericGraphNetPath.MAPPER, testObject, simulator, queryTick); } @NotNull diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index 607ab104044..b44e25fdd74 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -1,16 +1,29 @@ package gregtech.api.unification.material.properties; +import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; -import gregtech.api.graphnet.pipenet.block.IPipeStructure; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; + +import gregtech.api.graphnet.worldnet.WorldNetNode; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.List; import java.util.Map; +import java.util.Set; public class PipeNetProperties implements IMaterialProperty, IPipeNetNodeHandler { @@ -31,10 +44,22 @@ public void addToNets(World world, BlockPos pos, IPipeStructure structure) { } } + @Override + public Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { + List list = new ObjectArrayList<>(); + for (IPipeNetMaterialProperty p : properties.values()) { + if (p.supportedStructure(structure)) { + WorldPipeNetNode node = p.getFromNet(world, pos, structure); + if (node != null) list.add(node); + } + } + return list; + } + @Override public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) { for (IPipeNetMaterialProperty p : properties.values()) { - if (p.supportedStructure(structure)) p.removeFromNet(world, pos); + if (p.supportedStructure(structure)) p.removeFromNet(world, pos, structure); } } @@ -49,7 +74,10 @@ public interface IPipeNetMaterialProperty extends IMaterialProperty, IStringSeri void addToNet(World world, BlockPos pos, IPipeStructure structure); - void removeFromNet(World world, BlockPos pos); + @Nullable + WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure); + + void removeFromNet(World world, BlockPos pos, IPipeStructure structure); boolean supportedStructure(IPipeStructure structure); } diff --git a/src/main/java/gregtech/common/blocks/properties/PropertyShort.java b/src/main/java/gregtech/common/blocks/properties/PropertyShort.java new file mode 100644 index 00000000000..87fc052920c --- /dev/null +++ b/src/main/java/gregtech/common/blocks/properties/PropertyShort.java @@ -0,0 +1,91 @@ +package gregtech.common.blocks.properties; + + +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSet; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.block.properties.PropertyHelper; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Set; + +public class PropertyShort extends PropertyHelper { + private final ImmutableSet allowedValues; + + protected PropertyShort(String name, short min, short max) { + super(name, Short.class); + + if (min < 0) { + throw new IllegalArgumentException("Min value of " + name + " must be 0 or greater"); + } + else if (max <= min) { + throw new IllegalArgumentException("Max value of " + name + " must be greater than min (" + min + ")"); + } + else { + Set set = new ObjectOpenHashSet<>(); + + for (short i = min; i <= max; ++i) + { + set.add(i); + } + + this.allowedValues = ImmutableSet.copyOf(set); + } + } + + @Override + public @NotNull Collection getAllowedValues() + { + return this.allowedValues; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + else if (other instanceof PropertyShort propertyByte && super.equals(other)) { + return this.allowedValues.equals(propertyByte.allowedValues); + } + else + { + return false; + } + } + + @Override + public int hashCode() + { + return 31 * super.hashCode() + this.allowedValues.hashCode(); + } + + @Contract("_, _, _ -> new") + public static @NotNull PropertyShort create(String name, short min, short max) + { + return new PropertyShort(name, min, max); + } + + @SuppressWarnings("Guava") + @Override + public @NotNull Optional parseValue(@NotNull String value) { + try { + Short val = Short.valueOf(value); + return this.allowedValues.contains(val) ? Optional.of(val) : Optional.absent(); + } catch (NumberFormatException var3) { + return Optional.absent(); + } + } + + /** + * Get the name for the given value. + */ + @Override + public @NotNull String getName(Short value) + { + return value.toString(); + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/CableEnergyProperties.java b/src/main/java/gregtech/common/pipelike/block/CableEnergyProperties.java deleted file mode 100644 index 888745cf99c..00000000000 --- a/src/main/java/gregtech/common/pipelike/block/CableEnergyProperties.java +++ /dev/null @@ -1,58 +0,0 @@ -package gregtech.common.pipelike.block; - -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.logic.LossAbsoluteLogic; -import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.pipenet.block.CableStructure; -import gregtech.api.graphnet.pipenet.block.IPipeStructure; -import gregtech.api.unification.material.properties.MaterialProperties; -import gregtech.api.unification.material.properties.PipeNetProperties; - -import gregtech.common.pipelike.net.EnergyNet; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import org.jetbrains.annotations.NotNull; - -public class CableEnergyProperties implements PipeNetProperties.IPipeNetMaterialProperty { - - private final long voltageLimit; - private final long amperageLimit; - private final int temperatureLimit; - private final int lossPerAmp; - - public CableEnergyProperties(long voltageLimit, long amperageLimit, int temperatureLimit, int lossPerAmp) { - this.voltageLimit = voltageLimit; - this.amperageLimit = amperageLimit; - this.temperatureLimit = temperatureLimit; - this.lossPerAmp = lossPerAmp; - } - - @Override - public @NotNull String getName() { - return "cableEnergy"; - } - - @Override - public void verifyProperty(MaterialProperties properties) {} - - @Override - public void addToNet(World world, BlockPos pos, IPipeStructure structure) { - assert structure instanceof CableStructure; - NetLogicData newData = EnergyNet.getWorldNet(world).getOrCreateNode(pos).getData(); - newData.setLogicEntry(new LossAbsoluteLogic().setValue(lossPerAmp)); - } - - @Override - public void removeFromNet(World world, BlockPos pos) { - EnergyNet net = EnergyNet.getWorldNet(world); - NetNode node = net.getNode(pos); - if (node != null) net.removeNode(node); - } - - @Override - public boolean supportedStructure(IPipeStructure structure) { - return structure.getClass() == CableStructure.class; - } -} diff --git a/src/main/java/gregtech/common/pipelike/block/PipeFluidProperties.java b/src/main/java/gregtech/common/pipelike/block/PipeFluidProperties.java deleted file mode 100644 index 0df7f293cc3..00000000000 --- a/src/main/java/gregtech/common/pipelike/block/PipeFluidProperties.java +++ /dev/null @@ -1,4 +0,0 @@ -package gregtech.common.pipelike.block; - -public class PipeFluidProperties { -} diff --git a/src/main/java/gregtech/common/pipelike/block/PipeItemProperties.java b/src/main/java/gregtech/common/pipelike/block/PipeItemProperties.java deleted file mode 100644 index 496507d8ddd..00000000000 --- a/src/main/java/gregtech/common/pipelike/block/PipeItemProperties.java +++ /dev/null @@ -1,4 +0,0 @@ -package gregtech.common.pipelike.block; - -public class PipeItemProperties { -} diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java new file mode 100644 index 00000000000..f754e41abae --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -0,0 +1,48 @@ +package gregtech.common.pipelike.block.cable; + +import gregtech.api.graphnet.pipenet.physical.IBurnable; +import gregtech.api.graphnet.pipenet.physical.PipeMaterialBlock; +import gregtech.api.unification.material.Material; + +import gregtech.api.unification.material.registry.MaterialRegistry; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import org.apache.commons.lang3.tuple.Pair; + +import java.util.Collection; +import java.util.Map; + +public class CableBlock extends PipeMaterialBlock implements IBurnable { + + private static final Map> CACHE = new Object2ObjectOpenHashMap<>(); + + public CableBlock(CableStructure structure, MaterialRegistry registry, Collection materials) { + super(structure, registry, materials); + CACHE.compute(registry, (k, v) -> { + if (v == null) v = new Object2ObjectOpenHashMap<>(); + v.put(structure, this); + return v; + }); + } + + @Override + public void partialBurn(IBlockState state, World world, BlockPos pos) { + CableStructure structure = (CableStructure) getStructure(); + if (structure.partialBurnStructure() != null) { + CableBlock newBlock = CACHE.get(registry).get(structure.partialBurnStructure()); + world.setBlockState(pos, newBlock.getStateFromMeta(this.getMetaFromState(state))); + } + } + + // TODO + @Override + protected Pair getParticleTexture(World world, BlockPos blockPos) { + return null; + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableEnergyProperties.java b/src/main/java/gregtech/common/pipelike/block/cable/CableEnergyProperties.java new file mode 100644 index 00000000000..b8d6f747b42 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableEnergyProperties.java @@ -0,0 +1,139 @@ +package gregtech.common.pipelike.block.cable; + +import gregtech.api.GTValues; +import gregtech.api.fluids.FluidBuilder; +import gregtech.api.fluids.store.FluidStorageKeys; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.logic.TemperatureLogic; +import gregtech.api.graphnet.logic.TemperatureRestorationFunction; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.properties.FluidProperty; +import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.unification.material.properties.MaterialProperties; +import gregtech.api.unification.material.properties.PipeNetProperties; + +import gregtech.common.pipelike.net.energy.SuperconductorLogic; +import gregtech.common.pipelike.net.energy.WorldEnergyNet; + +import gregtech.common.pipelike.net.energy.VoltageLimitLogic; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import net.minecraftforge.fluids.Fluid; + +import org.jetbrains.annotations.NotNull; + +import static gregtech.api.unification.material.info.MaterialFlags.GENERATE_FOIL; + +public class CableEnergyProperties implements PipeNetProperties.IPipeNetMaterialProperty { + + public static final int INSULATION_BURN_TEMP = 1000; + + private final long voltageLimit; + private final long amperageLimit; + private int temperatureLimit; + private final long lossPerAmp; + /** + * + */ + private final int superconductorTemperature; + + /** + * Generate a CableEnergyProperties + * @param voltageLimit the voltage limit for the cable + * @param amperageLimit the base amperage for the cable. + * @param temperatureLimit the melt temperature of the cable. If zero, autogeneration will be attempted. + * @param lossPerAmp the base loss per amp per block traveled. + * @param superconductorTemperature the superconductor temperature. When the temperature is at or below + * superconductor temperature, loss will be treated as zero. A superconductor + * temperature of 0 or less will be treated as not a superconductor. + */ + public CableEnergyProperties(long voltageLimit, long amperageLimit, int temperatureLimit, long lossPerAmp, int superconductorTemperature) { + this.voltageLimit = voltageLimit; + this.amperageLimit = amperageLimit; + this.temperatureLimit = temperatureLimit; + this.lossPerAmp = lossPerAmp; + this.superconductorTemperature = superconductorTemperature; + } + + public boolean isSuperconductor() { + return this.superconductorTemperature > 1; + } + + @Override + public @NotNull String getName() { + return "cableEnergy"; + } + + @Override + public void verifyProperty(MaterialProperties properties) { + properties.ensureSet(PropertyKey.DUST, true); + if (properties.hasProperty(PropertyKey.INGOT)) { + // Ensure all Materials with Cables and voltage tier IV or above have a Foil for recipe generation + Material thisMaterial = properties.getMaterial(); + if (!isSuperconductor() && voltageLimit >= GTValues.V[GTValues.IV] && !thisMaterial.hasFlag(GENERATE_FOIL)) { + thisMaterial.addFlags(GENERATE_FOIL); + } + } + if (this.temperatureLimit == 0 && properties.hasProperty(PropertyKey.FLUID)) { + // autodetermine melt temperature from registered fluid + FluidProperty prop = properties.getProperty(PropertyKey.FLUID); + Fluid fluid = prop.getStorage().get(FluidStorageKeys.LIQUID); + if (fluid == null) { + FluidBuilder builder = prop.getStorage().getQueuedBuilder(FluidStorageKeys.LIQUID); + if (builder != null) { + this.temperatureLimit = builder.currentTemp(); + } + } else { + this.temperatureLimit = fluid.getTemperature(); + } + } + } + + @Override + public void addToNet(World world, BlockPos pos, IPipeStructure structure) { + assert structure instanceof CableStructure; + CableStructure cable = (CableStructure) structure; + long loss = lossPerAmp * cable.costFactor(); + long amperage = amperageLimit * cable.material(); + boolean insulated = cable.partialBurnStructure() != null; + // insulated cables cool down half as fast + float coolingFactor = (float) (Math.sqrt(cable.material()) / (insulated ? 8 : 4)); + WorldPipeNetNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); + NetLogicData newData = node.getData(); + newData.setLogicEntry(LossAbsoluteLogic.INSTANCE.getWith(loss)) + .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) + .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) + .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) + .setLogicEntry(TemperatureLogic.INSTANCE + .getWith(TemperatureRestorationFunction.GEOMETRIC_ARITHMETIC, coolingFactor, temperatureLimit, + insulated ? INSULATION_BURN_TEMP : null, 1, 100 * cable.material())); + if (superconductorTemperature > 0) { + newData.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorTemperature)); + } + } + + @Override + public WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { + return WorldEnergyNet.getWorldNet(world).getNode(pos); + } + + @Override + public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { + WorldEnergyNet net = WorldEnergyNet.getWorldNet(world); + NetNode node = net.getNode(pos); + if (node != null) net.removeNode(node); + } + + @Override + public boolean supportedStructure(IPipeStructure structure) { + return structure.getClass() == CableStructure.class; + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java new file mode 100644 index 00000000000..1db38b31bb1 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java @@ -0,0 +1,63 @@ +package gregtech.common.pipelike.block.cable; + +import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; + +import gregtech.api.unification.ore.OrePrefix; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Consumer; + +public record CableStructure(String name, int material, int costFactor, OrePrefix ore, @Nullable CableStructure partialBurnStructure, float renderThickness) implements IPipeMaterialStructure { + + public static final CableStructure WIRE_SINGLE = + new CableStructure("wire_single", 1, 2, OrePrefix.wireGtSingle, null, 0.125f); + public static final CableStructure WIRE_DOUBLE = + new CableStructure("wire_double", 2, 2, OrePrefix.wireGtDouble, null, 0.25f); + public static final CableStructure WIRE_QUADRUPLE = + new CableStructure("wire_quadruple", 4, 3, OrePrefix.wireGtQuadruple, null, 0.375f); + public static final CableStructure WIRE_OCTAL = + new CableStructure("wire_octal", 8, 3, OrePrefix.wireGtOctal, null, 0.5f); + public static final CableStructure WIRE_HEX = + new CableStructure("wire_hex", 16, 3, OrePrefix.wireGtHex, null, 0.75f); + + public static final CableStructure CABLE_SINGLE = + new CableStructure("cable_single", 1, 1, OrePrefix.cableGtSingle, WIRE_SINGLE, 0.25f); + public static final CableStructure CABLE_DOUBLE = + new CableStructure("cable_double", 2, 1, OrePrefix.cableGtDouble, WIRE_DOUBLE, 0.375f); + public static final CableStructure CABLE_QUADRUPLE = + new CableStructure("cable_quadruple", 4, 1, OrePrefix.cableGtQuadruple, WIRE_QUADRUPLE, 0.5f); + public static final CableStructure CABLE_OCTAL = + new CableStructure("cable_octal", 8, 1, OrePrefix.cableGtOctal, WIRE_OCTAL, 0.75f); + public static final CableStructure CABLE_HEX = + new CableStructure("cable_hex", 16, 1, OrePrefix.cableGtHex, WIRE_HEX, 1f); + + @Override + public @NotNull String getName() { + return this.name(); + } + + @Override + public OrePrefix getOrePrefix() { + return this.ore(); + } + + @Override + public float getRenderThickness() { + return renderThickness(); + } + + public static void registerDefaultStructures(Consumer register) { + register.accept(WIRE_SINGLE); + register.accept(WIRE_DOUBLE); + register.accept(WIRE_QUADRUPLE); + register.accept(WIRE_OCTAL); + register.accept(WIRE_HEX); + register.accept(CABLE_SINGLE); + register.accept(CABLE_DOUBLE); + register.accept(CABLE_QUADRUPLE); + register.accept(CABLE_OCTAL); + register.accept(CABLE_HEX); + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeFluidProperties.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeFluidProperties.java new file mode 100644 index 00000000000..85326b150f5 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeFluidProperties.java @@ -0,0 +1,4 @@ +package gregtech.common.pipelike.block.pipe; + +public class PipeFluidProperties { +} diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeItemProperties.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeItemProperties.java new file mode 100644 index 00000000000..e0c457ebf86 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeItemProperties.java @@ -0,0 +1,4 @@ +package gregtech.common.pipelike.block.pipe; + +public class PipeItemProperties { +} diff --git a/src/main/java/gregtech/common/pipelike/net/EnergyNet.java b/src/main/java/gregtech/common/pipelike/net/EnergyNet.java deleted file mode 100644 index 5eb6459d983..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/EnergyNet.java +++ /dev/null @@ -1,42 +0,0 @@ -package gregtech.common.pipelike.net; - -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; -import gregtech.api.graphnet.pipenet.WorldPipeNet; - -import net.minecraft.world.World; - -import org.jetbrains.annotations.NotNull; - -import java.util.Iterator; - -public final class EnergyNet extends WorldPipeNet { - - private static final String DATA_ID_BASE = "gregtech.energy_net"; - - public static EnergyNet getWorldNet(World world) { - final String DATA_ID = getDataID(DATA_ID_BASE, world); - EnergyNet net = (EnergyNet) world.loadData(EnergyNet.class, DATA_ID); - if (net == null) { - net = new EnergyNet(DATA_ID); - world.setData(DATA_ID, net); - } - return net; - } - - public EnergyNet(String name) { - super(name, DynamicWeightsShortestPathsAlgorithm::new, false); - } - - public Iterator getPaths(NetNode node) { - return backer.getPaths(node, FlowWorldPipeNetPath.MAPPER); - } - - @Override - public @NotNull NetEdge getNewEdge() { - return new NetFlowEdge(1); - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java new file mode 100644 index 00000000000..350b3d00c24 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -0,0 +1,171 @@ +package gregtech.common.pipelike.net.energy; + +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.capability.IEnergyContainer; +import gregtech.api.graphnet.AbstractGroupData; +import gregtech.api.graphnet.NetGroup; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.edge.util.FlowConsumer; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.PipeTileEntity; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.traverse.TraverseHelpers; +import gregtech.api.util.GTLog; +import gregtech.common.pipelikeold.cable.net.EnergyGroupData; + +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.Capability; + +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumMap; +import java.util.Iterator; + +public class EnergyCapabilityObject implements IPipeCapabilityObject, IEnergyContainer { + + private final WorldPipeNet net; + private final FlowWorldPipeNetPath.Provider provider; + private @Nullable PipeTileEntity tile; + + private final EnumMap internalBuffers = new EnumMap<>(EnumFacing.class); + + private boolean transferring = false; + + public EnergyCapabilityObject(@NotNull N net, WorldPipeNetNode node) { + // eh, duplicate references so what + this.net = net; + this.provider = net; + for (EnumFacing facing : EnumFacing.VALUES) { + AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); + edge.setData(NetLogicData.union(node.getData(), (NetLogicData) null)); + internalBuffers.put(facing, edge); + } + } + + @Override + public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { + if (tile == null || this.transferring) return 0; + this.transferring = true; + + SimulatorKey simulator = null; + if (simulate) simulator = SimulatorKey.getNewSimulatorInstance(); + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + + AbstractNetFlowEdge internalBuffer = this.internalBuffers.get(side); + long limit = internalBuffer.getFlowLimit(IPredicateTestObject.INSTANCE, net, tick, simulator); + if (limit <= 0) return 0; + + long availableAmperage = Math.min(amperage, limit); + FlowConsumer consumer = new FlowConsumer(internalBuffer, IPredicateTestObject.INSTANCE, net, availableAmperage, + tick, simulator); + + EnergyTraverseData data = new EnergyTraverseData(net, IPredicateTestObject.INSTANCE, simulator, tick, voltage, + tile.getPos(), side); + availableAmperage -= TraverseHelpers.traverseFlood(data, getPaths(data), amperage); + if (availableAmperage > 0) { + TraverseHelpers.traverseDumb(data, getPaths(data), data::handleOverflow, availableAmperage); + } + data.runPostActions(); + + consumer.finalReduction(availableAmperage); + this.transferring = false; + return amperage - availableAmperage; + } + + private Iterator getPaths(EnergyTraverseData data) { + assert tile != null; + return provider.getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), data.getQueryTick()); + } + + private long getFlux() { + if (tile == null) return 0; + NetNode node = net.getNode(tile.getPos()); + if (node == null) return 0; + NetGroup group = node.getGroupUnsafe(); + if (group == null) return 0; + AbstractGroupData data = group.getData(); + if (!(data instanceof EnergyGroupData e)) return 0; + return e.getEnergyFluxPerSec(); + } + + @Override + public long getInputAmperage() { + if (tile == null) return 0; + return tile.getNetLogicData(net.mapName).getLogicEntryDefaultable(ThroughputLogic.INSTANCE).getValue(); + } + + @Override + public long getInputVoltage() { + if (tile == null) return 0; + return tile.getNetLogicData(net.mapName).getLogicEntryDefaultable(VoltageLimitLogic.INSTANCE).getValue(); + } + + @Override + public void setTile(@Nullable PipeTileEntity tile) { + this.tile = tile; + } + + @Override + public Capability[] getCapabilities() { + return WorldEnergyNet.CAPABILITIES; + } + + @Override + public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { + if (capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER) { + return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER + .cast(this); + } + return null; + } + + @Override + public long getInputPerSec() { + return getFlux(); + } + + @Override + public long getOutputPerSec() { + return getFlux(); + } + + @Override + public boolean inputsEnergy(EnumFacing side) { + return true; + } + + @Override + public boolean outputsEnergy(EnumFacing side) { + return true; + } + + @Override + public long changeEnergy(long differenceAmount) { + GTLog.logger.fatal("Do not use changeEnergy() for cables! Use acceptEnergyFromNetwork()"); + return acceptEnergyFromNetwork(null, + differenceAmount / getInputAmperage(), + differenceAmount / getInputVoltage()) * getInputVoltage(); + } + + @Override + public long getEnergyStored() { + return 0; + } + + @Override + public long getEnergyCapacity() { + return getInputAmperage() * getInputVoltage(); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java new file mode 100644 index 00000000000..8a3f3dd0f21 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -0,0 +1,152 @@ +package gregtech.common.pipelike.net.energy; + +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.capability.IEnergyContainer; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.NodeLossResult; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.PipeTileEntity; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.traverse.AbstractTraverseData; + +import gregtech.api.util.GTUtility; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import journeymap.client.render.map.Tile; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; + +import java.util.function.Supplier; + +public class EnergyTraverseData extends AbstractTraverseData { + + private final Object2ObjectOpenHashMap lossCache; + + private final Object2ObjectOpenHashMap overVoltageInformation; + + private final long startVoltage; + private long pathVoltage; + + private final BlockPos sourcePos; + private final EnumFacing inputFacing; + + public EnergyTraverseData(IGraphNet net, IPredicateTestObject testObject, SimulatorKey simulator, long queryTick, + long startVoltage, BlockPos sourcePos, EnumFacing inputFacing) { + super(net, testObject, simulator, queryTick); + this.lossCache = new Object2ObjectOpenHashMap<>(); + this.overVoltageInformation = new Object2ObjectOpenHashMap<>(); + this.startVoltage = startVoltage; + this.sourcePos = sourcePos; + this.inputFacing = inputFacing; + } + + @Override + public boolean prepareForPathWalk(FlowWorldPipeNetPath path) { + this.pathVoltage = startVoltage; + this.overVoltageInformation.clear(); + this.overVoltageInformation.trim(10); + return false; + } + + @Override + public long traverseToNode(WorldPipeNetNode node, long flowReachingNode) { + VoltageLimitLogic limitLogic = node.getData().getLogicEntryNullable(VoltageLimitLogic.INSTANCE); + if (limitLogic != null) { + long voltage = limitLogic.getValue(); + if (voltage < pathVoltage) overVoltageInformation.put(node, + new OverVoltageInformation(voltage, flowReachingNode)); + } + + + NodeLossResult result = lossCache.get(node); + if (result != null) { + return result.applyLossFunction(flowReachingNode); + } else { + TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + result = temperatureLogic == null ? null : temperatureLogic.getLossResult(getQueryTick()); + if (result == null) { + if (node.getData().getLogicEntryDefaultable(SuperconductorLogic.INSTANCE) + .canSuperconduct(temperatureLogic == null ? TemperatureLogic.DEFAULT_TEMPERATURE : + temperatureLogic.getTemperature(getQueryTick()))) { + return flowReachingNode; + } + return flowReachingNode - node.getData().getLogicEntryDefaultable(LossAbsoluteLogic.INSTANCE).getValue(); + } + if (result.hasPostAction()) lossCache.put(node, result); + return result.applyLossFunction(flowReachingNode); + } + } + + public void handleOverflow(WorldPipeNetNode node, long overflow) { + TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + if (logic != null) { + // this occurs after finalization but before path reset. + logic.applyThermalEnergy(calculateHeatA(overflow, pathVoltage), getQueryTick()); + } + } + + @Override + public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachingDestination) { + this.pathVoltage = (long) GTUtility.geometricMean(pathVoltage, + overVoltageInformation.values().stream().mapToDouble(o -> (double) o.voltageCap).toArray()); + overVoltageInformation.forEach((k, v) -> v.doHeating(k, pathVoltage, getQueryTick())); + long availableFlow = flowReachingDestination; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) continue; // anti insert-to-our-source logic + + IEnergyContainer container = capability.getValue() + .getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, capability.getKey().getOpposite()); + if (container != null) { + availableFlow -= container.acceptEnergyFromNetwork(capability.getKey(), pathVoltage, availableFlow, + getSimulatorKey() != null); + } + } + return flowReachingDestination - availableFlow; + } + + public void runPostActions() { + lossCache.forEach((k, v) -> v.triggerPostAction(k)); + } + + private static int calculateHeatV(long amperage, long voltage, long maxVoltage) { + return (int) (amperage * (Math.log1p(Math.log((double) voltage / maxVoltage)) * 45 + 36.5)); + } + + private static int calculateHeatA(long amperage, long voltage) { + return (int) (amperage * (Math.log1p(Math.log((double) voltage)) * 45 + 36.5)); + } + + protected static class OverVoltageInformation implements Supplier { + + public final long voltageCap; + + private final long amperage; + + public OverVoltageInformation(long voltageCap, long amperage) { + this.voltageCap = voltageCap; + this.amperage = amperage; + } + + @Override + public Long get() { + return voltageCap; + } + + public void doHeating(WorldPipeNetNode node, long finalVoltage, long tick) { + TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + if (logic != null) { + logic.applyThermalEnergy(calculateHeatV(amperage, finalVoltage, voltageCap), tick); + } + } + + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/LossAbsoluteLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/LossAbsoluteLogic.java new file mode 100644 index 00000000000..3589621d041 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/LossAbsoluteLogic.java @@ -0,0 +1,28 @@ +package gregtech.common.pipelike.net.energy; + +import gregtech.api.graphnet.logic.AbstractLongLogicData; +import gregtech.api.graphnet.logic.INetLogicEntry; + +import org.jetbrains.annotations.NotNull; + +public final class LossAbsoluteLogic extends AbstractLongLogicData { + + public static final LossAbsoluteLogic INSTANCE = new LossAbsoluteLogic().setValue(0); + + @Override + public @NotNull String getName() { + return "LossAbsolute"; + } + + @Override + public LossAbsoluteLogic getNew() { + return new LossAbsoluteLogic(); + } + + @Override + public LossAbsoluteLogic union(INetLogicEntry other) { + if (other instanceof LossAbsoluteLogic l) { + return this.getWith(this.getValue() + l.getValue()); + } else return this; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java new file mode 100644 index 00000000000..7b8afe4bfd7 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java @@ -0,0 +1,24 @@ +package gregtech.common.pipelike.net.energy; + +import gregtech.api.graphnet.logic.AbstractIntLogicData; + +import org.jetbrains.annotations.NotNull; + +public class SuperconductorLogic extends AbstractIntLogicData { + + public static final SuperconductorLogic INSTANCE = new SuperconductorLogic().setValue(0); + + boolean canSuperconduct(int temp) { + return this.getValue() > temp; + } + + @Override + public @NotNull String getName() { + return "Superconductor"; + } + + @Override + public SuperconductorLogic getNew() { + return new SuperconductorLogic(); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java new file mode 100644 index 00000000000..9ff8103897b --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java @@ -0,0 +1,28 @@ +package gregtech.common.pipelike.net.energy; + +import gregtech.api.graphnet.logic.AbstractLongLogicData; +import gregtech.api.graphnet.logic.INetLogicEntry; + +import org.jetbrains.annotations.NotNull; + +public final class VoltageLimitLogic extends AbstractLongLogicData { + + public static final VoltageLimitLogic INSTANCE = new VoltageLimitLogic().setValue(0); + + @Override + public @NotNull String getName() { + return "VoltageLimit"; + } + + @Override + public VoltageLimitLogic getNew() { + return new VoltageLimitLogic().setValue(INSTANCE.getValue()); + } + + @Override + public VoltageLimitLogic union(INetLogicEntry other) { + if (other instanceof VoltageLimitLogic l) { + return this.getValue() < l.getValue() ? this : l; + } else return this; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java new file mode 100644 index 00000000000..b7fe53717df --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java @@ -0,0 +1,64 @@ +package gregtech.common.pipelike.net.energy; + +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNet; + +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import net.minecraft.world.World; + +import net.minecraftforge.common.capabilities.Capability; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; + +public final class WorldEnergyNet extends WorldPipeNet implements FlowWorldPipeNetPath.Provider { + + public static final Capability[] CAPABILITIES = new Capability[] { GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER }; + + private static final String DATA_ID_BASE = "gregtech.world_energy_net"; + + public static WorldEnergyNet getWorldNet(World world) { + final String DATA_ID = getDataID(DATA_ID_BASE, world); + WorldEnergyNet net = (WorldEnergyNet) world.loadData(WorldEnergyNet.class, DATA_ID); + if (net == null) { + net = new WorldEnergyNet(DATA_ID); + world.setData(DATA_ID, net); + } + return net; + } + + public WorldEnergyNet(String name) { + super(name, DynamicWeightsShortestPathsAlgorithm::new, false); + } + + @Override + public Capability[] getTargetCapabilities() { + return CAPABILITIES; + } + + @Override + public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { + return new IPipeCapabilityObject[] { new EnergyCapabilityObject(this, node) }; + } + + @Override + public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + return backer.getPaths(node, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); + } + + @Override + public @NotNull NetFlowEdge getNewEdge() { + return new NetFlowEdge(1); + } +} diff --git a/src/main/java/gregtech/common/pipelike/temp.java b/src/main/java/gregtech/common/pipelike/temp.java deleted file mode 100644 index 676bd7e2c5d..00000000000 --- a/src/main/java/gregtech/common/pipelike/temp.java +++ /dev/null @@ -1,4 +0,0 @@ -package gregtech.common.pipelike; - -public class temp { -} diff --git a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java index 2ebae018f96..9013ec89426 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java @@ -2,27 +2,32 @@ import gregtech.api.graphnet.AbstractGroupData; -import net.minecraft.world.World; +import net.minecraftforge.fml.common.FMLCommonHandler; public class EnergyGroupData extends AbstractGroupData { private long lastEnergyFluxPerSec; private long energyFluxPerSec; - private long lastTime; + private long updateTime; public long getEnergyFluxPerSec() { - World world = this.group.net.getWorld(); - if (world != null && !world.isRemote && (world.getTotalWorldTime() - lastTime) >= 20) { - lastTime = world.getTotalWorldTime(); - clearCache(); - } + updateCache(); return lastEnergyFluxPerSec; } public void addEnergyFluxPerSec(long energy) { + updateCache(); energyFluxPerSec += energy; } + private void updateCache() { + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + if (tick > updateTime) { + updateTime = updateTime + 20; + clearCache(); + } + } + public void clearCache() { lastEnergyFluxPerSec = energyFluxPerSec; energyFluxPerSec = 0; diff --git a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java index d1f62cb9fc2..5cac5214023 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java @@ -106,7 +106,7 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage SimulatorKey simulator = simulate ? SimulatorKey.getNewSimulatorInstance() : null; destSimulationCache = simulate ? new Object2LongOpenHashMap<>() : null; - this.getNet().getGraph().prepareForDynamicWeightAlgorithmRun(null, simulator); + this.getNet().getGraph().prepareForAlgorithmRun(null, simulator); long amperesUsed = distributionRespectCapacity(side, voltage, amperage, queryTick, this.getNet().getPaths(cable), simulator); if (amperesUsed < amperage) { diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java index 2d71a5c23ef..d09612c6293 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java @@ -102,7 +102,7 @@ public int fill(FluidStack resource, boolean doFill) { FluidStack helper = resource.copy(); if (!doFill) this.simulatorKey = SimulatorKey.getNewSimulatorInstance(); else this.simulatorKey = null; - this.getNet().getGraph().prepareForDynamicWeightAlgorithmRun(testObject, simulatorKey); + this.getNet().getGraph().prepareForAlgorithmRun(testObject, simulatorKey); mainloop: for (Iterator> iter = this.getNet() .getPaths(pipe); iter.hasNext();) { From b893b42f07afa37b313fafe4c0b9337b3830eb3e Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 15 Jul 2024 19:45:38 -0600 Subject: [PATCH 076/157] Complete rewrite pt3 --- .../gregtech/api/graphnet/GraphNetBacker.java | 1 + .../java/gregtech/api/graphnet/IGraphNet.java | 15 +- .../api/graphnet/MultiNetNodeHandler.java | 33 -- .../api/graphnet/MultiNodeHelper.java | 89 +++++ .../java/gregtech/api/graphnet/NetNode.java | 10 +- .../graphnet/gather/GTGraphGatherables.java | 14 +- .../gather/GatherMaterialStructuresEvent.java | 24 -- .../gather/GatherStructuresEvent.java | 34 ++ .../api/graphnet/logic/INetLogicEntry.java | 47 ++- .../logic/INetLogicEntryListener.java | 6 + .../api/graphnet/logic/NetLogicData.java | 72 +++- .../api/graphnet/logic/TemperatureLogic.java | 232 ------------ .../logic/TemperatureRestorationFunction.java | 98 ----- .../api/graphnet/pipenet/WorldPipeNet.java | 78 +++- .../graphnet/pipenet/WorldPipeNetNode.java | 22 +- .../pipenet/logic/EnumLossFunction.java | 98 +++++ .../pipenet/logic/TemperatureLogic.java | 285 ++++++++++++++ .../logic/TemperatureLossFunction.java | 91 +++++ .../graphnet/pipenet/physical/IBurnable.java | 3 + .../pipenet/physical/IInsulatable.java | 5 + .../physical/IPipeCapabilityObject.java | 1 + .../pipenet/physical/IPipeStructure.java | 42 ++ .../graphnet/pipenet/physical/PipeBlock.java | 218 ----------- .../pipenet/physical/PipeMaterialBlock.java | 217 ----------- .../physical/{ => block}/ItemPipeBlock.java | 27 +- .../physical/block/PipeMaterialBlock.java | 117 ++++++ .../physical/block/WorldPipeBlock.java | 358 ++++++++++++++++++ .../{ => tile}/PipeCapabilityWrapper.java | 2 +- .../physical/{ => tile}/PipeCoverHolder.java | 9 +- .../physical/tile/PipeMaterialTileEntity.java | 40 ++ .../physical/{ => tile}/PipeTileEntity.java | 189 +++++++-- .../pipenetold/tile/TileEntityPipeBase.java | 6 +- .../predicate/EdgePredicateHandler.java | 26 +- .../graphnet/predicate/IEdgePredicate.java | 16 +- .../graphnet/predicate/ShutterPredicate.java | 49 +++ .../graphnet/traverse/TraverseHelpers.java | 32 +- .../NeighborCacheTileEntityBase.java | 20 +- .../interfaces/INeighborCache.java | 7 + .../api/unification/material/Material.java | 40 +- .../materials/FirstDegreeMaterials.java | 18 +- .../properties/PipeNetProperties.java | 42 +- .../material/properties/PropertyKey.java | 11 +- .../material/properties/WireProperties.java | 227 ----------- .../api/unification/ore/OrePrefix.java | 29 +- .../java/gregtech/api/util/GTUtility.java | 10 + .../client/particle/GTOverheatParticle.java | 69 ++-- .../client/utils/RenderBufferHelper.java | 6 + .../java/gregtech/common/CommonProxy.java | 40 +- .../gregtech/common/blocks/MetaBlocks.java | 135 +++---- .../gregtech/common/covers/CoverShutter.java | 11 +- .../pipelike/block/cable/CableBlock.java | 30 +- .../block/cable/CableEnergyProperties.java | 139 ------- .../pipelike/block/cable/CableStructure.java | 37 +- .../common/pipelike/block/pipe/PipeBlock.java | 46 +++ .../pipelike/block/pipe/PipeStructure.java | 72 ++++ .../net/energy/EnergyCapabilityObject.java | 34 +- .../net/energy/EnergyTraverseData.java | 18 +- .../pipelike/net/fluid/WorldFluidNet.java | 72 ++++ .../pipelike/net/item/WorldItemNet.java | 70 ++++ .../properties/MaterialEnergyProperties.java | 204 ++++++++++ .../properties/MaterialFluidProperties.java | 187 +++++++++ .../properties/MaterialItemProperties.java | 101 +++++ .../common/pipelikeold/cable/BlockCable.java | 1 - .../common/pipelikeold/cable/Insulation.java | 1 - .../pipelikeold/cable/ItemBlockCable.java | 1 - .../cable/net/EnergyGroupData.java | 31 +- .../cable/net/EnergyNetHandler.java | 1 - .../pipelikeold/cable/net/WorldEnergyNet.java | 1 - .../cable/tile/TileEntityCable.java | 1 - .../material/CTMaterialBuilder.java | 4 +- .../material/MaterialPropertyExpansion.java | 24 +- .../groovy/MaterialPropertyExpansion.java | 51 ++- .../recipe/handlers/PartsRecipeHandler.java | 5 +- .../recipe/handlers/WireCombiningHandler.java | 16 +- .../recipe/handlers/WireRecipeHandler.java | 19 +- 75 files changed, 2821 insertions(+), 1616 deletions(-) delete mode 100644 src/main/java/gregtech/api/graphnet/MultiNetNodeHandler.java create mode 100644 src/main/java/gregtech/api/graphnet/MultiNodeHelper.java delete mode 100644 src/main/java/gregtech/api/graphnet/gather/GatherMaterialStructuresEvent.java create mode 100644 src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/INetLogicEntryListener.java delete mode 100644 src/main/java/gregtech/api/graphnet/logic/TemperatureLogic.java delete mode 100644 src/main/java/gregtech/api/graphnet/logic/TemperatureRestorationFunction.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/IInsulatable.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/PipeBlock.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/PipeMaterialBlock.java rename src/main/java/gregtech/api/graphnet/pipenet/physical/{ => block}/ItemPipeBlock.java (52%) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java rename src/main/java/gregtech/api/graphnet/pipenet/physical/{ => tile}/PipeCapabilityWrapper.java (92%) rename src/main/java/gregtech/api/graphnet/pipenet/physical/{ => tile}/PipeCoverHolder.java (96%) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java rename src/main/java/gregtech/api/graphnet/pipenet/physical/{ => tile}/PipeTileEntity.java (68%) create mode 100644 src/main/java/gregtech/api/graphnet/predicate/ShutterPredicate.java delete mode 100644 src/main/java/gregtech/api/unification/material/properties/WireProperties.java delete mode 100644 src/main/java/gregtech/common/pipelike/block/cable/CableEnergyProperties.java create mode 100644 src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java create mode 100644 src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java create mode 100644 src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java create mode 100644 src/main/java/gregtech/common/pipelike/properties/MaterialEnergyProperties.java create mode 100644 src/main/java/gregtech/common/pipelike/properties/MaterialFluidProperties.java create mode 100644 src/main/java/gregtech/common/pipelike/properties/MaterialItemProperties.java diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index fb58301b781..0e7f50d54d1 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -75,6 +75,7 @@ public boolean removeNode(@Nullable NetNode node) { public void removeVertex(GraphVertex vertex) { this.getGraph().removeVertex(vertex); this.vertexMap.remove(vertex.wrapped.getEquivalencyData()); + vertex.wrapped.onRemove(); } @Nullable diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index d7b9a6c43d2..d806eaf64ab 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -10,8 +10,6 @@ import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.worldnet.WorldNetNode; - import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -19,6 +17,7 @@ import org.jgrapht.traverse.BreadthFirstIterator; import java.util.Iterator; +import java.util.Set; public interface IGraphNet { @@ -79,7 +78,7 @@ default boolean usesDynamicWeights() { void removeEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays); /** - * Gets the net graph backing this graphnet. This should NEVER be modified directly. + * Gets the net graph backing this graphnet. This should NEVER be modified directly, but can be queried. * @return the backing net graph */ @ApiStatus.Internal @@ -146,6 +145,16 @@ public NetNode next() { }; } + /** + * Used in {@link MultiNodeHelper} to determine if a node can be traversed, based on the nets that have been + * recently traversed in the {@link MultiNodeHelper}. + * @param net a recently traversed net + * @return if node traversal should be blocked. + */ + default boolean clashesWith(IGraphNet net) { + return false; + } + /** * @return the class all registered nodes are expected to be children of. */ diff --git a/src/main/java/gregtech/api/graphnet/MultiNetNodeHandler.java b/src/main/java/gregtech/api/graphnet/MultiNetNodeHandler.java deleted file mode 100644 index d9da128ae0f..00000000000 --- a/src/main/java/gregtech/api/graphnet/MultiNetNodeHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -package gregtech.api.graphnet; - -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -import org.jetbrains.annotations.ApiStatus; - -public class MultiNetNodeHandler { - - protected final int allowedActiveNets; - protected final int timeoutDelay; - - protected final Object2LongOpenHashMap activeNets = new Object2LongOpenHashMap<>(); - - public MultiNetNodeHandler(int allowedActiveNets, int timeoutDelay) { - this.allowedActiveNets = allowedActiveNets; - this.timeoutDelay = timeoutDelay; - } - - public boolean traverse(IGraphNet net, long queryTick, boolean simulate) { - timeout(queryTick); - if (activeNets.size() < allowedActiveNets || activeNets.containsKey(net)) { - if (!simulate) activeNets.put(net, queryTick + timeoutDelay); - return true; - } else return false; - } - - private void timeout(long queryTick) { - var iter = activeNets.object2LongEntrySet().fastIterator(); - while (iter.hasNext()) { - var next = iter.next(); - if (next.getLongValue() <= queryTick) iter.remove(); - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java new file mode 100644 index 00000000000..74c7783b7d8 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java @@ -0,0 +1,89 @@ +package gregtech.api.graphnet; + +import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.INetLogicEntryListener; +import gregtech.api.graphnet.logic.NetLogicData; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * MultiNodeHelpers are utility objects used to preserve sync between multiple nodes owned by different graphs. They do + * this by
A) keeping a record of traversals to allow for blocking traversal when another net has been traversed + * recently and
B) make sure that logic entries requiring it are the same object across all synced nodes.

+ * MultiNodeHelpers have no standard implementation and must be handled by a net and its nodes; see + * {@link gregtech.api.graphnet.pipenet.WorldPipeNet} and {@link gregtech.api.graphnet.pipenet.WorldPipeNetNode} + * for an example of this in action. + */ +public class MultiNodeHelper implements INetLogicEntryListener { + + protected final Object2ObjectOpenHashMap handledNodes = new Object2ObjectOpenHashMap<>(); + + protected final Object2ObjectOpenHashMap recentTransferNets = new Object2ObjectOpenHashMap<>(); + protected final int transferTimeout; + + protected final NetLogicData mergedData = new NetLogicData(); + + public MultiNodeHelper(int transferTimeout) { + this.transferTimeout = transferTimeout; + } + + public boolean traverse(IGraphNet net, long queryTick, boolean simulate) { + var iter = recentTransferNets.object2ObjectEntrySet().fastIterator(); + boolean allowed = true; + while (iter.hasNext()) { + var next = iter.next(); + if (net.clashesWith(next.getKey())) { + if (next.getValue() <= queryTick) { + iter.remove(); + } else { + allowed = false; + break; + } + } + } + if (allowed && !simulate) { + recentTransferNets.put(net, queryTick + transferTimeout); + } + return allowed; + } + + @Override + public void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChange) { + // TODO have a helper or something on clientside to avoid redundant packets + handledNodes.forEach((k, v) -> v.getData().markLogicEntryAsUpdated(entry, fullChange)); + } + + public void addNode(NetNode node) { + handledNodes.put(node.getNet(), node); + List> toSet = new ObjectArrayList<>(); + for (INetLogicEntry entry : node.getData().getEntries()) { + if (entry.mergedToMultiNodeHelper()) { + INetLogicEntry existing = mergedData.getLogicEntryNullable(entry); + if (existing != null) { + existing.merge(node, entry); + // don't put it into the data yet because we're currently iterating through the data's entries. + toSet.add(existing); + } else { + entry.registerToMultiNodeHelper(this); + mergedData.setLogicEntry(entry); + } + } + } + for (INetLogicEntry entry : toSet) { + node.getData().setLogicEntry(entry); + } + } + + public void removeNode(NetNode node) { + if (handledNodes.remove(node.getNet(), node)) { + for (INetLogicEntry entry : this.mergedData.getEntries()) { + node.getData().removeLogicEntry(entry); + entry.unmerge(node); + } + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/NetNode.java b/src/main/java/gregtech/api/graphnet/NetNode.java index 9cebda4a2ed..0eb9f71011d 100644 --- a/src/main/java/gregtech/api/graphnet/NetNode.java +++ b/src/main/java/gregtech/api/graphnet/NetNode.java @@ -31,7 +31,7 @@ public abstract class NetNode implements INBTSerializable { private final IGraphNet net; private NetLogicData data; - private NetGroup group = null; + private @Nullable NetGroup group = null; @Nullable private ICacheableIterator> pathCache = null; @@ -110,9 +110,11 @@ public NetGroup setGroup(NetGroup group) { return group; } - void clearGroup() { - this.group = null; - } + /** + * Use this to remove references that would keep this node from being collected by the garbage collector. + * This is called when a node is removed from the graph and should be discarded. + */ + public void onRemove() {} @Override public NBTTagCompound serializeNBT() { diff --git a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java index 4ece50d3fec..b1112098dae 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java +++ b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java @@ -3,8 +3,9 @@ import gregtech.api.GTValues; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.INetLogicEntry; -import gregtech.api.graphnet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.common.pipelike.block.cable.CableStructure; +import gregtech.common.pipelike.block.pipe.PipeStructure; import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; import gregtech.api.graphnet.logic.MultiNetCountLogic; import gregtech.api.graphnet.logic.ThroughputLogic; @@ -61,7 +62,14 @@ public static void gatherLogics(GatherLogicsEvent event) { } @SubscribeEvent - public static void gatherMaterialStructures(GatherMaterialStructuresEvent event) { - CableStructure.registerDefaultStructures(event::registerMaterialStructure); + public static void gatherStructures(GatherStructuresEvent event) { + if (event.getStructure() == PipeStructure.class) { + GatherStructuresEvent cast = (GatherStructuresEvent) event; + PipeStructure.registerDefaultStructures(cast::registerMaterialStructure); + } + if (event.getStructure() == CableStructure.class) { + GatherStructuresEvent cast = (GatherStructuresEvent) event; + CableStructure.registerDefaultStructures(cast::registerMaterialStructure); + } } } diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherMaterialStructuresEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherMaterialStructuresEvent.java deleted file mode 100644 index c9ed5634b5e..00000000000 --- a/src/main/java/gregtech/api/graphnet/gather/GatherMaterialStructuresEvent.java +++ /dev/null @@ -1,24 +0,0 @@ -package gregtech.api.graphnet.gather; - -import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - -import net.minecraftforge.fml.common.eventhandler.Event; - -import java.util.Set; - -public class GatherMaterialStructuresEvent extends Event { - - final Set gathered = new ObjectOpenHashSet<>(); - - GatherMaterialStructuresEvent() {} - - public void registerMaterialStructure(IPipeMaterialStructure materialStructure) { - gathered.add(materialStructure); - } - - public Set getGathered() { - return gathered; - } -} diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java new file mode 100644 index 00000000000..b6b1b9eca8a --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java @@ -0,0 +1,34 @@ +package gregtech.api.graphnet.gather; + +import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; + +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraftforge.fml.common.eventhandler.Event; + +import java.util.Set; + +public class GatherStructuresEvent extends Event { + + final Set gathered = new ObjectOpenHashSet<>(); + + final Class structure; + + public GatherStructuresEvent(Class structure) { + this.structure = structure; + } + + public void registerMaterialStructure(T materialStructure) { + gathered.add(materialStructure); + } + + public Set getGathered() { + return gathered; + } + + public Class getStructure() { + return structure; + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java index 4cb66c61280..d3d99e7a26f 100644 --- a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java +++ b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java @@ -1,6 +1,8 @@ package gregtech.api.graphnet.logic; -import gregtech.api.graphnet.predicate.IEdgePredicate; +import gregtech.api.graphnet.MultiNodeHelper; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.network.IPacket; @@ -9,7 +11,6 @@ import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Nullable; /** @@ -31,10 +32,52 @@ default T union(INetLogicEntry other) { return null; } + /** + * Controls whether this logic entry should be merged to a MultiNodeHelper, if one is declared. + * The data entry must support {@link #merge(NetNode, INetLogicEntry)} with other entries of the same type, + * so that new nodes being added to the MultiNodeHelper can merge in. The multi node helper will ensure that + * all nodes registered to it contain the same object that their entries have been merged to, and when a node + * leaves the multi node helper {@link #unmerge(NetNode)} will be called for it. Server-Client sync is handled + * by the MultiNodeHelper, do not sync through NetLogicData. See {@link #registerToMultiNodeHelper(MultiNodeHelper)} + * @return whether logic entry should be merged to a MultiNodeHelper. + */ + default boolean mergedToMultiNodeHelper() { + return false; + } + + /** + * Called when this logic entry is added to a MultiNodeHelper. Any data syncing should go through the + * MultiNodeHelper after this method is called. + */ + default void registerToMultiNodeHelper(MultiNodeHelper helper) {} + + /** + * Should be used exclusively for {@link gregtech.api.graphnet.MultiNodeHelper} logic. + * @param otherOwner the net node being merged in + * @param other the logic being merged in + */ + default void merge(NetNode otherOwner, INetLogicEntry other) {} + + /** + * Should be used exclusively for {@link gregtech.api.graphnet.MultiNodeHelper} logic.
+ * Cannot be passed a logic entry since said logic entry would just be the instance this is being called for; + * if your logic needs to keep track then populate a map during {@link #merge(NetNode, INetLogicEntry)}. + * Keep in mind that this can be called for the data's original owner, despite + * {@link #merge(NetNode, INetLogicEntry)} not being called for the original owner. + * @param entryOwner the node being unmerged. + */ + default void unmerge(NetNode entryOwner) {} + default void registerToNetLogicData(NetLogicData data) {} + default void deregisterFromNetLogicData(NetLogicData data) {} + T getNew(); + default T cast(INetLogicEntry entry) { + return (T) entry; + } + default void encode(PacketBuffer buf) { encode(buf, true); } diff --git a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntryListener.java b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntryListener.java new file mode 100644 index 00000000000..91097246bcc --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntryListener.java @@ -0,0 +1,6 @@ +package gregtech.api.graphnet.logic; + +public interface INetLogicEntryListener { + + void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChange); +} diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index 42b3e464db5..318857dafae 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -2,29 +2,36 @@ import gregtech.api.graphnet.gather.GTGraphGatherables; -import gregtech.api.util.IDirtyNotifiable; - +import gregtech.api.graphnet.gather.GatherLogicsEvent; +import gregtech.api.graphnet.gather.GatherPredicatesEvent; +import gregtech.api.network.IPacket; import gregtech.api.util.function.TriConsumer; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectCollection; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; -import java.util.Map; +import java.io.IOException; import java.util.Set; -import java.util.function.BiConsumer; import java.util.function.Supplier; - -public final class NetLogicData implements INBTSerializable { +/** + * Note - since the internal map representation encodes keys using {@link IStringSerializable#getName()} on logics, + * making a logics class return two different names is a valid way to register multiple instances.
+ * Just make sure that a supplier is registered to {@link GatherLogicsEvent} for all + * associated names, so that decoding from nbt and packets is possible. + */ +public final class NetLogicData implements INBTSerializable, IPacket, INetLogicEntryListener { // TODO caching logic on simple logics to reduce amount of reduntant creation? private final Object2ObjectOpenHashMap> logicEntrySet; @@ -61,23 +68,39 @@ public NetLogicData setLogicEntry(INetLogicEntry entry) { return this; } + /** + * Returns all registered logic entries; this should be treated in read-only manner. + */ + public ObjectCollection> getEntries() { + return logicEntrySet.values(); + } + public NetLogicData removeLogicEntry(@NotNull INetLogicEntry key) { return removeLogicEntry(key.getName()); } public NetLogicData removeLogicEntry(@NotNull String key) { INetLogicEntry entry = logicEntrySet.remove(key); - if (entry != null) this.listeners.forEach(l -> l.markChanged(entry, true, true)); - logicEntrySet.trim(); + if (entry != null) { + entry.deregisterFromNetLogicData(this); + this.listeners.forEach(l -> l.markChanged(entry, true, true)); + logicEntrySet.trim(); + } return this; } + @Override public void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChange) { this.listeners.forEach(l -> l.markChanged(entry, false, fullChange)); } @Nullable - public > T getLogicEntryNullable(@NotNull T key) { + public INetLogicEntry getLogicEntryNullable(@NotNull String key) { + return logicEntrySet.get(key); + } + + @Nullable + public > T getLogicEntryNullable(@NotNull T key) { try { return (T) logicEntrySet.get(key.getName()); } catch (ClassCastException ignored) { @@ -128,7 +151,7 @@ public void addListener(LogicDataListener listener) { @Override public NBTTagList serializeNBT() { NBTTagList list = new NBTTagList(); - for (INetLogicEntry entry : logicEntrySet.values()) { + for (INetLogicEntry entry : getEntries()) { NBTTagCompound tag = new NBTTagCompound(); tag.setTag("Tag", entry.serializeNBT()); tag.setString("Name", entry.getName()); @@ -149,6 +172,33 @@ public void deserializeNBT(NBTTagList nbt) { } } + @Override + public void encode(PacketBuffer buf) { + buf.writeVarInt(getEntries().size()); + for (INetLogicEntry entry : getEntries()) { + buf.writeString(entry.getName()); + entry.encode(buf, true); + } + } + + @Override + public void decode(PacketBuffer buf) { + this.logicEntrySet.clear(); + int entryCount = buf.readVarInt(); + for (int i = 0; i < entryCount; i++) { + String name = buf.readString(255); + INetLogicEntry existing = getSupplier(name).get(); + // is there a softer exception I can throw that'll disconnect from server but not crash the game? + if (existing == null) + throw new RuntimeException("Could not find a matching supplier for an encoded INetLogicEntry. " + + "This suggests that the server and client have different GT versions or modifications."); + existing.registerToNetLogicData(this); + existing.decode(buf); + this.logicEntrySet.put(name, existing); + } + this.logicEntrySet.trim(); + } + private static Supplier> getSupplier(String identifier) { return GTGraphGatherables.getLogicsRegistry().getOrDefault(identifier, () -> null); } diff --git a/src/main/java/gregtech/api/graphnet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/logic/TemperatureLogic.java deleted file mode 100644 index 62ef7a7657a..00000000000 --- a/src/main/java/gregtech/api/graphnet/logic/TemperatureLogic.java +++ /dev/null @@ -1,232 +0,0 @@ -package gregtech.api.graphnet.logic; - -import gregtech.api.graphnet.pipenet.NodeLossResult; - -import gregtech.api.graphnet.pipenet.physical.IBurnable; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.nbt.NBTTagCompound; - -import net.minecraft.network.PacketBuffer; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public final class TemperatureLogic implements INetLogicEntry { - - public static final TemperatureLogic INSTANCE = new TemperatureLogic(); - - public static final int DEFAULT_TEMPERATURE = 293; - - @Nullable - private NetLogicData owner; - - private int temperatureMaximum; - private @Nullable Integer partialBurnTemperature; - private int temperatureMinimum; - private float energy; - private int thermalMass; - - private TemperatureRestorationFunction temperatureRestorationFunction; - private float restorationSpeedFactor; - private long lastRestorationTick; - - private TemperatureLogic() {} - - public TemperatureLogic getWith(TemperatureRestorationFunction temperatureRestorationFunction, float restorationSpeedFactor, int temperatureMaximum) { - return getWith(temperatureRestorationFunction, restorationSpeedFactor, temperatureMaximum, null); - } - - public TemperatureLogic getWith(TemperatureRestorationFunction temperatureRestorationFunction, float restorationSpeedFactor, int temperatureMaximum, @Nullable Integer partialBurnTemperature) { - return getWith(temperatureRestorationFunction, restorationSpeedFactor, temperatureMaximum, partialBurnTemperature, 1); - } - - public TemperatureLogic getWith(TemperatureRestorationFunction temperatureRestorationFunction, float restorationSpeedFactor, int temperatureMaximum, @Nullable Integer partialBurnTemperature, int temperatureMinimum) { - return getWith(temperatureRestorationFunction, restorationSpeedFactor, temperatureMaximum, partialBurnTemperature, temperatureMinimum, 1000); - } - - public TemperatureLogic getWith(TemperatureRestorationFunction temperatureRestorationFunction, float restorationSpeedFactor, int temperatureMaximum, @Nullable Integer partialBurnTemperature, int temperatureMinimum, int thermalMass) { - return getNew() - .setTemperatureRestorationFunction(temperatureRestorationFunction) - .setRestorationSpeedFactor(restorationSpeedFactor) - .setTemperatureMaximum(temperatureMaximum) - .setPartialBurnTemperature(partialBurnTemperature) - .setTemperatureMinimum(temperatureMinimum) - .setThermalMass(thermalMass); - } - - public TemperatureLogic getNew() { - return new TemperatureLogic(); - } - - public boolean aboveMax(long tick) { - return this.getTemperature(tick) > this.temperatureMaximum; - } - - public boolean belowMin(long tick) { - return this.getTemperature(tick) < this.temperatureMinimum; - } - - @Nullable - public NodeLossResult getLossResult(long tick) { - if (aboveMax(tick)) { - return new NodeLossResult(n -> { - World world = n.getNet().getWorld(); - BlockPos pos = n.getEquivalencyData(); - IBlockState state = world.getBlockState(pos); - if (state.getBlock() instanceof IBurnable burnable) { - burnable.fullyBurn(state, world, pos); - } else { - world.setBlockToAir(pos); - } - }, l -> 0L); - } else if (partialBurnTemperature != null && getTemperature(tick) > partialBurnTemperature) { - return new NodeLossResult(n -> { - World world = n.getNet().getWorld(); - BlockPos pos = n.getEquivalencyData(); - IBlockState state = world.getBlockState(pos); - if (state.getBlock() instanceof IBurnable burnable) { - burnable.partialBurn(state, world, pos); - } - }, l -> (long) (l * 0.5)); - } else { - return null; - } - } - - public void applyThermalEnergy(float energy, long tick) { - restoreTemperature(tick); - // since the decay logic is synced and deterministic, - // the only time client and server will desync is on external changes. - if (this.owner != null) this.owner.markLogicEntryAsUpdated(this, false); - this.energy += energy; - } - - public int getTemperature(long tick) { - restoreTemperature(tick); - return (int) (this.energy / this.thermalMass) + DEFAULT_TEMPERATURE; - } - - private void restoreTemperature(long tick) { - long timePassed = lastRestorationTick - tick; - this.lastRestorationTick = tick; - float energy = this.energy; - if (timePassed != 0) { - if (timePassed >= Integer.MAX_VALUE || timePassed < 0) { - this.energy = 0; - } else this.energy = temperatureRestorationFunction - .restoreTemperature(energy, restorationSpeedFactor, (int) timePassed); - } - } - - public TemperatureLogic setTemperatureRestorationFunction(TemperatureRestorationFunction temperatureRestorationFunction) { - this.temperatureRestorationFunction = temperatureRestorationFunction; - return this; - } - - public TemperatureRestorationFunction getTemperatureRestorationFunction() { - return temperatureRestorationFunction; - } - - public TemperatureLogic setRestorationSpeedFactor(float restorationSpeedFactor) { - this.restorationSpeedFactor = restorationSpeedFactor; - return this; - } - - public float getRestorationSpeedFactor() { - return restorationSpeedFactor; - } - - public TemperatureLogic setTemperatureMaximum(int temperatureMaximum) { - this.temperatureMaximum = temperatureMaximum; - return this; - } - - public int getTemperatureMaximum() { - return temperatureMaximum; - } - - public TemperatureLogic setPartialBurnTemperature(@Nullable Integer partialBurnTemperature) { - this.partialBurnTemperature = partialBurnTemperature; - return this; - } - - public @Nullable Integer getPartialBurnTemperature() { - return partialBurnTemperature; - } - - public TemperatureLogic setTemperatureMinimum(int temperatureMinimum) { - this.temperatureMinimum = temperatureMinimum; - return this; - } - - public int getTemperatureMinimum() { - return temperatureMinimum; - } - - public TemperatureLogic setThermalMass(int thermalMass) { - this.thermalMass = thermalMass; - return this; - } - - public int getThermalMass() { - return thermalMass; - } - - @Override - public @NotNull String getName() { - return "Temperature"; - } - - @Override - public void registerToNetLogicData(NetLogicData data) { - this.owner = data; - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tag = new NBTTagCompound(); - tag.setFloat("ThermalEnergy", this.energy); - tag.setInteger("TemperatureMax", this.temperatureMaximum); - tag.setInteger("TemperatureMin", this.temperatureMinimum); - tag.setInteger("ThermalMass", this.thermalMass); - tag.setInteger("RestorationFunction", temperatureRestorationFunction.ordinal()); - return tag; - } - - @Override - public void deserializeNBT(NBTTagCompound nbt) { - this.energy = nbt.getFloat("ThermalEnergy"); - this.temperatureMaximum = nbt.getInteger("TemperatureMax"); - this.temperatureMinimum = nbt.getInteger("TemperatureMin"); - this.thermalMass = nbt.getInteger("ThermalMass"); - this.temperatureRestorationFunction = - TemperatureRestorationFunction.values()[nbt.getInteger("RestorationFunction")]; - } - - @Override - public void encode(PacketBuffer buf, boolean fullChange) { - buf.writeFloat(this.energy); - if (fullChange) { - buf.writeVarInt(this.temperatureMaximum); - buf.writeVarInt(this.temperatureMinimum); - buf.writeVarInt(this.thermalMass); - buf.writeVarInt(this.temperatureRestorationFunction.ordinal()); - } - } - - @Override - public void decode(PacketBuffer buf, boolean fullChange) { - this.energy = buf.readFloat(); - if (fullChange) { - this.temperatureMaximum = buf.readVarInt(); - this.temperatureMinimum = buf.readVarInt(); - this.thermalMass = buf.readVarInt(); - this.temperatureRestorationFunction = - TemperatureRestorationFunction.values()[buf.readVarInt()]; - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/logic/TemperatureRestorationFunction.java b/src/main/java/gregtech/api/graphnet/logic/TemperatureRestorationFunction.java deleted file mode 100644 index c25afa4f12a..00000000000 --- a/src/main/java/gregtech/api/graphnet/logic/TemperatureRestorationFunction.java +++ /dev/null @@ -1,98 +0,0 @@ -package gregtech.api.graphnet.logic; - -/** - * A bunch of loss functions. By the power of Wolfram Alpha. - * Demonstration Graph - */ -public enum TemperatureRestorationFunction { - // DO NOT REORDER FUNCTIONS, THE ORDER IS USED FOR NBT SERIALIZATION - /** - * 100 thermal energy is lost every tick, modified by restoration speed factor. - *
A constant rate. - */ - ARITHMETIC { - @Override - public float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed) { - float initialThermalEnergy = thermalEnergy; - thermalEnergy -= b(thermalEnergy, restorationSpeedFactor); - if (thermalEnergy < initialThermalEnergy) return 0; - return tolerate(thermalEnergy); - } - }, - /** - * 10% of thermal energy is lost every tick, modified by restoration speed factor. - *
Faster than {@link TemperatureRestorationFunction#ARITHMETIC} at large values, but slower at small values. - */ - GEOMETRIC { - @Override - public float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed) { - thermalEnergy *= Math.pow(a(restorationSpeedFactor), timePassed); - return tolerate(thermalEnergy); - } - }, - /** - * thermal energy is raised to the power of 1 - 0.02 every tick, modified by restoration speed factor. - *
Faster than {@link TemperatureRestorationFunction#GEOMETRIC} at large values, but incredibly slow at small values. - */ - POWER { - @Override - public float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed) { - thermalEnergy = (float) (Math.signum(thermalEnergy) * - Math.pow(Math.abs(thermalEnergy), Math.pow(c(restorationSpeedFactor), timePassed))); - return tolerate(thermalEnergy); - } - }, - /** - * 10% of thermal energy is lost, then 100 more, every tick, both values modified by restoration speed factor. - *
Slightly faster than {@link TemperatureRestorationFunction#GEOMETRIC} at large values, - * slightly faster than {@link TemperatureRestorationFunction#ARITHMETIC} at small values. - */ - GEOMETRIC_ARITHMETIC { - @Override - public float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed) { - float initialThermalEnergy = thermalEnergy; - - float a = a(restorationSpeedFactor); - float b = b(thermalEnergy, restorationSpeedFactor); - thermalEnergy = (float) ((b - Math.pow(a, timePassed) * - (-a * thermalEnergy + b + thermalEnergy)) / (a - 1)); - - if (thermalEnergy < initialThermalEnergy) return 0; - return tolerate(thermalEnergy); - } - }, - /** - * thermal energy is raised to the power of 1 - 0.02, then 10% more is lost, every tick, both values modified by restoration speed factor. - *
Slightly faster than {@link TemperatureRestorationFunction#POWER} at large values, - * slightly faster than {@link TemperatureRestorationFunction#GEOMETRIC} at small values. - */ - POWER_GEOMETRIC { - @Override - public float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed) { - float c = c(restorationSpeedFactor); - thermalEnergy = (float) (Math.pow(a(restorationSpeedFactor), (Math.pow(c, timePassed) - 1) / (c - 1)) * - Math.pow(Math.abs(thermalEnergy), Math.pow(c, timePassed)) * Math.signum(thermalEnergy)); - return tolerate(thermalEnergy); - } - }; - - public static final float TOLERANCE = 0.1f; - - protected float tolerate(float value) { - return Math.abs(value) < TOLERANCE ? 0 : value; - } - - protected float a(float restorationSpeedFactor) { - return 1 - 0.1f * restorationSpeedFactor; - } - - protected float b(float thermalEnergy, float restorationSpeedFactor) { - return Math.signum(thermalEnergy) * 100 * restorationSpeedFactor; - } - - protected float c(float restorationSpeedFactor) { - return 1 - 0.02f * restorationSpeedFactor; - } - - public abstract float restoreTemperature(float thermalEnergy, float restorationSpeedFactor, int timePassed); -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 7f5700c50dd..22d97b69039 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -1,21 +1,26 @@ package gregtech.api.graphnet.pipenet; +import gregtech.api.cover.Cover; import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.MultiNetNodeHandler; +import gregtech.api.graphnet.MultiNodeHelper; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.alg.INetAlgorithm; +import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; -import gregtech.api.graphnet.logic.MultiNetCountLogic; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.graphnet.predicate.ShutterPredicate; import gregtech.api.graphnet.worldnet.WorldNet; -import gregtech.api.graphnet.worldnet.WorldNetNode; +import gregtech.api.util.IDirtyNotifiable; +import gregtech.common.covers.CoverShutter; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -26,7 +31,6 @@ import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; -import java.util.Collection; import java.util.Objects; import java.util.Set; import java.util.function.Function; @@ -57,6 +61,57 @@ public WorldPipeNet(String name, Function algorithmBui }); } + /** + * Called when a PipeTileEntity is marked dirty through {@link IDirtyNotifiable#markAsDirty()}, which is generally + * when the state of its covers is changed. + * @param node + * @param tile + */ + public void updatePredication(@NotNull WorldPipeNetNode node, @NotNull PipeTileEntity tile) { + for (EnumFacing facing : EnumFacing.VALUES) { + PipeTileEntity neighbor = tile.getPipeNeighbor(facing, false); + if (neighbor != null) { + WorldPipeNetNode neighborNode = this.getNode(neighbor.getPos()); + if (neighborNode != null) { + updatePredication(node, tile.getCoverHolder().getCoverAtSide(facing), neighborNode, + neighbor.getCoverHolder().getCoverAtSide(facing.getOpposite())); + } + } + } + } + + /** + * Preferred method to override if your net has custom predication rules. If the net is directed, + * this method will not be called twice, so special handling for directedness is needed. + * @param source the source of the edge. + * @param coverSource the cover on the source facing the target. + * @param target the target of the edge. + * @param coverTarget the cover on the target facing the source. + */ + public void updatePredication(@NotNull WorldPipeNetNode source, @Nullable Cover coverSource, + @NotNull WorldPipeNetNode target, @Nullable Cover coverTarget) { + NetEdge edge = getEdge(source, target); + if (edge == null) return; + edge.getPredicateHandler().clearPredicates(); + shutterify(edge, coverSource, coverTarget); + if (getGraph().isDirected()) { + edge = getEdge(target, source); + if (edge == null) return; + edge.getPredicateHandler().clearPredicates(); + shutterify(edge, coverSource, coverTarget); + } + } + + protected final void shutterify(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { + if (a instanceof CoverShutter s && !s.canPipePassThrough()) { + edge.getPredicateHandler().setPredicate(ShutterPredicate.INSTANCE); + return; + } + if (b instanceof CoverShutter s && !s.canPipePassThrough()) { + edge.getPredicateHandler().setPredicate(ShutterPredicate.INSTANCE); + } + } + public abstract Capability[] getTargetCapabilities(); public abstract IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node); @@ -89,19 +144,20 @@ public void synchronizeNode(WorldPipeNetNode node) { // this is disk-load safe, since this method is called during nbt deserialization. sameDimensionNetsStream().map(n -> n.getNode(node.getEquivalencyData())).filter(Objects::nonNull) .forEach(n -> { - if (n.handler != node.handler) { - if (node.handler == null) { + if (n.overlapHelper != node.overlapHelper) { + if (node.overlapHelper == null) { // n handler is not null - node.handler = n.handler; + node.overlapHelper = n.overlapHelper; + n.overlapHelper.addNode(node); return; } - } else if (n.handler == null) { + } else if (n.overlapHelper == null) { // both handlers are null - node.handler = new MultiNetNodeHandler(node.getData().getLogicEntryDefaultable( - MultiNetCountLogic.INSTANCE).getValue(), MULTI_NET_TIMEOUT); + node.overlapHelper = new MultiNodeHelper(MULTI_NET_TIMEOUT); } // n handler does not match cast handler - n.handler = node.handler; + n.overlapHelper = node.overlapHelper; + n.overlapHelper.addNode(node); }); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java index 4adc6834564..2fc4b2aff25 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java @@ -1,21 +1,17 @@ package gregtech.api.graphnet.pipenet; -import gregtech.api.graphnet.GraphNetBacker; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.MultiNetNodeHandler; -import gregtech.api.graphnet.pipenet.physical.PipeTileEntity; -import gregtech.api.graphnet.worldnet.WorldNet; +import gregtech.api.graphnet.MultiNodeHelper; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.worldnet.WorldNetNode; import net.minecraft.util.math.BlockPos; -import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.Nullable; public final class WorldPipeNetNode extends WorldNetNode { @Nullable - MultiNetNodeHandler handler; + MultiNodeHelper overlapHelper; public WorldPipeNetNode(WorldPipeNet net) { super(net); @@ -26,6 +22,14 @@ public PipeTileEntity getTileEntity() { return (PipeTileEntity) getNet().getWorld().getTileEntity(getEquivalencyData()); } + @Override + public void onRemove() { + if (this.overlapHelper != null) { + this.overlapHelper.removeNode(this); + this.overlapHelper = null; + } + } + @Override public WorldPipeNet getNet() { return (WorldPipeNet) super.getNet(); @@ -40,8 +44,8 @@ public WorldPipeNetNode setPos(BlockPos pos) { @Override public boolean traverse(long queryTick, boolean simulate) { - if (handler != null) { - return handler.traverse(this.getNet(), queryTick, simulate); + if (overlapHelper != null) { + return overlapHelper.traverse(this.getNet(), queryTick, simulate); } else return true; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java new file mode 100644 index 00000000000..af2bb13a83f --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java @@ -0,0 +1,98 @@ +package gregtech.api.graphnet.pipenet.logic; + +/** + * A bunch of loss functions. By the power of Wolfram Alpha. + * Demonstration Graph + */ +public enum EnumLossFunction { + // DO NOT REORDER FUNCTIONS, THE ORDER IS USED FOR NBT SERIALIZATION + /** + * x value is lost every tick. + *
A constant rate. + */ + ARITHMETIC { + @Override + public float applyLoss(float value, float factorX, float factorY, int timePassed) { + float initialThermalEnergy = value; + value -= Math.signum(value) * factorX; + if (value < initialThermalEnergy) return 0; + return tolerate(value); + } + }, + /** + * x% of value is lost every tick. + *
Faster than {@link EnumLossFunction#ARITHMETIC} at large values, but slower at small values. + */ + GEOMETRIC { + @Override + public float applyLoss(float value, float factorX, float factorY, int timePassed) { + value *= Math.pow(1 - (factorX / 100), timePassed); + return tolerate(value); + } + }, + /** + * value is raised to the power of 1 - x every tick. + *
Faster than {@link EnumLossFunction#GEOMETRIC} at large values, but incredibly slow at small values. + */ + POWER { + @Override + public float applyLoss(float value, float factorX, float factorY, int timePassed) { + value = (float) (Math.signum(value) * + Math.pow(Math.abs(value), Math.pow(1 - factorX, timePassed))); + return tolerate(value); + } + }, + /** + * x% of value is lost, then y more, every tick. + *
Slightly faster than {@link EnumLossFunction#GEOMETRIC} at large values, + * slightly faster than {@link EnumLossFunction#ARITHMETIC} at small values. + */ + GEOMETRIC_ARITHMETIC { + @Override + public float applyLoss(float value, float factorX, float factorY, int timePassed) { + float initialThermalEnergy = value; + + float a = 1 - (factorX / 100); + float b = Math.signum(value) * factorY; + value = (float) ((b - Math.pow(a, timePassed) * + (-a * value + b + value)) / (a - 1)); + + if (value < initialThermalEnergy) return 0; + return tolerate(value); + } + }, + /** + * value is raised to the power of 1 - x, then y% more is lost, every tick. + *
Slightly faster than {@link EnumLossFunction#POWER} at large values, + * slightly faster than {@link EnumLossFunction#GEOMETRIC} at small values. + */ + POWER_GEOMETRIC { + @Override + public float applyLoss(float value, float factorX, float factorY, int timePassed) { + float c = 1 - factorX; + value = (float) (Math.pow(1 - (factorY / 100), (Math.pow(c, timePassed) - 1) / (c - 1)) * + Math.pow(Math.abs(value), Math.pow(c, timePassed)) * Math.signum(value)); + return tolerate(value); + } + }, + /** + * The evaluation of value = value - x * (value ^ y) is recursively found for every tick passed. + */ + WEAK_SCALING { + @Override + public float applyLoss(float value, float factorX, float factorY, int timePassed) { + for (int i = 0; i < timePassed; i++) { + value -= factorX * Math.pow(value, factorY); + } + return 0; + } + }; + + public static final float TOLERANCE = 0.1f; + + protected float tolerate(float value) { + return Math.abs(value) < TOLERANCE ? 0 : value; + } + + public abstract float applyLoss(float value, float factorX, float factorY, int timePassed); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java new file mode 100644 index 00000000000..62a19e413da --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -0,0 +1,285 @@ +package gregtech.api.graphnet.pipenet.logic; + +import gregtech.api.graphnet.MultiNodeHelper; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.INetLogicEntryListener; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.pipenet.NodeLossResult; + +import gregtech.api.graphnet.pipenet.physical.IBurnable; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.nbt.NBTTagCompound; + +import net.minecraft.network.PacketBuffer; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.WeakReference; +import java.util.Objects; + +public final class TemperatureLogic implements INetLogicEntry { + + public static final TemperatureLogic INSTANCE = new TemperatureLogic(); + + public static final int DEFAULT_TEMPERATURE = 293; + + private WeakReference netListener; + private boolean isMultiNodeHelper = false; + + private int temperatureMaximum; + private @Nullable Integer partialBurnTemperature; + private int temperatureMinimum; + private float energy; + private int thermalMass; + + private @NotNull TemperatureLossFunction temperatureLossFunction = new TemperatureLossFunction(); + private int functionPriority; + private long lastRestorationTick; + + private TemperatureLogic() {} + + public TemperatureLogic getWith(@NotNull TemperatureLossFunction temperatureRestorationFunction, int temperatureMaximum) { + return getWith(temperatureRestorationFunction, temperatureMaximum, 1); + } + + public TemperatureLogic getWith(@NotNull TemperatureLossFunction temperatureRestorationFunction, int temperatureMaximum, int temperatureMinimum) { + return getWith(temperatureRestorationFunction, temperatureMaximum, temperatureMinimum, 1000); + } + + public TemperatureLogic getWith(@NotNull TemperatureLossFunction temperatureRestorationFunction, int temperatureMaximum, int temperatureMinimum, int thermalMass) { + return getWith(temperatureRestorationFunction, temperatureMaximum, temperatureMinimum, thermalMass, 0); + } + + public TemperatureLogic getWith(@NotNull TemperatureLossFunction temperatureRestorationFunction, int temperatureMaximum, int temperatureMinimum, int thermalMass, @Nullable Integer partialBurnTemperature) { + return getWith(temperatureRestorationFunction, temperatureMaximum, temperatureMinimum, thermalMass, partialBurnTemperature, 0); + } + + public TemperatureLogic getWith(@NotNull TemperatureLossFunction temperatureRestorationFunction, int temperatureMaximum, int temperatureMinimum, int thermalMass, @Nullable Integer partialBurnTemperature, int functionPriority) { + return getNew() + .setRestorationFunction(temperatureRestorationFunction) + .setTemperatureMaximum(temperatureMaximum) + .setTemperatureMinimum(temperatureMinimum) + .setThermalMass(thermalMass) + .setPartialBurnTemperature(partialBurnTemperature) + .setFunctionPriority(functionPriority); + } + + @Override + public void registerToMultiNodeHelper(MultiNodeHelper helper) { + this.isMultiNodeHelper = true; + this.netListener = new WeakReference<>(helper); + } + + @Override + public void registerToNetLogicData(NetLogicData data) { + if (!isMultiNodeHelper) this.netListener = new WeakReference<>(data); + } + + @Override + public void deregisterFromNetLogicData(NetLogicData data) { + if (!isMultiNodeHelper) this.netListener = new WeakReference<>(null); + } + + public TemperatureLogic getNew() { + return new TemperatureLogic(); + } + + @Nullable + public NodeLossResult getLossResult(long tick) { + if (getTemperature(tick) > getTemperatureMaximum()) { + return new NodeLossResult(n -> { + World world = n.getNet().getWorld(); + BlockPos pos = n.getEquivalencyData(); + IBlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof IBurnable burnable) { + burnable.fullyBurn(state, world, pos); + } else { + world.setBlockToAir(pos); + } + }, l -> 0L); + } else if (getPartialBurnTemperature() != null && getTemperature(tick) > getPartialBurnTemperature()) { + return new NodeLossResult(n -> { + World world = n.getNet().getWorld(); + BlockPos pos = n.getEquivalencyData(); + IBlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof IBurnable burnable) { + burnable.partialBurn(state, world, pos); + } + }, l -> (long) (l * 0.5)); + } else { + return null; + } + } + + public void applyThermalEnergy(float energy, long tick) { + restoreTemperature(tick); + // since the decay logic is synced and deterministic, + // the only time client and server will desync is on external changes. + INetLogicEntryListener listener = this.netListener.get(); + if (listener != null) listener.markLogicEntryAsUpdated(this, false); + + this.energy += energy; + } + + public int getTemperature(long tick) { + restoreTemperature(tick); + return (int) (this.energy / this.thermalMass) + DEFAULT_TEMPERATURE; + } + + private void restoreTemperature(long tick) { + long timePassed = lastRestorationTick - tick; + this.lastRestorationTick = tick; + float energy = this.energy; + if (timePassed != 0) { + if (timePassed >= Integer.MAX_VALUE || timePassed < 0) { + this.energy = 0; + } else this.energy = temperatureLossFunction + .restoreTemperature(energy, (int) timePassed); + } + } + + public TemperatureLogic setRestorationFunction(TemperatureLossFunction temperatureRestorationFunction) { + this.temperatureLossFunction = temperatureRestorationFunction; + return this; + } + + public TemperatureLossFunction getRestorationFunction() { + return temperatureLossFunction; + } + + public TemperatureLogic setFunctionPriority(int functionPriority) { + this.functionPriority = functionPriority; + return this; + } + + public int getFunctionPriority() { + return functionPriority; + } + + public TemperatureLogic setTemperatureMaximum(int temperatureMaximum) { + this.temperatureMaximum = temperatureMaximum; + return this; + } + + public int getTemperatureMaximum() { + return temperatureMaximum; + } + + public TemperatureLogic setPartialBurnTemperature(@Nullable Integer partialBurnTemperature) { + this.partialBurnTemperature = partialBurnTemperature; + return this; + } + + public @Nullable Integer getPartialBurnTemperature() { + return partialBurnTemperature; + } + + public TemperatureLogic setTemperatureMinimum(int temperatureMinimum) { + this.temperatureMinimum = temperatureMinimum; + return this; + } + + public int getTemperatureMinimum() { + return temperatureMinimum; + } + + public TemperatureLogic setThermalMass(int thermalMass) { + this.thermalMass = thermalMass; + return this; + } + + public int getThermalMass() { + return thermalMass; + } + + @Override + public @NotNull String getName() { + return "Temperature"; + } + + @Override + public boolean mergedToMultiNodeHelper() { + return true; + } + + @Override + public void merge(NetNode otherOwner, INetLogicEntry unknown) { + if (!(unknown instanceof TemperatureLogic other)) return; + if (other.getTemperatureMinimum() > this.getTemperatureMinimum()) + this.setTemperatureMinimum(other.getTemperatureMinimum()); + if (other.getTemperatureMaximum() < this.getTemperatureMaximum()) + this.setTemperatureMaximum(other.getTemperatureMaximum()); + // since merge also occurs during nbt load, ignore the other's thermal energy. + if (other.getThermalMass() < this.getThermalMass()) this.setThermalMass(other.getThermalMass()); + if (other.getFunctionPriority() > this.getFunctionPriority()) { + this.setRestorationFunction(other.getRestorationFunction()); + this.setFunctionPriority(other.getFunctionPriority()); + } + if (other.getPartialBurnTemperature() != null && (this.getPartialBurnTemperature() == null || + other.getPartialBurnTemperature() < this.getPartialBurnTemperature())) + this.setPartialBurnTemperature(other.getPartialBurnTemperature()); + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setFloat("ThermalEnergy", this.energy); + tag.setInteger("TemperatureMax", this.temperatureMaximum); + tag.setInteger("TemperatureMin", this.temperatureMinimum); + tag.setInteger("ThermalMass", this.thermalMass); + tag.setTag("RestorationFunction", this.temperatureLossFunction.serializeNBT()); + tag.setInteger("FunctionPrio", this.functionPriority); + if (partialBurnTemperature != null) tag.setInteger("PartialBurn", partialBurnTemperature); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + this.energy = nbt.getFloat("ThermalEnergy"); + this.temperatureMaximum = nbt.getInteger("TemperatureMax"); + this.temperatureMinimum = nbt.getInteger("TemperatureMin"); + this.thermalMass = nbt.getInteger("ThermalMass"); + this.temperatureLossFunction = new TemperatureLossFunction(nbt.getCompoundTag("RestorationFunction")); + this.functionPriority = nbt.getInteger("FunctionPrio"); + if (nbt.hasKey("PartialBurn")) { + this.partialBurnTemperature = nbt.getInteger("PartialBurn"); + } else this.partialBurnTemperature = null; + } + + @Override + public void encode(PacketBuffer buf, boolean fullChange) { + buf.writeFloat(this.energy); + if (fullChange) { + buf.writeVarInt(this.temperatureMaximum); + buf.writeVarInt(this.temperatureMinimum); + buf.writeVarInt(this.thermalMass); + this.temperatureLossFunction.encode(buf); + buf.writeVarInt(this.functionPriority); + buf.writeVarInt(Objects.requireNonNullElse(this.partialBurnTemperature, -1)); + } + } + + @Override + public void decode(PacketBuffer buf, boolean fullChange) { + this.lastRestorationTick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + this.energy = buf.readFloat(); + if (fullChange) { + this.temperatureMaximum = buf.readVarInt(); + this.temperatureMinimum = buf.readVarInt(); + this.thermalMass = buf.readVarInt(); + this.temperatureLossFunction.decode(buf); + this.functionPriority = buf.readVarInt(); + int partialBurn = buf.readVarInt(); + if (partialBurn != -1) this.partialBurnTemperature = partialBurn; + else this.partialBurnTemperature = null; + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java new file mode 100644 index 00000000000..cc6512faac0 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java @@ -0,0 +1,91 @@ +package gregtech.api.graphnet.pipenet.logic; + +import gregtech.api.network.IPacket; + +import it.unimi.dsi.fastutil.floats.Float2ObjectArrayMap; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.common.util.INBTSerializable; + +import java.util.Map; + +public class TemperatureLossFunction implements INBTSerializable, IPacket { + + private static final Map CABLE_LOSS_CACHE = new Float2ObjectArrayMap<>(); + private static final Map PIPE_LOSS_CACHE = new Float2ObjectArrayMap<>(); + + private EnumLossFunction function; + private float factorX; + private float factorY; + + public TemperatureLossFunction(EnumLossFunction function, float factorX) { + this.function = function; + this.factorX = factorX; + } + + public TemperatureLossFunction(EnumLossFunction function, float factorX, float factorY) { + this.function = function; + this.factorX = factorX; + this.factorY = factorY; + } + + public TemperatureLossFunction() {} + + public TemperatureLossFunction(NBTTagCompound tag) { + deserializeNBT(tag); + } + + public float restoreTemperature(float energy, int timePassed) { + return function.applyLoss(energy, factorX, factorY, timePassed); + } + + public static TemperatureLossFunction getOrCreateCable(float factor) { + TemperatureLossFunction function = CABLE_LOSS_CACHE.get(factor); + if (function == null) { + function = new TemperatureLossFunction(EnumLossFunction.WEAK_SCALING, factor, 0.35f); + CABLE_LOSS_CACHE.put(factor, function); + } + return function; + } + + public static TemperatureLossFunction getOrCreatePipe(float factor) { + TemperatureLossFunction function = PIPE_LOSS_CACHE.get(factor); + if (function == null) { + // since pipes are hollow the exponent is larger + function = new TemperatureLossFunction(EnumLossFunction.WEAK_SCALING, factor, 0.45f); + PIPE_LOSS_CACHE.put(factor, function); + } + return function; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setInteger("Ordinal", function.ordinal()); + tag.setFloat("X", factorX); + if (factorY != 0) tag.setFloat("Y", factorY); + return null; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + function = EnumLossFunction.values()[nbt.getInteger("Ordinal")]; + factorX = nbt.getFloat("X"); + factorY = nbt.getFloat("Y"); + } + + @Override + public void encode(PacketBuffer buf) { + buf.writeVarInt(function.ordinal()); + buf.writeFloat(factorX); + buf.writeFloat(factorY); + } + + @Override + public void decode(PacketBuffer buf) { + function = EnumLossFunction.values()[buf.readVarInt()]; + factorX = buf.readFloat(); + factorY = buf.readFloat(); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java index cd8cf7c46c2..9c0e527fb51 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java @@ -1,6 +1,7 @@ package gregtech.api.graphnet.pipenet.physical; import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; @@ -17,6 +18,8 @@ default void partialBurn(IBlockState state, World world, BlockPos pos) {} * Called when the block should be fully burned. */ default void fullyBurn(IBlockState state, World world, BlockPos pos) { + assert Blocks.FIRE != null; + world.setBlockState(pos, Blocks.FIRE.getDefaultState()); world.setBlockToAir(pos); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IInsulatable.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IInsulatable.java new file mode 100644 index 00000000000..b0d0bd72954 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IInsulatable.java @@ -0,0 +1,5 @@ +package gregtech.api.graphnet.pipenet.physical; + +public interface IInsulatable { + boolean isInsulated(); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java index 551c18a9cd0..51f688ccf71 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java @@ -1,5 +1,6 @@ package gregtech.api.graphnet.pipenet.physical; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java index 8b2ca66bcdd..9c25ed6fdbc 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java @@ -1,11 +1,24 @@ package gregtech.api.graphnet.pipenet.physical; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; + import net.minecraft.util.EnumFacing; import net.minecraft.util.IStringSerializable; +import net.minecraft.util.math.AxisAlignedBB; + +import java.util.ArrayList; +import java.util.List; public interface IPipeStructure extends IStringSerializable { + + /** + * Used as reference for misc things, e.g. rendering the backing of a cover. + * @return render thickness + */ float getRenderThickness(); + boolean isPaintable(); + /** * Allows for controlling what sides can be connected to based on current connections, * such as in the case of optical and laser pipes. @@ -13,4 +26,33 @@ public interface IPipeStructure extends IStringSerializable { default boolean canConnectTo(EnumFacing side, byte connectionMask) { return true; } + + default List getPipeBoxes(PipeTileEntity tileContext) { + List pipeBoxes = new ArrayList<>(); + float thickness = getRenderThickness(); + if ((tileContext.getConnectionMask() & 63) < 63) { + pipeBoxes.add(getSideBox(null, thickness)); + } + for (EnumFacing facing : EnumFacing.VALUES) { + if (tileContext.isConnected(facing)) + pipeBoxes.add(getSideBox(facing, thickness)); + } + return pipeBoxes; + } + + private static AxisAlignedBB getSideBox(EnumFacing side, float thickness) { + float min = (1.0f - thickness) / 2.0f, max = min + thickness; + float faceMin = 0f, faceMax = 1f; + + if (side == null) + return new AxisAlignedBB(min, min, min, max, max, max); + return switch (side) { + case WEST -> new AxisAlignedBB(faceMin, min, min, min, max, max); + case EAST -> new AxisAlignedBB(max, min, min, faceMax, max, max); + case NORTH -> new AxisAlignedBB(min, min, faceMin, max, max, min); + case SOUTH -> new AxisAlignedBB(min, min, max, max, max, faceMax); + case UP -> new AxisAlignedBB(min, max, min, max, faceMax, max); + case DOWN -> new AxisAlignedBB(min, faceMin, min, max, min, max); + }; + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeBlock.java deleted file mode 100644 index 8e05ee78c02..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeBlock.java +++ /dev/null @@ -1,218 +0,0 @@ -package gregtech.api.graphnet.pipenet.physical; - -import gregtech.api.block.BuiltInRenderBlock; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; -import gregtech.api.graphnet.pipenet.WorldPipeNet; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.util.GTUtility; -import gregtech.common.ConfigHolder; - -import gregtech.common.blocks.properties.PropertyByte; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import net.minecraft.block.Block; -import net.minecraft.block.SoundType; -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.entity.EntityLiving; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.item.Item; -import net.minecraft.item.ItemBlock; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; - -public abstract class PipeBlock extends BuiltInRenderBlock { - - private final IPipeStructure structure; - - public PipeBlock(IPipeStructure structure) { - super(net.minecraft.block.material.Material.IRON); - this.structure = structure; - setTranslationKey(getStructureName()); - setSoundType(SoundType.METAL); - setHardness(2.0f); - setResistance(3.0f); - setLightOpacity(0); - disableStats(); - } - - public IPipeStructure getStructure() { - return structure; - } - - public void doPlacementLogic(PipeTileEntity tile, EnumFacing placedBlockSearchSide) { - for (EnumFacing facing : EnumFacing.VALUES) { - TileEntity otherr = tile.getNeighbor(facing); - if (otherr instanceof PipeTileEntity other) { - // first check -- connect to matching mark pipes if side matches or config allows. - if (tile.getPaintingColor() == other.getPaintingColor() && (facing == placedBlockSearchSide || - !ConfigHolder.machines.gt6StylePipesCables)) { - connectTiles(tile, other, facing); - continue; - } - // second check -- connect to pipes with an open connection, no matter the mark status. - if (tile.isOpen(facing.getOpposite())) { - connectTiles(tile, other, facing); - } - } else if (facing == placedBlockSearchSide) { - // if the placed on tile supports one of our capabilities, connect to it. - tile.updateActiveStatus(facing, true); - } - } - } - - public void connectTiles(@NotNull PipeTileEntity tile1, @NotNull PipeTileEntity tile2, EnumFacing facingFrom1To2) { - // abort connection if either tile refuses it. - if (!tile1.canConnectTo(facingFrom1To2) || !tile2.canConnectTo(facingFrom1To2.getOpposite())) return; - - tile1.setOpen(facingFrom1To2); - tile2.setOpen(facingFrom1To2.getOpposite()); - if (tile1.getWorld().isRemote) return; - - boolean blocked1 = tile1.isBlocked(facingFrom1To2); - boolean blocked2 = tile2.isBlocked(facingFrom1To2.getOpposite()); - - Map tile2Nodes = new Object2ObjectOpenHashMap<>(); - for (WorldPipeNetNode tile : getNodesForTile(tile2)) { - tile2Nodes.put(tile.getNet(), tile); - } - - for (WorldPipeNetNode node : getNodesForTile(tile1)) { - WorldPipeNet net = node.getNet(); - WorldPipeNetNode other = tile2Nodes.get(net); - if (other == null) continue; - if (!blocked1 && !blocked2) { - net.addEdge(node, other, true); - } else if (net.getGraph().isDirected()) { - if (!blocked1) net.addEdge(other, node, false); - else if (!blocked2) net.addEdge(node, other, false); - } - } - } - - final Collection getNodesForTile(PipeTileEntity tile) { - assert !tile.getWorld().isRemote; - return tile.getBlockType().getHandler(tile.getBlockState()).getFromNets(tile.getWorld(), tile.getPos(), tile.getBlockType().getStructure()); - } - - @Override - public void onBlockAdded(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { - super.onBlockAdded(worldIn, pos, state); - if (!worldIn.isRemote) getHandler(worldIn.getBlockState(pos)).addToNets(worldIn, pos, getStructure()); - } - - @Override - public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { - super.breakBlock(worldIn, pos, state); - if (!worldIn.isRemote) getHandler(state).removeFromNets(worldIn, pos, getStructure()); - } - - @NotNull - protected abstract IPipeNetNodeHandler getHandler(IBlockState state); - - @Override - public boolean canCreatureSpawn(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, - @NotNull EntityLiving.SpawnPlacementType type) { - return false; - } - - public String getStructureName() { - return GTUtility.lowerUnderscoreToUpperCamel(getStructure().getName()); - } - - @Override - public void addInformation(@NotNull ItemStack stack, @Nullable World world, @NotNull List tooltip, - @NotNull ITooltipFlag flag) { - if (ConfigHolder.misc.debug) { - tooltip.add("MetaItem Id: " + getStructureName()); - } - } - - @Nullable - public static PipeBlock getPipeBlockFromItem(@NotNull ItemStack stack) { - Item item = stack.getItem(); - if (item instanceof ItemBlock p) { - Block block = p.getBlock(); - if (block instanceof PipeBlock pipe) { - return pipe; - } - } - return null; - } - - // tile entity // - - @Override - public boolean hasTileEntity(@NotNull IBlockState state) { - return true; - } - - @Nullable - public PipeTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { - TileEntity tile = world.getTileEntity(pos); - if (tile instanceof PipeTileEntity pipe) return pipe; - else return null; - } - - @Override - @NotNull - public PipeTileEntity createTileEntity(@NotNull World world, @NotNull IBlockState state) { - return new PipeTileEntity(this); - } - - @Override - public void onNeighborChange(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull BlockPos neighbor) { - super.onNeighborChange(world, pos, neighbor); - EnumFacing facing = GTUtility.getFacingToNeighbor(pos, neighbor); - if (facing == null) return; - PipeTileEntity tile = getTileEntity(world, pos); - if (tile != null) tile.onNeighborChanged(facing); - } - - // cover compatibility annoyance // - - @SuppressWarnings("deprecation") - @Override - public void neighborChanged(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos, @NotNull Block blockIn, @NotNull BlockPos fromPos) { - PipeTileEntity tile = getTileEntity(worldIn, pos); - if (tile != null) tile.getCoverHolder().updateInputRedstoneSignals(); - } - - @Override - public boolean shouldCheckWeakPower(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull EnumFacing side) { - // The check in World::getRedstonePower in the vanilla code base is reversed. Setting this to false will - // actually cause getWeakPower to be called, rather than prevent it. - return false; - } - - @SuppressWarnings("deprecation") - @Override - public int getWeakPower(@NotNull IBlockState blockState, @NotNull IBlockAccess blockAccess, @NotNull BlockPos pos, @NotNull EnumFacing side) { - PipeTileEntity tile = getTileEntity(blockAccess, pos); - return tile != null ? tile.getCoverHolder().getOutputRedstoneSignal(side) : 0; - } - - @Override - public boolean canConnectRedstone(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, EnumFacing side) { - PipeTileEntity tile = getTileEntity(world, pos); - return tile != null && tile.getCoverHolder().canConnectRedstone(side); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeMaterialBlock.java deleted file mode 100644 index 41a6d8e9859..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeMaterialBlock.java +++ /dev/null @@ -1,217 +0,0 @@ -package gregtech.api.graphnet.pipenet.physical; - -import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; -import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.recipes.ModHandler; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.Materials; -import gregtech.api.unification.material.info.MaterialFlags; -import gregtech.api.unification.material.properties.PropertyKey; -import gregtech.api.unification.material.registry.MaterialRegistry; -import gregtech.api.unification.ore.OrePrefix; -import gregtech.api.util.GTUtility; -import gregtech.common.ConfigHolder; -import gregtech.common.blocks.properties.PropertyMaterial; - -import net.minecraft.block.Block; -import net.minecraft.block.SoundType; -import net.minecraft.block.material.MapColor; -import net.minecraft.block.state.BlockStateContainer; -import net.minecraft.block.state.IBlockState; - -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.entity.Entity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemBlock; -import net.minecraft.item.ItemStack; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.List; -import java.util.Random; - -public abstract class PipeMaterialBlock extends PipeBlock { - - public final MaterialRegistry registry; - public final PropertyMaterial propertyMaterial; - - public PipeMaterialBlock(IPipeMaterialStructure structure, MaterialRegistry registry, Collection materials) { - super(structure); - this.registry = registry; - this.propertyMaterial = PropertyMaterial.create("Material", materials); - this.setDefaultState(this.blockState.getBaseState().withProperty(propertyMaterial, propertyMaterial.getAllowedValues().get(0))); - } - - @Override - public IPipeMaterialStructure getStructure() { - return (IPipeMaterialStructure) super.getStructure(); - } - - @NotNull - @Override - protected BlockStateContainer createBlockState() { - return new BlockStateContainer(this, propertyMaterial); - } - - @NotNull - public ItemStack getItem(@NotNull Material material) { - return GTUtility.toItem(getDefaultState().withProperty(propertyMaterial, material)); - } - - @NotNull - public Material getGtMaterial(int meta) { - if (meta >= propertyMaterial.getAllowedValues().size()) { - meta = 0; - } - return propertyMaterial.getAllowedValues().get(meta); - } - - @NotNull - public Material getGtMaterial(@NotNull ItemStack stack) { - return getGtMaterial(stack.getMetadata()); - } - - @NotNull - public Material getGtMaterial(@NotNull IBlockState state) { - return state.getValue(propertyMaterial); - } - - @NotNull - public IBlockState getBlock(@NotNull Material material) { - return getDefaultState().withProperty(propertyMaterial, material); - } - - @NotNull - @Override - @SuppressWarnings("deprecation") - public IBlockState getStateFromMeta(int meta) { - return getDefaultState().withProperty(propertyMaterial, getGtMaterial(meta)); - } - - @Override - public int getMetaFromState(@NotNull IBlockState state) { - return propertyMaterial.getAllowedValues().indexOf(state.getValue(propertyMaterial)); - } - - @Override - public int damageDropped(@NotNull IBlockState state) { - return getMetaFromState(state); - } - - @Override - public void getSubBlocks(@NotNull CreativeTabs tab, @NotNull NonNullList list) { - for (IBlockState state : blockState.getValidStates()) { - if (getGtMaterial(state) != Materials.NULL) { - list.add(GTUtility.toItem(state)); - } - } - } - - @NotNull - @Override - @SuppressWarnings("deprecation") - public MapColor getMapColor(@NotNull IBlockState state, @NotNull IBlockAccess worldIn, @NotNull BlockPos pos) { - return getMaterial(state).getMaterialMapColor(); - } - - @Override - public int getFlammability(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull EnumFacing face) { - Material material = getGtMaterial(world.getBlockState(pos)); - if (material.hasFlag(MaterialFlags.FLAMMABLE)) { - return 20; // flammability of things like Wood Planks - } - return super.getFlammability(world, pos, face); - } - - @Override - public int getFireSpreadSpeed(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull EnumFacing face) { - Material material = getGtMaterial(world.getBlockState(pos)); - if (material.hasFlag(MaterialFlags.FLAMMABLE)) { - return 5; // encouragement of things like Wood Planks - } - return super.getFireSpreadSpeed(world, pos, face); - } - - public OrePrefix getPrefix() { - return getStructure().getOrePrefix(); - } - @Override - protected @NotNull IPipeNetNodeHandler getHandler(IBlockState state) { - return state.getValue(propertyMaterial).getProperty(PropertyKey.PIPENET_PROPERTIES); - } - - @Override - public String getHarvestTool(@NotNull IBlockState state) { - Material material = getGtMaterial(state); - if (ModHandler.isMaterialWood(material)) { - return ToolClasses.AXE; - } - return ToolClasses.WRENCH; - } - - @NotNull - @Override - public SoundType getSoundType(@NotNull IBlockState state, @NotNull World world, @NotNull BlockPos pos, - @Nullable Entity entity) { - Material material = getGtMaterial(state); - if (ModHandler.isMaterialWood(material)) { - return SoundType.WOOD; - } - return SoundType.METAL; - } - - public SoundType getSoundType(ItemStack stack) { - Material material = getGtMaterial(stack); - if (ModHandler.isMaterialWood(material)) { - return SoundType.WOOD; - } - return SoundType.METAL; - } - - @Override - public int getHarvestLevel(@NotNull IBlockState state) { - Material material = getGtMaterial(state); - if (material.hasProperty(PropertyKey.DUST)) { - return material.getBlockHarvestLevel(); - } - return 1; - } - - @Override - @NotNull - @SuppressWarnings("deprecation") - public net.minecraft.block.material.Material getMaterial(@NotNull IBlockState state) { - Material material = getGtMaterial(state); - if (ModHandler.isMaterialWood(material)) { - return net.minecraft.block.material.Material.WOOD; - } - return super.getMaterial(state); - } - - @Override - public void addInformation(@NotNull ItemStack stack, @Nullable World world, @NotNull List tooltip, - @NotNull ITooltipFlag flag) { - if (ConfigHolder.misc.debug) { - tooltip.add("MetaItem Id: " + getStructureName() + getGtMaterial(stack).toCamelCaseString()); - } - } - - @Nullable - public static PipeMaterialBlock getPipeMaterialBlockFromItem(@NotNull ItemStack stack) { - Item item = stack.getItem(); - if (item instanceof ItemBlock) { - Block block = ((ItemBlock) item).getBlock(); - if (block instanceof PipeMaterialBlock) return (PipeMaterialBlock) block; - } - return null; - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/ItemPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java similarity index 52% rename from src/main/java/gregtech/api/graphnet/pipenet/physical/ItemPipeBlock.java rename to src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java index 4c2a72780fc..e7090ef8a03 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/ItemPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java @@ -1,12 +1,18 @@ -package gregtech.api.graphnet.pipenet.physical; +package gregtech.api.graphnet.pipenet.physical.block; + +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; + +import gregtech.common.items.MetaItems; -import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumDyeColor; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -14,22 +20,31 @@ public class ItemPipeBlock extends ItemBlock { - public ItemPipeBlock(PipeBlock block) { + public ItemPipeBlock(WorldPipeBlock block) { super(block); } @Override - public @NotNull PipeBlock getBlock() { - return (PipeBlock) super.getBlock(); + public @NotNull WorldPipeBlock getBlock() { + return (WorldPipeBlock) super.getBlock(); } @Override public boolean placeBlockAt(@NotNull ItemStack stack, @NotNull EntityPlayer player, @NotNull World world, @NotNull BlockPos pos, @NotNull EnumFacing side, float hitX, float hitY, float hitZ, @NotNull IBlockState newState) { if (super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, newState)) { + ItemStack offhand = player.getHeldItemOffhand(); + for (int i = 0; i < EnumDyeColor.values().length; i++) { + if (offhand.isItemEqual(MetaItems.SPRAY_CAN_DYES[i].getStackForm())) { + MetaItems.SPRAY_CAN_DYES[i].getBehaviours().get(0).onItemUse(player, world, + pos, EnumHand.OFF_HAND, EnumFacing.UP, 0, 0, 0); + break; + } + } + PipeTileEntity tile = getBlock().getTileEntity(world, pos); - // TODO set pipe color based on offhand here if (tile != null) { + tile.placedBy(stack, player); getBlock().doPlacementLogic(tile, side.getOpposite()); } return true; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java new file mode 100644 index 00000000000..c4807c0a1c4 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -0,0 +1,117 @@ +package gregtech.api.graphnet.pipenet.physical.block; + +import gregtech.api.GTValues; +import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; +import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; +import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.Materials; +import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.unification.material.registry.MaterialRegistry; +import gregtech.api.unification.ore.OrePrefix; +import gregtech.api.util.GTUtility; +import gregtech.common.blocks.MetaBlocks; +import gregtech.common.blocks.properties.PropertyMaterial; + +import net.minecraft.block.state.BlockStateContainer; +import net.minecraft.block.state.IBlockState; + +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +import net.minecraftforge.client.model.ModelLoader; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.WeakReference; +import java.util.Objects; + +public abstract class PipeMaterialBlock extends WorldPipeBlock { + + public final MaterialRegistry registry; + + public PipeMaterialBlock(IPipeMaterialStructure structure, MaterialRegistry registry) { + super(structure); + this.registry = registry; + } + + @Override + public IPipeMaterialStructure getStructure() { + return (IPipeMaterialStructure) super.getStructure(); + } + + @NotNull + public ItemStack getItem(@NotNull Material material) { + return new ItemStack(this, 1, registry.getIDForObject(material)); + } + + public Material getMaterialForStack(@NotNull ItemStack stack) { + return registry.getObjectById(stack.getMetadata()); + } + + @Override + public ItemStack getDrop(IBlockAccess world, BlockPos pos, IBlockState state) { + PipeMaterialTileEntity tile = getTileEntity(world, pos); + Material material; + if (tile != null) material = tile.getMaterial(); + else material = Materials.Aluminium; + return getItem(material); + } + + @Override + protected @NotNull IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos) { + PipeMaterialTileEntity tile = getTileEntity(world, pos); + if (tile != null) tile.getMaterial().getProperty(PropertyKey.PIPENET_PROPERTIES); + return Materials.Aluminium.getProperty(PropertyKey.PIPENET_PROPERTIES); + } + + /** + * to do {@link MetaBlocks#registerStateMappers()} + */ + public void onModelRegister() { + // TODO rendering + ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(this), stack -> getPipeRenderer().getModelLocation()); + for (IBlockState state : this.getBlockState().getValidStates()) { + ModelResourceLocation resourceLocation = new ModelResourceLocation( + new ResourceLocation(GTValues.MODID, // force pipe models to always be GT's + Objects.requireNonNull(this.getRegistryName()).getPath()), + MetaBlocks.statePropertiesToString(state.getProperties())); + // noinspection ConstantConditions + ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(this), + this.getMetaFromState(state), resourceLocation); + } + } + + // tile entity // + + @Override + public @Nullable PipeMaterialTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { + if (GTUtility.arePosEqual(lastTilePos, pos)) { + PipeTileEntity tile = lastTile.get(); + if (tile != null) return (PipeMaterialTileEntity) tile; + } + TileEntity tile = world.getTileEntity(pos); + if (tile instanceof PipeMaterialTileEntity pipe) { + lastTilePos = pos; + lastTile = new WeakReference<>(pipe); + return pipe; + } + else return null; + } + + @Override + public @NotNull PipeTileEntity createTileEntity(@NotNull World world, @NotNull IBlockState state) { + return new PipeMaterialTileEntity(this); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java new file mode 100644 index 00000000000..85bbfbe8af7 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java @@ -0,0 +1,358 @@ +package gregtech.api.graphnet.pipenet.physical.block; + +import gregtech.api.block.BuiltInRenderBlock; + +import gregtech.api.cover.Cover; +import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; +import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCoverHolder; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.items.toolitem.ToolClasses; +import gregtech.api.items.toolitem.ToolHelper; +import gregtech.api.util.EntityDamageUtil; +import gregtech.api.util.GTUtility; +import gregtech.common.ConfigHolder; + +import gregtech.common.blocks.BlockFrame; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.block.Block; +import net.minecraft.block.SoundType; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumDyeColor; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.NonNullList; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +import net.minecraftforge.fml.common.FMLCommonHandler; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public abstract class WorldPipeBlock extends BuiltInRenderBlock { + + // do not touch these two unless you know what you are doing + protected BlockPos lastTilePos = new BlockPos(0, 0, 0); + protected WeakReference lastTile = new WeakReference<>(null); + + private final IPipeStructure structure; + + public WorldPipeBlock(IPipeStructure structure) { + super(net.minecraft.block.material.Material.IRON); + this.structure = structure; + setTranslationKey(structure.getName()); + setSoundType(SoundType.METAL); + setHardness(2.0f); + setResistance(3.0f); + setLightOpacity(0); + disableStats(); + } + + public IPipeStructure getStructure() { + return structure; + } + + // net logic // + + public void doPlacementLogic(PipeTileEntity tile, EnumFacing placedBlockSearchSide) { + for (EnumFacing facing : EnumFacing.VALUES) { + TileEntity otherr = tile.getNeighbor(facing); + if (otherr instanceof PipeTileEntity other) { + // first check -- does the other tile have a cover that would prevent connection + Cover cover = other.getCoverHolder().getCoverAtSide(facing.getOpposite()); + if (cover != null && !cover.canPipePassThrough()) continue; + // second check -- connect to matching mark pipes if side matches or config allows. + if (tile.getPaintingColor() == other.getPaintingColor() && (facing == placedBlockSearchSide || + !ConfigHolder.machines.gt6StylePipesCables)) { + connectTiles(tile, other, facing); + continue; + } + // third check -- connect to pipes with an open connection, no matter the mark status. + if (tile.isConnected(facing.getOpposite())) { + connectTiles(tile, other, facing); + } + } else if (facing == placedBlockSearchSide) { + // if the placed on tile supports one of our capabilities, connect to it. + tile.updateActiveStatus(facing, true); + } + } + } + + public void connectTiles(@NotNull PipeTileEntity tile1, @NotNull PipeTileEntity tile2, EnumFacing facingFrom1To2) { + // abort connection if either tile refuses it. + if (!tile1.canConnectTo(facingFrom1To2) || !tile2.canConnectTo(facingFrom1To2.getOpposite())) return; + + // if one of the pipes is larger than the other, render it closed. + tile1.setConnected(facingFrom1To2, + tile1.getStructure().getRenderThickness() > tile2.getStructure().getRenderThickness()); + tile2.setConnected(facingFrom1To2.getOpposite(), + tile2.getStructure().getRenderThickness() > tile1.getStructure().getRenderThickness()); + if (tile1.getWorld().isRemote) return; + + boolean blocked1 = tile1.isBlocked(facingFrom1To2); + boolean blocked2 = tile2.isBlocked(facingFrom1To2.getOpposite()); + + Map tile2Nodes = new Object2ObjectOpenHashMap<>(); + for (WorldPipeNetNode tile : getNodesForTile(tile2)) { + tile2Nodes.put(tile.getNet(), tile); + } + + for (WorldPipeNetNode node : getNodesForTile(tile1)) { + WorldPipeNet net = node.getNet(); + WorldPipeNetNode other = tile2Nodes.get(net); + if (other == null) continue; + if (!blocked1 && !blocked2) { + net.addEdge(node, other, true); + } else if (net.getGraph().isDirected()) { + if (!blocked1) net.addEdge(other, node, false); + else if (!blocked2) net.addEdge(node, other, false); + } + } + } + + public final Collection getNodesForTile(PipeTileEntity tile) { + assert !tile.getWorld().isRemote; + return tile.getBlockType().getHandler(tile.getWorld(), tile.getPos()) + .getFromNets(tile.getWorld(), tile.getPos(), tile.getStructure()); + } + + @Override + public void onBlockAdded(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { + super.onBlockAdded(worldIn, pos, state); + if (!worldIn.isRemote) getHandler(worldIn, pos).addToNets(worldIn, pos, getStructure()); + } + + @Override + public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { + super.breakBlock(worldIn, pos, state); + if (!worldIn.isRemote) getHandler(worldIn, pos).removeFromNets(worldIn, pos, getStructure()); + } + + @NotNull + protected abstract IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos); + + // misc stuff // + + @Override + public void getDrops(@NotNull NonNullList drops, @NotNull IBlockAccess world, @NotNull BlockPos pos, + @NotNull IBlockState state, int fortune) { + PipeTileEntity tile = getTileEntity(world, pos); + if (tile == null) drops.add(getDrop(world, pos, state)); + else tile.getDrops(drops, state); + } + + public ItemStack getDrop(IBlockAccess world, BlockPos pos, IBlockState state) { + return new ItemStack(this, 1, damageDropped(state)); + } + + @Override + public boolean canCreatureSpawn(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, + @NotNull EntityLiving.SpawnPlacementType type) { + return false; + } + + @Override + public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, + @NotNull Entity entityIn) { + if (worldIn.isRemote || !(entityIn instanceof EntityLivingBase living)) return; + PipeTileEntity tile = getTileEntity(worldIn, pos); + if (tile != null && tile.getFrameMaterial() == null && tile.getOffsetTimer() % 10 == 0) { + TemperatureLogic logic = tile.getTemperatureLogic(); + if (logic != null) { + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + EntityDamageUtil.applyTemperatureDamage(living, logic.getTemperature(tick), 1f, 5); + } + } + } + + @Override + public boolean recolorBlock(@NotNull World world, @NotNull BlockPos pos, @NotNull EnumFacing side, + @NotNull EnumDyeColor color) { + if (getStructure().isPaintable()) { + PipeTileEntity tile = getTileEntity(world, pos); + if (tile != null && tile.getPaintingColor() != color.colorValue) { + tile.setPaintingColor(color.colorValue); + return true; + } + } + return false; + } + + // collision boxes // + + @SuppressWarnings("deprecation") + @Override + public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos, + @NotNull AxisAlignedBB entityBox, @NotNull List collidingBoxes, + @Nullable Entity entityIn, boolean isActualState) { + PipeTileEntity tile = getTileEntity(worldIn, pos); + if (tile != null) { + if (tile.getFrameMaterial() != null) { + AxisAlignedBB box = BlockFrame.COLLISION_BOX.offset(pos); + if (box.intersects(entityBox)) { + collidingBoxes.add(box); + } + return; + } + for (AxisAlignedBB axisAlignedBB : getStructure().getPipeBoxes(tile)) { + AxisAlignedBB offsetBox = axisAlignedBB.offset(pos); + if (offsetBox.intersects(entityBox)) collidingBoxes.add(offsetBox); + } + } else { + collidingBoxes.add(FULL_BLOCK_AABB); + } + } + + @SuppressWarnings("deprecation") + @Nullable + @Override + public RayTraceResult collisionRayTrace(@NotNull IBlockState blockState, @NotNull World worldIn, @NotNull BlockPos pos, + @NotNull Vec3d start, @NotNull Vec3d end) { + if (worldIn.isRemote && hasPipeCollisionChangingItem(worldIn, pos, GTUtility.getSP())) { + return super.collisionRayTrace(blockState, worldIn, pos, start, end); + } + PipeTileEntity tile = getTileEntity(worldIn, pos); + if (tile == null) { + return super.collisionRayTrace(blockState, worldIn, pos, start, end); + } + RayTraceResult min = null; + double minDistSqrd = Double.MAX_VALUE; + for (AxisAlignedBB aabb : getStructure().getPipeBoxes(tile)) { + RayTraceResult result = rayTrace(pos, start, end, aabb); + if (result == null) continue; + double distSqrd = start.squareDistanceTo(result.hitVec); + if (distSqrd < minDistSqrd) { + min = result; + minDistSqrd = distSqrd; + } + } + return min; + } + + public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, Entity entity) { + if (entity instanceof EntityPlayer player) { + return hasPipeCollisionChangingItem(world, pos, player.getHeldItemMainhand()) || + hasPipeCollisionChangingItem(world, pos, player.getHeldItemOffhand()) || + entity.isSneaking() && isHoldingPipe(player); + } + return false; + } + + public boolean isHoldingPipe(EntityPlayer player) { + return isPipeItem(player.getHeldItemMainhand()) || isPipeItem(player.getHeldItemOffhand()); + } + + public boolean isPipeItem(ItemStack stack) { + return stack.getItem() instanceof ItemPipeBlock block && this.getClass().isInstance(block.getBlock()); + } + + public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, ItemStack stack) { + if (isPipeTool(stack)) return true; + + PipeTileEntity tile = getTileEntity(world, pos); + if (tile == null) return false; + + PipeCoverHolder coverable = tile.getCoverHolder(); + final boolean hasAnyCover = coverable.hasAnyCover(); + + if (hasAnyCover && ToolHelper.isTool(stack, ToolClasses.SCREWDRIVER)) return true; + final boolean acceptsCovers = coverable.acceptsCovers(); + + return GTUtility.isCoverBehaviorItem(stack, () -> hasAnyCover, coverDef -> acceptsCovers); + } + + public boolean isPipeTool(@NotNull ItemStack stack) { + return ToolHelper.isTool(stack, ToolClasses.WRENCH); + } + + // tile entity // + + @Override + public boolean hasTileEntity(@NotNull IBlockState state) { + return true; + } + + @Nullable + public PipeTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { + if (GTUtility.arePosEqual(lastTilePos, pos)) { + PipeTileEntity tile = lastTile.get(); + if (tile != null) return tile; + } + TileEntity tile = world.getTileEntity(pos); + if (tile instanceof PipeTileEntity pipe) { + lastTilePos = pos; + lastTile = new WeakReference<>(pipe); + return pipe; + } + else return null; + } + + @Override + @NotNull + public PipeTileEntity createTileEntity(@NotNull World world, @NotNull IBlockState state) { + return new PipeTileEntity(this); + } + + @Override + public void onNeighborChange(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull BlockPos neighbor) { + super.onNeighborChange(world, pos, neighbor); + EnumFacing facing = GTUtility.getFacingToNeighbor(pos, neighbor); + if (facing == null) return; + PipeTileEntity tile = getTileEntity(world, pos); + if (tile != null) tile.onNeighborChanged(facing); + } + + // cover compatibility annoyance // + + @SuppressWarnings("deprecation") + @Override + public void neighborChanged(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos, @NotNull Block blockIn, @NotNull BlockPos fromPos) { + PipeTileEntity tile = getTileEntity(worldIn, pos); + if (tile != null) tile.getCoverHolder().updateInputRedstoneSignals(); + } + + @Override + public boolean shouldCheckWeakPower(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull EnumFacing side) { + // The check in World::getRedstonePower in the vanilla code base is reversed. Setting this to false will + // actually cause getWeakPower to be called, rather than prevent it. + return false; + } + + @SuppressWarnings("deprecation") + @Override + public int getWeakPower(@NotNull IBlockState blockState, @NotNull IBlockAccess blockAccess, @NotNull BlockPos pos, @NotNull EnumFacing side) { + PipeTileEntity tile = getTileEntity(blockAccess, pos); + return tile != null ? tile.getCoverHolder().getOutputRedstoneSignal(side) : 0; + } + + @Override + public boolean canConnectRedstone(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, EnumFacing side) { + PipeTileEntity tile = getTileEntity(world, pos); + return tile != null && tile.getCoverHolder().canConnectRedstone(side); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCapabilityWrapper.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java similarity index 92% rename from src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCapabilityWrapper.java rename to src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java index 65044da1deb..31b03be71fb 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCapabilityWrapper.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.pipenet.physical; +package gregtech.api.graphnet.pipenet.physical.tile; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCoverHolder.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java similarity index 96% rename from src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCoverHolder.java rename to src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java index cb9633e60d3..7a5dea00174 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeCoverHolder.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java @@ -1,9 +1,8 @@ -package gregtech.api.graphnet.pipenet.physical; +package gregtech.api.graphnet.pipenet.physical.tile; import gregtech.api.cover.Cover; import gregtech.api.cover.CoverHolder; import gregtech.api.cover.CoverSaveHandler; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; import gregtech.api.util.GTUtility; import gregtech.common.ConfigHolder; @@ -57,7 +56,7 @@ public final void addCover(@NotNull EnumFacing side, @NotNull Cover cover) { // do not sync or handle logic on client side CoverSaveHandler.writeCoverPlacement(this, COVER_ATTACHED_PIPE, side, cover); if (cover.shouldAutoConnectToPipes()) { - if (holder.canConnectTo(side)) holder.setOpen(side); + if (holder.canConnectTo(side)) holder.setConnected(side, false); } } @@ -80,8 +79,8 @@ public final void removeCover(@NotNull EnumFacing side) { writeCustomData(COVER_REMOVED_PIPE, buffer -> buffer.writeByte(side.getIndex())); if (cover.shouldAutoConnectToPipes()) { PipeTileEntity other; - if (holder.isOpen(side) && (other = holder.getPipeNeighbor(side)) != null && !other.isOpen(side.getOpposite())) - holder.setClosed(side); + if (holder.isConnected(side) && (other = holder.getPipeNeighbor(side, true)) != null && !other.isConnected(side.getOpposite())) + holder.setDisconnected(side); } holder.notifyBlockUpdate(); holder.markAsDirty(); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java new file mode 100644 index 00000000000..53a3e9c5bf8 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java @@ -0,0 +1,40 @@ +package gregtech.api.graphnet.pipenet.physical.tile; + +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.Materials; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; + +import org.jetbrains.annotations.NotNull; + +public class PipeMaterialTileEntity extends PipeTileEntity { + + private Material material; + + public PipeMaterialTileEntity(PipeMaterialBlock block) { + super(block); + } + + @Override + public void placedBy(ItemStack stack, EntityPlayer player) { + super.placedBy(stack, player); + setMaterial(getBlockType().getMaterialForStack(stack)); + } + + @Override + public @NotNull PipeMaterialBlock getBlockType() { + return (PipeMaterialBlock) super.getBlockType(); + } + + public void setMaterial(Material material) { + this.material = material; + } + + public Material getMaterial() { + if (material == null) return Materials.Aluminium; + return material; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java similarity index 68% rename from src/main/java/gregtech/api/graphnet/pipenet/physical/PipeTileEntity.java rename to src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 1a903970e17..9cf5a28d928 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -1,24 +1,34 @@ -package gregtech.api.graphnet.pipenet.physical; +package gregtech.api.graphnet.pipenet.physical.tile; import gregtech.api.GregTechAPI; -import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; import gregtech.api.graphnet.gather.GTGraphGatherables; import gregtech.api.graphnet.logic.INetLogicEntry; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.physical.IInsulatable; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.metatileentity.NeighborCacheTileEntityBase; import gregtech.api.unification.material.Material; +import gregtech.client.particle.GTOverheatParticle; + +import gregtech.common.blocks.MetaBlocks; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.ITickable; +import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -28,27 +38,31 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.IOException; import java.util.EnumMap; import java.util.Map; import java.util.Set; import static gregtech.api.capability.GregtechDataCodes.UPDATE_PAINT; +import static gregtech.api.capability.GregtechDataCodes.UPDATE_PIPE_LOGIC; public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITickable { private final Object2ObjectOpenHashMap netLogicDatas = new Object2ObjectOpenHashMap<>(); private final ObjectOpenHashSet listeners = new ObjectOpenHashSet<>(); - private final PipeBlock block; + private final WorldPipeBlock block; // information that is only required for determining graph topology should be stored on the tile entity level, // while information interacted with during graph traversal should be stored on the NetLogicData level. private byte connectionMask; + private byte renderMask; private byte blockedMask; private int paintingColor; @@ -61,19 +75,31 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick private final Object2ObjectOpenHashMap, IPipeCapabilityObject> capabilities = new Object2ObjectOpenHashMap<>(); private final Object2ObjectOpenHashMap netCapabilities = new Object2ObjectOpenHashMap<>(); + @Nullable + private TemperatureLogic temperatureLogic; + @SideOnly(Side.CLIENT) + @Nullable + private GTOverheatParticle overheatParticle; + private final int offset = (int) (Math.random() * 20); - public PipeTileEntity(PipeBlock block) { + public PipeTileEntity(WorldPipeBlock block) { this.block = block; } @Nullable - public PipeTileEntity getPipeNeighbor(EnumFacing facing) { - TileEntity tile = getNeighbor(facing); + public PipeTileEntity getPipeNeighbor(EnumFacing facing, boolean allowChunkloading) { + TileEntity tile = allowChunkloading ? getNeighbor(facing) : getNeighborNoChunkloading(facing); if (tile instanceof PipeTileEntity pipe) return pipe; else return null; } + public void getDrops(NonNullList drops, @NotNull IBlockState state) { + drops.add(this.getBlockType().getDrop(this.getWorld(), this.getPos(), state)); + if (getFrameMaterial() != null) + drops.add(MetaBlocks.FRAMES.get(getFrameMaterial()).getItem(getFrameMaterial())); + } + public ItemStack getDrop() { return new ItemStack(getBlockType(), 1, getBlockType().damageDropped(getBlockState())); } @@ -82,26 +108,46 @@ public long getOffsetTimer() { return FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter() + offset; } + public void placedBy(ItemStack stack, EntityPlayer player) {} + + public IPipeStructure getStructure() { + return getBlockType().getStructure(); + } + // mask // public boolean canConnectTo(EnumFacing facing) { - return this.getBlockType().getStructure().canConnectTo(facing, connectionMask); + return this.getStructure().canConnectTo(facing, connectionMask); } - public void setOpen(EnumFacing facing) { + public void setConnected(EnumFacing facing, boolean renderClosed) { this.connectionMask |= 1 << facing.ordinal(); updateActiveStatus(facing, false); + if (renderClosed) { + this.renderMask |= 1 << facing.ordinal(); + } else { + this.renderMask &= ~(1 << facing.ordinal()); + } } - public void setClosed(EnumFacing facing) { + public void setDisconnected(EnumFacing facing) { this.connectionMask &= ~(1 << facing.ordinal()); + this.renderMask &= ~(1 << facing.ordinal()); updateActiveStatus(facing, false); } - public boolean isOpen(EnumFacing facing) { + public boolean isConnected(EnumFacing facing) { return (this.connectionMask & 1 << facing.ordinal()) > 0; } + public boolean renderClosed(EnumFacing facing) { + return (this.renderMask & 1 << facing.ordinal()) > 0; + } + + public byte getConnectionMask() { + return connectionMask; + } + public void setBlocked(EnumFacing facing) { this.blockedMask |= 1 << facing.ordinal(); } @@ -114,6 +160,10 @@ public boolean isBlocked(EnumFacing facing) { return (this.blockedMask & 1 << facing.ordinal()) > 0; } + public byte getBlockedMask() { + return blockedMask; + } + // paint // public int getPaintingColor() { @@ -168,7 +218,7 @@ public void onLoad() { } public void removeTicker(ITickable ticker) { - this.tickers.remove(this); + this.tickers.remove(ticker); //noinspection ConstantValue if (!this.isTicking() && getWorld() != null) getWorld().tickableTileEntities.remove(this); } @@ -218,7 +268,7 @@ public void updateActiveStatus(@Nullable EnumFacing facing, boolean canOpenConne } return; } - if (!this.isOpen(facing) && !canOpenConnection) { + if (!this.isConnected(facing) && !canOpenConnection) { setAllIdle(facing); return; } @@ -241,7 +291,7 @@ public void updateActiveStatus(@Nullable EnumFacing facing, boolean canOpenConne } netCapability.getKey().setActive(oneMatch); } - if (oneActive) this.setOpen(facing); + if (oneActive) this.setConnected(facing, false); } private void setAllIdle(EnumFacing facing) { @@ -277,7 +327,7 @@ public T getCapability(@NotNull Capability capability, @Nullable EnumFaci Cover cover = facing == null ? null : getCoverHolder().getCoverAtSide(facing); if (cover == null) { - if (facing == null || isOpen(facing)) { + if (facing == null || isConnected(facing)) { return pipeCapability; } return null; @@ -285,7 +335,7 @@ public T getCapability(@NotNull Capability capability, @Nullable EnumFaci T coverCapability = cover.getCapability(capability, pipeCapability); if (coverCapability == pipeCapability) { - if (isOpen(facing)) { + if (isConnected(facing)) { return pipeCapability; } return null; @@ -300,7 +350,7 @@ public NetLogicData getNetLogicData(String netName) { } @Override - public @NotNull PipeBlock getBlockType() { + public @NotNull WorldPipeBlock getBlockType() { return block; } @@ -308,19 +358,24 @@ public NetLogicData getNetLogicData(String netName) { public void setWorld(@NotNull World worldIn) { if (worldIn == this.getWorld()) return; super.setWorld(worldIn); + this.initialize(worldIn); + } + + protected void initialize(World worldIn) { if (!worldIn.isRemote) { this.netLogicDatas.clear(); this.capabilities.clear(); this.netCapabilities.clear(); this.listeners.forEach(NetLogicData.LogicDataListener::invalidate); this.listeners.clear(); + boolean firstNode = true; for (WorldPipeNetNode node : getBlockType().getNodesForTile(this)) { this.addCapabilities(node.getNet().getNewCapabilityObjects(node)); this.netCapabilities.put(node, new PipeCapabilityWrapper(node.getNet().getTargetCapabilities())); String netName = node.getNet().mapName; netLogicDatas.put(netName, node.getData()); var listener = node.getData().new LogicDataListener((e, r, f) -> - writeCustomData(GregtechDataCodes.UPDATE_PIPE_LOGIC, buf -> { + writeCustomData(UPDATE_PIPE_LOGIC, buf -> { buf.writeString(netName); buf.writeString(e.getName()); buf.writeBoolean(r); @@ -331,6 +386,11 @@ public void setWorld(@NotNull World worldIn) { })); this.listeners.add(listener); node.getData().addListener(listener); + if (firstNode) { + firstNode = false; + this.temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + } + node.getNet().updatePredication(node, this); } this.netLogicDatas.trim(); this.listeners.trim(); @@ -362,34 +422,30 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { @Override public void writeInitialSyncData(@NotNull PacketBuffer buf) { - NBTTagCompound tag = new NBTTagCompound(); + buf.writeVarInt(netLogicDatas.size()); for (Map.Entry entry : netLogicDatas.entrySet()) { - tag.setTag(entry.getKey(), entry.getValue().serializeNBT()); + buf.writeString(entry.getKey()); + entry.getValue().encode(buf); } - buf.writeCompoundTag(tag); } @Override public void receiveInitialSyncData(@NotNull PacketBuffer buf) { if (world.isRemote) { netLogicDatas.clear(); - try { - NBTTagCompound logics = buf.readCompoundTag(); - if (logics == null) return; - for (String name : logics.getKeySet()) { - NetLogicData data = new NetLogicData(); - data.deserializeNBT((NBTTagList) logics.getTag("LogicData")); - netLogicDatas.put(name, data); - } - } catch (IOException e) { - throw new RuntimeException(e); + int count = buf.readVarInt(); + for (int i = 0; i < count; i++) { + String key = buf.readString(255); + NetLogicData data = new NetLogicData(); + data.decode(buf); + netLogicDatas.put(key, data); } } } @Override public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { - if (discriminator == GregtechDataCodes.UPDATE_PIPE_LOGIC) { + if (discriminator == UPDATE_PIPE_LOGIC) { // extra check just to make sure we don't affect actual net data with our writes if (world.isRemote) { String netName = buf.readString(255); @@ -399,21 +455,69 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { if (removed) { this.netLogicDatas.computeIfPresent(netName, (k, v) -> v.removeLogicEntry(identifier)); } else { - INetLogicEntry logic = GTGraphGatherables.getLogicsRegistry() - .getOrDefault(identifier, () -> null).get(); - logic.decode(buf, fullChange); - this.netLogicDatas.compute(netName, (k, v) -> { - if (v == null) v = new NetLogicData(); - v.setLogicEntry(logic); - return v; - }); + if (fullChange) { + INetLogicEntry logic = GTGraphGatherables.getLogicsRegistry() + .getOrDefault(identifier, () -> null).get(); + logic.decode(buf, fullChange); + this.netLogicDatas.compute(netName, (k, v) -> { + if (v == null) v = new NetLogicData(); + v.setLogicEntry(logic); + return v; + }); + } else { + NetLogicData data = this.netLogicDatas.get(netName); + if (data != null) { + INetLogicEntry entry = data.getLogicEntryNullable(identifier); + if (entry != null) entry.decode(buf); + } else return; + } + if (identifier.equals(TemperatureLogic.INSTANCE.getName())) { + TemperatureLogic tempLogic = this.netLogicDatas.get(netName) + .getLogicEntryNullable(TemperatureLogic.INSTANCE); + if (tempLogic != null) updateTemperatureLogic(tempLogic); + } } } + } else if (discriminator == UPDATE_PAINT) { + this.paintingColor = buf.readInt(); } else { this.getCoverHolder().readCustomData(discriminator, buf); } } + // particle // + + public void updateTemperatureLogic(@NotNull TemperatureLogic logic) { + if (overheatParticle == null || !overheatParticle.isAlive()) { + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + int temp = logic.getTemperature(tick); + if (temp > GTOverheatParticle.TEMPERATURE_CUTOFF) { + IPipeStructure structure = this.getStructure(); + overheatParticle = new GTOverheatParticle(this, logic, structure.getPipeBoxes(this), + structure instanceof IInsulatable i && i.isInsulated()); + } + } else { + overheatParticle.setTemperatureLogic(logic); + } + } + + public @Nullable TemperatureLogic getTemperatureLogic() { + return temperatureLogic; + } + + @SideOnly(Side.CLIENT) + public void killOverheatParticle() { + if (overheatParticle != null) { + overheatParticle.setExpired(); + overheatParticle = null; + } + } + + @SideOnly(Side.CLIENT) + public boolean isOverheatParticleAlive() { + return overheatParticle != null && overheatParticle.isAlive(); + } + // misc overrides // @Override @@ -444,5 +548,8 @@ public void markDirty() { public void markAsDirty() { markDirty(); // this most notably gets called when the covers of a pipe get updated, aka the edge predicates need syncing. + for (var node : this.netCapabilities.keySet()) { + node.getNet().updatePredication(node, this); + } } } diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java index 1b63c7f8bc6..144847d52ca 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java @@ -403,7 +403,7 @@ public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { BlockPipe pipeBlock = getPipeBlock(); if (pipeBlock != null) { // noinspection ConstantConditions - compound.setString("PipeBlock", pipeBlock.getRegistryName().toString()); + compound.setString("WorldPipeBlock", pipeBlock.getRegistryName().toString()); } compound.setInteger("PipeNetVersion", 2); compound.setInteger("PipeType", pipeType.ordinal()); @@ -424,8 +424,8 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { return; } super.readFromNBT(compound); - if (compound.hasKey("PipeBlock", NBT.TAG_STRING)) { - Block block = Block.REGISTRY.getObject(new ResourceLocation(compound.getString("PipeBlock"))); + if (compound.hasKey("WorldPipeBlock", NBT.TAG_STRING)) { + Block block = Block.REGISTRY.getObject(new ResourceLocation(compound.getString("WorldPipeBlock"))); // noinspection unchecked this.pipeBlock = block instanceof BlockPipeblockPipe ? (BlockPipe) blockPipe : null; diff --git a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java index e6bb6659889..09bacf5a552 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java +++ b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java @@ -2,18 +2,27 @@ import gregtech.api.graphnet.gather.GTGraphGatherables; +import gregtech.api.graphnet.gather.GatherPredicatesEvent; +import gregtech.api.graphnet.logic.INetLogicEntry; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; import java.util.Map; import java.util.function.Predicate; import java.util.function.Supplier; +/** + * Note - since the internal map representation encodes keys using {@link IStringSerializable#getName()} on predicates, + * making a predicate class return two different names is a valid way to register multiple instances.
+ * Just make sure that a supplier is registered to {@link GatherPredicatesEvent} for all + * associated names, so that decoding from nbt and packets is possible. + */ public final class EdgePredicateHandler implements INBTSerializable, Predicate { private final Map> predicateSet; @@ -26,10 +35,17 @@ private EdgePredicateHandler(Map> predicateSet) { this.predicateSet = predicateSet; } + /** + * If the {@link IEdgePredicate#union(IEdgePredicate)} operation is not supported for this predicate, + * nothing happens if a predicate is already present. + */ public EdgePredicateHandler mergePredicate(IEdgePredicate predicate) { IEdgePredicate current = predicateSet.get(predicate.getName()); + if (current == null) return setPredicate(predicate); + if (predicate.getClass().isInstance(current)) { predicate = current.union(predicate); + if (predicate == null) return this; } return setPredicate(predicate); } @@ -40,10 +56,18 @@ public EdgePredicateHandler setPredicate(IEdgePredicate predicate) { } public EdgePredicateHandler removePredicate(IEdgePredicate key) { - predicateSet.remove(key.getName()); + return removePredicate(key.getName()); + } + + public EdgePredicateHandler removePredicate(String key) { + predicateSet.remove(key); return this; } + public void clearPredicates() { + this.predicateSet.clear(); + } + @Override public boolean test(IPredicateTestObject iPredicateTestObject) { // TODO predicate 'categories' or 'affinities' that determine order of operations with and-y and or-y behavior? diff --git a/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java b/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java index ff15d4e48cf..29e4b70fa44 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java +++ b/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java @@ -7,6 +7,7 @@ import net.minecraftforge.common.util.INBTSerializable; import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; /** * Note - all implementers of this interface are suggested to be final, in order to avoid unexpected {@link #union(IEdgePredicate)} behavior. @@ -22,12 +23,17 @@ default void deserializeNBTNaive(NBTBase nbt) { * For example, if a predicate handler has 2 and-y predicates and 3 or-y predicates, * the effective result of evaluation will be:
(andy1) && (andy2) && (ory1 || ory2 || ory3) */ - default boolean andy() { - return false; - } + boolean andy(); + + T getNew(); boolean test(IPredicateTestObject object); - @Contract("_ -> new") - T union(IEdgePredicate other); + /** + * Returns null if the operation is not supported. + */ + @Nullable + default T union(IEdgePredicate other) { + return null; + } } diff --git a/src/main/java/gregtech/api/graphnet/predicate/ShutterPredicate.java b/src/main/java/gregtech/api/graphnet/predicate/ShutterPredicate.java new file mode 100644 index 00000000000..f28fde26cdb --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/predicate/ShutterPredicate.java @@ -0,0 +1,49 @@ +package gregtech.api.graphnet.predicate; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import gregtech.common.covers.CoverShutter; + +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagByte; + +import net.minecraft.nbt.NBTTagString; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class ShutterPredicate implements IEdgePredicate { + + public static final ShutterPredicate INSTANCE = new ShutterPredicate(); + + private ShutterPredicate() {} + + @Override + @Deprecated + public ShutterPredicate getNew() { + return INSTANCE; + } + + @Override + public @NotNull String getName() { + return "Shuttered"; + } + + @Override + public NBTTagString serializeNBT() { + return new NBTTagString(""); + } + + @Override + public void deserializeNBT(NBTTagString nbt) {} + + @Override + public boolean andy() { + return true; + } + + @Override + public boolean test(IPredicateTestObject object) { + return false; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index ad9dfd55878..aa62dda90e9 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -36,9 +36,11 @@ public static paths, long flowIn) { + boolean simulate = data.getSimulatorKey() != null; long availableFlow = flowIn; pathloop: while (paths.hasNext()) { + List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); long pathFlowIn = availableFlow; long pathFlow = availableFlow; P path = paths.next(); @@ -55,6 +57,14 @@ public static finalTargetNode.traverse(data.getQueryTick(), false)); + } + } else continue pathloop; + long flowLimit = edge.getFlowLimit(data.getTestObject(), data.getGraphNet(), data.getQueryTick(), data.getSimulatorKey()); if (flowLimit < pathFlow) { double ratio = (double) flowLimit / pathFlow; @@ -65,11 +75,13 @@ public static , D @NotNull Iterator

paths, @Nullable BiConsumer overflowListener, long flowIn) { + boolean simulate = data.getSimulatorKey() != null; + boolean flow = overflowListener != null; long availableFlow = flowIn; pathloop: while (paths.hasNext()) { + List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); long pathFlowIn = availableFlow; long pathFlow = availableFlow; P path = paths.next(); @@ -106,8 +121,8 @@ public static , D List nodes = path.getOrderedNodes(); List edges = path.getOrderedEdges(); - FlowConsumerList flowConsumers = overflowListener == null ? null : new FlowConsumerList(); - List> overflowReporters = overflowListener == null ? null : new ObjectArrayList<>(); + FlowConsumerList flowConsumers = flow ? new FlowConsumerList() : null; + List> overflowReporters = flow ? new ObjectArrayList<>() : null; assert nodes.size() == edges.size() + 1; N targetNode = nodes.get(0); @@ -116,7 +131,15 @@ public static , D for (int i = 0; i < edges.size(); i++) { E edge = edges.get(i); targetNode = nodes.get(i + 1); - if (overflowListener != null && edge instanceof AbstractNetFlowEdge flowEdge) { + + if (targetNode.traverse(data.getQueryTick(), true)) { + if (!simulate) { + N finalTargetNode = targetNode; + pathTraverseCalls.add(() -> finalTargetNode.traverse(data.getQueryTick(), false)); + } + } else continue pathloop; + + if (flow && edge instanceof AbstractNetFlowEdge flowEdge) { long flowLimit = flowEdge.getFlowLimit(data.getTestObject(), data.getGraphNet(), data.getQueryTick(), data.getSimulatorKey()); if (flowLimit < pathFlow) { long overflow = pathFlow - flowLimit; @@ -135,10 +158,11 @@ public static , D } long accepted = data.finalizeAtDestination(targetNode, pathFlow); long unaccepted = pathFlow - accepted; - if (overflowListener != null) { + if (flow) { flowConsumers.doConsumption(unaccepted); overflowReporters.forEach((c) -> c.accept(unaccepted)); } + if (!simulate) pathTraverseCalls.forEach(Runnable::run); availableFlow -= pathFlowIn - unaccepted; if (availableFlow <= 0) break; diff --git a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java index ea37e85c017..263f3773fff 100644 --- a/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java +++ b/src/main/java/gregtech/api/metatileentity/NeighborCacheTileEntityBase.java @@ -67,17 +67,33 @@ public void onChunkUnload() { @Override public @Nullable TileEntity getNeighbor(@NotNull EnumFacing facing) { - if (world == null || pos == null) return null; + if (world() == null || pos() == null) return null; int i = facing.getIndex(); TileEntity neighbor = this.neighbors[i]; if (neighbor == this || (neighbor != null && neighbor.isInvalid())) { - neighbor = world.getTileEntity(pos.offset(facing)); + neighbor = world().getTileEntity(pos().offset(facing)); this.neighbors[i] = neighbor; this.neighborsInvalidated = false; } return neighbor; } + @Override + public @Nullable TileEntity getNeighborNoChunkloading(@NotNull EnumFacing facing) { + if (world() == null || pos() == null) return null; + int i = facing.getIndex(); + TileEntity neighbor = this.neighbors[i]; + if (neighbor == this || (neighbor != null && neighbor.isInvalid())) { + BlockPos pos = pos().offset(facing); + if (world().isBlockLoaded(pos)) { + neighbor = world().getTileEntity(pos); + this.neighbors[i] = neighbor; + this.neighborsInvalidated = false; + } else return null; + } + return neighbor; + } + public void onNeighborChanged(@NotNull EnumFacing facing) { this.neighbors[facing.getIndex()] = this; } diff --git a/src/main/java/gregtech/api/metatileentity/interfaces/INeighborCache.java b/src/main/java/gregtech/api/metatileentity/interfaces/INeighborCache.java index cf6a662d2cb..d40ba85510b 100644 --- a/src/main/java/gregtech/api/metatileentity/interfaces/INeighborCache.java +++ b/src/main/java/gregtech/api/metatileentity/interfaces/INeighborCache.java @@ -3,6 +3,8 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,6 +21,11 @@ public interface INeighborCache extends IHasWorldObjectAndCoords { return world().getTileEntity(pos().offset(facing)); } + default @Nullable TileEntity getNeighborNoChunkloading(@NotNull EnumFacing facing) { + BlockPos pos = pos().offset(facing); + return world().isBlockLoaded(pos) ? world().getTileEntity(pos) : null; + } + /** * Called when an adjacent neighboring block has changed at a side in some way * diff --git a/src/main/java/gregtech/api/unification/material/Material.java b/src/main/java/gregtech/api/unification/material/Material.java index 0b2478a1ad9..e88bb48d7d6 100644 --- a/src/main/java/gregtech/api/unification/material/Material.java +++ b/src/main/java/gregtech/api/unification/material/Material.java @@ -18,6 +18,8 @@ import gregtech.api.util.LocalizationUtils; import gregtech.api.util.SmallDigits; +import gregtech.common.pipelike.properties.MaterialEnergyProperties; + import net.minecraft.enchantment.Enchantment; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fluids.Fluid; @@ -1032,37 +1034,33 @@ public Builder addOreByproducts(Material... byproducts) { return this; } - public Builder cableProperties(long voltage, int amperage, int loss) { - properties.setProperty(PropertyKey.WIRE, new WireProperties((int) voltage, amperage, loss)); - return this; + private PipeNetProperties getOrCreatePipeNetProperties() { + if (properties.hasProperty(PropertyKey.PIPENET_PROPERTIES)) { + return properties.getProperty(PropertyKey.PIPENET_PROPERTIES); + } else { + PipeNetProperties prop = new PipeNetProperties(); + properties.setProperty(PropertyKey.PIPENET_PROPERTIES, prop); + return prop; + } } - public Builder cableProperties(long voltage, int amperage, int loss, int meltTemperature) { - properties.setProperty(PropertyKey.WIRE, - new WireProperties((int) voltage, amperage, loss, meltTemperature)); + public Builder cableProperties(long voltage, long amperage, long loss) { + getOrCreatePipeNetProperties().setProperty(MaterialEnergyProperties.create(voltage, amperage, loss)); return this; } - public Builder cableProperties(long voltage, int amperage, int loss, boolean isSuperCon) { - return cableProperties(voltage, amperage, loss, 0, isSuperCon); - } - - public Builder cableProperties(long voltage, int amperage, int loss, int meltTemperature, boolean isSuperCon) { - properties.setProperty(PropertyKey.WIRE, - new WireProperties((int) voltage, amperage, loss, meltTemperature, isSuperCon)); + public Builder cablePropertiesT(long voltage, long amperage, long loss, int meltTemperature) { + getOrCreatePipeNetProperties().setProperty(MaterialEnergyProperties.createT(voltage, amperage, loss, meltTemperature)); return this; } - public Builder cableProperties(long voltage, int amperage, int loss, boolean isSuperCon, - int criticalTemperature) { - return cableProperties(voltage, amperage, loss, 0, isSuperCon, criticalTemperature); + public Builder cablePropertiesS(long voltage, long amperage, long loss, int superconductorTemperature) { + getOrCreatePipeNetProperties().setProperty(MaterialEnergyProperties.createS(voltage, amperage, loss, superconductorTemperature)); + return this; } - public Builder cableProperties(long voltage, int amperage, int loss, int meltTemperature, boolean isSuperCon, - int criticalTemperature) { - properties.setProperty(PropertyKey.WIRE, - new WireProperties((int) voltage, amperage, loss, meltTemperature, isSuperCon, - criticalTemperature)); + public Builder cableProperties(long voltage, long amperage, long loss, int meltTemperature, int superconductorTemperature) { + getOrCreatePipeNetProperties().setProperty(new MaterialEnergyProperties(voltage, amperage, loss, meltTemperature, superconductorTemperature)); return this; } diff --git a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java index c5136fc4a32..034644e69c7 100644 --- a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java @@ -1312,7 +1312,7 @@ public static void register() { .color(0xE1B454).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Manganese, 1, Phosphorus, 1) - .cableProperties(GTValues.V[GTValues.LV], 2, 0, true, 78) + .cablePropertiesS(GTValues.V[GTValues.LV], 2, GTValues.V[GTValues.ULV], 500) .blast(1200, GasTier.LOW) .build(); @@ -1322,7 +1322,7 @@ public static void register() { .color(0x331900).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Magnesium, 1, Boron, 2) - .cableProperties(GTValues.V[GTValues.MV], 4, 0, true, 78) + .cablePropertiesS(GTValues.V[GTValues.MV], 4, GTValues.V[GTValues.LV], 500) .blast(b -> b .temp(2500, GasTier.LOW) .blastStats(VA[HV], 1000) @@ -1335,7 +1335,7 @@ public static void register() { .color(0x555555).iconSet(SHINY) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Mercury, 1, Barium, 2, Calcium, 2, Copper, 3, Oxygen, 8) - .cableProperties(GTValues.V[GTValues.HV], 4, 0, true, 78) + .cablePropertiesS(GTValues.V[GTValues.HV], 4, GTValues.V[GTValues.MV], 500) .blast(b -> b .temp(3300, GasTier.LOW) .blastStats(VA[HV], 1500) @@ -1348,7 +1348,7 @@ public static void register() { .color(0x008700).iconSet(SHINY) .flags(DECOMPOSITION_BY_CENTRIFUGING) .components(Uranium238, 1, Platinum, 3) - .cableProperties(GTValues.V[GTValues.EV], 6, 0, true, 30) + .cablePropertiesS(GTValues.V[GTValues.EV], 6, GTValues.V[GTValues.HV], 500) .blast(b -> b .temp(4400, GasTier.MID) .blastStats(VA[EV], 1000) @@ -1362,7 +1362,7 @@ public static void register() { .color(0x330033).iconSet(SHINY) .flags(DECOMPOSITION_BY_CENTRIFUGING) .components(Samarium, 1, Iron, 1, Arsenic, 1, Oxygen, 1) - .cableProperties(GTValues.V[GTValues.IV], 6, 0, true, 30) + .cablePropertiesS(GTValues.V[GTValues.IV], 6, GTValues.V[GTValues.EV], 500) .blast(b -> b .temp(5200, GasTier.MID) .blastStats(VA[EV], 1500) @@ -1375,7 +1375,7 @@ public static void register() { .color(0x994C00).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING, GENERATE_FINE_WIRE) .components(Indium, 4, Tin, 2, Barium, 2, Titanium, 1, Copper, 7, Oxygen, 14) - .cableProperties(GTValues.V[GTValues.LuV], 8, 0, true, 5) + .cablePropertiesS(GTValues.V[GTValues.LuV], 8, GTValues.V[GTValues.IV], 500) .blast(b -> b .temp(6000, GasTier.HIGH) .blastStats(VA[IV], 1000) @@ -1388,7 +1388,7 @@ public static void register() { .color(0x0A0A0A) .flags(DECOMPOSITION_BY_CENTRIFUGING, GENERATE_FINE_WIRE) .components(Uranium238, 1, Rhodium, 1, Naquadah, 2) - .cableProperties(GTValues.V[GTValues.ZPM], 8, 0, true, 5) + .cablePropertiesS(GTValues.V[GTValues.ZPM], 8, GTValues.V[LuV], 500) .blast(b -> b .temp(9000, GasTier.HIGH) .blastStats(VA[IV], 1500) @@ -1403,7 +1403,7 @@ public static void register() { .color(0x7D9673).iconSet(METALLIC) .flags(DECOMPOSITION_BY_CENTRIFUGING, GENERATE_FINE_WIRE) .components(NaquadahEnriched, 4, Trinium, 3, Europium, 2, Duranium, 1) - .cableProperties(GTValues.V[GTValues.UV], 16, 0, true, 3) + .cablePropertiesS(GTValues.V[GTValues.UV], 16, GTValues.V[GTValues.ZPM], 500) .blast(b -> b .temp(9900, GasTier.HIGH) .blastStats(VA[LuV], 1200) @@ -1417,7 +1417,7 @@ public static void register() { .color(0xFFFFFF).iconSet(BRIGHT) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Ruthenium, 1, Trinium, 2, Americium, 1, Neutronium, 2, Oxygen, 8) - .cableProperties(GTValues.V[GTValues.UHV], 24, 0, true, 3) + .cablePropertiesS(GTValues.V[GTValues.UHV], 24, GTValues.V[GTValues.UV], 500) .blast(b -> b .temp(10800, GasTier.HIGHER) .blastStats(VA[ZPM], 1000) diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index b44e25fdd74..91f313e02c2 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -1,29 +1,32 @@ package gregtech.api.unification.material.properties; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.graphnet.worldnet.WorldNetNode; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.ore.IOreRegistrationHandler; + +import gregtech.api.unification.ore.OrePrefix; +import gregtech.api.util.function.TriConsumer; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Set; + +import static gregtech.api.unification.material.info.MaterialFlags.NO_UNIFICATION; public class PipeNetProperties implements IMaterialProperty, IPipeNetNodeHandler { @@ -33,14 +36,29 @@ public void setProperty(IPipeNetMaterialProperty property) { this.properties.put(property.getName(), property); } + public boolean hasProperty(String propertyName) { + return this.properties.containsKey(propertyName); + } + + public T getProperty(String propertyName) { + return (T) this.properties.get(propertyName); + } + public void removeProperty(String propertyName) { this.properties.remove(propertyName); } + public boolean generatesStructure(IPipeStructure structure) { + for (IPipeNetMaterialProperty p : properties.values()) { + if (p.generatesStructure(structure)) return true; + } + return false; + } + @Override public void addToNets(World world, BlockPos pos, IPipeStructure structure) { for (IPipeNetMaterialProperty p : properties.values()) { - if (p.supportedStructure(structure)) p.addToNet(world, pos, structure); + p.addToNet(world, pos, structure); } } @@ -48,10 +66,8 @@ public void addToNets(World world, BlockPos pos, IPipeStructure structure) { public Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { List list = new ObjectArrayList<>(); for (IPipeNetMaterialProperty p : properties.values()) { - if (p.supportedStructure(structure)) { - WorldPipeNetNode node = p.getFromNet(world, pos, structure); - if (node != null) list.add(node); - } + WorldPipeNetNode node = p.getFromNet(world, pos, structure); + if (node != null) list.add(node); } return list; } @@ -59,7 +75,7 @@ public Collection getFromNets(World world, BlockPos pos, IPipe @Override public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) { for (IPipeNetMaterialProperty p : properties.values()) { - if (p.supportedStructure(structure)) p.removeFromNet(world, pos, structure); + p.removeFromNet(world, pos, structure); } } @@ -77,8 +93,10 @@ public interface IPipeNetMaterialProperty extends IMaterialProperty, IStringSeri @Nullable WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure); + void mutateData(NetLogicData data, IPipeStructure structure); + void removeFromNet(World world, BlockPos pos, IPipeStructure structure); - boolean supportedStructure(IPipeStructure structure); + boolean generatesStructure(IPipeStructure structure); } } diff --git a/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java b/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java index 0b783a3c776..273caab6dbd 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java +++ b/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java @@ -5,23 +5,24 @@ public class PropertyKey { public static final PropertyKey BLAST = new PropertyKey<>("blast", BlastProperty.class); public static final PropertyKey DUST = new PropertyKey<>("dust", DustProperty.class); public static final PropertyKey PIPENET_PROPERTIES = new PropertyKey<>("net_pipe", PipeNetProperties.class); - public static final PropertyKey FLUID_PIPE = new PropertyKey<>("fluid_pipe", - FluidPipeProperties.class); public static final PropertyKey FLUID = new PropertyKey<>("fluid", FluidProperty.class); public static final PropertyKey GEM = new PropertyKey<>("gem", GemProperty.class); public static final PropertyKey INGOT = new PropertyKey<>("ingot", IngotProperty.class); public static final PropertyKey POLYMER = new PropertyKey<>("polymer", PolymerProperty.class); - public static final PropertyKey ITEM_PIPE = new PropertyKey<>("item_pipe", - ItemPipeProperties.class); public static final PropertyKey ORE = new PropertyKey<>("ore", OreProperty.class); public static final PropertyKey TOOL = new PropertyKey<>("tool", ToolProperty.class); public static final PropertyKey ROTOR = new PropertyKey<>("rotor", RotorProperty.class); - public static final PropertyKey WIRE = new PropertyKey<>("wire", WireProperties.class); public static final PropertyKey WOOD = new PropertyKey<>("wood", WoodProperty.class); // Empty property used to allow property-less Materials without removing base type enforcement public static final PropertyKey EMPTY = new PropertyKey<>("empty", EmptyProperty.class); + + public static final PropertyKey FLUID_PIPE = new PropertyKey<>("fluid_pipe", + FluidPipeProperties.class); + public static final PropertyKey ITEM_PIPE = new PropertyKey<>("item_pipe", + ItemPipeProperties.class); + private final String key; private final Class type; diff --git a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java b/src/main/java/gregtech/api/unification/material/properties/WireProperties.java deleted file mode 100644 index 9d5b310d97f..00000000000 --- a/src/main/java/gregtech/api/unification/material/properties/WireProperties.java +++ /dev/null @@ -1,227 +0,0 @@ -package gregtech.api.unification.material.properties; - -import gregtech.api.GTValues; -import gregtech.api.fluids.FluidBuilder; -import gregtech.api.fluids.store.FluidStorageKeys; -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.unification.material.Material; - -import net.minecraftforge.fluids.Fluid; - -import java.util.List; -import java.util.Objects; - -import static gregtech.api.unification.material.info.MaterialFlags.GENERATE_FOIL; - -public class WireProperties implements IMaterialProperty, IPipeNetData { - - private int voltage; - private int amperage; - private int lossPerBlock; - private int meltTemperature; - private int superconductorCriticalTemperature; - private boolean isSuperconductor; - - public WireProperties(int voltage, int baseAmperage, int lossPerBlock) { - this(voltage, baseAmperage, lossPerBlock, 0, false); - } - - public WireProperties(int voltage, int baseAmperage, int lossPerBlock, int meltTemperature) { - this(voltage, baseAmperage, lossPerBlock, meltTemperature, false); - } - - public WireProperties(int voltage, int baseAmperage, int lossPerBlock, int meltTemperature, boolean isSuperCon) { - this(voltage, baseAmperage, lossPerBlock, meltTemperature, isSuperCon, 0); - } - - public WireProperties(int voltage, int baseAmperage, int lossPerBlock, int meltTemperature, boolean isSuperCon, - int criticalTemperature) { - this.voltage = voltage; - this.amperage = baseAmperage; - this.lossPerBlock = isSuperCon ? 0 : lossPerBlock; - this.meltTemperature = meltTemperature; - this.superconductorCriticalTemperature = isSuperCon ? criticalTemperature : 0; - this.isSuperconductor = isSuperCon; - } - - /** - * Default values constructor - */ - public WireProperties() { - this(8, 1, 1, 0, false); - } - - /** - * Retrieves the current wire voltage - * - * @return The current wire voltage - */ - public int getVoltage() { - return voltage; - } - - /** - * Sets the current wire voltage - * - * @param voltage The new wire voltage - */ - public void setVoltage(int voltage) { - this.voltage = voltage; - } - - /** - * Retrieves the current wire amperage - * - * @return The current wire amperage - */ - public int getAmperage() { - return amperage; - } - - /** - * Sets the current wire amperage - * - * @param amperage The new current wire amperage - */ - public void setAmperage(int amperage) { - this.amperage = amperage; - } - - /** - * Retrieves the current wire loss per block - * - * @return The current wire loss per block - */ - public int getLoss() { - return lossPerBlock; - } - - /** - * Sets the current wire loss per block - * - * @param lossPerBlock The new wire loss per block - */ - public void setLossPerBlock(int lossPerBlock) { - this.lossPerBlock = lossPerBlock; - } - - /** - * Retrieves the current melt temperature. - * - * @return The current melt temperature - */ - public int getMeltTemperature() { - return meltTemperature == 0 ? 3000 : meltTemperature; - } - - /** - * Sets the current melt temperature - * - * @param meltTemperature The new melt temperature - */ - public void setMeltTemperature(int meltTemperature) { - this.meltTemperature = meltTemperature; - } - - /** - * If the current wire is a Superconductor wire - * - * @return {@code true} if the current wire is a Superconductor - */ - public boolean isSuperconductor() { - return isSuperconductor; - } - - /** - * Sets the current wire to a superconductor wire - * - * @param isSuperconductor The new wire superconductor status - */ - public void setSuperconductor(boolean isSuperconductor) { - this.isSuperconductor = isSuperconductor; - } - - /** - * Retrieves the critical temperature of the superconductor (the temperature at which the superconductive phase - * transition happens) - * - * @return Critical temperature of the material - */ - public int getSuperconductorCriticalTemperature() { - return superconductorCriticalTemperature; - } - - /** - * Sets the material's critical temperature - * - * @param criticalTemperature The new critical temperature - */ - public void setSuperconductorCriticalTemperature(int criticalTemperature) { - this.superconductorCriticalTemperature = this.isSuperconductor ? criticalTemperature : 0; - } - - @Override - public void verifyProperty(MaterialProperties properties) { - properties.ensureSet(PropertyKey.DUST, true); - if (properties.hasProperty(PropertyKey.INGOT)) { - // Ensure all Materials with Cables and voltage tier IV or above have a Foil for recipe generation - Material thisMaterial = properties.getMaterial(); - if (!isSuperconductor && voltage >= GTValues.V[GTValues.IV] && !thisMaterial.hasFlag(GENERATE_FOIL)) { - thisMaterial.addFlags(GENERATE_FOIL); - } - } - if (this.meltTemperature == 0 && properties.hasProperty(PropertyKey.FLUID)) { - // autodetermine melt temperature from registered fluid - FluidProperty prop = properties.getProperty(PropertyKey.FLUID); - Fluid fluid = prop.getStorage().get(FluidStorageKeys.LIQUID); - if (fluid == null) { - FluidBuilder builder = prop.getStorage().getQueuedBuilder(FluidStorageKeys.LIQUID); - if (builder != null) { - this.setMeltTemperature(builder.currentTemp()); - } - } else { - this.setMeltTemperature(fluid.getTemperature()); - } - } - } - - @Override - public double getWeightFactor() { - return this.getLoss() + 0.001 / this.getAmperage(); - } - - @Override - public int getThroughput() { - return this.getAmperage(); - } - - @Override - public WireProperties getSumData(List datas) { - int amperage = this.getAmperage(); - int voltage = this.getVoltage(); - int loss = this.getLoss(); - for (WireProperties data : datas) { - amperage = Math.min(amperage, data.getAmperage()); - voltage = Math.min(voltage, data.getVoltage()); - loss += data.getLoss(); - } - return new WireProperties(voltage, amperage, loss); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - WireProperties that = (WireProperties) o; - return voltage == that.voltage && amperage == that.amperage && lossPerBlock == that.lossPerBlock && - meltTemperature == that.meltTemperature && - superconductorCriticalTemperature == that.superconductorCriticalTemperature && - isSuperconductor == that.isSuperconductor; - } - - @Override - public int hashCode() { - return Objects.hash(voltage, amperage, lossPerBlock, meltTemperature, superconductorCriticalTemperature, - isSuperconductor); - } -} diff --git a/src/main/java/gregtech/api/unification/ore/OrePrefix.java b/src/main/java/gregtech/api/unification/ore/OrePrefix.java index 0a159028f1d..de664c8f877 100644 --- a/src/main/java/gregtech/api/unification/ore/OrePrefix.java +++ b/src/main/java/gregtech/api/unification/ore/OrePrefix.java @@ -255,32 +255,23 @@ public class OrePrefix { public static final OrePrefix frameGt = new OrePrefix("frameGt", M * 2, null, null, ENABLE_UNIFICATION, material -> material.hasFlag(GENERATE_FRAME)); - public static final OrePrefix pipeTinyFluid = new OrePrefix("pipeTinyFluid", M / 2, null, null, ENABLE_UNIFICATION, + public static final OrePrefix pipeTiny = new OrePrefix("pipeTiny", M / 2, null, null, ENABLE_UNIFICATION, null); - public static final OrePrefix pipeSmallFluid = new OrePrefix("pipeSmallFluid", M, null, null, ENABLE_UNIFICATION, + public static final OrePrefix pipeSmall = new OrePrefix("pipeSmall", M, null, null, ENABLE_UNIFICATION, null); - public static final OrePrefix pipeNormalFluid = new OrePrefix("pipeNormalFluid", M * 3, null, null, + public static final OrePrefix pipeNormal = new OrePrefix("pipeNormal", M * 3, null, null, ENABLE_UNIFICATION, null); - public static final OrePrefix pipeLargeFluid = new OrePrefix("pipeLargeFluid", M * 6, null, null, + public static final OrePrefix pipeLarge = new OrePrefix("pipeLarge", M * 6, null, null, ENABLE_UNIFICATION, null); - public static final OrePrefix pipeHugeFluid = new OrePrefix("pipeHugeFluid", M * 12, null, null, ENABLE_UNIFICATION, + public static final OrePrefix pipeHuge = new OrePrefix("pipeHuge", M * 12, null, null, ENABLE_UNIFICATION, null); - public static final OrePrefix pipeQuadrupleFluid = new OrePrefix("pipeQuadrupleFluid", M * 4, null, null, + public static final OrePrefix pipeQuadruple = new OrePrefix("pipeQuadruple", M * 4, null, null, ENABLE_UNIFICATION, null); - public static final OrePrefix pipeNonupleFluid = new OrePrefix("pipeNonupleFluid", M * 9, null, null, + public static final OrePrefix pipeNonuple = new OrePrefix("pipeNonuple", M * 9, null, null, ENABLE_UNIFICATION, null); - public static final OrePrefix pipeTinyItem = new OrePrefix("pipeTinyItem", M / 2, null, null, ENABLE_UNIFICATION, - null); - public static final OrePrefix pipeSmallItem = new OrePrefix("pipeSmallItem", M, null, null, ENABLE_UNIFICATION, - null); - public static final OrePrefix pipeNormalItem = new OrePrefix("pipeNormalItem", M * 3, null, null, + public static final OrePrefix pipeTinyRestrictive = new OrePrefix("pipeSmallRestrictive", M / 2, null, null, ENABLE_UNIFICATION, null); - public static final OrePrefix pipeLargeItem = new OrePrefix("pipeLargeItem", M * 6, null, null, ENABLE_UNIFICATION, - null); - public static final OrePrefix pipeHugeItem = new OrePrefix("pipeHugeItem", M * 12, null, null, ENABLE_UNIFICATION, - null); - public static final OrePrefix pipeSmallRestrictive = new OrePrefix("pipeSmallRestrictive", M, null, null, ENABLE_UNIFICATION, null); public static final OrePrefix pipeNormalRestrictive = new OrePrefix("pipeNormalRestrictive", M * 3, null, null, @@ -289,6 +280,10 @@ public class OrePrefix { ENABLE_UNIFICATION, null); public static final OrePrefix pipeHugeRestrictive = new OrePrefix("pipeHugeRestrictive", M * 12, null, null, ENABLE_UNIFICATION, null); + public static final OrePrefix pipeQuadrupleRestrictive = new OrePrefix("pipeQuadrupleRestrictive", M * 4, null, null, + ENABLE_UNIFICATION, null); + public static final OrePrefix pipeNonupleRestrictive = new OrePrefix("pipeNonupleRestrictive", M * 9, null, null, + ENABLE_UNIFICATION, null); public static final OrePrefix wireGtHex = new OrePrefix("wireGtHex", M * 8, null, null, ENABLE_UNIFICATION, null); public static final OrePrefix wireGtOctal = new OrePrefix("wireGtOctal", M * 4, null, null, ENABLE_UNIFICATION, diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index c751a87c7fb..9da695d5db8 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -23,7 +23,9 @@ import net.minecraft.block.BlockSnow; import net.minecraft.block.material.MapColor; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.SoundEvents; import net.minecraft.inventory.Slot; @@ -50,6 +52,8 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandlerItem; import net.minecraftforge.fml.relauncher.ReflectionHelper; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; @@ -894,4 +898,10 @@ public static double geometricMean(double first, double... numbers) { } return Math.pow(first, 1D / (1 + numbers.length)); } + + @NotNull + @SideOnly(Side.CLIENT) + public static EntityPlayer getSP() { + return Minecraft.getMinecraft().player; + } } diff --git a/src/main/java/gregtech/client/particle/GTOverheatParticle.java b/src/main/java/gregtech/client/particle/GTOverheatParticle.java index 614a2b47f21..e6df6596ba6 100644 --- a/src/main/java/gregtech/client/particle/GTOverheatParticle.java +++ b/src/main/java/gregtech/client/particle/GTOverheatParticle.java @@ -1,6 +1,8 @@ package gregtech.client.particle; import gregtech.api.GTValues; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.client.renderer.IRenderSetup; import gregtech.client.shader.postprocessing.BloomEffect; import gregtech.client.shader.postprocessing.BloomType; @@ -8,7 +10,6 @@ import gregtech.client.utils.RenderBufferHelper; import gregtech.client.utils.RenderUtil; import gregtech.common.ConfigHolder; -import gregtech.common.pipelikeold.cable.tile.TileEntityCable; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; @@ -16,7 +17,9 @@ import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -32,6 +35,8 @@ */ public class GTOverheatParticle extends GTBloomParticle { + public static final int TEMPERATURE_CUTOFF = 400; + /** * Source */ @@ -145,36 +150,51 @@ public static int getBlackBodyColor(int temperature) { return RenderUtil.interpolateColor(color, blackBodyColors[index + 1], temperature % 200 / 200f); } - private final TileEntityCable tileEntity; + private final PipeTileEntity tileEntity; + private @NotNull TemperatureLogic temperatureLogic; - protected final int meltTemp; - protected int temperature = 293; - protected List pipeBoxes; + protected List pipeBoxes; protected boolean insulated; protected float alpha = 0; protected int color = blackBodyColors[0]; - public GTOverheatParticle(@NotNull TileEntityCable tileEntity, int meltTemp, @NotNull List pipeBoxes, - boolean insulated) { + public GTOverheatParticle(@NotNull PipeTileEntity tileEntity, @NotNull TemperatureLogic temperatureLogic, + @NotNull List pipeBoxes, boolean insulated) { super(tileEntity.getPos().getX(), tileEntity.getPos().getY(), tileEntity.getPos().getZ()); this.tileEntity = tileEntity; - this.meltTemp = meltTemp; + this.temperatureLogic = temperatureLogic; this.pipeBoxes = pipeBoxes; updatePipeBoxes(pipeBoxes); this.insulated = insulated; } - public void updatePipeBoxes(@NotNull List pipeBoxes) { + private int getTemperature() { + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + return temperatureLogic.getTemperature(tick); + } + + public void updatePipeBoxes(@NotNull List pipeBoxes) { this.pipeBoxes = pipeBoxes; - for (Cuboid6 cuboid : this.pipeBoxes) { - cuboid.expand(0.001); + for (AxisAlignedBB cuboid : this.pipeBoxes) { + cuboid.expand(0.001, 0.001, 0.001); } } - public void setTemperature(int temperature) { - this.temperature = temperature; - if (temperature <= 293 || temperature > meltTemp) { + public void setTemperatureLogic(@NotNull TemperatureLogic logic) { + this.temperatureLogic = logic; + } + + @Override + public void onUpdate() { + if (tileEntity.isInvalid() || !tileEntity.isOverheatParticleAlive()) { + setExpired(); + tileEntity.killOverheatParticle(); + return; + } + int temperature = getTemperature(); + + if (temperature <= TEMPERATURE_CUTOFF || temperature > temperatureLogic.getTemperatureMaximum()) { setExpired(); return; } @@ -187,16 +207,8 @@ public void setTemperature(int temperature) { alpha = 0.8f; } color = getBlackBodyColor(temperature); - } - - @Override - public void onUpdate() { - if (tileEntity.isInvalid() || !tileEntity.isParticleAlive()) { - setExpired(); - return; - } - if (temperature > 400 && GTValues.RNG.nextFloat() < 0.04) { + if (GTValues.RNG.nextFloat() < 0.04) { spawnSmoke(); } } @@ -215,8 +227,7 @@ private void spawnSmoke() { public String toString() { return "GTOverheatParticle{" + "tileEntity=" + tileEntity + - ", meltTemp=" + meltTemp + - ", temperature=" + temperature + + ", temperatureLogic=" + temperatureLogic + ", pipeBoxes=" + pipeBoxes + ", insulated=" + insulated + ", alpha=" + alpha + @@ -244,7 +255,7 @@ public void renderBloomEffect(@NotNull BufferBuilder buffer, @NotNull EffectRend float blue = (color & 0xFF) / 255f; buffer.setTranslation(posX - context.cameraX(), posY - context.cameraY(), posZ - context.cameraZ()); - for (Cuboid6 cuboid : pipeBoxes) { + for (AxisAlignedBB cuboid : pipeBoxes) { RenderBufferHelper.renderCubeFace(buffer, cuboid, red, green, blue, alpha, true); } } @@ -252,10 +263,8 @@ public void renderBloomEffect(@NotNull BufferBuilder buffer, @NotNull EffectRend @Override public boolean shouldRenderBloomEffect(@NotNull EffectRenderContext context) { if (this.insulated) return false; - for (Cuboid6 cuboid : pipeBoxes) { - if (!context.camera().isBoxInFrustum( - cuboid.min.x + posX, cuboid.min.y + posY, cuboid.min.z + posZ, - cuboid.max.x + posX, cuboid.max.y + posY, cuboid.max.z + posZ)) { + for (AxisAlignedBB cuboid : pipeBoxes) { + if (!context.camera().isBoundingBoxInFrustum(cuboid)) { return false; } } diff --git a/src/main/java/gregtech/client/utils/RenderBufferHelper.java b/src/main/java/gregtech/client/utils/RenderBufferHelper.java index b1cffd4c734..cd4e8902163 100644 --- a/src/main/java/gregtech/client/utils/RenderBufferHelper.java +++ b/src/main/java/gregtech/client/utils/RenderBufferHelper.java @@ -2,6 +2,7 @@ import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.MathHelper; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -55,6 +56,11 @@ public static void renderCubeFace(BufferBuilder buffer, Cuboid6 cuboid, float r, renderCubeFace(buffer, cuboid.min.x, cuboid.min.y, cuboid.min.z, cuboid.max.x, cuboid.max.y, cuboid.max.z, r, g, b, a, shade); } + public static void renderCubeFace(BufferBuilder buffer, AxisAlignedBB cuboid, float r, float g, float b, float a, + boolean shade) { + renderCubeFace(buffer, cuboid.minX, cuboid.minY, cuboid.minZ, cuboid.maxX, cuboid.maxY, cuboid.maxZ, r, g, + b, a, shade); + } public static void renderCubeFace(BufferBuilder buffer, double minX, double minY, double minZ, double maxX, double maxY, double maxZ, float red, float green, float blue, float alpha) { diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index 5908f048f41..bcb3fdf0da8 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -4,6 +4,7 @@ import gregtech.api.GregTechAPI; import gregtech.api.block.VariantItemBlock; import gregtech.api.block.machines.MachineItemBlock; +import gregtech.api.graphnet.pipenet.physical.block.ItemPipeBlock; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.toolitem.IGTTool; import gregtech.api.recipes.GTRecipeInputCache; @@ -24,6 +25,8 @@ import gregtech.common.blocks.*; import gregtech.common.items.MetaItems; import gregtech.common.items.ToolItems; +import gregtech.common.pipelike.block.cable.CableBlock; +import gregtech.common.pipelike.block.pipe.PipeBlock; import gregtech.common.pipelikeold.cable.BlockCable; import gregtech.common.pipelikeold.cable.ItemBlockCable; import gregtech.common.pipelikeold.fluidpipe.BlockFluidPipe; @@ -86,33 +89,10 @@ public static void registerBlocks(RegistryEvent.Register event) { if (material.hasProperty(PropertyKey.ORE) && !material.hasFlag(MaterialFlags.DISABLE_ORE_BLOCK)) { createOreBlock(material); } - - if (material.hasProperty(PropertyKey.WIRE)) { - for (BlockCable cable : CABLES.get(materialRegistry.getModid())) { - if (!cable.getItemPipeType(null).isCable() || - !material.getProperty(PropertyKey.WIRE).isSuperconductor()) - cable.addCableMaterial(material, material.getProperty(PropertyKey.WIRE)); - } - } - if (material.hasProperty(PropertyKey.FLUID_PIPE)) { - for (BlockFluidPipe pipe : FLUID_PIPES.get(materialRegistry.getModid())) { - if (!pipe.getItemPipeType(pipe.getItem(material)).getOrePrefix().isIgnored(material)) { - pipe.addPipeMaterial(material, material.getProperty(PropertyKey.FLUID_PIPE)); - } - } - } - if (material.hasProperty(PropertyKey.ITEM_PIPE)) { - for (BlockItemPipe pipe : ITEM_PIPES.get(materialRegistry.getModid())) { - if (!pipe.getItemPipeType(pipe.getItem(material)).getOrePrefix().isIgnored(material)) { - pipe.addPipeMaterial(material, material.getProperty(PropertyKey.ITEM_PIPE)); - } - } - } } - for (BlockCable cable : CABLES.get(materialRegistry.getModid())) registry.register(cable); - for (BlockFluidPipe pipe : FLUID_PIPES.get(materialRegistry.getModid())) registry.register(pipe); - for (BlockItemPipe pipe : ITEM_PIPES.get(materialRegistry.getModid())) registry.register(pipe); + for (CableBlock cable : CABLES.get(materialRegistry.getModid())) registry.register(cable); + for (PipeBlock cable : MATERIAL_PIPES.get(materialRegistry.getModid())) registry.register(cable); } for (BlockOpticalPipe pipe : OPTICAL_PIPES) registry.register(pipe); for (BlockLaserPipe pipe : LASER_PIPES) registry.register(pipe); @@ -225,12 +205,10 @@ public static void registerItems(RegistryEvent.Register event) { registry.register(createItemBlock(MACHINE, MachineItemBlock::new)); for (MaterialRegistry materialRegistry : GregTechAPI.materialManager.getRegistries()) { - for (BlockCable cable : CABLES.get(materialRegistry.getModid())) - registry.register(createItemBlock(cable, ItemBlockCable::new)); - for (BlockFluidPipe pipe : FLUID_PIPES.get(materialRegistry.getModid())) - registry.register(createItemBlock(pipe, ItemBlockFluidPipe::new)); - for (BlockItemPipe pipe : ITEM_PIPES.get(materialRegistry.getModid())) - registry.register(createItemBlock(pipe, ItemBlockItemPipe::new)); + for (CableBlock cable : CABLES.get(materialRegistry.getModid())) + registry.register(createItemBlock(cable, ItemPipeBlock::new)); + for (PipeBlock cable : MATERIAL_PIPES.get(materialRegistry.getModid())) + registry.register(createItemBlock(cable, ItemPipeBlock::new)); } for (BlockOpticalPipe pipe : OPTICAL_PIPES) registry.register(createItemBlock(pipe, ItemBlockOpticalPipe::new)); for (BlockLaserPipe pipe : LASER_PIPES) registry.register(createItemBlock(pipe, ItemBlockLaserPipe::new)); diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 0b63d47b6b7..ca194d0ef72 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -2,11 +2,14 @@ import gregtech.api.GregTechAPI; import gregtech.api.block.machines.BlockMachine; +import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.graphnet.pipenetold.longdist.BlockLongDistancePipe; import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; +import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.unification.ore.OrePrefix; @@ -18,9 +21,6 @@ import gregtech.client.model.modelfactories.BakedModelHandler; import gregtech.client.renderer.handler.MetaTileEntityRenderer; import gregtech.client.renderer.handler.MetaTileEntityTESR; -import gregtech.client.renderer.pipe.CableRenderer; -import gregtech.client.renderer.pipe.FluidPipeRenderer; -import gregtech.client.renderer.pipe.ItemPipeRenderer; import gregtech.client.renderer.pipe.LaserPipeRenderer; import gregtech.client.renderer.pipe.OpticalPipeRenderer; import gregtech.common.ConfigHolder; @@ -38,26 +38,16 @@ import gregtech.common.blocks.wood.BlockRubberSapling; import gregtech.common.blocks.wood.BlockWoodenDoor; import gregtech.common.items.MetaItems; -import gregtech.common.pipelikeold.cable.BlockCable; -import gregtech.common.pipelikeold.cable.Insulation; -import gregtech.common.pipelikeold.cable.tile.TileEntityCable; -import gregtech.common.pipelikeold.cable.tile.TileEntityCableTickable; -import gregtech.common.pipelikeold.fluidpipe.BlockFluidPipe; -import gregtech.common.pipelikeold.fluidpipe.FluidPipeType; +import gregtech.common.pipelike.block.cable.CableBlock; +import gregtech.common.pipelike.block.cable.CableStructure; +import gregtech.common.pipelike.block.pipe.PipeBlock; +import gregtech.common.pipelike.block.pipe.PipeStructure; import gregtech.common.pipelikeold.fluidpipe.longdistance.LDFluidPipeType; -import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; -import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipeTickable; -import gregtech.common.pipelikeold.itempipe.BlockItemPipe; -import gregtech.common.pipelikeold.itempipe.ItemPipeType; import gregtech.common.pipelikeold.itempipe.longdistance.LDItemPipeType; -import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipe; -import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipeTickable; import gregtech.common.pipelikeold.laser.BlockLaserPipe; import gregtech.common.pipelikeold.laser.LaserPipeType; -import gregtech.common.pipelikeold.laser.tile.TileEntityLaserPipe; import gregtech.common.pipelikeold.optical.BlockOpticalPipe; import gregtech.common.pipelikeold.optical.OpticalPipeType; -import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.block.Block; import net.minecraft.block.BlockFence; @@ -102,6 +92,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -114,9 +105,8 @@ public class MetaBlocks { private MetaBlocks() {} public static BlockMachine MACHINE; - public static final Map CABLES = new Object2ObjectOpenHashMap<>(); - public static final Map FLUID_PIPES = new Object2ObjectOpenHashMap<>(); - public static final Map ITEM_PIPES = new Object2ObjectOpenHashMap<>(); + public static final Map CABLES = new Object2ObjectOpenHashMap<>(); + public static final Map MATERIAL_PIPES = new Object2ObjectOpenHashMap<>(); public static final BlockOpticalPipe[] OPTICAL_PIPES = new BlockOpticalPipe[OpticalPipeType.values().length]; public static final BlockLaserPipe[] LASER_PIPES = new BlockLaserPipe[OpticalPipeType.values().length]; public static BlockLongDistancePipe LD_ITEM_PIPE; @@ -192,26 +182,28 @@ public static void init() { for (MaterialRegistry registry : GregTechAPI.materialManager.getRegistries()) { String modid = registry.getModid(); - BlockCable[] cables = new BlockCable[Insulation.VALUES.length]; - for (Insulation ins : Insulation.VALUES) { - cables[ins.ordinal()] = new BlockCable(ins, registry); - cables[ins.ordinal()].setRegistryName(modid, ins.getName()); - } - CABLES.put(modid, cables); - BlockFluidPipe[] fluidPipes = new BlockFluidPipe[FluidPipeType.VALUES.length]; - for (FluidPipeType type : FluidPipeType.VALUES) { - fluidPipes[type.ordinal()] = new BlockFluidPipe(type, registry); - fluidPipes[type.ordinal()].setRegistryName(modid, String.format("fluid_pipe_%s", type.name)); + Set structuresCable = CableBlock.gatherStructures(); + CableBlock[] cables = new CableBlock[structuresCable.size()]; + int i = 0; + for (CableStructure struct : structuresCable) { + CableBlock block = new CableBlock(struct, registry); + block.setRegistryName(modid, String.format("cable_%s", struct.getName())); + cables[i] = block; + i++; } - FLUID_PIPES.put(modid, fluidPipes); + CABLES.put(modid, cables); - BlockItemPipe[] itemPipes = new BlockItemPipe[ItemPipeType.VALUES.length]; - for (ItemPipeType type : ItemPipeType.VALUES) { - itemPipes[type.ordinal()] = new BlockItemPipe(type, registry); - itemPipes[type.ordinal()].setRegistryName(modid, String.format("item_pipe_%s", type.name)); + Set structuresPipe = PipeBlock.gatherStructures(); + PipeBlock[] pipes = new PipeBlock[structuresPipe.size()]; + i = 0; + for (PipeStructure struct : structuresPipe) { + PipeBlock block = new PipeBlock(struct, registry); + block.setRegistryName(modid, String.format("material_pipe_%s", struct.getName())); + pipes[i] = block; + i++; } - ITEM_PIPES.put(modid, itemPipes); + MATERIAL_PIPES.put(modid, pipes); } for (OpticalPipeType type : OpticalPipeType.values()) { OPTICAL_PIPES[type.ordinal()] = new BlockOpticalPipe(type); @@ -425,14 +417,8 @@ private static void createSurfaceRockBlock(String modid, Material[] materials, i public static void registerTileEntity() { GameRegistry.registerTileEntity(MetaTileEntityHolder.class, gregtechId("machine")); - GameRegistry.registerTileEntity(TileEntityCable.class, gregtechId("cable")); - GameRegistry.registerTileEntity(TileEntityCableTickable.class, gregtechId("cable_tickable")); - GameRegistry.registerTileEntity(TileEntityFluidPipe.class, gregtechId("fluid_pipe")); - GameRegistry.registerTileEntity(TileEntityItemPipe.class, gregtechId("item_pipe")); - GameRegistry.registerTileEntity(TileEntityOpticalPipe.class, gregtechId("optical_pipe")); - GameRegistry.registerTileEntity(TileEntityLaserPipe.class, gregtechId("laser_pipe")); - GameRegistry.registerTileEntity(TileEntityFluidPipeTickable.class, gregtechId("fluid_pipe_active")); - GameRegistry.registerTileEntity(TileEntityItemPipeTickable.class, gregtechId("item_pipe_active")); + GameRegistry.registerTileEntity(PipeTileEntity.class, gregtechId("pipe")); + GameRegistry.registerTileEntity(PipeMaterialTileEntity.class, gregtechId("material_pipe")); } @SideOnly(Side.CLIENT) @@ -440,9 +426,8 @@ public static void registerItemModels() { ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(MACHINE), stack -> MetaTileEntityRenderer.MODEL_LOCATION); for (MaterialRegistry registry : GregTechAPI.materialManager.getRegistries()) { - for (BlockCable cable : CABLES.get(registry.getModid())) cable.onModelRegister(); - for (BlockFluidPipe pipe : FLUID_PIPES.get(registry.getModid())) pipe.onModelRegister(); - for (BlockItemPipe pipe : ITEM_PIPES.get(registry.getModid())) pipe.onModelRegister(); + for (CableBlock cable : CABLES.get(registry.getModid())) cable.onModelRegister(); + for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) pipe.onModelRegister(); } for (BlockOpticalPipe pipe : OPTICAL_PIPES) ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(pipe), @@ -540,18 +525,19 @@ public static void registerStateMappers() { IStateMapper normalStateMapper; for (MaterialRegistry registry : GregTechAPI.materialManager.getRegistries()) { - normalStateMapper = new SimpleStateMapper(CableRenderer.INSTANCE.getModelLocation()); - for (BlockCable cable : CABLES.get(registry.getModid())) { - ModelLoader.setCustomStateMapper(cable, normalStateMapper); - } - normalStateMapper = new SimpleStateMapper(FluidPipeRenderer.INSTANCE.getModelLocation()); - for (BlockFluidPipe pipe : FLUID_PIPES.get(registry.getModid())) { - ModelLoader.setCustomStateMapper(pipe, normalStateMapper); - } - normalStateMapper = new SimpleStateMapper(ItemPipeRenderer.INSTANCE.getModelLocation()); - for (BlockItemPipe pipe : ITEM_PIPES.get(registry.getModid())) { - ModelLoader.setCustomStateMapper(pipe, normalStateMapper); - } + // TODO rendering +// normalStateMapper = new SimpleStateMapper(CableRenderer.INSTANCE.getModelLocation()); +// for (BlockCable cable : CABLES.get(registry.getModid())) { +// ModelLoader.setCustomStateMapper(cable, normalStateMapper); +// } +// normalStateMapper = new SimpleStateMapper(FluidPipeRenderer.INSTANCE.getModelLocation()); +// for (BlockFluidPipe pipe : FLUID_PIPES.get(registry.getModid())) { +// ModelLoader.setCustomStateMapper(pipe, normalStateMapper); +// } +// normalStateMapper = new SimpleStateMapper(ItemPipeRenderer.INSTANCE.getModelLocation()); +// for (BlockItemPipe pipe : ITEM_PIPES.get(registry.getModid())) { +// ModelLoader.setCustomStateMapper(pipe, normalStateMapper); +// } } normalStateMapper = new SimpleStateMapper(OpticalPipeRenderer.INSTANCE.getModelLocation()); for (BlockOpticalPipe pipe : OPTICAL_PIPES) { @@ -687,22 +673,21 @@ public static void registerOreDict() { } } for (MaterialRegistry registry : GregTechAPI.materialManager.getRegistries()) { - for (BlockCable cable : CABLES.get(registry.getModid())) { - for (Material pipeMaterial : cable.getEnabledMaterials()) { - ItemStack itemStack = cable.getItem(pipeMaterial); - OreDictUnifier.registerOre(itemStack, cable.getPrefix(), pipeMaterial); - } - } - for (BlockFluidPipe pipe : FLUID_PIPES.get(registry.getModid())) { - for (Material pipeMaterial : pipe.getEnabledMaterials()) { - ItemStack itemStack = pipe.getItem(pipeMaterial); - OreDictUnifier.registerOre(itemStack, pipe.getPrefix(), pipeMaterial); - } - } - for (BlockItemPipe pipe : ITEM_PIPES.get(registry.getModid())) { - for (Material pipeMaterial : pipe.getEnabledMaterials()) { - ItemStack itemStack = pipe.getItem(pipeMaterial); - OreDictUnifier.registerOre(itemStack, pipe.getPrefix(), pipeMaterial); + for (Material material : registry.getAllMaterials()) { + PipeNetProperties properties = material.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (properties != null) { + for (CableBlock cable : CABLES.get(registry.getModid())) { + if (properties.generatesStructure(cable.getStructure())) { + ItemStack itemStack = cable.getItem(material); + OreDictUnifier.registerOre(itemStack, cable.getStructure().getOrePrefix(), material); + } + } + for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) { + if (properties.generatesStructure(pipe.getStructure())) { + ItemStack itemStack = pipe.getItem(material); + OreDictUnifier.registerOre(itemStack, pipe.getStructure().getOrePrefix(), material); + } + } } } } diff --git a/src/main/java/gregtech/common/covers/CoverShutter.java b/src/main/java/gregtech/common/covers/CoverShutter.java index 2a279b65cff..9c228ecbf53 100644 --- a/src/main/java/gregtech/common/covers/CoverShutter.java +++ b/src/main/java/gregtech/common/covers/CoverShutter.java @@ -5,6 +5,7 @@ import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; +import gregtech.api.graphnet.predicate.ShutterPredicate; import gregtech.client.renderer.texture.Textures; import net.minecraft.entity.player.EntityPlayer; @@ -22,6 +23,9 @@ import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Consumer; public class CoverShutter extends CoverBase implements IControllable { @@ -76,7 +80,7 @@ public boolean canPipePassThrough() { @Override public @NotNull EnumActionResult onSoftMalletClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, @NotNull CuboidRayTraceResult hitResult) { - this.isWorkingAllowed = !this.isWorkingAllowed; + setWorkingEnabled(!this.isWorkingAllowed); if (!playerIn.world.isRemote) { playerIn.sendMessage(new TextComponentTranslation(isWorkingEnabled() ? "cover.shutter.message.enabled" : "cover.shutter.message.disabled")); @@ -91,7 +95,10 @@ public boolean isWorkingEnabled() { @Override public void setWorkingEnabled(boolean isActivationAllowed) { - isWorkingAllowed = isActivationAllowed; + if (isActivationAllowed != isWorkingAllowed) { + isWorkingAllowed = isActivationAllowed; + markDirty(); + } } @Override diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index f754e41abae..7c8631ccbe2 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -1,29 +1,35 @@ package gregtech.common.pipelike.block.cable; +import gregtech.api.graphnet.gather.GatherStructuresEvent; import gregtech.api.graphnet.pipenet.physical.IBurnable; -import gregtech.api.graphnet.pipenet.physical.PipeMaterialBlock; -import gregtech.api.unification.material.Material; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; +import gregtech.api.items.toolitem.ToolClasses; +import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.unification.material.registry.MaterialRegistry; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; + import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; -import java.util.Collection; import java.util.Map; +import java.util.Set; public class CableBlock extends PipeMaterialBlock implements IBurnable { private static final Map> CACHE = new Object2ObjectOpenHashMap<>(); - public CableBlock(CableStructure structure, MaterialRegistry registry, Collection materials) { - super(structure, registry, materials); + public CableBlock(CableStructure structure, MaterialRegistry registry) { + super(structure, registry); CACHE.compute(registry, (k, v) -> { if (v == null) v = new Object2ObjectOpenHashMap<>(); v.put(structure, this); @@ -31,16 +37,28 @@ public CableBlock(CableStructure structure, MaterialRegistry registry, Collectio }); } + @Override + public boolean isPipeTool(@NotNull ItemStack stack) { + return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); + } + + public static Set gatherStructures() { + GatherStructuresEvent event = new GatherStructuresEvent<>(CableStructure.class); + MinecraftForge.EVENT_BUS.post(event); + return event.getGathered(); + } + @Override public void partialBurn(IBlockState state, World world, BlockPos pos) { CableStructure structure = (CableStructure) getStructure(); if (structure.partialBurnStructure() != null) { CableBlock newBlock = CACHE.get(registry).get(structure.partialBurnStructure()); + //noinspection deprecation world.setBlockState(pos, newBlock.getStateFromMeta(this.getMetaFromState(state))); } } - // TODO + // TODO rendering @Override protected Pair getParticleTexture(World world, BlockPos blockPos) { return null; diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableEnergyProperties.java b/src/main/java/gregtech/common/pipelike/block/cable/CableEnergyProperties.java deleted file mode 100644 index b8d6f747b42..00000000000 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableEnergyProperties.java +++ /dev/null @@ -1,139 +0,0 @@ -package gregtech.common.pipelike.block.cable; - -import gregtech.api.GTValues; -import gregtech.api.fluids.FluidBuilder; -import gregtech.api.fluids.store.FluidStorageKeys; -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.logic.TemperatureLogic; -import gregtech.api.graphnet.logic.TemperatureRestorationFunction; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.properties.FluidProperty; -import gregtech.api.unification.material.properties.PropertyKey; -import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; -import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.logic.ThroughputLogic; -import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.unification.material.properties.MaterialProperties; -import gregtech.api.unification.material.properties.PipeNetProperties; - -import gregtech.common.pipelike.net.energy.SuperconductorLogic; -import gregtech.common.pipelike.net.energy.WorldEnergyNet; - -import gregtech.common.pipelike.net.energy.VoltageLimitLogic; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import net.minecraftforge.fluids.Fluid; - -import org.jetbrains.annotations.NotNull; - -import static gregtech.api.unification.material.info.MaterialFlags.GENERATE_FOIL; - -public class CableEnergyProperties implements PipeNetProperties.IPipeNetMaterialProperty { - - public static final int INSULATION_BURN_TEMP = 1000; - - private final long voltageLimit; - private final long amperageLimit; - private int temperatureLimit; - private final long lossPerAmp; - /** - * - */ - private final int superconductorTemperature; - - /** - * Generate a CableEnergyProperties - * @param voltageLimit the voltage limit for the cable - * @param amperageLimit the base amperage for the cable. - * @param temperatureLimit the melt temperature of the cable. If zero, autogeneration will be attempted. - * @param lossPerAmp the base loss per amp per block traveled. - * @param superconductorTemperature the superconductor temperature. When the temperature is at or below - * superconductor temperature, loss will be treated as zero. A superconductor - * temperature of 0 or less will be treated as not a superconductor. - */ - public CableEnergyProperties(long voltageLimit, long amperageLimit, int temperatureLimit, long lossPerAmp, int superconductorTemperature) { - this.voltageLimit = voltageLimit; - this.amperageLimit = amperageLimit; - this.temperatureLimit = temperatureLimit; - this.lossPerAmp = lossPerAmp; - this.superconductorTemperature = superconductorTemperature; - } - - public boolean isSuperconductor() { - return this.superconductorTemperature > 1; - } - - @Override - public @NotNull String getName() { - return "cableEnergy"; - } - - @Override - public void verifyProperty(MaterialProperties properties) { - properties.ensureSet(PropertyKey.DUST, true); - if (properties.hasProperty(PropertyKey.INGOT)) { - // Ensure all Materials with Cables and voltage tier IV or above have a Foil for recipe generation - Material thisMaterial = properties.getMaterial(); - if (!isSuperconductor() && voltageLimit >= GTValues.V[GTValues.IV] && !thisMaterial.hasFlag(GENERATE_FOIL)) { - thisMaterial.addFlags(GENERATE_FOIL); - } - } - if (this.temperatureLimit == 0 && properties.hasProperty(PropertyKey.FLUID)) { - // autodetermine melt temperature from registered fluid - FluidProperty prop = properties.getProperty(PropertyKey.FLUID); - Fluid fluid = prop.getStorage().get(FluidStorageKeys.LIQUID); - if (fluid == null) { - FluidBuilder builder = prop.getStorage().getQueuedBuilder(FluidStorageKeys.LIQUID); - if (builder != null) { - this.temperatureLimit = builder.currentTemp(); - } - } else { - this.temperatureLimit = fluid.getTemperature(); - } - } - } - - @Override - public void addToNet(World world, BlockPos pos, IPipeStructure structure) { - assert structure instanceof CableStructure; - CableStructure cable = (CableStructure) structure; - long loss = lossPerAmp * cable.costFactor(); - long amperage = amperageLimit * cable.material(); - boolean insulated = cable.partialBurnStructure() != null; - // insulated cables cool down half as fast - float coolingFactor = (float) (Math.sqrt(cable.material()) / (insulated ? 8 : 4)); - WorldPipeNetNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); - NetLogicData newData = node.getData(); - newData.setLogicEntry(LossAbsoluteLogic.INSTANCE.getWith(loss)) - .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) - .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) - .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) - .setLogicEntry(TemperatureLogic.INSTANCE - .getWith(TemperatureRestorationFunction.GEOMETRIC_ARITHMETIC, coolingFactor, temperatureLimit, - insulated ? INSULATION_BURN_TEMP : null, 1, 100 * cable.material())); - if (superconductorTemperature > 0) { - newData.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorTemperature)); - } - } - - @Override - public WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { - return WorldEnergyNet.getWorldNet(world).getNode(pos); - } - - @Override - public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { - WorldEnergyNet net = WorldEnergyNet.getWorldNet(world); - NetNode node = net.getNode(pos); - if (node != null) net.removeNode(node); - } - - @Override - public boolean supportedStructure(IPipeStructure structure) { - return structure.getClass() == CableStructure.class; - } -} diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java index 1db38b31bb1..5edc4cf0405 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java @@ -1,5 +1,6 @@ package gregtech.common.pipelike.block.cable; +import gregtech.api.graphnet.pipenet.physical.IInsulatable; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.unification.ore.OrePrefix; @@ -9,29 +10,33 @@ import java.util.function.Consumer; -public record CableStructure(String name, int material, int costFactor, OrePrefix ore, @Nullable CableStructure partialBurnStructure, float renderThickness) implements IPipeMaterialStructure { +public record CableStructure(String name, int material, int costFactor, OrePrefix ore, + @Nullable CableStructure partialBurnStructure, @Nullable Integer partialBurnThreshold, + float renderThickness) implements IPipeMaterialStructure, IInsulatable { + + public static final int INSULATION_BURN_TEMP = 1000; public static final CableStructure WIRE_SINGLE = - new CableStructure("wire_single", 1, 2, OrePrefix.wireGtSingle, null, 0.125f); + new CableStructure("wire_single", 1, 2, OrePrefix.wireGtSingle, null, null, 0.125f); public static final CableStructure WIRE_DOUBLE = - new CableStructure("wire_double", 2, 2, OrePrefix.wireGtDouble, null, 0.25f); + new CableStructure("wire_double", 2, 2, OrePrefix.wireGtDouble, null, null, 0.25f); public static final CableStructure WIRE_QUADRUPLE = - new CableStructure("wire_quadruple", 4, 3, OrePrefix.wireGtQuadruple, null, 0.375f); + new CableStructure("wire_quadruple", 4, 3, OrePrefix.wireGtQuadruple, null, null, 0.375f); public static final CableStructure WIRE_OCTAL = - new CableStructure("wire_octal", 8, 3, OrePrefix.wireGtOctal, null, 0.5f); + new CableStructure("wire_octal", 8, 3, OrePrefix.wireGtOctal, null, null, 0.5f); public static final CableStructure WIRE_HEX = - new CableStructure("wire_hex", 16, 3, OrePrefix.wireGtHex, null, 0.75f); + new CableStructure("wire_hex", 16, 3, OrePrefix.wireGtHex, null, null, 0.75f); public static final CableStructure CABLE_SINGLE = - new CableStructure("cable_single", 1, 1, OrePrefix.cableGtSingle, WIRE_SINGLE, 0.25f); + new CableStructure("cable_single", 1, 1, OrePrefix.cableGtSingle, WIRE_SINGLE, INSULATION_BURN_TEMP, 0.25f); public static final CableStructure CABLE_DOUBLE = - new CableStructure("cable_double", 2, 1, OrePrefix.cableGtDouble, WIRE_DOUBLE, 0.375f); + new CableStructure("cable_double", 2, 1, OrePrefix.cableGtDouble, WIRE_DOUBLE, INSULATION_BURN_TEMP, 0.375f); public static final CableStructure CABLE_QUADRUPLE = - new CableStructure("cable_quadruple", 4, 1, OrePrefix.cableGtQuadruple, WIRE_QUADRUPLE, 0.5f); + new CableStructure("cable_quadruple", 4, 1, OrePrefix.cableGtQuadruple, WIRE_QUADRUPLE, INSULATION_BURN_TEMP, 0.5f); public static final CableStructure CABLE_OCTAL = - new CableStructure("cable_octal", 8, 1, OrePrefix.cableGtOctal, WIRE_OCTAL, 0.75f); + new CableStructure("cable_octal", 8, 1, OrePrefix.cableGtOctal, WIRE_OCTAL, INSULATION_BURN_TEMP, 0.75f); public static final CableStructure CABLE_HEX = - new CableStructure("cable_hex", 16, 1, OrePrefix.cableGtHex, WIRE_HEX, 1f); + new CableStructure("cable_hex", 16, 1, OrePrefix.cableGtHex, WIRE_HEX, INSULATION_BURN_TEMP, 1f); @Override public @NotNull String getName() { @@ -48,6 +53,16 @@ public float getRenderThickness() { return renderThickness(); } + @Override + public boolean isPaintable() { + return true; + } + + @Override + public boolean isInsulated() { + return partialBurnStructure() != null; + } + public static void registerDefaultStructures(Consumer register) { register.accept(WIRE_SINGLE); register.accept(WIRE_DOUBLE); diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java new file mode 100644 index 00000000000..78c39715248 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java @@ -0,0 +1,46 @@ +package gregtech.common.pipelike.block.pipe; + +import gregtech.api.graphnet.gather.GatherStructuresEvent; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.physical.IBurnable; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; + +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.unification.material.registry.MaterialRegistry; + +import gregtech.api.util.EntityDamageUtil; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import net.minecraftforge.common.MinecraftForge; + +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +public class PipeBlock extends PipeMaterialBlock implements IBurnable { + + public PipeBlock(PipeStructure structure, MaterialRegistry registry) { + super(structure, registry); + } + + public static Set gatherStructures() { + GatherStructuresEvent event = new GatherStructuresEvent<>(PipeStructure.class); + MinecraftForge.EVENT_BUS.post(event); + return event.getGathered(); + } + + // TODO rendering + @Override + protected Pair getParticleTexture(World world, BlockPos blockPos) { + return null; + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java new file mode 100644 index 00000000000..671d2e32bbb --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java @@ -0,0 +1,72 @@ +package gregtech.common.pipelike.block.pipe; + +import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; +import gregtech.api.unification.ore.OrePrefix; + +import gregtech.common.pipelike.block.cable.CableStructure; + +import org.jetbrains.annotations.NotNull; + +import java.util.function.Consumer; + +public record PipeStructure(String name, int material, int channelCount, boolean restrictive, OrePrefix ore, float renderThickness) + implements IPipeMaterialStructure { + + public static final PipeStructure TINY = new PipeStructure("tiny", 1, 1, false, OrePrefix.pipeTiny, 0.25f); + public static final PipeStructure SMALL = new PipeStructure("small", 2, 1, false, OrePrefix.pipeSmall, 0.375f); + public static final PipeStructure NORMAL = new PipeStructure("normal", 6, 1, false, OrePrefix.pipeNormal, 0.5f); + public static final PipeStructure LARGE = new PipeStructure("large", 12, 1, false, OrePrefix.pipeLarge, 0.75f); + public static final PipeStructure HUGE = new PipeStructure("huge", 24, 1, false, OrePrefix.pipeHuge, 0.875f); + + // TODO adjust quadruple and nonuple thicknesses to 0.5f and 0.75f respectively, and update textures accordingly + public static final PipeStructure QUADRUPLE = new PipeStructure("quadruple", 8, 4, false, OrePrefix.pipeQuadruple, 0.95f); + public static final PipeStructure NONUPLE = new PipeStructure("nonuple", 18, 9, false, OrePrefix.pipeNonuple, 0.95f); + + + public static final PipeStructure TINY_RESTRICTIVE = new PipeStructure("tiny_restrictive", 1, 1, true, OrePrefix.pipeTinyRestrictive, 0.25f); + public static final PipeStructure SMALL_RESTRICTIVE = new PipeStructure("small_restrictive", 2, 1, true, OrePrefix.pipeSmallRestrictive, 0.375f); + public static final PipeStructure NORMAL_RESTRICTIVE = new PipeStructure("normal_restrictive", 6, 1, true, OrePrefix.pipeNormalRestrictive, 0.5f); + public static final PipeStructure LARGE_RESTRICTIVE = new PipeStructure("large_restrictive", 12, 1, true, OrePrefix.pipeLargeRestrictive, 0.75f); + public static final PipeStructure HUGE_RESTRICTIVE = new PipeStructure("huge_restrictive", 24, 1, true, OrePrefix.pipeHugeRestrictive, 0.875f); + + public static final PipeStructure QUADRUPLE_RESTRICTIVE = new PipeStructure("quadruple_restrictive", 8, 4, true, OrePrefix.pipeQuadrupleRestrictive, 0.95f); + public static final PipeStructure NONUPLE_RESTRICTIVE = new PipeStructure("nonuple_restrictive", 18, 9, true, OrePrefix.pipeNonupleRestrictive, 0.95f); + + @Override + public @NotNull String getName() { + return this.name(); + } + + @Override + public OrePrefix getOrePrefix() { + return this.ore(); + } + + @Override + public float getRenderThickness() { + return this.renderThickness(); + } + + @Override + public boolean isPaintable() { + return true; + } + + public static void registerDefaultStructures(Consumer register) { + register.accept(TINY); + register.accept(SMALL); + register.accept(NORMAL); + register.accept(LARGE); + register.accept(HUGE); + register.accept(QUADRUPLE); + register.accept(NONUPLE); + register.accept(TINY_RESTRICTIVE); + register.accept(SMALL_RESTRICTIVE); + register.accept(NORMAL_RESTRICTIVE); + register.accept(LARGE_RESTRICTIVE); + register.accept(HUGE_RESTRICTIVE); + register.accept(QUADRUPLE_RESTRICTIVE); + register.accept(NONUPLE_RESTRICTIVE); + } + +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 350b3d00c24..fc5e52f2992 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -6,7 +6,6 @@ import gregtech.api.graphnet.NetGroup; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.edge.util.FlowConsumer; import gregtech.api.graphnet.logic.NetLogicData; @@ -15,7 +14,7 @@ import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; -import gregtech.api.graphnet.pipenet.physical.PipeTileEntity; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.TraverseHelpers; @@ -80,8 +79,16 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage data.runPostActions(); consumer.finalReduction(availableAmperage); + + long accepted = amperage - availableAmperage; + if (!simulate) { + EnergyGroupData group = getEnergyData(); + if (group != null) { + group.addEnergyInPerSec(accepted * voltage, data.getQueryTick()); + } + } this.transferring = false; - return amperage - availableAmperage; + return accepted; } private Iterator getPaths(EnergyTraverseData data) { @@ -89,15 +96,16 @@ private Iterator getPaths(EnergyTraverseData data) { return provider.getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), data.getQueryTick()); } - private long getFlux() { - if (tile == null) return 0; + @Nullable + private EnergyGroupData getEnergyData() { + if (tile == null) return null; NetNode node = net.getNode(tile.getPos()); - if (node == null) return 0; + if (node == null) return null; NetGroup group = node.getGroupUnsafe(); - if (group == null) return 0; + if (group == null) return null; AbstractGroupData data = group.getData(); - if (!(data instanceof EnergyGroupData e)) return 0; - return e.getEnergyFluxPerSec(); + if (!(data instanceof EnergyGroupData e)) return null; + return e; } @Override @@ -133,12 +141,16 @@ public T getCapabilityForSide(Capability capability, @Nullable EnumFacing @Override public long getInputPerSec() { - return getFlux(); + EnergyGroupData data = getEnergyData(); + if (data == null) return 0; + else return data.getEnergyFluxPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter())[0]; } @Override public long getOutputPerSec() { - return getFlux(); + EnergyGroupData data = getEnergyData(); + if (data == null) return 0; + else return data.getEnergyFluxPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter())[1]; } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index 8a3f3dd0f21..53b2c59957d 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -4,26 +4,23 @@ import gregtech.api.capability.IEnergyContainer; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.pipenet.physical.PipeTileEntity; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.AbstractTraverseData; import gregtech.api.util.GTUtility; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import gregtech.common.pipelikeold.cable.net.EnergyGroupData; -import journeymap.client.render.map.Tile; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; +import java.util.List; import java.util.function.Supplier; public class EnergyTraverseData extends AbstractTraverseData { @@ -110,7 +107,12 @@ public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachin getSimulatorKey() != null); } } - return flowReachingDestination - availableFlow; + long accepted = flowReachingDestination - availableFlow; + if (getSimulatorKey() == null && destination.getGroupUnsafe() != null && + destination.getGroupSafe().getData() instanceof EnergyGroupData data) { + data.addEnergyOutPerSec(accepted * pathVoltage, getQueryTick()); + } + return accepted; } public void runPostActions() { diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java new file mode 100644 index 00000000000..538e24567e2 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -0,0 +1,72 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.common.pipelike.net.energy.EnergyCapabilityObject; +import gregtech.common.pipelike.net.energy.WorldEnergyNet; + +import gregtech.common.pipelike.net.item.WorldItemNet; + +import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; + +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; + +public class WorldFluidNet extends WorldPipeNet implements FlowWorldPipeNetPath.Provider { + + public static final Capability[] CAPABILITIES = new Capability[] { CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY }; + + private static final String DATA_ID_BASE = "gregtech.world_energy_net"; + + public static WorldFluidNet getWorldNet(World world) { + final String DATA_ID = getDataID(DATA_ID_BASE, world); + WorldFluidNet net = (WorldFluidNet) world.loadData(WorldFluidNet.class, DATA_ID); + if (net == null) { + net = new WorldFluidNet(DATA_ID); + world.setData(DATA_ID, net); + } + return net; + } + + public WorldFluidNet(String name) { + super(name, DynamicWeightsShortestPathsAlgorithm::new, false); + } + + @Override + public boolean clashesWith(IGraphNet net) { + return net instanceof WorldItemNet; + } + + @Override + public Capability[] getTargetCapabilities() { + return CAPABILITIES; + } + + @Override + public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { + return new IPipeCapabilityObject[] { }; + } + + @Override + public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + return backer.getPaths(node, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); + } + + @Override + public @NotNull NetFlowEdge getNewEdge() { + return new NetFlowEdge(10); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java new file mode 100644 index 00000000000..562cb5f2083 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -0,0 +1,70 @@ +package gregtech.common.pipelike.net.item; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import gregtech.common.pipelike.net.fluid.WorldFluidNet; + +import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; + +import net.minecraftforge.items.CapabilityItemHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; + +public class WorldItemNet extends WorldPipeNet implements FlowWorldPipeNetPath.Provider { + + public static final Capability[] CAPABILITIES = new Capability[] { CapabilityItemHandler.ITEM_HANDLER_CAPABILITY }; + + private static final String DATA_ID_BASE = "gregtech.world_energy_net"; + + public static WorldItemNet getWorldNet(World world) { + final String DATA_ID = getDataID(DATA_ID_BASE, world); + WorldItemNet net = (WorldItemNet) world.loadData(WorldItemNet.class, DATA_ID); + if (net == null) { + net = new WorldItemNet(DATA_ID); + world.setData(DATA_ID, net); + } + return net; + } + + public WorldItemNet(String name) { + super(name, DynamicWeightsShortestPathsAlgorithm::new, false); + } + + @Override + public boolean clashesWith(IGraphNet net) { + return net instanceof WorldFluidNet; + } + + @Override + public Capability[] getTargetCapabilities() { + return CAPABILITIES; + } + + @Override + public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { + return new IPipeCapabilityObject[] { }; + } + + @Override + public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + return backer.getPaths(node, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); + } + + @Override + public @NotNull NetFlowEdge getNewEdge() { + return new NetFlowEdge(10); + } +} diff --git a/src/main/java/gregtech/common/pipelike/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/properties/MaterialEnergyProperties.java new file mode 100644 index 00000000000..1f4657f214b --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/properties/MaterialEnergyProperties.java @@ -0,0 +1,204 @@ +package gregtech.common.pipelike.properties; + +import gregtech.api.GTValues; +import gregtech.api.fluids.FluidBuilder; +import gregtech.api.fluids.store.FluidStorageKeys; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.pipenet.logic.EnumLossFunction; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.properties.FluidProperty; +import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.unification.ore.IOreRegistrationHandler; +import gregtech.api.unification.ore.OrePrefix; +import gregtech.api.util.function.TriConsumer; +import gregtech.common.pipelike.block.cable.CableStructure; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.unification.material.properties.MaterialProperties; +import gregtech.api.unification.material.properties.PipeNetProperties; + +import gregtech.common.pipelike.block.pipe.PipeStructure; + +import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; +import gregtech.common.pipelike.net.energy.SuperconductorLogic; +import gregtech.common.pipelike.net.energy.VoltageLimitLogic; +import gregtech.common.pipelike.net.energy.WorldEnergyNet; + +import it.unimi.dsi.fastutil.floats.Float2ObjectArrayMap; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import net.minecraftforge.fluids.Fluid; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +import static gregtech.api.unification.material.info.MaterialFlags.GENERATE_FOIL; +import static gregtech.api.unification.material.info.MaterialFlags.NO_UNIFICATION; + +public final class MaterialEnergyProperties implements PipeNetProperties.IPipeNetMaterialProperty { + + public static final String KEY = "energy"; + + private final long voltageLimit; + private final long amperageLimit; + private int temperatureLimit; + private final long lossPerAmp; + private final int superconductorCriticalTemperature; + + /** + * Generate a MaterialEnergyProperties + * @param voltageLimit the voltage limit for the cable + * @param amperageLimit the base amperage for the cable. + * @param lossPerAmp the base loss per amp per block traveled. + * @param temperatureLimit the melt temperature of the cable. If zero, autogeneration will be attempted. + * @param superconductorCriticalTemperature the superconductor temperature. When the temperature is at or below + * superconductor temperature, loss will be treated as zero. A superconductor + * temperature of 0 or less will be treated as not a superconductor. + */ + public MaterialEnergyProperties(long voltageLimit, long amperageLimit, long lossPerAmp, int temperatureLimit, int superconductorCriticalTemperature) { + this.voltageLimit = voltageLimit; + this.amperageLimit = amperageLimit; + this.temperatureLimit = temperatureLimit; + this.lossPerAmp = lossPerAmp; + this.superconductorCriticalTemperature = superconductorCriticalTemperature; + } + + public static MaterialEnergyProperties createT(long voltageLimit, long amperageLimit, long lossPerAmp, int temperatureLimit) { + return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, temperatureLimit, 0); + + } + + public static MaterialEnergyProperties createS(long voltageLimit, long amperageLimit, long lossPerAmp, int superconductorCriticalTemperature) { + return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, 0, superconductorCriticalTemperature); + + } + + public static MaterialEnergyProperties create(long voltageLimit, long amperageLimit, long lossPerAmp) { + return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, 0, 0); + + } + + public static IOreRegistrationHandler registrationHandler(TriConsumer handler) { + return (orePrefix, material) -> { + if (material.hasProperty(PropertyKey.PIPENET_PROPERTIES) && !material.hasFlag(NO_UNIFICATION) && + material.getProperty(PropertyKey.PIPENET_PROPERTIES).hasProperty(KEY)) { + handler.accept(orePrefix, material, + material.getProperty(PropertyKey.PIPENET_PROPERTIES).getProperty(KEY)); + } + }; + } + + public boolean isSuperconductor() { + return this.superconductorCriticalTemperature > 1; + } + + @Override + public @NotNull String getName() { + return KEY; + } + + @Override + public void verifyProperty(MaterialProperties properties) { + properties.ensureSet(PropertyKey.DUST, true); + if (properties.hasProperty(PropertyKey.INGOT)) { + // Ensure all Materials with Cables and voltage tier IV or above have a Foil for recipe generation + Material thisMaterial = properties.getMaterial(); + if (!isSuperconductor() && voltageLimit >= GTValues.V[GTValues.IV] && !thisMaterial.hasFlag(GENERATE_FOIL)) { + thisMaterial.addFlags(GENERATE_FOIL); + } + } + if (this.temperatureLimit == 0 && properties.hasProperty(PropertyKey.FLUID)) { + // autodetermine melt temperature from registered fluid + FluidProperty prop = properties.getProperty(PropertyKey.FLUID); + Fluid fluid = prop.getStorage().get(FluidStorageKeys.LIQUID); + if (fluid == null) { + FluidBuilder builder = prop.getStorage().getQueuedBuilder(FluidStorageKeys.LIQUID); + if (builder != null) { + this.temperatureLimit = builder.currentTemp(); + } + } else { + this.temperatureLimit = fluid.getTemperature(); + } + } + } + + @Override + public void addToNet(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof CableStructure cable) { + WorldPipeNetNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); + mutateData(node.getData(), cable); + } else if (structure instanceof PipeStructure pipe) { + long amperage = amperageLimit * pipe.material() / 2; + if (amperage == 0) return; // skip pipes that are too small + WorldPipeNetNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); + mutateData(node.getData(), pipe); + } + } + + @Override + public void mutateData(NetLogicData data, IPipeStructure structure) { + if (structure instanceof CableStructure cable) { + long loss = lossPerAmp * cable.costFactor(); + long amperage = amperageLimit * cable.material(); + boolean insulated = cable.partialBurnStructure() != null; + // insulated cables cool down half as fast + float coolingFactor = (float) (Math.sqrt(cable.material()) / (insulated ? 8 : 4)); + data.setLogicEntry(LossAbsoluteLogic.INSTANCE.getWith(loss)) + .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) + .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) + .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) + .setLogicEntry(TemperatureLogic.INSTANCE + .getWith(TemperatureLossFunction.getOrCreateCable(coolingFactor), temperatureLimit, 1, + 100 * cable.material(), cable.partialBurnThreshold())); + if (superconductorCriticalTemperature > 0) { + data.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorCriticalTemperature)); + } + } else if (structure instanceof PipeStructure pipe) { + long amperage = amperageLimit * pipe.material() / 2; + if (amperage == 0) return; // skip pipes that are too small + long loss = lossPerAmp * (pipe.material() > 6 ? 3 : 2); + float coolingFactor = (float) Math.sqrt((double) pipe.material() / (4 + pipe.channelCount())); + data.setLogicEntry(LossAbsoluteLogic.INSTANCE.getWith(loss)) + .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) + .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) + .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) + .setLogicEntry(TemperatureLogic.INSTANCE + .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), temperatureLimit, 1, + 50 * pipe.material(), null)); + if (superconductorCriticalTemperature > 0) { + data.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorCriticalTemperature)); + } + } + } + + @Override + @Nullable + public WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof CableStructure || structure instanceof PipeStructure) + return WorldEnergyNet.getWorldNet(world).getNode(pos); + else return null; + } + + @Override + public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof CableStructure || structure instanceof PipeStructure) { + WorldEnergyNet net = WorldEnergyNet.getWorldNet(world); + NetNode node = net.getNode(pos); + if (node != null) net.removeNode(node); + } + } + + @Override + public boolean generatesStructure(IPipeStructure structure) { + return structure.getClass() == CableStructure.class; + } +} diff --git a/src/main/java/gregtech/common/pipelike/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/properties/MaterialFluidProperties.java new file mode 100644 index 00000000000..a5839d901c7 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/properties/MaterialFluidProperties.java @@ -0,0 +1,187 @@ +package gregtech.common.pipelike.properties; + +import gregtech.api.GTValues; +import gregtech.api.fluids.FluidBuilder; +import gregtech.api.fluids.FluidConstants; +import gregtech.api.fluids.FluidState; +import gregtech.api.fluids.attribute.FluidAttribute; +import gregtech.api.fluids.attribute.FluidAttributes; +import gregtech.api.fluids.store.FluidStorageKeys; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.unification.material.properties.FluidProperty; +import gregtech.api.unification.material.properties.MaterialProperties; +import gregtech.api.unification.material.properties.PipeNetProperties; + +import gregtech.api.unification.material.properties.PropertyKey; + +import gregtech.common.pipelike.block.cable.CableStructure; +import gregtech.common.pipelike.block.pipe.PipeStructure; + +import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; +import gregtech.common.pipelike.net.energy.VoltageLimitLogic; + +import gregtech.common.pipelike.net.energy.WorldEnergyNet; +import gregtech.common.pipelike.net.fluid.WorldFluidNet; + +import it.unimi.dsi.fastutil.objects.Object2BooleanMap; +import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fluids.Fluid; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumSet; +import java.util.Set; + +public class MaterialFluidProperties implements PipeNetProperties.IPipeNetMaterialProperty { + + public static final String KEY = "fluid"; + + private final Set containableAttributes = new ObjectOpenHashSet<>(); + private final EnumSet containableStates = EnumSet.of(FluidState.LIQUID); + + private int maxFluidTemperature; + private final int minFluidTemperature; + + private final long baseThroughput; + private final float priority; + + public MaterialFluidProperties(long baseThroughput, int maxFluidTemperature, int minFluidTemperature, float priority) { + this.baseThroughput = baseThroughput; + this.maxFluidTemperature = maxFluidTemperature; + this.minFluidTemperature = minFluidTemperature; + this.priority = priority; + } + + public static MaterialFluidProperties createMax(long baseThroughput, int maxFluidTemperature) { + return createMax(baseThroughput, maxFluidTemperature, 2048f / baseThroughput); + } + + public static MaterialFluidProperties createMax(long baseThroughput, int maxFluidTemperature, float priority) { + return new MaterialFluidProperties(baseThroughput, maxFluidTemperature, FluidConstants.CRYOGENIC_FLUID_THRESHOLD + 1, priority); + } + + public static MaterialFluidProperties createMin(long baseThroughput, int minFluidTemperature) { + return createMin(baseThroughput, minFluidTemperature, 2048f / baseThroughput); + } + + public static MaterialFluidProperties createMin(long baseThroughput, int minFluidTemperature, float priority) { + return new MaterialFluidProperties(baseThroughput, 0, minFluidTemperature, priority); + } + + public static MaterialFluidProperties create(long baseThroughput) { + return create(baseThroughput, 2048f / baseThroughput); + } + + public static MaterialFluidProperties create(long baseThroughput, float priority) { + return new MaterialFluidProperties(baseThroughput, 0, 0, priority); + } + + public MaterialFluidProperties contains(FluidState state) { + this.containableStates.add(state); + return this; + } + + public MaterialFluidProperties contains(FluidAttribute attribute) { + this.containableAttributes.add(attribute); + return this; + } + + public MaterialFluidProperties notContains(FluidState state) { + this.containableStates.remove(state); + return this; + } + + public MaterialFluidProperties notContains(FluidAttribute attribute) { + this.containableAttributes.remove(attribute); + return this; + } + + public boolean canContain(FluidState state) { + return this.containableStates.contains(state); + } + + public boolean canContain(FluidAttribute attribute) { + return this.containableAttributes.contains(attribute); + } + + @Override + public @NotNull String getName() { + return KEY; + } + + @Override + public void verifyProperty(MaterialProperties properties) { + if (!properties.hasProperty(PropertyKey.WOOD)) { + properties.ensureSet(PropertyKey.INGOT, true); + } + + if (this.maxFluidTemperature == 0 && properties.hasProperty(PropertyKey.FLUID)) { + // autodetermine melt temperature from registered fluid + FluidProperty prop = properties.getProperty(PropertyKey.FLUID); + Fluid fluid = prop.getStorage().get(FluidStorageKeys.LIQUID); + if (fluid == null) { + FluidBuilder builder = prop.getStorage().getQueuedBuilder(FluidStorageKeys.LIQUID); + if (builder != null) { + this.maxFluidTemperature = builder.currentTemp(); + } + } else { + this.maxFluidTemperature = fluid.getTemperature(); + } + } + } + + @Override + public void addToNet(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof PipeStructure pipe) { + WorldPipeNetNode node = WorldFluidNet.getWorldNet(world).getOrCreateNode(pos); + mutateData(node.getData(), pipe); + } + } + + @Override + public void mutateData(NetLogicData data, IPipeStructure structure) { + if (structure instanceof PipeStructure pipe) { + long throughput = baseThroughput * pipe.material(); + float coolingFactor = (float) Math.sqrt((double) pipe.material() / (4 + pipe.channelCount())); + double weight = priority * (pipe.restrictive() ? 100d : 1d) * pipe.channelCount() / pipe.material(); + data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(weight)) + .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)) + .setLogicEntry(TemperatureLogic.INSTANCE + .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), maxFluidTemperature, + minFluidTemperature, 50 * pipe.material(), null)); + } + } + + @Override + public @Nullable WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof PipeStructure) + return WorldFluidNet.getWorldNet(world).getNode(pos); + else return null; + } + + @Override + public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof PipeStructure) { + WorldFluidNet net = WorldFluidNet.getWorldNet(world); + NetNode node = net.getNode(pos); + if (node != null) net.removeNode(node); + } + } + + @Override + public boolean generatesStructure(IPipeStructure structure) { + return structure.getClass() == PipeStructure.class; + } +} diff --git a/src/main/java/gregtech/common/pipelike/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/properties/MaterialItemProperties.java new file mode 100644 index 00000000000..b799ee6a1f8 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/properties/MaterialItemProperties.java @@ -0,0 +1,101 @@ +package gregtech.common.pipelike.properties; + +import gregtech.api.fluids.FluidBuilder; +import gregtech.api.fluids.FluidConstants; +import gregtech.api.fluids.FluidState; +import gregtech.api.fluids.attribute.FluidAttribute; +import gregtech.api.fluids.store.FluidStorageKeys; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.unification.material.properties.FluidProperty; +import gregtech.api.unification.material.properties.MaterialProperties; +import gregtech.api.unification.material.properties.PipeNetProperties; +import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.common.pipelike.block.pipe.PipeStructure; + +import gregtech.common.pipelike.net.item.WorldItemNet; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fluids.Fluid; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumSet; +import java.util.Set; + +public class MaterialItemProperties implements PipeNetProperties.IPipeNetMaterialProperty { + + public static final String KEY = "item"; + + private final long baseThroughput; + private final float priority; + + public MaterialItemProperties(long baseThroughput, float priority) { + this.baseThroughput = baseThroughput; + this.priority = priority; + } + public static MaterialItemProperties create(long baseThroughput) { + return new MaterialItemProperties(baseThroughput, 2048f / baseThroughput); + } + + @Override + public @NotNull String getName() { + return KEY; + } + + @Override + public void verifyProperty(MaterialProperties properties) { + if (!properties.hasProperty(PropertyKey.WOOD)) { + properties.ensureSet(PropertyKey.INGOT, true); + } + } + + @Override + public void addToNet(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof PipeStructure pipe) { + WorldPipeNetNode node = WorldItemNet.getWorldNet(world).getOrCreateNode(pos); + mutateData(node.getData(), pipe); + } + } + + @Override + public void mutateData(NetLogicData data, IPipeStructure structure) { + if (structure instanceof PipeStructure pipe) { + long throughput = baseThroughput * pipe.material(); + double weight = priority * (pipe.restrictive() ? 100d : 1d) * pipe.channelCount() / pipe.material(); + data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(weight)) + .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)); + } + } + + @Override + public @Nullable WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof PipeStructure) + return WorldItemNet.getWorldNet(world).getNode(pos); + else return null; + } + + @Override + public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof PipeStructure) { + WorldItemNet net = WorldItemNet.getWorldNet(world); + NetNode node = net.getNode(pos); + if (node != null) net.removeNode(node); + } + } + + @Override + public boolean generatesStructure(IPipeStructure structure) { + return structure.getClass() == PipeStructure.class; + } +} diff --git a/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java b/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java index 2e37fe4e6ca..3bdf2706209 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java @@ -9,7 +9,6 @@ import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.CableRenderer; diff --git a/src/main/java/gregtech/common/pipelikeold/cable/Insulation.java b/src/main/java/gregtech/common/pipelikeold/cable/Insulation.java index 4ecdb939a6c..b1bc89894ef 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/Insulation.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/Insulation.java @@ -1,7 +1,6 @@ package gregtech.common.pipelikeold.cable; import gregtech.api.graphnet.pipenetold.block.material.IMaterialPipeType; -import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.unification.ore.OrePrefix; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/common/pipelikeold/cable/ItemBlockCable.java b/src/main/java/gregtech/common/pipelikeold/cable/ItemBlockCable.java index 3b03a0e14ef..1ba813b11be 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/ItemBlockCable.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/ItemBlockCable.java @@ -3,7 +3,6 @@ import gregtech.api.GTValues; import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; import gregtech.api.graphnet.pipenetold.block.material.ItemBlockMaterialPipe; -import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.GTUtility; import gregtech.client.utils.TooltipHelper; import gregtech.common.ConfigHolder; diff --git a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java index 9013ec89426..eed36045dae 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java @@ -6,30 +6,37 @@ public class EnergyGroupData extends AbstractGroupData { - private long lastEnergyFluxPerSec; - private long energyFluxPerSec; + private final long[] lastEnergyFluxPerSec = new long[2]; + private final long[] energyFluxPerSec = new long[2]; private long updateTime; - public long getEnergyFluxPerSec() { - updateCache(); + + public long[] getEnergyFluxPerSec(long queryTick) { + updateCache(queryTick); return lastEnergyFluxPerSec; } - public void addEnergyFluxPerSec(long energy) { - updateCache(); - energyFluxPerSec += energy; + public void addEnergyInPerSec(long energy, long queryTick) { + updateCache(queryTick); + energyFluxPerSec[0] += energy; + } + + public void addEnergyOutPerSec(long energy, long queryTick) { + updateCache(queryTick); + energyFluxPerSec[1] += energy; } - private void updateCache() { - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - if (tick > updateTime) { + private void updateCache(long queryTick) { + if (queryTick > updateTime) { updateTime = updateTime + 20; clearCache(); } } public void clearCache() { - lastEnergyFluxPerSec = energyFluxPerSec; - energyFluxPerSec = 0; + lastEnergyFluxPerSec[0] = energyFluxPerSec[0]; + lastEnergyFluxPerSec[1] = energyFluxPerSec[1]; + energyFluxPerSec[0] = 0; + energyFluxPerSec[1] = 0; } } diff --git a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java index 5cac5214023..5548a3321bf 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java @@ -10,7 +10,6 @@ import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.edge.util.FlowConsumerList; -import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.FacingPos; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; diff --git a/src/main/java/gregtech/common/pipelikeold/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelikeold/cable/net/WorldEnergyNet.java index f4a00f48f5f..3af22fc6583 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/net/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/net/WorldEnergyNet.java @@ -6,7 +6,6 @@ import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.unification.material.properties.WireProperties; import gregtech.common.pipelikeold.cable.Insulation; import gregtech.common.pipelikeold.cable.tile.TileEntityCable; diff --git a/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCable.java index 8768892d834..6974d7191d3 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCable.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCable.java @@ -10,7 +10,6 @@ import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.util.TaskScheduler; import gregtech.api.util.TextFormattingUtil; import gregtech.client.particle.GTOverheatParticle; diff --git a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java index d12a134adc5..f8c780b6aa7 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java @@ -239,8 +239,8 @@ public CTMaterialBuilder ingotSmeltInto(Material m) { } @ZenMethod - public CTMaterialBuilder cableProperties(long voltage, int amperage, int loss, @Optional boolean isSuperCon) { - backingBuilder.cableProperties(voltage, amperage, loss, isSuperCon); + public CTMaterialBuilder cableProperties(long voltage, int amperage, int loss, @Optional int meltTemperature, @Optional int superConTemperature) { + backingBuilder.cableProperties(voltage, amperage, loss, meltTemperature, superConTemperature); return this; } diff --git a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java index c9a2560a0d6..9ab25c9414e 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java @@ -9,6 +9,9 @@ import gregtech.api.unification.material.properties.*; import crafttweaker.annotations.ZenRegister; + +import gregtech.common.pipelike.properties.MaterialEnergyProperties; + import stanhebben.zenscript.annotations.Optional; import stanhebben.zenscript.annotations.ZenExpansion; import stanhebben.zenscript.annotations.ZenMethod; @@ -72,7 +75,8 @@ public static boolean hasTools(Material m) { @ZenMethod public static boolean hasWires(Material m) { - return m.hasProperty(PropertyKey.WIRE); + return m.hasProperty(PropertyKey.PIPENET_PROPERTIES) && + m.getProperty(PropertyKey.PIPENET_PROPERTIES).hasProperty(MaterialEnergyProperties.KEY); } //////////////////////////////////// @@ -246,18 +250,12 @@ public static void addTools(Material m, float toolSpeed, float toolAttackDamage, } @ZenMethod - public static void addWires(Material m, int voltage, int baseAmperage, int lossPerBlock, - @Optional boolean isSuperCon, @Optional int criticalTemp, - @Optional int meltTemperature) { + public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock, + @Optional int meltTemperature, @Optional int superconductorTemp) { if (checkFrozen("add Wires to a material")) return; - if (m.hasProperty(PropertyKey.WIRE)) { - m.getProperty(PropertyKey.WIRE).setVoltage(voltage); - m.getProperty(PropertyKey.WIRE).setAmperage(baseAmperage); - m.getProperty(PropertyKey.WIRE).setLossPerBlock(lossPerBlock); - m.getProperty(PropertyKey.WIRE).setMeltTemperature(meltTemperature); - m.getProperty(PropertyKey.WIRE).setSuperconductor(isSuperCon); - m.getProperty(PropertyKey.WIRE).setSuperconductorCriticalTemperature(criticalTemp); - } else m.setProperty(PropertyKey.WIRE, - new WireProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, isSuperCon, criticalTemp)); + if (!m.hasProperty(PropertyKey.PIPENET_PROPERTIES)) { + m.setProperty(PropertyKey.PIPENET_PROPERTIES, new PipeNetProperties()); + } + m.getProperty(PropertyKey.PIPENET_PROPERTIES).setProperty(new MaterialEnergyProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, superconductorTemp)); } } diff --git a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java index 126ca31e162..87e6d848a61 100644 --- a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java @@ -14,14 +14,16 @@ import gregtech.api.unification.material.properties.IngotProperty; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.unification.material.properties.OreProperty; +import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.properties.ToolProperty; -import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.unification.material.properties.WoodProperty; import com.cleanroommc.groovyscript.api.GroovyBlacklist; import com.cleanroommc.groovyscript.api.GroovyLog; +import gregtech.common.pipelike.properties.MaterialEnergyProperties; + import static gregtech.integration.groovy.GroovyScriptModule.checkFrozen; @SuppressWarnings("unused") @@ -68,7 +70,8 @@ public static boolean hasTools(Material m) { } public static boolean hasWires(Material m) { - return m.hasProperty(PropertyKey.WIRE); + return m.hasProperty(PropertyKey.PIPENET_PROPERTIES) && + m.getProperty(PropertyKey.PIPENET_PROPERTIES).hasProperty(MaterialEnergyProperties.KEY); } //////////////////////////////////// @@ -319,43 +322,33 @@ public static void addTools(Material m, float toolSpeed, float toolAttackDamage, .durabilityMultiplier(durabilityMultiplier)); } - public static void addWires(Material m, int voltage, int baseAmperage, int lossPerBlock) { - addWires(m, voltage, baseAmperage, lossPerBlock, false, 0); - } - - public static void addWires(Material m, int voltage, int baseAmperage, int lossPerBlock, boolean isSuperCon) { - addWires(m, voltage, baseAmperage, lossPerBlock, isSuperCon, 0); + public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock) { + addWires(m, voltage, baseAmperage, lossPerBlock, 0); } - public static void addWires(Material m, int voltage, int baseAmperage, int lossPerBlock, boolean isSuperCon, - int criticalTemp) { - addWires(m, voltage, baseAmperage, lossPerBlock, isSuperCon, criticalTemp, 0); + public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock, int meltTemperature) { + addWires(m, voltage, baseAmperage, lossPerBlock, meltTemperature, 0); } - public static void addWires(Material m, int voltage, int baseAmperage, int lossPerBlock, boolean isSuperCon, - int criticalTemp, int meltTemperature) { + public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock, int meltTemperature, + int superconductorTemp) { if (checkFrozen("add Wires to a material")) return; - if (m.hasProperty(PropertyKey.WIRE)) { - m.getProperty(PropertyKey.WIRE).setVoltage(voltage); - m.getProperty(PropertyKey.WIRE).setAmperage(baseAmperage); - m.getProperty(PropertyKey.WIRE).setLossPerBlock(lossPerBlock); - m.getProperty(PropertyKey.WIRE).setMeltTemperature(meltTemperature); - m.getProperty(PropertyKey.WIRE).setSuperconductor(isSuperCon); - m.getProperty(PropertyKey.WIRE).setSuperconductorCriticalTemperature(criticalTemp); - } else m.setProperty(PropertyKey.WIRE, - new WireProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, isSuperCon, criticalTemp)); + if (!m.hasProperty(PropertyKey.PIPENET_PROPERTIES)) { + m.setProperty(PropertyKey.PIPENET_PROPERTIES, new PipeNetProperties()); + } + m.getProperty(PropertyKey.PIPENET_PROPERTIES).setProperty(new MaterialEnergyProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, superconductorTemp)); } - public static void addCables(Material m, int voltage, int baseAmperage, int lossPerBlock) { - addWires(m, voltage, baseAmperage, lossPerBlock, false, 0); + public static void addCables(Material m, long voltage, long baseAmperage, long lossPerBlock) { + addWires(m, voltage, baseAmperage, lossPerBlock); } - public static void addCables(Material m, int voltage, int baseAmperage, int lossPerBlock, boolean isSuperCon) { - addWires(m, voltage, baseAmperage, lossPerBlock, isSuperCon, 0); + public static void addCables(Material m, long voltage, long baseAmperage, long lossPerBlock, int meltTemperature) { + addWires(m, voltage, baseAmperage, lossPerBlock, meltTemperature); } - public static void addCables(Material m, int voltage, int baseAmperage, int lossPerBlock, boolean isSuperCon, - int criticalTemp) { - addWires(m, voltage, baseAmperage, lossPerBlock, isSuperCon, criticalTemp); + public static void addCables(Material m, int voltage, int baseAmperage, int lossPerBlock, int meltTemperature, + int superconductorTemp) { + addWires(m, voltage, baseAmperage, lossPerBlock, meltTemperature, superconductorTemp); } } diff --git a/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java index ddff63fd34a..e5bbbc7a408 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java @@ -19,6 +19,8 @@ import gregtech.common.items.MetaItems; import gregtech.common.items.behaviors.AbstractMaterialPartBehavior; +import gregtech.common.pipelike.properties.MaterialEnergyProperties; + import net.minecraft.item.EnumDyeColor; import net.minecraft.item.ItemStack; @@ -150,7 +152,8 @@ public static void processFineWire(OrePrefix fineWirePrefix, Material material, OreDictUnifier.get(fineWirePrefix, material), 'x', new UnificationEntry(OrePrefix.foil, material)); - if (material.hasProperty(PropertyKey.WIRE)) { + if (material.hasProperty(PropertyKey.PIPENET_PROPERTIES) && + material.getProperty(PropertyKey.PIPENET_PROPERTIES).hasProperty(MaterialEnergyProperties.KEY)) { RecipeMaps.WIREMILL_RECIPES.recipeBuilder() .input(OrePrefix.wireGtSingle, material) .circuitMeta(1) diff --git a/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java index 388558a8d2d..e88b76afba5 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java @@ -6,11 +6,13 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; import gregtech.api.unification.material.properties.PropertyKey; -import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.unification.stack.UnificationEntry; import com.google.common.collect.ImmutableMap; + +import gregtech.common.pipelike.properties.MaterialEnergyProperties; + import org.apache.commons.lang3.ArrayUtils; import java.util.Map; @@ -33,20 +35,20 @@ public class WireCombiningHandler { public static void register() { // Generate Wire Packer/Unpacker recipes TODO Move into generateWireCombining? - wireGtSingle.addProcessingHandler(PropertyKey.WIRE, WireCombiningHandler::processWireCompression); + wireGtSingle.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireCombiningHandler::processWireCompression)); // Generate manual recipes for combining Wires/Cables for (OrePrefix wirePrefix : WIRE_DOUBLING_ORDER) { - wirePrefix.addProcessingHandler(PropertyKey.WIRE, WireCombiningHandler::generateWireCombiningRecipe); + wirePrefix.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireCombiningHandler::generateWireCombiningRecipe)); } // Generate Cable -> Wire recipes in the unpacker for (OrePrefix cablePrefix : cableToWireMap.keySet()) { - cablePrefix.addProcessingHandler(PropertyKey.WIRE, WireCombiningHandler::processCableStripping); + cablePrefix.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireCombiningHandler::processCableStripping)); } } - private static void generateWireCombiningRecipe(OrePrefix wirePrefix, Material material, WireProperties property) { + private static void generateWireCombiningRecipe(OrePrefix wirePrefix, Material material, MaterialEnergyProperties property) { int wireIndex = ArrayUtils.indexOf(WIRE_DOUBLING_ORDER, wirePrefix); if (wireIndex < WIRE_DOUBLING_ORDER.length - 1) { @@ -72,7 +74,7 @@ private static void generateWireCombiningRecipe(OrePrefix wirePrefix, Material m } } - private static void processWireCompression(OrePrefix prefix, Material material, WireProperties property) { + private static void processWireCompression(OrePrefix prefix, Material material,MaterialEnergyProperties property) { for (int startTier = 0; startTier < 4; startTier++) { for (int i = 1; i < 5 - startTier; i++) { PACKER_RECIPES.recipeBuilder() @@ -92,7 +94,7 @@ private static void processWireCompression(OrePrefix prefix, Material material, } } - private static void processCableStripping(OrePrefix prefix, Material material, WireProperties property) { + private static void processCableStripping(OrePrefix prefix, Material material, MaterialEnergyProperties property) { PACKER_RECIPES.recipeBuilder() .input(prefix, material) .output(cableToWireMap.get(prefix), material) diff --git a/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java index 129150429d5..651e9a84fff 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java @@ -6,13 +6,14 @@ import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.PropertyKey; -import gregtech.api.unification.material.properties.WireProperties; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.unification.stack.UnificationEntry; import gregtech.api.util.GTUtility; import com.google.common.collect.ImmutableMap; +import gregtech.common.pipelike.properties.MaterialEnergyProperties; + import java.util.Map; import static gregtech.api.GTValues.*; @@ -51,19 +52,19 @@ public class WireRecipeHandler { public static void register() { // Generate 1x Wire creation recipes (Wiremill, Extruder, Wire Cutters) - wireGtSingle.addProcessingHandler(PropertyKey.WIRE, WireRecipeHandler::processWireSingle); + wireGtSingle.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::processWireSingle)); // Generate Cable Covering Recipes - wireGtSingle.addProcessingHandler(PropertyKey.WIRE, WireRecipeHandler::generateCableCovering); - wireGtDouble.addProcessingHandler(PropertyKey.WIRE, WireRecipeHandler::generateCableCovering); - wireGtQuadruple.addProcessingHandler(PropertyKey.WIRE, WireRecipeHandler::generateCableCovering); - wireGtOctal.addProcessingHandler(PropertyKey.WIRE, WireRecipeHandler::generateCableCovering); - wireGtHex.addProcessingHandler(PropertyKey.WIRE, WireRecipeHandler::generateCableCovering); + wireGtSingle.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); + wireGtDouble.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); + wireGtQuadruple.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); + wireGtOctal.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); + wireGtHex.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); } private static final OrePrefix[] wireSizes = { wireGtDouble, wireGtQuadruple, wireGtOctal, wireGtHex }; - public static void processWireSingle(OrePrefix wirePrefix, Material material, WireProperties property) { + public static void processWireSingle(OrePrefix wirePrefix, Material material, MaterialEnergyProperties property) { OrePrefix prefix = material.hasProperty(PropertyKey.INGOT) ? ingot : material.hasProperty(PropertyKey.GEM) ? gem : dust; @@ -101,7 +102,7 @@ public static void processWireSingle(OrePrefix wirePrefix, Material material, Wi } } - public static void generateCableCovering(OrePrefix wirePrefix, Material material, WireProperties property) { + public static void generateCableCovering(OrePrefix wirePrefix, Material material, MaterialEnergyProperties property) { // Superconductors have no Cables, so exit early if (property.isSuperconductor()) return; From 3c7fc39249485d6664112eb323b7d03a03d2197d Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 17 Jul 2024 18:41:33 -0600 Subject: [PATCH 077/157] Complete rewrite pt4 --- .../gregtech/api/graphnet/GraphNetBacker.java | 44 ++- .../java/gregtech/api/graphnet/IGraphNet.java | 6 +- .../DynamicWeightsShortestPathsAlgorithm.java | 5 - .../api/graphnet/alg/INetAlgorithm.java | 4 - .../api/graphnet/alg/NetAlgorithmWrapper.java | 6 - .../graphnet/edge/AbstractNetFlowEdge.java | 15 +- .../gregtech/api/graphnet/edge/NetEdge.java | 9 +- .../api/graphnet/edge/NetFlowEdge.java | 31 +- .../api/graphnet/edge/NetFlowSharedEdge.java | 4 - .../api/graphnet/edge/util/FlowConsumer.java | 72 ---- .../graphnet/edge/util/FlowConsumerList.java | 67 ---- .../api/graphnet/graph/INetGraph.java | 9 +- .../api/graphnet/graph/NetDirectedGraph.java | 20 +- .../graphnet/graph/NetUndirectedGraph.java | 20 +- .../gregtech/api/graphnet/path/INetPath.java | 10 + .../api/graphnet/pipenet/NodeLossResult.java | 10 +- .../api/graphnet/pipenet/WorldPipeNet.java | 40 +- .../logic/EdgeCoverReferenceLogic.java | 147 ++++++++ .../pipenet/logic/TemperatureLogic.java | 8 +- .../pipenet/physical/tile/PipeTileEntity.java | 10 + .../predicate/ShutterPredicate.java | 10 +- .../graphnet/pipenetold/WorldPipeNetBase.java | 10 +- .../predicate/EdgePredicateHandler.java | 2 +- .../graphnet/predicate/IEdgePredicate.java | 1 - .../api/graphnet/servernet/ServerNet.java | 13 +- .../graphnet/traverse/DistributorHelper.java | 30 ++ .../traverse/IEqualizableTraverseData.java | 21 ++ .../traverse/IRoundRobinTraverseData.java | 26 ++ .../api/graphnet/traverse/ITraverseData.java | 17 +- .../graphnet/traverse/TraverseHelpers.java | 346 +++++++++++++++--- .../traverse/util/CompleteLossOperator.java | 17 + .../traverse/util/FlatLossOperator.java | 21 ++ .../traverse/util/FlowConsumptionStack.java | 48 +++ .../traverse/util/IdentityLossOperator.java | 17 + .../traverse/util/MultLossOperator.java | 21 ++ .../traverse/util/ReversibleLossOperator.java | 8 + .../api/graphnet/worldnet/WorldNet.java | 16 +- .../gregtech/api/util/DimensionFacingPos.java | 47 +++ .../java/gregtech/api/util/GTUtility.java | 14 + .../gregtech/common/covers/CoverShutter.java | 4 - .../block/pipe/PipeFluidProperties.java | 4 - .../block/pipe/PipeItemProperties.java | 4 - .../net/energy/EnergyCapabilityObject.java | 10 +- .../net/energy/EnergyTraverseData.java | 14 +- .../pipelike/net/energy/WorldEnergyNet.java | 10 +- .../pipelike/net/fluid/WorldFluidNet.java | 12 +- .../pipelike/net/item/WorldItemNet.java | 12 +- .../cable/net/EnergyNetHandler.java | 1 - .../fluidpipe/net/FluidNetHandler.java | 1 - 49 files changed, 927 insertions(+), 367 deletions(-) delete mode 100644 src/main/java/gregtech/api/graphnet/edge/util/FlowConsumer.java delete mode 100644 src/main/java/gregtech/api/graphnet/edge/util/FlowConsumerList.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java rename src/main/java/gregtech/api/graphnet/{ => pipenet}/predicate/ShutterPredicate.java (78%) create mode 100644 src/main/java/gregtech/api/graphnet/traverse/DistributorHelper.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/util/CompleteLossOperator.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/util/FlatLossOperator.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/util/IdentityLossOperator.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/util/ReversibleLossOperator.java create mode 100644 src/main/java/gregtech/api/util/DimensionFacingPos.java delete mode 100644 src/main/java/gregtech/common/pipelike/block/pipe/PipeFluidProperties.java delete mode 100644 src/main/java/gregtech/common/pipelike/block/pipe/PipeItemProperties.java diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index 0e7f50d54d1..f5c168de6d2 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -37,18 +37,27 @@ */ public final class GraphNetBacker { + private final IGraphNet backedNet; private final INetGraph pipeGraph; private final Object2ObjectOpenHashMap vertexMap; - private final NetAlgorithmWrapper netAlgorithm; + private final NetAlgorithmWrapper[] netAlgorithms; - public GraphNetBacker(IGraphNet backedNet, Function algorithmBuilder, - INetGraph graph) { - graph.setOwningNet(this); + @SafeVarargs + public GraphNetBacker(IGraphNet backedNet, INetGraph graph, + Function... algorithmBuilders) { + this.backedNet = backedNet; this.pipeGraph = graph; - this.netAlgorithm = new NetAlgorithmWrapper(backedNet, algorithmBuilder); + this.netAlgorithms = new NetAlgorithmWrapper[algorithmBuilders.length]; + for (int i = 0; i < algorithmBuilders.length; i++) { + this.netAlgorithms[i] = new NetAlgorithmWrapper(backedNet, algorithmBuilders[i]); + } this.vertexMap = new Object2ObjectOpenHashMap<>(); } + public IGraphNet getBackedNet() { + return backedNet; + } + public void addNode(NetNode node) { GraphVertex vertex = new GraphVertex(node); getGraph().addVertex(vertex); @@ -63,7 +72,7 @@ public NetNode getNode(Object equivalencyData) { public boolean removeNode(@Nullable NetNode node) { if (node != null) { - if (this.getGraph().edgesOf(node.wrapper).size() != 0) this.invalidateAlg(); + if (this.getGraph().edgesOf(node.wrapper).size() != 0) this.invalidateAlgs(); if (node.getGroupUnsafe() != null) { node.getGroupUnsafe().splitNode(node); } else this.removeVertex(node.wrapper); @@ -107,29 +116,32 @@ public void removeEdge(GraphEdge edge) { this.getGraph().removeEdge(edge); } - public boolean dynamicWeights() { - return netAlgorithm.getNet().usesDynamicWeights() && netAlgorithm.supportsDynamicWeights(); - } - /** * Note - if an error is thrown with a stacktrace descending from this method, * most likely a bad remapper was passed in.
* This method should never be exposed outside the net this backer is backing due to this fragility. */ - public > Iterator getPaths(@Nullable NetNode node, @NotNull NetPathMapper remapper, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + public > Iterator getPaths(@Nullable NetNode node, int algorithmID, @NotNull NetPathMapper remapper, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { if (node == null) return Collections.emptyIterator(); Iterator> cache = node.getPathCache(); if (cache != null) return (Iterator) cache; - Iterator iter = this.netAlgorithm.getPathsIterator(node.wrapper, remapper, testObject, simulator, queryTick); + this.getGraph().setupInternal(this, backedNet.usesDynamicWeights(algorithmID)); + Iterator iter = this.netAlgorithms[algorithmID].getPathsIterator(node.wrapper, remapper, testObject, simulator, queryTick); if (iter instanceof ICacheableIterator) { return (Iterator) node.setPathCache((ICacheableIterator) iter); } else return iter; } - public void invalidateAlg() { - this.netAlgorithm.invalidate(); + public void invalidateAlg(int algorithmID) { + this.netAlgorithms[algorithmID].invalidate(); + } + + public void invalidateAlgs() { + for (NetAlgorithmWrapper netAlgorithm : this.netAlgorithms) { + netAlgorithm.invalidate(); + } } public INetGraph getGraph() { @@ -164,13 +176,13 @@ public void readFromNBT(NBTTagCompound nbt) { Int2ObjectOpenHashMap vertexMap = new Int2ObjectOpenHashMap<>(vertexCount); for (int i = 0; i < vertexCount; i++) { NBTTagCompound tag = vertices.getCompoundTag(String.valueOf(i)); - NetNode node = this.netAlgorithm.getNet().getNewNode(); + NetNode node = this.backedNet.getNewNode(); node.deserializeNBT(tag); if (tag.hasKey("GroupID")) { int id = tag.getInteger("GroupID"); NetGroup group = groupMap.get(id); if (group == null) { - group = new NetGroup(this.netAlgorithm.getNet()); + group = new NetGroup(this.backedNet); groupMap.put(id, group); } group.addNode(node); diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index d806eaf64ab..19369050244 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -23,10 +23,10 @@ public interface IGraphNet { /** * Controls whether dynamic weight lookup will be used. - * If the algorithm does not support dynamic weights, this will be ignored. + * Dynamic weight lookup can be more expensive, so this should not be enabled unless necessary. */ - default boolean usesDynamicWeights() { - return true; + default boolean usesDynamicWeights(int algorithmID) { + return false; } /** diff --git a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java index 3485a574701..71469004238 100644 --- a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java @@ -33,11 +33,6 @@ public DynamicWeightsShortestPathsAlgorithm(IGraphNet net) { return new LimitedIterator<>(source, searchSpace, remapper); } - @Override - public boolean supportsDynamicWeights() { - return true; - } - protected class LimitedIterator> implements ICacheableIterator { private static final int MAX_ITERATIONS = 100; diff --git a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java index acd0d22f5b2..252c1ffabc3 100644 --- a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java @@ -9,8 +9,4 @@ public interface INetAlgorithm { > Iterator getPathsIterator(GraphVertex source, NetPathMapper remapper); - default boolean supportsDynamicWeights() { - return false; - } - } diff --git a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java index 876fa011e29..fd7a7c08420 100644 --- a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java +++ b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java @@ -7,7 +7,6 @@ import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,11 +34,6 @@ public void invalidate() { this.alg = null; } - public boolean supportsDynamicWeights() { - if (alg == null) alg = builder.apply(net); - return alg.supportsDynamicWeights(); - } - public > Iterator getPathsIterator(GraphVertex source, NetPathMapper remapper, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { net.getGraph().prepareForAlgorithmRun(testObject, simulator, queryTick); if (alg == null) alg = builder.apply(net); diff --git a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java index d0a4b16fb94..233786c5f6b 100644 --- a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java @@ -5,13 +5,11 @@ import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; import java.util.Set; import java.util.WeakHashMap; -import java.util.function.Supplier; public abstract class AbstractNetFlowEdge extends NetEdge { @@ -24,11 +22,12 @@ public AbstractNetFlowEdge() { } @Override - public double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick, - Supplier<@NotNull Double> defaultWeight) { - if (cannotSupportChannel(channel, queryTick, simulator)) { - return defaultWeight.get() * 1000000; - } else return defaultWeight.get(); + public double getDynamicWeight(IPredicateTestObject channel, IGraphNet net, @Nullable SimulatorKey simulator, long queryTick, + double defaultWeight) { + long flow = getFlowLimit(channel, net, queryTick, simulator); + if (flow <= 0) { + return defaultWeight * getThroughput() * Short.MAX_VALUE; + } else return defaultWeight * getThroughput() / flow; } public boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick, @Nullable SimulatorKey simulator) { @@ -61,7 +60,7 @@ public long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long que else return getChannels(simulator).getFlowLimit(channel, graph, queryTick); } - public long getConsumedLimit(IPredicateTestObject channel, long queryTick, @Nullable SimulatorKey simulator) { + protected long getConsumedLimit(IPredicateTestObject channel, long queryTick, @Nullable SimulatorKey simulator) { if (!this.test(channel)) return 0; else return getChannels(simulator).getConsumedLimit(channel, queryTick); } diff --git a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java index 51052d40ad4..069f5c32708 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java @@ -1,5 +1,6 @@ package gregtech.api.graphnet.edge; +import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.logic.NetLogicData; @@ -14,8 +15,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.function.Supplier; - public class NetEdge implements INBTSerializable { /** @@ -59,9 +58,9 @@ public boolean test(IPredicateTestObject object) { else return predicateHandler.test(object); } - public double getDynamicWeight(IPredicateTestObject channel, SimulatorKey simulator, long queryTick, - Supplier<@NotNull Double> defaultWeight) { - return defaultWeight.get(); + public double getDynamicWeight(IPredicateTestObject channel, IGraphNet graph, @Nullable SimulatorKey simulator, + long queryTick, double defaultWeight) { + return defaultWeight; } @Override diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java index 831aba48198..84bd84b4e42 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java @@ -1,16 +1,12 @@ package gregtech.api.graphnet.edge; import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.PipeNetNode; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; import java.util.List; import java.util.Set; @@ -18,6 +14,7 @@ public class NetFlowEdge extends AbstractNetFlowEdge { private final int flowBufferTicks; + private final int regenerationTime; /** * NetEdge that provides standard flow behavior handling @@ -28,6 +25,20 @@ public class NetFlowEdge extends AbstractNetFlowEdge { */ public NetFlowEdge(int flowBufferTicks) { this.flowBufferTicks = Math.max(flowBufferTicks, 1); + this.regenerationTime = 1; + } + + /** + * NetEdge that provides standard flow behavior handling + * + * @param flowBufferMult Determines maximum mult of 'buffer' flow capacity that can be built up along edges. Allows + * for once-an-interval push/pull operations instead of needing them every unit of time + * for maximum throughput. + * @param regenerationTime Ticks required for flow to regenerate once. Allows slowing down the rate of regeneration. + */ + public NetFlowEdge(int flowBufferMult, int regenerationTime) { + this.flowBufferTicks = Math.max(flowBufferMult, 1); + this.regenerationTime = Math.max(regenerationTime, 1); } @Override @@ -121,22 +132,22 @@ void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount @Override public void recalculateFlowLimits(long queryTick) { if (!this.init) { - this.map.defaultReturnValue((long) getThroughput() * flowBufferTicks); + this.map.defaultReturnValue(getThroughput() * flowBufferTicks); this.init = true; } - int time = (int) (queryTick - this.lastQueryTick); - if (time < 0) { + int regenerationUnits = (int) (queryTick - this.lastQueryTick) / regenerationTime; + if (regenerationUnits < 0) { this.map.clear(); - } else { + } else if (regenerationUnits > 0) { List toRemove = new ObjectArrayList<>(); this.map.replaceAll((k, v) -> { - v += (long) time * getThroughput(); + v += (long) regenerationUnits * getThroughput(); if (v >= map.defaultReturnValue()) toRemove.add(k); return v; }); toRemove.forEach(this.map::removeLong); + this.lastQueryTick += (long) regenerationUnits * regenerationTime; } - this.lastQueryTick = queryTick; } @Override diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java index 518b67ea32f..26fea9c1ea0 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java @@ -1,9 +1,6 @@ package gregtech.api.graphnet.edge; import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.PipeNetNode; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; @@ -12,7 +9,6 @@ import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; import java.util.List; import java.util.Set; diff --git a/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumer.java b/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumer.java deleted file mode 100644 index 35189c5bdd9..00000000000 --- a/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumer.java +++ /dev/null @@ -1,72 +0,0 @@ -package gregtech.api.graphnet.edge.util; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; - -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import java.util.function.Consumer; -import java.util.function.UnaryOperator; - -public class FlowConsumer { - - private final AbstractNetFlowEdge edge; - private final IPredicateTestObject testObject; - private final IGraphNet graph; - private double flow; - private final long tick; - private final SimulatorKey simulatorKey; - private final Consumer extra; - - public FlowConsumer(AbstractNetFlowEdge edge, IPredicateTestObject testObject, IGraphNet graph, long flow, - long tick, SimulatorKey simulatorKey) { - this(edge, testObject, graph, flow, tick, simulatorKey, null); - } - - public FlowConsumer(AbstractNetFlowEdge edge, IPredicateTestObject testObject, IGraphNet graph, long flow, - long tick, SimulatorKey simulatorKey, Consumer extra) { - this.edge = edge; - this.testObject = testObject; - this.graph = graph; - this.flow = flow; - this.tick = tick; - this.simulatorKey = simulatorKey; - this.extra = extra; - } - - public void modifyRatio(Double ratio) { - this.flow *= ratio; - } - - public void modifyReduction(Long reduction) { - this.flow -= reduction; - } - - public void modifyArbitrary(UnaryOperator modification) { - this.flow = modification.apply(this.flow); - } - - public void finalRatio(Double finalRatio) { - modifyRatio(finalRatio); - consume(); - } - - public void finalReduction(Long finalReduction) { - modifyReduction(finalReduction); - consume(); - } - - public void finalArbitrary(UnaryOperator modification) { - modifyArbitrary(modification); - consume(); - } - - public void consume() { - long consumption = (long) Math.ceil(this.flow); - if (consumption > 0) { - edge.consumeFlowLimit(testObject, graph, consumption, tick, simulatorKey); - if (extra != null) extra.accept(consumption); - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumerList.java b/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumerList.java deleted file mode 100644 index 51fa3f926f1..00000000000 --- a/src/main/java/gregtech/api/graphnet/edge/util/FlowConsumerList.java +++ /dev/null @@ -1,67 +0,0 @@ -package gregtech.api.graphnet.edge.util; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; - -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import java.util.function.Consumer; -import java.util.function.UnaryOperator; - -public class FlowConsumerList extends ObjectArrayList { - - public void add(AbstractNetFlowEdge edge, IPredicateTestObject testObject, IGraphNet graph, long flow, - long tick, SimulatorKey simulatorKey) { - this.add(new FlowConsumer(edge, testObject, graph, flow, tick, simulatorKey)); - } - - public void add(AbstractNetFlowEdge edge, IPredicateTestObject testObject, IGraphNet graph, long flow, - long tick, SimulatorKey simulatorKey, Consumer extra) { - this.add(new FlowConsumer(edge, testObject, graph, flow, tick, simulatorKey, extra)); - } - - public void modifyRatios(double ratio) { - for (FlowConsumer consumer : this) { - consumer.modifyRatio(ratio); - } - } - - public void modifyReductions(long reduction) { - for (FlowConsumer consumer : this) { - consumer.modifyReduction(reduction); - } - } - - public void modifyArbitrary(UnaryOperator modifier) { - for (FlowConsumer consumer : this) { - consumer.modifyArbitrary(modifier); - } - } - - public void doConsumption(double finalRatio) { - for (FlowConsumer consumer : this) { - consumer.finalRatio(finalRatio); - } - } - - public void doConsumption(long finalReduction) { - for (FlowConsumer consumer : this) { - consumer.finalReduction(finalReduction); - } - } - - public void doConsumption(UnaryOperator finalModifier) { - for (FlowConsumer consumer : this) { - consumer.finalArbitrary(finalModifier); - } - } - - public void doConsumption() { - for (FlowConsumer consumer : this) { - consumer.consume(); - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/graph/INetGraph.java b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java index 8a244c5b277..05edbcecc16 100644 --- a/src/main/java/gregtech/api/graphnet/graph/INetGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java @@ -9,10 +9,13 @@ public interface INetGraph extends Graph { - @ApiStatus.Internal - void setOwningNet(GraphNetBacker net); - void prepareForAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, long queryTick); boolean isDirected(); + + /** + * This should only be called by {@link GraphNetBacker} + */ + @ApiStatus.Internal + void setupInternal(GraphNetBacker backer, boolean dynamicWeights); } diff --git a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java index 0a8ff118cc0..61636af23ec 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java @@ -12,7 +12,8 @@ public class NetDirectedGraph extends SimpleDirectedWeightedGraph implements INetGraph { - private GraphNetBacker net = null; + private boolean dynamicWeights; + private IGraphNet net; private IPredicateTestObject testObject; private SimulatorKey simulator; @@ -22,13 +23,6 @@ public NetDirectedGraph(Supplier vertexSupplier, Supplier super.getEdgeWeight(graphEdge)); + if (dynamicWeights) { + return graphEdge.wrapped.getDynamicWeight(testObject, net, simulator, queryTick, super.getEdgeWeight(graphEdge)); } else return super.getEdgeWeight(graphEdge); } else return Double.POSITIVE_INFINITY; } diff --git a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java index f0ecf7b4529..ad7a3daacea 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java @@ -12,7 +12,8 @@ public class NetUndirectedGraph extends SimpleWeightedGraph implements INetGraph { - private GraphNetBacker net = null; + private boolean dynamicWeights; + private IGraphNet net; private IPredicateTestObject testObject; private SimulatorKey simulator; @@ -22,13 +23,6 @@ public NetUndirectedGraph(Supplier vertexSupplier, Supplier super.getEdgeWeight(graphEdge)); + if (dynamicWeights) { + return graphEdge.wrapped.getDynamicWeight(testObject, net, simulator, queryTick, super.getEdgeWeight(graphEdge)); } else return super.getEdgeWeight(graphEdge); } else return Double.POSITIVE_INFINITY; } diff --git a/src/main/java/gregtech/api/graphnet/path/INetPath.java b/src/main/java/gregtech/api/graphnet/path/INetPath.java index 5cdf3fb1cfa..50d0f5fe55c 100644 --- a/src/main/java/gregtech/api/graphnet/path/INetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/INetPath.java @@ -9,8 +9,18 @@ import java.util.List; public interface INetPath { + List getOrderedNodes(); + default N getSourceNode() { + return getOrderedNodes().get(0); + } + + default N getTargetNode() { + List nodes = getOrderedNodes(); + return nodes.get(nodes.size() - 1); + } + List getOrderedEdges(); double getWeight(); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java index 7d000ffdcc8..41c5ef2999f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java @@ -1,5 +1,7 @@ package gregtech.api.graphnet.pipenet; +import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; + import net.minecraft.util.Tuple; import org.jetbrains.annotations.NotNull; @@ -11,9 +13,9 @@ public final class NodeLossResult { private final @Nullable Consumer postAction; - private final @NotNull UnaryOperator lossFunction; + private final @NotNull ReversibleLossOperator lossFunction; - public NodeLossResult(@Nullable Consumer postAction, @NotNull UnaryOperator lossFunction) { + public NodeLossResult(@Nullable Consumer postAction, @NotNull ReversibleLossOperator lossFunction) { this.postAction = postAction; this.lossFunction = lossFunction; } @@ -27,7 +29,7 @@ public void triggerPostAction(WorldPipeNetNode node) { this.postAction.accept(node); } - public long applyLossFunction(long value) { - return this.lossFunction.apply(value); + public @NotNull ReversibleLossOperator getLossFunction() { + return lossFunction; } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 22d97b69039..436e858b8e8 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -9,7 +9,7 @@ import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.predicate.ShutterPredicate; +import gregtech.api.graphnet.pipenet.predicate.ShutterPredicate; import gregtech.api.graphnet.worldnet.WorldNet; import gregtech.api.util.IDirtyNotifiable; @@ -42,9 +42,10 @@ public abstract class WorldPipeNet extends WorldNet { private static final Object2ObjectOpenHashMap>> dimensionNets = new Object2ObjectOpenHashMap<>(); - public WorldPipeNet(String name, Function algorithmBuilder, - Function graphBuilder) { - super(name, algorithmBuilder, graphBuilder); + @SafeVarargs + public WorldPipeNet(String name, Function graphBuilder, + Function... algorithmBuilders) { + super(name, graphBuilder, algorithmBuilders); dimensionNets.compute(getDimension(), (k, v) -> { if (v == null) v = new ObjectOpenHashSet<>(); v.add(new WeakReference<>(this)); @@ -52,8 +53,9 @@ public WorldPipeNet(String name, Function algorithmBui }); } - public WorldPipeNet(String name, Function algorithmBuilder, boolean directed) { - super(name, algorithmBuilder, directed); + @SafeVarargs + public WorldPipeNet(String name, boolean directed, Function... algorithmBuilders) { + super(name, directed, algorithmBuilders); dimensionNets.compute(getDimension(), (k, v) -> { if (v == null) v = new ObjectOpenHashSet<>(); v.add(new WeakReference<>(this)); @@ -64,34 +66,32 @@ public WorldPipeNet(String name, Function algorithmBui /** * Called when a PipeTileEntity is marked dirty through {@link IDirtyNotifiable#markAsDirty()}, which is generally * when the state of its covers is changed. - * @param node - * @param tile + * @param tile the tile marked dirty. + * @param node the associated node. */ public void updatePredication(@NotNull WorldPipeNetNode node, @NotNull PipeTileEntity tile) { for (EnumFacing facing : EnumFacing.VALUES) { PipeTileEntity neighbor = tile.getPipeNeighbor(facing, false); - if (neighbor != null) { - WorldPipeNetNode neighborNode = this.getNode(neighbor.getPos()); - if (neighborNode != null) { - updatePredication(node, tile.getCoverHolder().getCoverAtSide(facing), neighborNode, - neighbor.getCoverHolder().getCoverAtSide(facing.getOpposite())); - } - } + if (neighbor == null) continue; + WorldPipeNetNode neighborNode = this.getNode(neighbor.getPos()); + if (neighborNode == null) continue; + NetEdge edge = getEdge(node, neighborNode); + if (edge == null) continue; + predicateEdge(edge, node, tile.getCoverHolder().getCoverAtSide(facing), neighborNode, + neighbor.getCoverHolder().getCoverAtSide(facing.getOpposite())); } } /** * Preferred method to override if your net has custom predication rules. If the net is directed, - * this method will not be called twice, so special handling for directedness is needed. + * this method will not be called twice, so special handling for directedness is needed. * @param source the source of the edge. * @param coverSource the cover on the source facing the target. * @param target the target of the edge. * @param coverTarget the cover on the target facing the source. */ - public void updatePredication(@NotNull WorldPipeNetNode source, @Nullable Cover coverSource, - @NotNull WorldPipeNetNode target, @Nullable Cover coverTarget) { - NetEdge edge = getEdge(source, target); - if (edge == null) return; + public void predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode source, @Nullable Cover coverSource, + @NotNull WorldPipeNetNode target, @Nullable Cover coverTarget) { edge.getPredicateHandler().clearPredicates(); shutterify(edge, coverSource, coverTarget); if (getGraph().isDirected()) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java new file mode 100644 index 00000000000..69a0e85039b --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java @@ -0,0 +1,147 @@ +package gregtech.api.graphnet.pipenet.logic; + +import gregtech.api.cover.Cover; +import gregtech.api.graphnet.logic.INetLogicEntry; + +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.util.DimensionFacingPos; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.WeakReference; + +public class EdgeCoverReferenceLogic implements INetLogicEntry { + public static final EdgeCoverReferenceLogic INSTANCE = new EdgeCoverReferenceLogic(); + + @Nullable + private WeakReference coverSource; + private DimensionFacingPos coverSourcePos; + @Nullable + private WeakReference coverTarget; + private DimensionFacingPos coverTargetPos; + + @Contract("_,_ -> this") + public EdgeCoverReferenceLogic coverSource(@NotNull DimensionFacingPos pos, @NotNull Cover cover) { + this.coverSource = new WeakReference<>(cover); + this.coverSourcePos = pos; + return this; + } + + @Contract("_,_ -> this") + public EdgeCoverReferenceLogic coverTarget(@NotNull DimensionFacingPos pos, @NotNull Cover cover) { + this.coverTarget = new WeakReference<>(cover); + this.coverTargetPos = pos; + return this; + } + + private @Nullable Cover getSource() { + if (coverSource == null) return null; + Cover ref = coverSource.get(); + if (ref == null) { + World world = DimensionManager.getWorld(coverSourcePos.getDimension()); + if (world == null || !world.isBlockLoaded(coverSourcePos.getPos())) return null; + + TileEntity tile = world.getTileEntity(coverSourcePos.getPos()); + if (tile instanceof PipeTileEntity pipe) { + Cover cover = pipe.getCoverHolder().getCoverAtSide(coverSourcePos.getFacing()); + if (cover != null) { + this.coverSource = new WeakReference<>(cover); + return cover; + } else { + // the cover doesn't exist, which makes no sense since we have a reference to its location but whatever + this.coverSource = null; + return null; + } + } else { + // the pipe doesn't exist, which makes no sense since the edge holding us exists but whatever + this.coverSource = null; + return null; + } + } else { + return ref; + } + } + + private @Nullable Cover getTarget() { + if (coverTarget == null) return null; + Cover ref = coverTarget.get(); + if (ref == null) { + World world = DimensionManager.getWorld(coverTargetPos.getDimension()); + if (world == null || !world.isBlockLoaded(coverTargetPos.getPos())) return null; + + TileEntity tile = world.getTileEntity(coverTargetPos.getPos()); + if (tile instanceof PipeTileEntity pipe) { + Cover cover = pipe.getCoverHolder().getCoverAtSide(coverTargetPos.getFacing()); + if (cover != null) { + this.coverTarget = new WeakReference<>(cover); + return cover; + } else { + // the cover doesn't exist, which makes no sense since we have a reference to its location but whatever + this.coverTarget = null; + return null; + } + } else { + // the pipe doesn't exist, which makes no sense since the edge holding us exists but whatever + this.coverTarget = null; + return null; + } + } else { + return ref; + } + } + + @Override + public @NotNull String getName() { + return "EdgeCoverReference"; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setLong("SourcePos", coverSourcePos.getPos().toLong()); + tag.setByte("SourceFacing", (byte) coverSourcePos.getFacing().ordinal()); + tag.setInteger("SourceDim", coverSourcePos.getDimension()); + tag.setLong("TargetPos", coverTargetPos.getPos().toLong()); + tag.setByte("TargetFacing", (byte) coverTargetPos.getFacing().ordinal()); + tag.setInteger("TargetDim", coverTargetPos.getDimension()); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + this.coverSourcePos = new DimensionFacingPos(BlockPos.fromLong(nbt.getLong("SourcePos")), + EnumFacing.VALUES[nbt.getByte("SourceFacing")], nbt.getInteger("SourceDim")); + this.coverSource = new WeakReference<>(null); + this.coverTargetPos = new DimensionFacingPos(BlockPos.fromLong(nbt.getLong("TargetPos")), + EnumFacing.VALUES[nbt.getByte("TargetFacing")], nbt.getInteger("TargetDim")); + this.coverTarget = coverSource; + } + + @Override + public EdgeCoverReferenceLogic getNew() { + return new EdgeCoverReferenceLogic(); + } + + // this logic never needs to be sent to the client, it is purely for graph calculations + @Override + public void encode(PacketBuffer buf, boolean fullChange) {} + + @Override + public void decode(PacketBuffer buf, boolean fullChange) {} + + public interface IThroughputLimiterCover extends Cover { + long getLimit(); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index 62a19e413da..97b4334c2c8 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -9,6 +9,10 @@ import gregtech.api.graphnet.pipenet.physical.IBurnable; +import gregtech.api.graphnet.traverse.util.CompleteLossOperator; + +import gregtech.api.graphnet.traverse.util.MultLossOperator; + import net.minecraft.block.state.IBlockState; import net.minecraft.nbt.NBTTagCompound; @@ -104,7 +108,7 @@ public NodeLossResult getLossResult(long tick) { } else { world.setBlockToAir(pos); } - }, l -> 0L); + }, CompleteLossOperator.INSTANCE); } else if (getPartialBurnTemperature() != null && getTemperature(tick) > getPartialBurnTemperature()) { return new NodeLossResult(n -> { World world = n.getNet().getWorld(); @@ -113,7 +117,7 @@ public NodeLossResult getLossResult(long tick) { if (state.getBlock() instanceof IBurnable burnable) { burnable.partialBurn(state, world, pos); } - }, l -> (long) (l * 0.5)); + }, new MultLossOperator(0.5)); } else { return null; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 9cf5a28d928..4ddbb92cb63 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -35,6 +35,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -552,4 +553,13 @@ public void markAsDirty() { node.getNet().updatePredication(node, this); } } + + public static @Nullable PipeTileEntity getTileNoLoading(BlockPos pos, int dimension) { + World world = DimensionManager.getWorld(dimension); + if (world == null || !world.isBlockLoaded(pos)) return null; + + TileEntity tile = world.getTileEntity(pos); + if (tile instanceof PipeTileEntity pipe) return pipe; + else return null; + } } diff --git a/src/main/java/gregtech/api/graphnet/predicate/ShutterPredicate.java b/src/main/java/gregtech/api/graphnet/pipenet/predicate/ShutterPredicate.java similarity index 78% rename from src/main/java/gregtech/api/graphnet/predicate/ShutterPredicate.java rename to src/main/java/gregtech/api/graphnet/pipenet/predicate/ShutterPredicate.java index f28fde26cdb..ba9ee9d08f3 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/ShutterPredicate.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/predicate/ShutterPredicate.java @@ -1,16 +1,12 @@ -package gregtech.api.graphnet.predicate; +package gregtech.api.graphnet.pipenet.predicate; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.common.covers.CoverShutter; - -import net.minecraft.nbt.NBTBase; -import net.minecraft.nbt.NBTTagByte; +import gregtech.api.graphnet.predicate.IEdgePredicate; import net.minecraft.nbt.NBTTagString; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public final class ShutterPredicate implements IEdgePredicate { @@ -31,7 +27,7 @@ public ShutterPredicate getNew() { @Override public NBTTagString serializeNBT() { - return new NBTTagString(""); + return new NBTTagString(); } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java b/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java index 9477056972a..1f195bb0764 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java @@ -45,11 +45,11 @@ public abstract class WorldPipeNetBase> backer; - WorldPipeNetBase(String name, boolean isDirected, - Function algorithmBuilder, - INetGraph graph) { + @SafeVarargs + WorldPipeNetBase(String name, boolean isDirected, INetGraph graph, + Function... algorithmBuilders) { super(name); - this.backer = new GraphNetBacker(this, algorithmBuilder, graph, this.needsDynamicWeights()); + this.backer = new GraphNetBacker(this, graph, algorithmBuilders); this.isDirected = isDirected; } @@ -63,7 +63,7 @@ public final boolean isDirected() { } protected void markAlgInvalid() { - this.backer.invalidateAlg(); + this.backer.invalidateAlgs(); } public World getWorld() { diff --git a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java index 09bacf5a552..205317e6e38 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java +++ b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java @@ -3,7 +3,7 @@ import gregtech.api.graphnet.gather.GTGraphGatherables; import gregtech.api.graphnet.gather.GatherPredicatesEvent; -import gregtech.api.graphnet.logic.INetLogicEntry; + import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; diff --git a/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java b/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java index 29e4b70fa44..eb86764f042 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java +++ b/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java @@ -6,7 +6,6 @@ import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Nullable; /** diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java index bfcf07f82ad..1e2746b44e3 100644 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java @@ -29,15 +29,16 @@ public abstract class ServerNet extends WorldSavedData implements IGraphNet { protected final GraphNetBacker backer; - public ServerNet(String name, Function algorithmBuilder, - Function graphBuilder, boolean dynamicWeights) { + @SafeVarargs + public ServerNet(String name, Function graphBuilder, + Function... algorithmBuilders) { super(name); - this.backer = new GraphNetBacker(this, algorithmBuilder, graphBuilder.apply(this), dynamicWeights); + this.backer = new GraphNetBacker(this, graphBuilder.apply(this), algorithmBuilders); } - public ServerNet(String name, Function algorithmBuilder, - boolean directed, boolean dynamicWeights) { - this(name, algorithmBuilder, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), dynamicWeights); + @SafeVarargs + public ServerNet(String name, boolean directed, Function... algorithmBuilders) { + this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), algorithmBuilders); } @Override diff --git a/src/main/java/gregtech/api/graphnet/traverse/DistributorHelper.java b/src/main/java/gregtech/api/graphnet/traverse/DistributorHelper.java new file mode 100644 index 00000000000..e983b449205 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/DistributorHelper.java @@ -0,0 +1,30 @@ +package gregtech.api.graphnet.traverse; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import java.util.List; +import java.util.function.LongSupplier; +import java.util.function.Supplier; + +public class DistributorHelper { + + private final long maximum; + private long consumption; + + public DistributorHelper(long maximum, long consumption) { + this.maximum = maximum; + this.consumption = consumption; + } + + public void addConsumption(long consumption) { + this.consumption += consumption; + } + + public boolean supportsMult(long mult) { + return this.maximum >= this.consumption * mult; + } + + public long withMult(long mult) { + return this.consumption * mult; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java new file mode 100644 index 00000000000..1fbfaf5cb1b --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java @@ -0,0 +1,21 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.path.INetPath; + +public interface IEqualizableTraverseData> { + + int getDestinationsAtNode(N node); + + /** + * Whether a path should be skipped before running the collection process on it. + * The return of {@link ITraverseData#prepareForPathWalk(INetPath)} will be ignored during traversal. + */ + boolean shouldSkipPath(P path); + + /** + * Should return how much flow the destination with the smallest maximum allowed flow among destinations at + * this node requires. + */ + long getMaxFlowToLeastDestination(N node); +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java new file mode 100644 index 00000000000..3200c345aca --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java @@ -0,0 +1,26 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.path.INetPath; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayDeque; +import java.util.LinkedHashSet; + +public interface IRoundRobinTraverseData> { + + /** + * The traversal cache must be cached and persistent between traversals, + * but not modified by anything external to {@link TraverseHelpers}. + * @return the traversal cache. + */ + @NotNull + ArrayDeque getTraversalCache(); + + /** + * Whether a path should be skipped before checking it against the round robin cache. + * The return of {@link ITraverseData#prepareForPathWalk(INetPath)} will be ignored during traversal. + */ + boolean shouldSkipPath(P path); +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java index 3294e6c183b..733f0fb7689 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java @@ -3,11 +3,12 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.path.INetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; + import org.jetbrains.annotations.Nullable; public interface ITraverseData> { @@ -32,9 +33,9 @@ public interface ITraverseData> { * * @param node the node being traversed * @param flowReachingNode the flow that has reached this node. - * @return the flow continuing onward after loss is applied. + * @return the loss operator for the node. */ - long traverseToNode(N node, long flowReachingNode); + ReversibleLossOperator traverseToNode(N node, long flowReachingNode); /** * Reports that the traverse has finished a path walk, for finalization. @@ -44,4 +45,14 @@ public interface ITraverseData> { * @return the amount of flow that should be consumed, before walking the next path. */ long finalizeAtDestination(N destination, long flowReachingDestination); + + /** + * Allows for reporting a smaller capacity along an edge than it actually has. Do not report a larger capacity + * than the actual edge or things will break. + * @param edge the edge to get capacity for. + * @return a non-negative capacity that is less than or equal to the true capacity of the edge. + */ + default long getFlowLimit(AbstractNetFlowEdge edge) { + return edge.getFlowLimit(this.getTestObject(), this.getGraphNet(), this.getQueryTick(), this.getSimulatorKey()); + } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index aa62dda90e9..c0d96228ad7 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -3,20 +3,28 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.util.FlowConsumerList; import gregtech.api.graphnet.path.INetPath; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import gregtech.api.graphnet.traverse.util.FlowConsumptionStack; +import gregtech.api.util.GTUtility; -import net.minecraftforge.fml.common.FMLCommonHandler; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jgrapht.alg.util.Pair; +import java.util.ArrayDeque; import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.function.Supplier; public final class TraverseHelpers { @@ -41,48 +49,37 @@ public static pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); - long pathFlowIn = availableFlow; long pathFlow = availableFlow; P path = paths.next(); if (data.prepareForPathWalk(path)) continue; List nodes = path.getOrderedNodes(); List edges = path.getOrderedEdges(); - FlowConsumerList flowConsumers = new FlowConsumerList(); assert nodes.size() == edges.size() + 1; - N targetNode = nodes.get(0); - pathFlow = data.traverseToNode(targetNode, pathFlow); + FlowConsumptionStack stack = new FlowConsumptionStack(data.traverseToNode(nodes.get(0), pathFlow)); + pathFlow = stack.applyLatestLossFunction(pathFlow); for (int i = 0; i < edges.size(); i++) { E edge = edges.get(i); - targetNode = nodes.get(i + 1); + N targetNode = nodes.get(i + 1); if (targetNode.traverse(data.getQueryTick(), true)) { if (!simulate) { - N finalTargetNode = targetNode; - pathTraverseCalls.add(() -> finalTargetNode.traverse(data.getQueryTick(), false)); + pathTraverseCalls.add(() -> targetNode.traverse(data.getQueryTick(), false)); } } else continue pathloop; - long flowLimit = edge.getFlowLimit(data.getTestObject(), data.getGraphNet(), data.getQueryTick(), data.getSimulatorKey()); - if (flowLimit < pathFlow) { - double ratio = (double) flowLimit / pathFlow; - flowConsumers.modifyRatios(ratio); - pathFlowIn *= ratio; - pathFlow = flowLimit; - } - flowConsumers.add(edge, data.getTestObject(), data.getGraphNet(), pathFlow, data.getQueryTick(), data.getSimulatorKey()); - pathFlow = data.traverseToNode(targetNode, pathFlow); - + pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); + stack.add(flow -> consumeFlowLimit(edge, data, flow), data.traverseToNode(targetNode, pathFlow)); + pathFlow = stack.applyLatestLossFunction(pathFlow); if (pathFlow <= 0) continue pathloop; } - long accepted = data.finalizeAtDestination(targetNode, pathFlow); - double ratio = (double) accepted / pathFlow; - flowConsumers.doConsumption(ratio); + + long accepted = data.finalizeAtDestination(nodes.get(nodes.size() - 1), pathFlow); if (!simulate) pathTraverseCalls.forEach(Runnable::run); - availableFlow -= pathFlowIn * ratio; + availableFlow -= stack.consumeWithEndValue(accepted); if (availableFlow <= 0) break; } @@ -90,6 +87,10 @@ public static data, long consumption) { + edge.consumeFlowLimit(data.getTestObject(), data.getGraphNet(), consumption, data.getQueryTick(), data.getSimulatorKey()); + } + /** * Provides logic for traversing a net that simply finds the lowest weight path that it can traverse, * and then traverses it. Optionally supports flow, in which case overflows will be reported @@ -108,66 +109,315 @@ public static , D @Nullable BiConsumer overflowListener, long flowIn) { boolean simulate = data.getSimulatorKey() != null; - boolean flow = overflowListener != null; - long availableFlow = flowIn; + boolean isFlow = overflowListener != null; + long availableFlow = isFlow ? flowIn : 0; pathloop: while (paths.hasNext()) { List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); - long pathFlowIn = availableFlow; - long pathFlow = availableFlow; + long pathFlow = isFlow ? availableFlow : 1; P path = paths.next(); if (data.prepareForPathWalk(path)) continue; List nodes = path.getOrderedNodes(); List edges = path.getOrderedEdges(); - FlowConsumerList flowConsumers = flow ? new FlowConsumerList() : null; - List> overflowReporters = flow ? new ObjectArrayList<>() : null; + List> overflowReporters = isFlow ? new ObjectArrayList<>() : null; assert nodes.size() == edges.size() + 1; - N targetNode = nodes.get(0); - pathFlow = data.traverseToNode(targetNode, pathFlow); + FlowConsumptionStack stack = isFlow ? new FlowConsumptionStack(data.traverseToNode(nodes.get(0), pathFlow)) : null; + if (isFlow) pathFlow = stack.applyLatestLossFunction(pathFlow); for (int i = 0; i < edges.size(); i++) { E edge = edges.get(i); - targetNode = nodes.get(i + 1); + N targetNode = nodes.get(i + 1); if (targetNode.traverse(data.getQueryTick(), true)) { if (!simulate) { - N finalTargetNode = targetNode; - pathTraverseCalls.add(() -> finalTargetNode.traverse(data.getQueryTick(), false)); + pathTraverseCalls.add(() -> targetNode.traverse(data.getQueryTick(), false)); } } else continue pathloop; - if (flow && edge instanceof AbstractNetFlowEdge flowEdge) { - long flowLimit = flowEdge.getFlowLimit(data.getTestObject(), data.getGraphNet(), data.getQueryTick(), data.getSimulatorKey()); - if (flowLimit < pathFlow) { - long overflow = pathFlow - flowLimit; - N finalTargetNode = targetNode; + if (isFlow) { + AbstractNetFlowEdge flowEdge = (AbstractNetFlowEdge) edge; + long limit = data.getFlowLimit(flowEdge); + if (pathFlow > limit) { + long overflow = pathFlow - limit; + pathFlow = limit; overflowReporters.add(reduction -> { long finalOverflow = overflow - reduction; - if (finalOverflow > 0) overflowListener.accept(finalTargetNode, finalOverflow); + if (finalOverflow > 0) overflowListener.accept(targetNode, finalOverflow); }); - pathFlow = flowLimit; } - flowConsumers.add(flowEdge, data.getTestObject(), data.getGraphNet(), pathFlow, data.getQueryTick(), data.getSimulatorKey()); + stack.add(flow -> consumeFlowLimit(flowEdge, data, flow), data.traverseToNode(targetNode, pathFlow)); + pathFlow = stack.applyLatestLossFunction(pathFlow); } - pathFlow = data.traverseToNode(targetNode, pathFlow); if (pathFlow <= 0) continue pathloop; } - long accepted = data.finalizeAtDestination(targetNode, pathFlow); + long accepted = data.finalizeAtDestination(nodes.get(edges.size()), pathFlow); long unaccepted = pathFlow - accepted; - if (flow) { - flowConsumers.doConsumption(unaccepted); + if (isFlow) { + availableFlow -= stack.consumeWithEndValue(accepted); overflowReporters.forEach((c) -> c.accept(unaccepted)); } if (!simulate) pathTraverseCalls.forEach(Runnable::run); - availableFlow -= pathFlowIn - unaccepted; if (availableFlow <= 0) break; } return flowIn - availableFlow; } + + /** + * Provides logic for traversing a flow net in an equal distribution manner. Operates in the following stages: + *

+ * Stage One (collection) -- collect paths into a list while iterating, gathering a map of edges to flow info. + * Get numbers for what is needed to provide 1 flow per node destination per path, ignoring potential loss. + * If a path cannot be traversed, it is either trimmed or we abort based on {@code strict}. + *

+ * Stage Two (scaling) -- scale up the mult with a binary search until we get the largest mult where no edge + * capacities are exceeded. If this mult is 0, abort and return 0. + *

+ * Stage Three (traversal) -- traverse the collected paths and perform consumption and flow, using the multiplier + * from stage two. + * + * @param data the traversal data. + * @param paths the paths to traverse. + * @param flowIn the flow to traverse with. + * @param strict whether to abort if one of the destination paths cannot be traversed due to node restrictions, + * not edge restrictions. + * @return the consumed flow. + */ + public static , D extends ITraverseData & IEqualizableTraverseData> long traverseEqualDistribution( + @NotNull D data, + @NotNull Iterator

paths, + long flowIn, + boolean strict) { + // collection + Map, DistributorHelper> distributorHelperMap = new Object2ObjectOpenHashMap<>(); + Object2IntOpenHashMap

desiredMap = new Object2IntOpenHashMap<>(); + int totalDesired = 0; + long maxMult = flowIn; + pathsloop: + while (paths.hasNext()) { + P path = paths.next(); + if (data.shouldSkipPath(path)) continue; + + List nodes = path.getOrderedNodes(); + List edges = path.getOrderedEdges(); + assert nodes.size() == edges.size() + 1; + for (N node : nodes) { + if (!node.traverse(data.getQueryTick(), true)) { + if (strict) return 0; + else continue pathsloop; + } + } + N dest = nodes.get(nodes.size() - 1); + int desired = data.getDestinationsAtNode(dest); + totalDesired += desired; + desiredMap.put(path, desired); + maxMult = Math.min(maxMult, data.getMaxFlowToLeastDestination(dest)); + for (int i = 0; i < edges.size(); i++) { + E edge = edges.get(i); + N targetNode = nodes.get(i + 1); + distributorHelperMap.compute(Pair.of(edge, targetNode), (k, v) -> { + if (v == null) { + v = new DistributorHelper(k.getFirst().getFlowLimit(data.getTestObject(), + data.getGraphNet(), data.getQueryTick(), data.getSimulatorKey()), desired); + return v; + } else { + v.addConsumption(desired); + return v; + } + }); + } + } + maxMult = Math.min(maxMult, flowIn / totalDesired); + // scaling + long mult = GTUtility.binarySearch(0, maxMult, l -> { + for (DistributorHelper helper : distributorHelperMap.values()) { + if (!helper.supportsMult(l)) return false; + } + return true; + }, false); + if (mult == 0) return 0; + // traversal + boolean simulate = data.getSimulatorKey() != null; + long availableFlow = flowIn; + pathloop: + for (var entry : desiredMap.object2IntEntrySet()) { + List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); + long pathFlow = entry.getIntValue() * mult; + P path = entry.getKey(); + + // no skipping paths at this stage + data.prepareForPathWalk(path); + + List nodes = path.getOrderedNodes(); + List edges = path.getOrderedEdges(); + assert nodes.size() == edges.size() + 1; + + FlowConsumptionStack stack = new FlowConsumptionStack(data.traverseToNode(nodes.get(0), pathFlow)); + pathFlow = stack.applyLatestLossFunction(pathFlow); + + for (int i = 0; i < edges.size(); i++) { + E edge = edges.get(i); + N targetNode = nodes.get(i + 1); + + if (targetNode.traverse(data.getQueryTick(), true)) { + if (!simulate) { + pathTraverseCalls.add(() -> targetNode.traverse(data.getQueryTick(), false)); + } + } else continue pathloop; + + pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); + stack.add(flow -> consumeFlowLimit(edge, data, flow), data.traverseToNode(targetNode, pathFlow)); + pathFlow = stack.applyLatestLossFunction(pathFlow); + + if (pathFlow <= 0) continue pathloop; + } + + long accepted = data.finalizeAtDestination(nodes.get(nodes.size() - 1), pathFlow); + if (!simulate) pathTraverseCalls.forEach(Runnable::run); + availableFlow -= stack.consumeWithEndValue(accepted); + + if (availableFlow <= 0) break; + } + + return flowIn - availableFlow; + } + + /** + * Provides logic for traversing a flow net in an equal distribution manner within a dynamic weights context. + * Calls {@link #traverseEqualDistribution(ITraverseData, Iterator, long, boolean)} repeatedly, using a fresh + * collection of paths from the {@code pathsSupplier} until + * {@link #traverseEqualDistribution(ITraverseData, Iterator, long, boolean)} returns 0 or 100 iterations are + * performed. + * + * @param data the traversal data. + * @param pathsSupplier the supplier for a fresh set of paths. + * @param flowIn the flow to traverse with. + * @param strict whether to abort if one of the destination paths cannot be traversed due to node restrictions, + * not edge restrictions. + * @return the consumed flow. + */ + public static , D extends ITraverseData & IEqualizableTraverseData> long traverseEqualDistribution( + @NotNull D data, + @NotNull Supplier> pathsSupplier, + long flowIn, + boolean strict) { + long availableFlow = flowIn; + byte iterationCount = 0; + while (iterationCount <= 100) { + iterationCount++; + Iterator

paths = pathsSupplier.get(); + long flow = traverseEqualDistribution(data, paths, availableFlow, strict); + if (flow == 0) break; + else availableFlow -= flow; + } + + return flowIn - availableFlow; + } + + /** + * Provides logic for traversing a flow net in a round robin manner. This implementation merely ensures that + * destinations will be walked to in a predictable manner through the use of a cache, any balancing must + * be done on the {@link ITraverseData}'s end. + * + * @param data the traversal data. + * @param paths the paths to traverse. + * @param flowIn the flow to traverse with. + * @param strict whether to abort if one of the destination paths cannot be traversed due to node restrictions, + * not edge restrictions. + * @return the consumed flow. + */ + public static , D extends ITraverseData & IRoundRobinTraverseData> long traverseRoundRobin( + @NotNull D data, + @NotNull Iterator

paths, + long flowIn, + boolean strict) { + long availableFlow = flowIn; + ArrayDeque cache = data.getTraversalCache(); + + Map skippedPaths = new Object2ObjectOpenHashMap<>(); + while (paths.hasNext()) { + P path = paths.next(); + N destinationNode = path.getTargetNode(); + if (data.shouldSkipPath(path)) continue; + + N nextUp = cache.peekFirst(); + if (destinationNode.equals(nextUp)) { + // path is next up in the ordering, we can traverse. + cache.removeFirst(); + cache.addLast(destinationNode); + long accepted = rrTraverse(data, path, availableFlow, strict); + if (accepted == -1) return flowIn - availableFlow; + else availableFlow -= accepted; + } else { + // this path isn't the next one up, skip it unless it's a completely new destination. + if (cache.contains(destinationNode)) skippedPaths.put(destinationNode, path); + else { + cache.addLast(destinationNode); + long accepted = rrTraverse(data, path, availableFlow, strict); + if (accepted == -1) return flowIn - availableFlow; + else availableFlow -= accepted; + } + } + } + // finally, try and work through skipped paths + while (true) { + P path = skippedPaths.get(cache.peekFirst()); + if (path == null) break; + N dest = cache.removeFirst(); + skippedPaths.remove(dest); + cache.addLast(dest); + long accepted = rrTraverse(data, path, availableFlow, strict); + if (accepted == -1) return flowIn - availableFlow; + else availableFlow -= accepted; + } + + return flowIn - availableFlow; + } + + private static , D extends ITraverseData & IRoundRobinTraverseData> long rrTraverse( + @NotNull D data, + @NotNull P path, + long flowIn, + boolean strict) { + + boolean simulate = data.getSimulatorKey() != null; + List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); + long pathFlow = flowIn; + + data.prepareForPathWalk(path); + + List nodes = path.getOrderedNodes(); + List edges = path.getOrderedEdges(); + assert nodes.size() == edges.size() + 1; + + FlowConsumptionStack stack = new FlowConsumptionStack(data.traverseToNode(nodes.get(0), pathFlow)); + pathFlow = stack.applyLatestLossFunction(pathFlow); + + for (int i = 0; i < edges.size(); i++) { + E edge = edges.get(i); + N targetNode = nodes.get(i + 1); + + if (targetNode.traverse(data.getQueryTick(), true)) { + if (!simulate) { + pathTraverseCalls.add(() -> targetNode.traverse(data.getQueryTick(), false)); + } + } else return strict ? -1 : 0; + + pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); + stack.add(flow -> consumeFlowLimit(edge, data, flow), data.traverseToNode(targetNode, pathFlow)); + pathFlow = stack.applyLatestLossFunction(pathFlow); + + if (pathFlow <= 0) return 0; + } + + long accepted = data.finalizeAtDestination(nodes.get(nodes.size() - 1), pathFlow); + if (!simulate) pathTraverseCalls.forEach(Runnable::run); + + return stack.consumeWithEndValue(accepted); + } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/CompleteLossOperator.java b/src/main/java/gregtech/api/graphnet/traverse/util/CompleteLossOperator.java new file mode 100644 index 00000000000..5f9ca222104 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/util/CompleteLossOperator.java @@ -0,0 +1,17 @@ +package gregtech.api.graphnet.traverse.util; + +public class CompleteLossOperator implements ReversibleLossOperator { + public static final CompleteLossOperator INSTANCE = new CompleteLossOperator(); + + private CompleteLossOperator() {} + + @Override + public double applyLoss(double value) { + return 0; + } + + @Override + public double undoLoss(double value) { + return 0; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/FlatLossOperator.java b/src/main/java/gregtech/api/graphnet/traverse/util/FlatLossOperator.java new file mode 100644 index 00000000000..b53ca293d37 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/util/FlatLossOperator.java @@ -0,0 +1,21 @@ +package gregtech.api.graphnet.traverse.util; + +public class FlatLossOperator implements ReversibleLossOperator { + + private final double loss; + + public FlatLossOperator(double loss) { + assert loss > 0; + this.loss = loss; + } + + @Override + public double applyLoss(double value) { + return value - loss; + } + + @Override + public double undoLoss(double value) { + return value + loss; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java b/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java new file mode 100644 index 00000000000..04a5b5ad6f7 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java @@ -0,0 +1,48 @@ +package gregtech.api.graphnet.traverse.util; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import java.util.List; +import java.util.function.LongConsumer; + +public class FlowConsumptionStack { + + private final List flowConsumers = new ObjectArrayList<>(); + + private final List operators = new ObjectArrayList<>(); + + private final ReversibleLossOperator initialOperator; + + public FlowConsumptionStack() { + this.initialOperator = IdentityLossOperator.INSTANCE; + } + + public FlowConsumptionStack(ReversibleLossOperator initialOperator) { + this.initialOperator = initialOperator; + } + + public long applyLatestLossFunction(long value) { + if (operators.isEmpty()) return (long) Math.floor(initialOperator.applyLoss(value)); + else return (long) Math.floor(operators.get(operators.size() - 1).applyLoss(value)); + } + + public void add(LongConsumer flowConsumer, ReversibleLossOperator postLoss) { + flowConsumers.add(flowConsumer); + operators.add(postLoss); + } + + /** + * Walks backwards along the loss operators and applies consumption to flow consumers. + * @param endValue the target end value + * @return the value that needs to be pushed into the start of the stack to achieve the end value. + */ + public long consumeWithEndValue(long endValue) { + double value = endValue; + for (int i = operators.size() - 1; i >= 0; i--) { + ReversibleLossOperator operator = operators.get(i); + value = operator.undoLoss(value); + flowConsumers.get(i).accept((long) Math.ceil(value)); + } + return (long) Math.ceil(initialOperator.undoLoss(value)); + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/IdentityLossOperator.java b/src/main/java/gregtech/api/graphnet/traverse/util/IdentityLossOperator.java new file mode 100644 index 00000000000..b0f8d105566 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/util/IdentityLossOperator.java @@ -0,0 +1,17 @@ +package gregtech.api.graphnet.traverse.util; + +public class IdentityLossOperator implements ReversibleLossOperator { + public static final IdentityLossOperator INSTANCE = new IdentityLossOperator(); + + private IdentityLossOperator() {} + + @Override + public double applyLoss(double value) { + return value; + } + + @Override + public double undoLoss(double value) { + return value; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java b/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java new file mode 100644 index 00000000000..8b43231f425 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java @@ -0,0 +1,21 @@ +package gregtech.api.graphnet.traverse.util; + +public class MultLossOperator implements ReversibleLossOperator { + + private final double mult; + + public MultLossOperator(double mult) { + assert mult > 0 && mult <= 1; + this.mult = mult; + } + + @Override + public double applyLoss(double value) { + return value * mult; + } + + @Override + public double undoLoss(double value) { + return value / mult; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/ReversibleLossOperator.java b/src/main/java/gregtech/api/graphnet/traverse/util/ReversibleLossOperator.java new file mode 100644 index 00000000000..b6d860bd402 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/util/ReversibleLossOperator.java @@ -0,0 +1,8 @@ +package gregtech.api.graphnet.traverse.util; + +public interface ReversibleLossOperator { + + double applyLoss(double value); + + double undoLoss(double value); +} diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java index 7cdbc5573cf..a5421758e65 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -34,16 +34,16 @@ public abstract class WorldNet extends WorldSavedData implements IGraphNet, Gene protected final GraphNetBacker backer; private World world; - public WorldNet(String name, Function algorithmBuilder, - Function graphBuilder) { + @SafeVarargs + public WorldNet(String name, Function graphBuilder, + Function... algorithmBuilders) { super(name); - this.backer = new GraphNetBacker(this, algorithmBuilder, graphBuilder.apply(this)); + this.backer = new GraphNetBacker(this, graphBuilder.apply(this), algorithmBuilders); } - public WorldNet(String name, Function algorithmBuilder, - boolean directed) { - this(name, algorithmBuilder, - directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder()); + @SafeVarargs + public WorldNet(String name, boolean directed, Function... algorithmBuilders) { + this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), algorithmBuilders); } public void setWorld(World world) { @@ -57,7 +57,7 @@ public World getWorld() { @Override public Iterator getPaths(NetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { nodeClassCheck(node); - return backer.getPaths(node, GenericGraphNetPath.MAPPER, testObject, simulator, queryTick); + return backer.getPaths(node, 0, GenericGraphNetPath.MAPPER, testObject, simulator, queryTick); } @NotNull diff --git a/src/main/java/gregtech/api/util/DimensionFacingPos.java b/src/main/java/gregtech/api/util/DimensionFacingPos.java new file mode 100644 index 00000000000..223c6be1f88 --- /dev/null +++ b/src/main/java/gregtech/api/util/DimensionFacingPos.java @@ -0,0 +1,47 @@ +package gregtech.api.util; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +import java.util.Objects; + +public class DimensionFacingPos { + + private final BlockPos pos; + private final EnumFacing facing; + private final int dimension; + private final int hashCode; + + public DimensionFacingPos(BlockPos pos, EnumFacing facing, int dimension) { + this.pos = pos; + this.facing = facing; + this.dimension = dimension; + this.hashCode = Objects.hash(pos, facing, dimension); + } + + public int getDimension() { + return dimension; + } + + public EnumFacing getFacing() { + return facing; + } + + public BlockPos getPos() { + return pos; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DimensionFacingPos that = (DimensionFacingPos) o; + return dimension == that.dimension && Objects.equals(pos, that.pos) && + facing == that.facing; + } + + @Override + public int hashCode() { + return hashCode; + } +} diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 9da695d5db8..bfc228bc3c1 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -75,6 +75,7 @@ import java.util.function.BooleanSupplier; import java.util.function.DoubleSupplier; import java.util.function.Function; +import java.util.function.LongPredicate; import java.util.function.Predicate; import static gregtech.api.GTValues.V; @@ -904,4 +905,17 @@ public static double geometricMean(double first, double... numbers) { public static EntityPlayer getSP() { return Minecraft.getMinecraft().player; } + + public static long binarySearch(long minValue, long maxValue, LongPredicate test, boolean ascending) { + while (maxValue - minValue > 1) { + long middle = (minValue + maxValue) / 2; + // XOR + if (test.test(middle) ^ !ascending) { + maxValue = middle; + } else { + minValue = maxValue; + } + } + return ascending ? maxValue : minValue; + } } diff --git a/src/main/java/gregtech/common/covers/CoverShutter.java b/src/main/java/gregtech/common/covers/CoverShutter.java index 9c228ecbf53..00807fc0d95 100644 --- a/src/main/java/gregtech/common/covers/CoverShutter.java +++ b/src/main/java/gregtech/common/covers/CoverShutter.java @@ -5,7 +5,6 @@ import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.predicate.ShutterPredicate; import gregtech.client.renderer.texture.Textures; import net.minecraft.entity.player.EntityPlayer; @@ -23,9 +22,6 @@ import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; public class CoverShutter extends CoverBase implements IControllable { diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeFluidProperties.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeFluidProperties.java deleted file mode 100644 index 85326b150f5..00000000000 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeFluidProperties.java +++ /dev/null @@ -1,4 +0,0 @@ -package gregtech.common.pipelike.block.pipe; - -public class PipeFluidProperties { -} diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeItemProperties.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeItemProperties.java deleted file mode 100644 index e0c457ebf86..00000000000 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeItemProperties.java +++ /dev/null @@ -1,4 +0,0 @@ -package gregtech.common.pipelike.block.pipe; - -public class PipeItemProperties { -} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index fc5e52f2992..644e73f76af 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -7,7 +7,6 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.edge.util.FlowConsumer; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; @@ -67,20 +66,17 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage if (limit <= 0) return 0; long availableAmperage = Math.min(amperage, limit); - FlowConsumer consumer = new FlowConsumer(internalBuffer, IPredicateTestObject.INSTANCE, net, availableAmperage, - tick, simulator); EnergyTraverseData data = new EnergyTraverseData(net, IPredicateTestObject.INSTANCE, simulator, tick, voltage, tile.getPos(), side); availableAmperage -= TraverseHelpers.traverseFlood(data, getPaths(data), amperage); if (availableAmperage > 0) { - TraverseHelpers.traverseDumb(data, getPaths(data), data::handleOverflow, availableAmperage); + availableAmperage -= TraverseHelpers.traverseDumb(data, getPaths(data), data::handleOverflow, availableAmperage); } data.runPostActions(); - - consumer.finalReduction(availableAmperage); - long accepted = amperage - availableAmperage; + + internalBuffer.consumeFlowLimit(IPredicateTestObject.INSTANCE, net, accepted, tick, simulator); if (!simulate) { EnergyGroupData group = getEnergyData(); if (group != null) { diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index 53b2c59957d..68442d79c96 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -11,6 +11,9 @@ import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.AbstractTraverseData; +import gregtech.api.graphnet.traverse.util.FlatLossOperator; +import gregtech.api.graphnet.traverse.util.IdentityLossOperator; +import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; import gregtech.api.util.GTUtility; import gregtech.common.pipelikeold.cable.net.EnergyGroupData; @@ -20,7 +23,6 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import java.util.List; import java.util.function.Supplier; public class EnergyTraverseData extends AbstractTraverseData { @@ -54,7 +56,7 @@ public boolean prepareForPathWalk(FlowWorldPipeNetPath path) { } @Override - public long traverseToNode(WorldPipeNetNode node, long flowReachingNode) { + public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowReachingNode) { VoltageLimitLogic limitLogic = node.getData().getLogicEntryNullable(VoltageLimitLogic.INSTANCE); if (limitLogic != null) { long voltage = limitLogic.getValue(); @@ -65,7 +67,7 @@ public long traverseToNode(WorldPipeNetNode node, long flowReachingNode) { NodeLossResult result = lossCache.get(node); if (result != null) { - return result.applyLossFunction(flowReachingNode); + return result.getLossFunction(); } else { TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); result = temperatureLogic == null ? null : temperatureLogic.getLossResult(getQueryTick()); @@ -73,12 +75,12 @@ public long traverseToNode(WorldPipeNetNode node, long flowReachingNode) { if (node.getData().getLogicEntryDefaultable(SuperconductorLogic.INSTANCE) .canSuperconduct(temperatureLogic == null ? TemperatureLogic.DEFAULT_TEMPERATURE : temperatureLogic.getTemperature(getQueryTick()))) { - return flowReachingNode; + return IdentityLossOperator.INSTANCE; } - return flowReachingNode - node.getData().getLogicEntryDefaultable(LossAbsoluteLogic.INSTANCE).getValue(); + return new FlatLossOperator(node.getData().getLogicEntryDefaultable(LossAbsoluteLogic.INSTANCE).getValue()); } if (result.hasPostAction()) lossCache.put(node, result); - return result.applyLossFunction(flowReachingNode); + return result.getLossFunction(); } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java index b7fe53717df..603dcb837cc 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java @@ -2,7 +2,6 @@ import gregtech.api.capability.GregtechCapabilities; import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; @@ -39,7 +38,12 @@ public static WorldEnergyNet getWorldNet(World world) { } public WorldEnergyNet(String name) { - super(name, DynamicWeightsShortestPathsAlgorithm::new, false); + super(name, false, DynamicWeightsShortestPathsAlgorithm::new); + } + + @Override + public boolean usesDynamicWeights(int algorithmID) { + return true; } @Override @@ -54,7 +58,7 @@ public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { @Override public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { - return backer.getPaths(node, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); + return backer.getPaths(node, 0, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 538e24567e2..55b70709a65 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -1,6 +1,5 @@ package gregtech.common.pipelike.net.fluid; -import gregtech.api.capability.GregtechCapabilities; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.graphnet.edge.NetFlowEdge; @@ -10,8 +9,6 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.common.pipelike.net.energy.EnergyCapabilityObject; -import gregtech.common.pipelike.net.energy.WorldEnergyNet; import gregtech.common.pipelike.net.item.WorldItemNet; @@ -42,7 +39,12 @@ public static WorldFluidNet getWorldNet(World world) { } public WorldFluidNet(String name) { - super(name, DynamicWeightsShortestPathsAlgorithm::new, false); + super(name, false, DynamicWeightsShortestPathsAlgorithm::new); + } + + @Override + public boolean usesDynamicWeights(int algorithmID) { + return true; } @Override @@ -62,7 +64,7 @@ public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { @Override public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { - return backer.getPaths(node, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); + return backer.getPaths(node, 0, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 562cb5f2083..51d6e28de96 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -14,7 +14,6 @@ import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.items.CapabilityItemHandler; @@ -40,7 +39,12 @@ public static WorldItemNet getWorldNet(World world) { } public WorldItemNet(String name) { - super(name, DynamicWeightsShortestPathsAlgorithm::new, false); + super(name, false, DynamicWeightsShortestPathsAlgorithm::new); + } + + @Override + public boolean usesDynamicWeights(int algorithmID) { + return true; } @Override @@ -60,11 +64,11 @@ public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { @Override public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { - return backer.getPaths(node, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); + return backer.getPaths(node, 0, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); } @Override public @NotNull NetFlowEdge getNewEdge() { - return new NetFlowEdge(10); + return new NetFlowEdge(5, 4); } } diff --git a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java index 5548a3321bf..4afd7138770 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java @@ -9,7 +9,6 @@ import gregtech.api.graphnet.pipenetold.NodeLossResult; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.edge.util.FlowConsumerList; import gregtech.api.util.FacingPos; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java index d09612c6293..8b44ebf32eb 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java @@ -7,7 +7,6 @@ import gregtech.api.graphnet.pipenetold.NodeLossResult; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.edge.util.FlowConsumerList; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.covers.CoverFluidRegulator; From f8c591dc981695f6e6ad2c487aae21df02a00f12 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 25 Jul 2024 20:56:28 -0600 Subject: [PATCH 078/157] Complete rewrite pt5 --- .../api/block/UnlistedByteProperty.java | 36 +++ .../api/block/UnlistedFloatProperty.java | 36 +++ .../api/block/UnlistedPropertyMaterial.java | 37 +++ .../graphnet/pipenet/WorldPipeNetNode.java | 29 ++- .../pipenet/physical/IPipeStructure.java | 4 + .../physical/block/PipeMaterialBlock.java | 35 +-- .../physical/block/WorldPipeBlock.java | 43 +++- .../pipenet/physical/tile/IActivable.java | 8 + .../tile/PipeActivableTileEntity.java | 31 +++ .../physical/tile/PipeMaterialTileEntity.java | 17 ++ .../pipenet/physical/tile/PipeTileEntity.java | 77 +++++- .../graphnet/pipenetold/IBlockAppearance.java | 2 +- .../block/material/BlockMaterialPipe.java | 2 +- .../api/unification/material/Material.java | 2 +- .../java/gregtech/api/util/GTUtility.java | 13 + .../java/gregtech/client/ClientProxy.java | 23 +- .../renderer/pipe/AbstractPipeModel.java | 172 +++++++++++++ .../renderer/pipe/ActivablePipeModel.java | 134 ++++++++++ .../client/renderer/pipe/CableModel.java | 106 ++++++++ .../client/renderer/pipe/PipeItemModel.java | 65 +++++ .../client/renderer/pipe/PipeModel.java | 126 ++++++++++ .../renderer/pipe/cache/ActivableSQC.java | 75 ++++++ .../renderer/pipe/cache/BlockableSQC.java | 73 ++++++ .../renderer/pipe/cache/ColorQuadCache.java | 42 ++++ .../renderer/pipe/cache/ExtraCappedSQC.java | 71 ++++++ .../renderer/pipe/cache/RestrictiveSQC.java | 78 ++++++ .../pipe/cache/StructureQuadCache.java | 127 ++++++++++ .../renderer/pipe/quad/PipeQuadHelper.java | 234 ++++++++++++++++++ .../pipe/quad/RecolorableBakedQuad.java | 188 ++++++++++++++ .../client/renderer/pipe/quad/UVCorner.java | 14 ++ .../client/renderer/pipe/quad/UVMapper.java | 21 ++ .../renderer/pipe/util/ActivableCacheKey.java | 17 ++ .../client/renderer/pipe/util/CacheKey.java | 47 ++++ .../pipe/util/PipeSpriteWoodClarifier.java | 14 ++ .../renderer/pipe/util/SpriteInformation.java | 11 + .../pipe/util/SpriteInformationWrapper.java | 34 +++ .../renderer/pipe/util/WoodCacheKey.java | 40 +++ .../{pipe => pipeold}/CableRenderer.java | 2 +- .../{pipe => pipeold}/FluidPipeRenderer.java | 2 +- .../{pipe => pipeold}/ItemPipeRenderer.java | 2 +- .../{pipe => pipeold}/LaserPipeRenderer.java | 2 +- .../OpticalPipeRenderer.java | 2 +- .../{pipe => pipeold}/PipeRenderer.java | 2 +- .../client/renderer/texture/Textures.java | 203 ++++++++------- .../gregtech/common/blocks/MetaBlocks.java | 83 ++++--- .../pipelike/block/cable/CableBlock.java | 6 - .../pipelike/block/cable/CableStructure.java | 41 +-- .../pipelike/block/laser/LaserPipeBlock.java | 44 ++++ .../pipelike/block/laser/LaserStructure.java | 48 ++++ .../block/optical/OpticalPipeBlock.java | 43 ++++ .../block/optical/OpticalStructure.java | 50 ++++ .../common/pipelike/block/pipe/PipeBlock.java | 6 - .../pipelike/block/pipe/PipeStructure.java | 71 ++++-- .../pipelike/handlers/LaserNetHandler.java | 45 ++++ .../MaterialEnergyProperties.java | 15 +- .../MaterialFluidProperties.java | 15 +- .../MaterialItemProperties.java | 28 +-- .../pipelike/handlers/OpticalNetHandler.java | 44 ++++ .../pipelike/net/item/WorldItemNet.java | 2 +- .../pipelike/net/laser/WorldLaserNet.java | 54 ++++ .../pipelike/net/optical/WorldOpticalNet.java | 60 +++++ .../common/pipelikeold/cable/BlockCable.java | 4 +- .../pipelikeold/fluidpipe/BlockFluidPipe.java | 4 +- .../pipelikeold/itempipe/BlockItemPipe.java | 4 +- .../pipelikeold/laser/BlockLaserPipe.java | 2 +- .../pipelikeold/optical/BlockOpticalPipe.java | 2 +- .../material/MaterialPropertyExpansion.java | 2 +- .../groovy/MaterialPropertyExpansion.java | 2 +- .../recipe/handlers/PartsRecipeHandler.java | 2 +- .../recipe/handlers/WireCombiningHandler.java | 3 +- .../recipe/handlers/WireRecipeHandler.java | 4 +- .../{insulation_5.png => insulation_full.png} | Bin 72 files changed, 2690 insertions(+), 293 deletions(-) create mode 100644 src/main/java/gregtech/api/block/UnlistedByteProperty.java create mode 100644 src/main/java/gregtech/api/block/UnlistedFloatProperty.java create mode 100644 src/main/java/gregtech/api/block/UnlistedPropertyMaterial.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IActivable.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/CableModel.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/PipeModel.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java rename src/main/java/gregtech/client/renderer/{pipe => pipeold}/CableRenderer.java (99%) rename src/main/java/gregtech/client/renderer/{pipe => pipeold}/FluidPipeRenderer.java (98%) rename src/main/java/gregtech/client/renderer/{pipe => pipeold}/ItemPipeRenderer.java (98%) rename src/main/java/gregtech/client/renderer/{pipe => pipeold}/LaserPipeRenderer.java (99%) rename src/main/java/gregtech/client/renderer/{pipe => pipeold}/OpticalPipeRenderer.java (98%) rename src/main/java/gregtech/client/renderer/{pipe => pipeold}/PipeRenderer.java (99%) create mode 100644 src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java create mode 100644 src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java create mode 100644 src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java create mode 100644 src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java create mode 100644 src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java rename src/main/java/gregtech/common/pipelike/{properties => handlers}/MaterialEnergyProperties.java (97%) rename src/main/java/gregtech/common/pipelike/{properties => handlers}/MaterialFluidProperties.java (92%) rename src/main/java/gregtech/common/pipelike/{properties => handlers}/MaterialItemProperties.java (75%) create mode 100644 src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java create mode 100644 src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java create mode 100644 src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java rename src/main/resources/assets/gregtech/textures/blocks/cable/{insulation_5.png => insulation_full.png} (100%) diff --git a/src/main/java/gregtech/api/block/UnlistedByteProperty.java b/src/main/java/gregtech/api/block/UnlistedByteProperty.java new file mode 100644 index 00000000000..5e90f08b40a --- /dev/null +++ b/src/main/java/gregtech/api/block/UnlistedByteProperty.java @@ -0,0 +1,36 @@ +package gregtech.api.block; + +import net.minecraftforge.common.property.IUnlistedProperty; + +import org.jetbrains.annotations.NotNull; + +public class UnlistedByteProperty implements IUnlistedProperty { + + private final String name; + + public UnlistedByteProperty(@NotNull String name) { + this.name = name; + } + + @NotNull + @Override + public String getName() { + return this.name; + } + + @Override + public boolean isValid(Byte value) { + return true; + } + + @NotNull + @Override + public Class getType() { + return Byte.class; + } + + @Override + public String valueToString(@NotNull Byte value) { + return value.toString(); + } +} diff --git a/src/main/java/gregtech/api/block/UnlistedFloatProperty.java b/src/main/java/gregtech/api/block/UnlistedFloatProperty.java new file mode 100644 index 00000000000..e35f2e1a396 --- /dev/null +++ b/src/main/java/gregtech/api/block/UnlistedFloatProperty.java @@ -0,0 +1,36 @@ +package gregtech.api.block; + +import net.minecraftforge.common.property.IUnlistedProperty; + +import org.jetbrains.annotations.NotNull; + +public class UnlistedFloatProperty implements IUnlistedProperty { + + private final String name; + + public UnlistedFloatProperty(@NotNull String name) { + this.name = name; + } + + @NotNull + @Override + public String getName() { + return this.name; + } + + @Override + public boolean isValid(Float value) { + return true; + } + + @NotNull + @Override + public Class getType() { + return Float.class; + } + + @Override + public String valueToString(@NotNull Float value) { + return value.toString(); + } +} diff --git a/src/main/java/gregtech/api/block/UnlistedPropertyMaterial.java b/src/main/java/gregtech/api/block/UnlistedPropertyMaterial.java new file mode 100644 index 00000000000..df9efb767e1 --- /dev/null +++ b/src/main/java/gregtech/api/block/UnlistedPropertyMaterial.java @@ -0,0 +1,37 @@ +package gregtech.api.block; + +import gregtech.api.unification.material.Material; + +import net.minecraftforge.common.property.IUnlistedProperty; + +import org.jetbrains.annotations.NotNull; + +public class UnlistedPropertyMaterial implements IUnlistedProperty { + + private final String name; + + public UnlistedPropertyMaterial(@NotNull String name) { + this.name = name; + } + + @NotNull + @Override + public String getName() { + return name; + } + + @Override + public boolean isValid(Material value) { + return true; + } + + @Override + public Class getType() { + return Material.class; + } + + @Override + public String valueToString(Material value) { + return value.toString(); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java index 2fc4b2aff25..bca18bf5ce9 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java @@ -4,22 +4,47 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.worldnet.WorldNetNode; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + import org.jetbrains.annotations.Nullable; +import java.lang.ref.WeakReference; + public final class WorldPipeNetNode extends WorldNetNode { @Nullable MultiNodeHelper overlapHelper; + private WeakReference tileReference; + public WorldPipeNetNode(WorldPipeNet net) { super(net); } public PipeTileEntity getTileEntity() { - // should this be cached? It's only ever used for active nodes when they are being targeted by a path traversal. - return (PipeTileEntity) getNet().getWorld().getTileEntity(getEquivalencyData()); + return getTileEntity(true); + } + + @Nullable + public PipeTileEntity getTileEntityNoLoading() { + return getTileEntity(false); + } + + private PipeTileEntity getTileEntity(boolean allowLoading) { + if (tileReference != null) { + PipeTileEntity tile = tileReference.get(); + if (tile != null) return tile; + } + World world = getNet().getWorld(); + if (!allowLoading && !world.isBlockLoaded(getEquivalencyData())) return null; + TileEntity tile = world.getTileEntity(getEquivalencyData()); + if (tile instanceof PipeTileEntity pipe) { + this.tileReference = new WeakReference<>(pipe); + return pipe; + } else return null; } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java index 9c25ed6fdbc..b1bce3c0ecc 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java @@ -2,6 +2,8 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.client.renderer.pipe.AbstractPipeModel; + import net.minecraft.util.EnumFacing; import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.AxisAlignedBB; @@ -19,6 +21,8 @@ public interface IPipeStructure extends IStringSerializable { boolean isPaintable(); + AbstractPipeModel getModel(); + /** * Allows for controlling what sides can be connected to based on current connections, * such as in the case of optical and laser pipes. diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index c4807c0a1c4..52190ce8753 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -17,7 +17,10 @@ import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.ModelBakery; import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -31,6 +34,11 @@ import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -56,6 +64,7 @@ public ItemStack getItem(@NotNull Material material) { return new ItemStack(this, 1, registry.getIDForObject(material)); } + @Nullable public Material getMaterialForStack(@NotNull ItemStack stack) { return registry.getObjectById(stack.getMetadata()); } @@ -76,23 +85,6 @@ public ItemStack getDrop(IBlockAccess world, BlockPos pos, IBlockState state) { return Materials.Aluminium.getProperty(PropertyKey.PIPENET_PROPERTIES); } - /** - * to do {@link MetaBlocks#registerStateMappers()} - */ - public void onModelRegister() { - // TODO rendering - ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(this), stack -> getPipeRenderer().getModelLocation()); - for (IBlockState state : this.getBlockState().getValidStates()) { - ModelResourceLocation resourceLocation = new ModelResourceLocation( - new ResourceLocation(GTValues.MODID, // force pipe models to always be GT's - Objects.requireNonNull(this.getRegistryName()).getPath()), - MetaBlocks.statePropertiesToString(state.getProperties())); - // noinspection ConstantConditions - ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(this), - this.getMetaFromState(state), resourceLocation); - } - } - // tile entity // @Override @@ -114,4 +106,13 @@ public void onModelRegister() { public @NotNull PipeTileEntity createTileEntity(@NotNull World world, @NotNull IBlockState state) { return new PipeMaterialTileEntity(this); } + + @Override + protected Pair getParticleTexture(World world, BlockPos blockPos) { + PipeMaterialTileEntity tile = getTileEntity(world, blockPos); + if (tile != null) { + return ImmutablePair.of(getStructure().getModel().getParticleTexture(tile.getMaterial()), tile.getPaintingColor()); + } + return null; + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java index 85bbfbe8af7..3ca8ea1e76b 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java @@ -18,13 +18,14 @@ import gregtech.common.blocks.BlockFrame; +import gregtech.common.creativetab.GTCreativeTabs; + import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.block.Block; import net.minecraft.block.SoundType; import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; @@ -32,6 +33,7 @@ import net.minecraft.item.EnumDyeColor; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.NonNullList; import net.minecraft.util.math.AxisAlignedBB; @@ -41,11 +43,11 @@ import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fml.common.FMLCommonHandler; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -71,6 +73,7 @@ public WorldPipeBlock(IPipeStructure structure) { setResistance(3.0f); setLightOpacity(0); disableStats(); + setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); } public IPipeStructure getStructure() { @@ -196,13 +199,27 @@ public boolean recolorBlock(@NotNull World world, @NotNull BlockPos pos, @NotNul if (getStructure().isPaintable()) { PipeTileEntity tile = getTileEntity(world, pos); if (tile != null && tile.getPaintingColor() != color.colorValue) { - tile.setPaintingColor(color.colorValue); + tile.setPaintingColor(color.colorValue, false); return true; } } return false; } + @Override + public boolean canRenderInLayer(@NotNull IBlockState state, @NotNull BlockRenderLayer layer) { + return getStructure().getModel().canRenderInLayer(layer); + } + + @Override + protected Pair getParticleTexture(World world, BlockPos blockPos) { + PipeTileEntity tile = getTileEntity(world, blockPos); + if (tile != null) { + return ImmutablePair.of(getStructure().getModel().getParticleTexture(), tile.getPaintingColor()); + } + return null; + } + // collision boxes // @SuppressWarnings("deprecation") @@ -271,6 +288,12 @@ public boolean isPipeItem(ItemStack stack) { return stack.getItem() instanceof ItemPipeBlock block && this.getClass().isInstance(block.getBlock()); } + @Nullable + public static WorldPipeBlock getBlockFromItem(@NotNull ItemStack stack) { + if (stack.getItem() instanceof ItemPipeBlock block) return block.getBlock(); + else return null; + } + public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, ItemStack stack) { if (isPipeTool(stack)) return true; @@ -292,6 +315,14 @@ public boolean isPipeTool(@NotNull ItemStack stack) { // tile entity // + @Override + public @NotNull IBlockState getExtendedState(@NotNull IBlockState state, @NotNull IBlockAccess world, + @NotNull BlockPos pos) { + PipeTileEntity tile = getTileEntity(world, pos); + if (tile == null) return state; + else return tile.getRenderInformation((IExtendedBlockState) state); + } + @Override public boolean hasTileEntity(@NotNull IBlockState state) { return true; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IActivable.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IActivable.java new file mode 100644 index 00000000000..10bf362dee5 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IActivable.java @@ -0,0 +1,8 @@ +package gregtech.api.graphnet.pipenet.physical.tile; + +public interface IActivable { + + void setActive(boolean active); + + boolean isActive(); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java new file mode 100644 index 00000000000..227537c3ded --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java @@ -0,0 +1,31 @@ +package gregtech.api.graphnet.pipenet.physical.tile; + +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; + +import gregtech.client.renderer.pipe.ActivablePipeModel; + +import net.minecraftforge.common.property.IExtendedBlockState; + +public class PipeActivableTileEntity extends PipeTileEntity implements IActivable { + + private boolean active; + + public PipeActivableTileEntity(WorldPipeBlock block) { + super(block); + } + + @Override + public void setActive(boolean active) { + this.active = active; + } + + @Override + public boolean isActive() { + return active; + } + + @Override + public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { + return super.getRenderInformation(state).withProperty(ActivablePipeModel.ACTIVE_PROPERTY, isActive()); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java index 53a3e9c5bf8..a33e5bf1d12 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java @@ -5,9 +5,16 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; +import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.util.GTUtility; + +import gregtech.client.renderer.pipe.PipeModel; + import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraftforge.common.property.IExtendedBlockState; + import org.jetbrains.annotations.NotNull; public class PipeMaterialTileEntity extends PipeTileEntity { @@ -37,4 +44,14 @@ public Material getMaterial() { if (material == null) return Materials.Aluminium; return material; } + + @Override + public int getDefaultPaintingColor() { + return GTUtility.convertRGBtoARGB(getMaterial().getMaterialRGB()); + } + + @Override + public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { + return super.getRenderInformation(state).withProperty(PipeModel.MATERIAL_PROPERTY, getMaterial()); + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 4ddbb92cb63..962c7508007 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -18,6 +18,7 @@ import gregtech.client.particle.GTOverheatParticle; +import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.common.blocks.MetaBlocks; import net.minecraft.block.state.IBlockState; @@ -37,6 +38,7 @@ import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; @@ -49,11 +51,12 @@ import java.util.Map; import java.util.Set; -import static gregtech.api.capability.GregtechDataCodes.UPDATE_PAINT; -import static gregtech.api.capability.GregtechDataCodes.UPDATE_PIPE_LOGIC; +import static gregtech.api.capability.GregtechDataCodes.*; public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITickable { + public static final int DEFAULT_COLOR = 0xFFFFFFFF; + private final Object2ObjectOpenHashMap netLogicDatas = new Object2ObjectOpenHashMap<>(); private final ObjectOpenHashSet listeners = new ObjectOpenHashSet<>(); @@ -68,7 +71,7 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick private int paintingColor; - private Material frameMaterial; + private @Nullable Material frameMaterial; private final Set tickers = new ObjectOpenHashSet<>(); @@ -129,12 +132,22 @@ public void setConnected(EnumFacing facing, boolean renderClosed) { } else { this.renderMask &= ~(1 << facing.ordinal()); } + syncConnected(); } public void setDisconnected(EnumFacing facing) { this.connectionMask &= ~(1 << facing.ordinal()); this.renderMask &= ~(1 << facing.ordinal()); updateActiveStatus(facing, false); + syncConnected(); + } + + private void syncConnected() { + writeCustomData(UPDATE_CONNECTIONS, buffer -> { + buffer.writeByte(connectionMask); + buffer.writeByte(renderMask); + }); + markDirty(); } public boolean isConnected(EnumFacing facing) { @@ -151,10 +164,17 @@ public byte getConnectionMask() { public void setBlocked(EnumFacing facing) { this.blockedMask |= 1 << facing.ordinal(); + syncBlocked(); } public void setUnblocked(EnumFacing facing) { this.blockedMask &= ~(1 << facing.ordinal()); + syncBlocked(); + } + + private void syncBlocked() { + writeCustomData(UPDATE_BLOCKED_CONNECTIONS, buffer -> buffer.writeByte(blockedMask)); + markDirty(); } public boolean isBlocked(EnumFacing facing) { @@ -171,10 +191,13 @@ public int getPaintingColor() { return isPainted() ? paintingColor : getDefaultPaintingColor(); } - public void setPaintingColor(int paintingColor) { + public void setPaintingColor(int paintingColor, boolean alphaSensitive) { + if (!alphaSensitive) { + paintingColor |= 0xFF000000; + } this.paintingColor = paintingColor; if (!getWorld().isRemote) { - writeCustomData(UPDATE_PAINT, buffer -> buffer.writeInt(paintingColor)); + writeCustomData(UPDATE_PAINT, buffer -> buffer.writeInt(this.paintingColor)); markDirty(); } } @@ -184,16 +207,25 @@ public boolean isPainted() { } public int getDefaultPaintingColor() { - return 0xFFFFFF; + return DEFAULT_COLOR; } // frame // - public void setFrameMaterial(Material frameMaterial) { + public void setFrameMaterial(@Nullable Material frameMaterial) { this.frameMaterial = frameMaterial; + syncFrameMaterial(); } - public Material getFrameMaterial() { + private void syncFrameMaterial() { + writeCustomData(UPDATE_FRAME_MATERIAL, buffer -> { + if (frameMaterial != null) buffer.writeString(this.frameMaterial.getRegistryName()); + else buffer.writeString(""); + }); + markDirty(); + } + + public @Nullable Material getFrameMaterial() { return frameMaterial; } @@ -406,7 +438,7 @@ protected void initialize(World worldIn) { compound.setByte("ConnectionMask", connectionMask); compound.setByte("BlockedMask", blockedMask); compound.setInteger("Paint", paintingColor); - compound.setString("Frame", frameMaterial.getRegistryName()); + if (frameMaterial != null) compound.setString("Frame", frameMaterial.getRegistryName()); compound.setTag("Covers", getCoverHolder().serializeNBT()); return compound; } @@ -417,7 +449,8 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { connectionMask = compound.getByte("ConnectionMask"); blockedMask = compound.getByte("BlockedMask"); paintingColor = compound.getInteger("Paint"); - this.frameMaterial = GregTechAPI.materialManager.getMaterial(compound.getString("Frame")); + if (compound.hasKey("Frame")) this.frameMaterial = GregTechAPI.materialManager.getMaterial(compound.getString("Frame")); + else this.frameMaterial = null; this.getCoverHolder().deserializeNBT(compound.getCompoundTag("Covers")); } @@ -479,6 +512,15 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { } } } + } else if (discriminator == UPDATE_CONNECTIONS) { + this.connectionMask = buf.readByte(); + this.renderMask = buf.readByte(); + } else if (discriminator == UPDATE_BLOCKED_CONNECTIONS) { + this.blockedMask = buf.readByte(); + } else if (discriminator == UPDATE_FRAME_MATERIAL) { + String name = buf.readString(255); + if (name.equals("")) this.frameMaterial = null; + else this.frameMaterial = GregTechAPI.materialManager.getMaterial(name); } else if (discriminator == UPDATE_PAINT) { this.paintingColor = buf.readInt(); } else { @@ -562,4 +604,19 @@ public void markAsDirty() { if (tile instanceof PipeTileEntity pipe) return pipe; else return null; } + + public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { + byte frameMask = 0; + for (EnumFacing facing : EnumFacing.VALUES) { + if (getCoverHolder().hasCover(facing)) frameMask |= 1 << facing.ordinal(); + } + frameMask = (byte) ~frameMask; + return state.withProperty(AbstractPipeModel.THICKNESS_PROPERTY, this.getStructure().getRenderThickness()) + .withProperty(AbstractPipeModel.CONNECTION_MASK_PROPERTY, connectionMask) + .withProperty(AbstractPipeModel.CLOSED_MASK_PROPERTY, renderMask) + .withProperty(AbstractPipeModel.BLOCKED_MASK_PROPERTY, blockedMask) + .withProperty(AbstractPipeModel.COLOR_PROPERTY, getPaintingColor()) + .withProperty(AbstractPipeModel.FRAME_MATERIAL_PROPERTY, frameMaterial) + .withProperty(AbstractPipeModel.FRAME_MASK_PROPERTY, frameMask); + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/IBlockAppearance.java b/src/main/java/gregtech/api/graphnet/pipenetold/IBlockAppearance.java index 02bac4c2521..380b3cda974 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/IBlockAppearance.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/IBlockAppearance.java @@ -28,7 +28,7 @@ public interface IBlockAppearance { IBlockState getVisualState(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull EnumFacing side); /** - * This function returns whether the block's renderer will visually connect to other blocks implementing + * This function returns whether the block's model will visually connect to other blocks implementing * IBlockAppearance. */ boolean supportsVisualConnections(); diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/BlockMaterialPipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/BlockMaterialPipe.java index 8099e34b9bb..18e1237e3d6 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/BlockMaterialPipe.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/BlockMaterialPipe.java @@ -11,7 +11,7 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.unification.ore.OrePrefix; -import gregtech.client.renderer.pipe.PipeRenderer; +import gregtech.client.renderer.pipeold.PipeRenderer; import gregtech.common.blocks.MetaBlocks; import net.minecraft.block.state.IBlockState; diff --git a/src/main/java/gregtech/api/unification/material/Material.java b/src/main/java/gregtech/api/unification/material/Material.java index e88bb48d7d6..ef61dc804fa 100644 --- a/src/main/java/gregtech/api/unification/material/Material.java +++ b/src/main/java/gregtech/api/unification/material/Material.java @@ -18,7 +18,7 @@ import gregtech.api.util.LocalizationUtils; import gregtech.api.util.SmallDigits; -import gregtech.common.pipelike.properties.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.MaterialEnergyProperties; import net.minecraft.enchantment.Enchantment; import net.minecraft.util.ResourceLocation; diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index bfc228bc3c1..a4367b9255c 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -918,4 +918,17 @@ public static long binarySearch(long minValue, long maxValue, LongPredicate test } return ascending ? maxValue : minValue; } + + public static int[] convertARGBtoArray(int argb) { + int a = argb >> 24 & 255; + int r = argb >> 16 & 255; + int g = argb >> 8 & 255; + int b = argb & 255; + return new int[] {a, r, g, b}; + } + + @Contract(pure = true) + public static boolean evalMask(@NotNull EnumFacing facing, byte mask) { + return (mask & (1 << facing.ordinal())) > 0; + } } diff --git a/src/main/java/gregtech/client/ClientProxy.java b/src/main/java/gregtech/client/ClientProxy.java index 7fb4773d478..4f406755bc7 100644 --- a/src/main/java/gregtech/client/ClientProxy.java +++ b/src/main/java/gregtech/client/ClientProxy.java @@ -15,12 +15,9 @@ import gregtech.client.model.customtexture.MetadataSectionCTM; import gregtech.client.renderer.handler.FacadeRenderer; import gregtech.client.renderer.handler.MetaTileEntityRenderer; -import gregtech.client.renderer.pipe.CableRenderer; -import gregtech.client.renderer.pipe.FluidPipeRenderer; -import gregtech.client.renderer.pipe.ItemPipeRenderer; -import gregtech.client.renderer.pipe.LaserPipeRenderer; -import gregtech.client.renderer.pipe.OpticalPipeRenderer; -import gregtech.client.renderer.pipe.PipeRenderer; +import gregtech.client.renderer.pipe.ActivablePipeModel; +import gregtech.client.renderer.pipe.CableModel; +import gregtech.client.renderer.pipe.PipeModel; import gregtech.client.utils.ItemRenderCompat; import gregtech.client.utils.TooltipHelper; import gregtech.common.CommonProxy; @@ -46,6 +43,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.client.event.ModelBakeEvent; import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.Constants; @@ -86,14 +84,8 @@ public void onPreLoad() { } MetaTileEntityRenderer.preInit(); - CableRenderer.INSTANCE.preInit(); - FluidPipeRenderer.INSTANCE.preInit(); - ItemPipeRenderer.INSTANCE.preInit(); - OpticalPipeRenderer.INSTANCE.preInit(); - LaserPipeRenderer.INSTANCE.preInit(); MetaEntities.initRenderers(); TextureUtils.addIconRegister(GTFluidRegistration.INSTANCE::registerSprites); - TextureUtils.addIconRegister(PipeRenderer::initializeRestrictor); } @Override @@ -116,6 +108,13 @@ public static void registerColors() { ToolItems.registerColors(); } + @SubscribeEvent + public static void registerBakedModels(ModelBakeEvent event) { + PipeModel.registerModels(event.getModelRegistry()); + CableModel.registerModels(event.getModelRegistry()); + ActivablePipeModel.registerModels(event.getModelRegistry()); + } + @SubscribeEvent public static void registerModels(ModelRegistryEvent event) { MetaBlocks.registerStateMappers(); diff --git a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java new file mode 100644 index 00000000000..fe58561fee6 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java @@ -0,0 +1,172 @@ +package gregtech.client.renderer.pipe; + +import gregtech.api.block.UnlistedByteProperty; +import gregtech.api.block.UnlistedFloatProperty; +import gregtech.api.block.UnlistedIntegerProperty; +import gregtech.api.block.UnlistedPropertyMaterial; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.info.MaterialIconType; +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.cache.ColorQuadCache; +import gregtech.client.renderer.pipe.cache.StructureQuadCache; +import gregtech.client.renderer.pipe.quad.PipeQuadHelper; + +import gregtech.client.renderer.pipe.util.CacheKey; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemOverrideList; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumFacing; + +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; +import net.minecraftforge.client.MinecraftForgeClient; +import net.minecraftforge.common.property.IExtendedBlockState; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +@SideOnly(Side.CLIENT) +public abstract class AbstractPipeModel implements IBakedModel { + + public static UnlistedFloatProperty THICKNESS_PROPERTY = new UnlistedFloatProperty("thickness"); + + public static UnlistedPropertyMaterial FRAME_MATERIAL_PROPERTY = new UnlistedPropertyMaterial("frame_material"); + public static UnlistedByteProperty FRAME_MASK_PROPERTY = new UnlistedByteProperty("frame_mask"); + + public static UnlistedByteProperty CONNECTION_MASK_PROPERTY = new UnlistedByteProperty("connection_mask"); + public static UnlistedByteProperty CLOSED_MASK_PROPERTY = new UnlistedByteProperty("closed_mask"); + public static UnlistedByteProperty BLOCKED_MASK_PROPERTY = new UnlistedByteProperty("blocked_mask"); + public static UnlistedIntegerProperty COLOR_PROPERTY = new UnlistedIntegerProperty("color"); + + private static final List EMPTY = new ArrayList<>(); + + protected final Object2ObjectOpenHashMap frameCache = new Object2ObjectOpenHashMap<>(); + protected final Object2ObjectOpenHashMap pipeCache = new Object2ObjectOpenHashMap<>(); + + private final ModelResourceLocation loc; + + public AbstractPipeModel(ModelResourceLocation loc) { + this.loc = loc; + } + + @Override + public @NotNull List getQuads(IBlockState state, EnumFacing side, long rand) { + if (state instanceof IExtendedBlockState ext) { + K key = toKey(ext); + Material frameMaterial = ext.getValue(FRAME_MATERIAL_PROPERTY); + byte frameMask = ext.getValue(FRAME_MASK_PROPERTY); + return getQuads(key, ext.getValue(CONNECTION_MASK_PROPERTY), ext.getValue(CLOSED_MASK_PROPERTY), + ext.getValue(BLOCKED_MASK_PROPERTY), ext.getValue(COLOR_PROPERTY), frameMaterial, frameMask); + } + return EMPTY; + } + + public @NotNull List getQuads(K key, byte connectionMask, byte closedMask, byte blockedMask, int argb, + @Nullable Material frameMaterial, byte frameMask) { + List quads = new ObjectArrayList<>(); + + StructureQuadCache cache = pipeCache.get(key); + if (cache == null) { + cache = constructForKey(key); + pipeCache.put(key, cache); + } + cache.addToList(quads, connectionMask, closedMask, + blockedMask, argb); + + if (frameMaterial != null) { + ResourceLocation rl = MaterialIconType.frameGt.getBlockTexturePath(frameMaterial.getMaterialIconSet()); + ColorQuadCache frame = frameCache.get(rl); + if (frame == null) { + frame = new ColorQuadCache(PipeQuadHelper + .createFrame(Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(rl.toString()))); + frameCache.put(rl, frame); + } + List frameQuads = frame.getQuads(GTUtility.convertRGBtoARGB(frameMaterial.getMaterialRGB())); + for (int i = 0; i < 6; i++) { + if ((frameMask & (1 << i)) > 0) { + quads.add(frameQuads.get(i)); + } + } + } + return quads; + } + + protected abstract @NotNull K toKey(@NotNull IExtendedBlockState state); + + protected final @NotNull CacheKey defaultKey(@NotNull IExtendedBlockState state) { + return new CacheKey(state.getValue(THICKNESS_PROPERTY)); + } + + protected abstract StructureQuadCache constructForKey(K key); + + public @NotNull TextureAtlasSprite getParticleTexture(Material material) { + return getParticleTexture(); + } + + @Override + public boolean isAmbientOcclusion() { + return false; + } + + @Override + public boolean isGui3d() { + return true; + } + + @Override + public boolean isBuiltInRenderer() { + return false; + } + + public ModelResourceLocation getLoc() { + return loc; + } + + @Nullable + protected abstract PipeItemModel getItemModel(@NotNull ItemStack stack, World world, EntityLivingBase entity); + + @Override + public @NotNull ItemOverrideList getOverrides() { + return FakeItemOverrideList.INSTANCE; + } + + public boolean canRenderInLayer(BlockRenderLayer layer) { + return layer == BlockRenderLayer.CUTOUT_MIPPED; + } + + protected static BlockRenderLayer getCurrentRenderLayer() { + return MinecraftForgeClient.getRenderLayer(); + } + + protected static class FakeItemOverrideList extends ItemOverrideList { + public static final FakeItemOverrideList INSTANCE = new FakeItemOverrideList(); + + @Override + public @NotNull IBakedModel handleItemState(@NotNull IBakedModel originalModel, @NotNull ItemStack stack, World world, + EntityLivingBase entity) { + if (originalModel instanceof AbstractPipeModel model) { + PipeItemModel item = model.getItemModel(stack, world, entity); + if (item != null) return item; + } + return originalModel; + } + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java new file mode 100644 index 00000000000..c1fefff4e73 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java @@ -0,0 +1,134 @@ +package gregtech.client.renderer.pipe; + +import gregtech.api.block.UnlistedBooleanProperty; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.unification.material.Material; +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.cache.ActivableSQC; +import gregtech.client.renderer.pipe.cache.StructureQuadCache; +import gregtech.client.renderer.pipe.quad.PipeQuadHelper; +import gregtech.client.renderer.pipe.util.ActivableCacheKey; +import gregtech.client.renderer.pipe.util.CacheKey; + +import gregtech.client.renderer.pipe.util.SpriteInformation; + +import gregtech.client.renderer.texture.Textures; + +import gregtech.client.utils.BloomEffectUtil; + +import gregtech.common.ConfigHolder; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.IRegistry; +import net.minecraft.world.World; +import net.minecraftforge.common.property.IExtendedBlockState; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.function.Supplier; + +public class ActivablePipeModel extends AbstractPipeModel { + + public static final UnlistedBooleanProperty ACTIVE_PROPERTY = new UnlistedBooleanProperty("active"); + + public static final ActivablePipeModel OPTICAL = new ActivablePipeModel(Textures.OPTICAL_PIPE_IN, + Textures.OPTICAL_PIPE_SIDE, Textures.OPTICAL_PIPE_SIDE_OVERLAY, Textures.OPTICAL_PIPE_SIDE_OVERLAY_ACTIVE, + false, "optical"); + public static final ActivablePipeModel LASER = new ActivablePipeModel(Textures.LASER_PIPE_IN, + Textures.LASER_PIPE_SIDE, Textures.LASER_PIPE_OVERLAY, Textures.LASER_PIPE_OVERLAY_EMISSIVE, + true, "laser"); + + private static final ResourceLocation loc = GTUtility.gregtechId("block/pipe_activable"); + + private final Supplier inTex; + private final Supplier sideTex; + private final Supplier overlayTex; + private final Supplier overlayActiveTex; + + private final boolean emissiveActive; + + public ActivablePipeModel(@NotNull Supplier inTex, @NotNull Supplier sideTex, + @NotNull Supplier overlayTex, + @NotNull Supplier overlayActiveTex, boolean emissiveActive, + String variant) { + super(new ModelResourceLocation(loc, variant)); + this.inTex = inTex; + this.sideTex = sideTex; + this.overlayTex = overlayTex; + this.overlayActiveTex = overlayActiveTex; + this.emissiveActive = emissiveActive; + } + + @Override + public @NotNull List getQuads(ActivableCacheKey key, byte connectionMask, byte closedMask, + byte blockedMask, int argb, @Nullable Material frameMaterial, + byte frameMask) { + boolean bloomLayer = getCurrentRenderLayer() == BloomEffectUtil.getEffectiveBloomLayer(); + // don't render the main shape to the bloom layer + List quads = bloomLayer ? new ObjectArrayList<>() : + super.getQuads(key, connectionMask, closedMask, blockedMask, argb, frameMaterial, frameMask); + + if (!bloomLayer && (!key.isActive() || !allowActive())) { + ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, argb, false); + } else { + if (emissiveActive && bloomLayer) { + ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, argb, true); + } else if (!emissiveActive && getCurrentRenderLayer() == BlockRenderLayer.CUTOUT_MIPPED) { + ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, argb, true); + } + } + return quads; + } + + @Override + public @NotNull TextureAtlasSprite getParticleTexture() { + return sideTex.get().sprite(); + } + + @Override + protected @NotNull ActivableCacheKey toKey(@NotNull IExtendedBlockState state) { + return new ActivableCacheKey(state.getValue(THICKNESS_PROPERTY), state.getValue(ACTIVE_PROPERTY)); + } + + @Override + protected StructureQuadCache constructForKey(ActivableCacheKey key) { + return ActivableSQC.create(PipeQuadHelper.create(key.getThickness()), inTex.get(), sideTex.get(), overlayTex.get(), overlayActiveTex.get()); + } + + @Override + public boolean canRenderInLayer(BlockRenderLayer layer) { + return layer == BlockRenderLayer.CUTOUT_MIPPED || (allowActive() && emissiveActive && layer == BloomEffectUtil.getEffectiveBloomLayer()); + } + + public boolean allowActive() { + return !ConfigHolder.client.preventAnimatedCables; + } + + @Override + protected @Nullable PipeItemModel getItemModel(@NotNull ItemStack stack, World world, + EntityLivingBase entity) { + WorldPipeBlock block = WorldPipeBlock.getBlockFromItem(stack); + if (block == null) return null; + return new PipeItemModel<>(this, new ActivableCacheKey(block.getStructure().getRenderThickness(), false), PipeTileEntity.DEFAULT_COLOR); + } + + public static void registerModels(IRegistry registry) { + registry.putObject(OPTICAL.getLoc(), OPTICAL); + registry.putObject(LASER.getLoc(), LASER); + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/CableModel.java b/src/main/java/gregtech/client/renderer/pipe/CableModel.java new file mode 100644 index 00000000000..7afb06f71c7 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/CableModel.java @@ -0,0 +1,106 @@ +package gregtech.client.renderer.pipe; + +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.cache.ExtraCappedSQC; +import gregtech.client.renderer.pipe.cache.StructureQuadCache; + +import gregtech.client.renderer.pipe.quad.PipeQuadHelper; +import gregtech.client.renderer.pipe.util.CacheKey; +import gregtech.client.renderer.pipe.util.SpriteInformation; +import gregtech.client.renderer.pipe.util.WoodCacheKey; +import gregtech.client.renderer.texture.Textures; + +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.IRegistry; +import net.minecraft.world.World; +import net.minecraftforge.common.property.IExtendedBlockState; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +@SideOnly(Side.CLIENT) +public class CableModel extends AbstractPipeModel { + + public static final CableModel INSTANCE = new CableModel("wire"); + public static final CableModel[] INSULATED_INSTANCES = new CableModel[Textures.INSULATION.length]; + + private static final ResourceLocation loc = GTUtility.gregtechId("block/cable"); + + static { + for (int i = 0; i < INSULATED_INSTANCES.length; i++) { + INSULATED_INSTANCES[i] = new CableModel(Textures.INSULATION[i], Textures.INSULATION_FULL, "insulated_" + i); + } + } + + private final Supplier wireTex; + private final Supplier insulationTex; + private final Supplier fullInsulationTex; + + public CableModel(@NotNull Supplier wireTex, @Nullable Supplier insulationTex, + @Nullable Supplier fullInsulationTex, String variant) { + super(new ModelResourceLocation(loc, variant)); + this.wireTex = wireTex; + this.insulationTex = insulationTex; + this.fullInsulationTex = fullInsulationTex; + } + + public CableModel(@Nullable Supplier insulationTex, + @Nullable Supplier fullInsulationTex, String variant) { + this(Textures.WIRE, insulationTex, fullInsulationTex, variant); + } + + public CableModel(String variant) { + this(null, null, variant); + } + + @Override + public @NotNull TextureAtlasSprite getParticleTexture() { + return wireTex.get().sprite(); + } + + @Override + protected @NotNull CacheKey toKey(@NotNull IExtendedBlockState state) { + return defaultKey(state); + } + + @Override + protected StructureQuadCache constructForKey(CacheKey key) { + SpriteInformation sideTex = fullInsulationTex != null ? fullInsulationTex.get() : wireTex.get(); + if (insulationTex == null) { + return StructureQuadCache.create(PipeQuadHelper.create(key.getThickness()), wireTex.get(), sideTex); + } else { + return ExtraCappedSQC.create(PipeQuadHelper.create(key.getThickness()), wireTex.get(), sideTex, insulationTex.get()); + } + } + + @Override + protected @Nullable PipeItemModel getItemModel(@NotNull ItemStack stack, World world, + EntityLivingBase entity) { + WorldPipeBlock block = WorldPipeBlock.getBlockFromItem(stack); + if (block == null) return null; + Material mater = block instanceof PipeMaterialBlock mat ? mat.getMaterialForStack(stack) : null; + return new PipeItemModel<>(this, new CacheKey(block.getStructure().getRenderThickness()), mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : PipeTileEntity.DEFAULT_COLOR); + } + + public static void registerModels(IRegistry registry) { + registry.putObject(INSTANCE.getLoc(), INSTANCE); + for (CableModel model : INSULATED_INSTANCES) { + registry.putObject(model.getLoc(), model); + } + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java new file mode 100644 index 00000000000..6d9f1b8cb59 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java @@ -0,0 +1,65 @@ +package gregtech.client.renderer.pipe; + +import com.github.bsideup.jabel.Desugar; + +import gregtech.client.renderer.pipe.AbstractPipeModel; + +import gregtech.client.renderer.pipe.util.CacheKey; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemOverrideList; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.util.EnumFacing; + +import net.minecraft.util.IStringSerializable; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Objects; + +public class PipeItemModel implements IBakedModel { + + private final AbstractPipeModel basis; + private final K key; + private final int argb; + + public PipeItemModel(AbstractPipeModel basis, K key, int argb) { + this.basis = basis; + this.key = key; + this.argb = argb; + } + + @Override + public @NotNull List getQuads(IBlockState state, EnumFacing side, long rand) { + return basis.getQuads(key, (byte) 0b1100, (byte) 0b0, (byte) 0b0, argb, null, (byte) 0b0); + } + + @Override + public boolean isAmbientOcclusion() { + return basis.isAmbientOcclusion(); + } + + @Override + public boolean isGui3d() { + return basis.isGui3d(); + } + + @Override + public boolean isBuiltInRenderer() { + return false; + } + + @Override + public @NotNull TextureAtlasSprite getParticleTexture() { + return basis.getParticleTexture(); + } + + @Override + public @NotNull ItemOverrideList getOverrides() { + return ItemOverrideList.NONE; + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java new file mode 100644 index 00000000000..07855a74462 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java @@ -0,0 +1,126 @@ +package gregtech.client.renderer.pipe; + +import gregtech.api.block.UnlistedPropertyMaterial; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.cache.BlockableSQC; +import gregtech.client.renderer.pipe.cache.RestrictiveSQC; +import gregtech.client.renderer.pipe.cache.StructureQuadCache; +import gregtech.client.renderer.pipe.quad.PipeQuadHelper; +import gregtech.client.renderer.pipe.util.PipeSpriteWoodClarifier; +import gregtech.client.renderer.pipe.util.WoodCacheKey; +import gregtech.client.renderer.texture.Textures; + +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.IRegistry; +import net.minecraft.world.World; +import net.minecraftforge.common.property.IExtendedBlockState; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +@SideOnly(Side.CLIENT) +public class PipeModel extends AbstractPipeModel { + + public static final UnlistedPropertyMaterial MATERIAL_PROPERTY = new UnlistedPropertyMaterial("material"); + + public static final PipeModel[] INSTANCES = new PipeModel[7]; + public static final PipeModel[] RESTRICTIVE_INSTANCES = new PipeModel[INSTANCES.length]; + + private static final ResourceLocation loc = GTUtility.gregtechId("block/pipe_material"); + + static { + model(0, wood -> Textures.PIPE_TINY.get()); + model(1, wood -> wood ? Textures.PIPE_SMALL_WOOD.get() : Textures.PIPE_SMALL.get()); + model(2, wood -> wood ? Textures.PIPE_NORMAL_WOOD.get() : Textures.PIPE_NORMAL.get()); + model(3, wood -> wood ? Textures.PIPE_LARGE_WOOD.get() : Textures.PIPE_LARGE.get()); + model(4, wood -> Textures.PIPE_HUGE.get()); + model(5, wood -> Textures.PIPE_QUADRUPLE.get()); + model(6, wood -> Textures.PIPE_NONUPLE.get()); + } + + private static void model(int i, PipeSpriteWoodClarifier clarifier) { + INSTANCES[i] = new PipeModel(clarifier, false, i + "_standard"); + RESTRICTIVE_INSTANCES[i] = new PipeModel(clarifier, true, i + "_restrictive"); + } + + private final @NotNull PipeSpriteWoodClarifier inTex; + private final @NotNull PipeSpriteWoodClarifier sideTex; + private final @Nullable PipeSpriteWoodClarifier restrictiveTex; + private final @NotNull PipeSpriteWoodClarifier blockedTex; + + public PipeModel(@NotNull PipeSpriteWoodClarifier inTex, @NotNull PipeSpriteWoodClarifier sideTex, + @Nullable PipeSpriteWoodClarifier restrictiveTex, + @NotNull PipeSpriteWoodClarifier blockedTex, String variant) { + super(new ModelResourceLocation(loc, variant)); + this.inTex = inTex; + this.sideTex = sideTex; + this.restrictiveTex = restrictiveTex; + this.blockedTex = blockedTex; + } + + public PipeModel(@NotNull PipeSpriteWoodClarifier inTex, @NotNull PipeSpriteWoodClarifier sideTex, + boolean restrictive, String variant) { + this(inTex, sideTex, restrictive ? wood -> Textures.RESTRICTIVE_OVERLAY.get() : null, + wood -> Textures.PIPE_BLOCKED_OVERLAY_UP.get(), variant); + } + + public PipeModel(@NotNull PipeSpriteWoodClarifier inTex, boolean restrictive, String variant) { + this(inTex, wood -> wood ? Textures.PIPE_SIDE_WOOD.get() : Textures.PIPE_SIDE.get(), restrictive, variant); + } + + @Override + public @NotNull TextureAtlasSprite getParticleTexture() { + return sideTex.getSprite(false).sprite(); + } + + public @NotNull TextureAtlasSprite getParticleTexture(Material material) { + return sideTex.getSprite(material.hasProperty(PropertyKey.WOOD)).sprite(); + } + + @Override + protected @NotNull WoodCacheKey toKey(@NotNull IExtendedBlockState state) { + return new WoodCacheKey(state.getValue(THICKNESS_PROPERTY), + state.getValue(MATERIAL_PROPERTY).hasProperty(PropertyKey.WOOD)); + } + + @Override + protected StructureQuadCache constructForKey(WoodCacheKey key) { + if (restrictiveTex != null) { + return RestrictiveSQC.create(PipeQuadHelper.create(key.getThickness()), inTex.getSprite(key.isWood()), + sideTex.getSprite(key.isWood()), blockedTex.getSprite(key.isWood()), + restrictiveTex.getSprite(key.isWood())); + } else { + return BlockableSQC.create(PipeQuadHelper.create(key.getThickness()), inTex.getSprite(key.isWood()), + sideTex.getSprite(key.isWood()), blockedTex.getSprite(key.isWood())); + } + } + + @Override + @Nullable + protected PipeItemModel getItemModel(@NotNull ItemStack stack, World world, EntityLivingBase entity) { + WorldPipeBlock block = WorldPipeBlock.getBlockFromItem(stack); + if (block == null) return null; + Material mater = null; + boolean wood = block instanceof PipeMaterialBlock mat && (mater = mat.getMaterialForStack(stack)) != null && + mater.hasProperty(PropertyKey.WOOD); + return new PipeItemModel<>(this, new WoodCacheKey(block.getStructure().getRenderThickness(), wood), mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : PipeTileEntity.DEFAULT_COLOR); + } + + public static void registerModels(IRegistry registry) { + for (PipeModel model : INSTANCES) { + registry.putObject(model.getLoc(), model); + } + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java new file mode 100644 index 00000000000..ef25c17a481 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java @@ -0,0 +1,75 @@ +package gregtech.client.renderer.pipe.cache; + +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.quad.PipeQuadHelper; +import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; +import gregtech.client.renderer.pipe.util.SpriteInformation; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.util.EnumFacing; + +import org.jetbrains.annotations.NotNull; + +import java.util.EnumMap; +import java.util.List; + +public class ActivableSQC extends StructureQuadCache { + + protected final EnumMap overlayCoords = new EnumMap<>(EnumFacing.class); + protected final EnumMap overlayActiveCoords = new EnumMap<>(EnumFacing.class); + + protected final SpriteInformation overlayTex; + protected final SpriteInformation overlayActiveTex; + + protected ActivableSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, + SpriteInformation overlayTex, SpriteInformation overlayActiveTex) { + super(helper, endTex, sideTex); + this.overlayTex = overlayTex; + this.overlayActiveTex = overlayActiveTex; + } + + public static @NotNull ActivableSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation overlayTex, SpriteInformation overlayActiveTex) { + ActivableSQC cache = new ActivableSQC(helper, endTex, sideTex, overlayTex, overlayActiveTex); + cache.buildPrototype(); + return cache; + } + + @Override + protected List buildPrototypeInternal() { + List quads = super.buildPrototypeInternal(); + buildOverlay(quads); + buildOverlayActive(quads); + return quads; + } + + protected void buildOverlay(List list) { + helper.setTargetSprite(overlayTex); + for (EnumFacing facing : EnumFacing.VALUES) { + int start = list.size(); + list.addAll(helper.visitTube(facing)); + overlayCoords.put(facing, new SubListAddress(start, list.size())); + } + } + + protected void buildOverlayActive(List list) { + helper.setTargetSprite(overlayActiveTex); + for (EnumFacing facing : EnumFacing.VALUES) { + int start = list.size(); + list.addAll(helper.visitTube(facing)); + overlayActiveCoords.put(facing, new SubListAddress(start, list.size())); + } + } + + public void addOverlay(List list, byte overlayMask, int argb, boolean active) { + List quads = cache.getQuads(argb); + for (EnumFacing facing : EnumFacing.VALUES) { + if (GTUtility.evalMask(facing, overlayMask)) { + if (active) { + list.addAll(overlayActiveCoords.get(facing).getSublist(quads)); + } else { + list.addAll(overlayCoords.get(facing).getSublist(quads)); + } + } + } + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java new file mode 100644 index 00000000000..d34a9976198 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java @@ -0,0 +1,73 @@ +package gregtech.client.renderer.pipe.cache; + +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.quad.PipeQuadHelper; +import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; +import gregtech.client.renderer.pipe.util.SpriteInformation; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.util.EnumFacing; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import org.jetbrains.annotations.NotNull; + +import java.util.EnumMap; +import java.util.List; + +@SideOnly(Side.CLIENT) +public class BlockableSQC extends StructureQuadCache { + + protected final EnumMap blockedCoords = new EnumMap<>(EnumFacing.class); + + protected final SpriteInformation blockedTex; + + protected BlockableSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, + SpriteInformation blockedTex) { + super(helper, endTex, sideTex); + this.blockedTex = blockedTex; + } + + public static @NotNull BlockableSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation blockedTex) { + BlockableSQC cache = new BlockableSQC(helper, endTex, sideTex, blockedTex); + cache.buildPrototype(); + return cache; + } + + @Override + protected List buildPrototypeInternal() { + List quads = super.buildPrototypeInternal(); + buildBlocked(quads); + return quads; + } + + protected void buildBlocked(List list) { + helper.setTargetSprite(blockedTex); + for (EnumFacing facing : EnumFacing.VALUES) { + int start = list.size(); + list.addAll(helper.visitTube(facing)); + blockedCoords.put(facing, new SubListAddress(start, list.size())); + } + } + + @Override + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, int argb) { + List quads = cache.getQuads(argb); + for (EnumFacing facing : EnumFacing.VALUES) { + if (GTUtility.evalMask(facing, connectionMask)) { + list.addAll(tubeCoords.get(facing).getSublist(quads)); + if (GTUtility.evalMask(facing, closedMask)) { + list.addAll(capperClosedCoords.get(facing).getSublist(quads)); + } else { + list.addAll(capperCoords.get(facing).getSublist(quads)); + } + if (GTUtility.evalMask(facing, blockedMask)) { + list.addAll(blockedCoords.get(facing).getSublist(quads)); + } + } else { + list.addAll(coreCoords.get(facing).getSublist(quads)); + } + } + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java new file mode 100644 index 00000000000..d6b06a5e223 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java @@ -0,0 +1,42 @@ +package gregtech.client.renderer.pipe.cache; + +import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; + +import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.List; + +@SideOnly(Side.CLIENT) +public final class ColorQuadCache { + + // TODO dynamic cache growth & collapse + private static final int CACHE_LIMIT = 20; + + private final List prototypes; + + private final Int2ObjectLinkedOpenHashMap> cache; + + public ColorQuadCache(List prototypes) { + this.prototypes = prototypes; + this.cache = new Int2ObjectLinkedOpenHashMap<>(); + } + + public List getQuads(int argb) { + List existing = cache.getAndMoveToFirst(argb); + if (existing == null) { + existing = new ObjectArrayList<>(); + for (RecolorableBakedQuad quad : prototypes) { + existing.add(quad.withColor(argb)); + } + cache.put(argb, existing); + if (cache.size() > CACHE_LIMIT) cache.removeLast(); + } + return existing; + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java new file mode 100644 index 00000000000..657b8c42e43 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java @@ -0,0 +1,71 @@ +package gregtech.client.renderer.pipe.cache; + +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.quad.PipeQuadHelper; +import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; +import gregtech.client.renderer.pipe.util.SpriteInformation; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.util.EnumFacing; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import org.jetbrains.annotations.NotNull; + +import java.util.EnumMap; +import java.util.List; + +@SideOnly(Side.CLIENT) +public class ExtraCappedSQC extends StructureQuadCache { + + protected final EnumMap extraCapperCoords = new EnumMap<>(EnumFacing.class); + + protected final SpriteInformation extraEndTex; + + protected ExtraCappedSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, + SpriteInformation extraEndTex) { + super(helper, endTex, sideTex); + this.extraEndTex = extraEndTex; + } + + public static @NotNull ExtraCappedSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation extraEndTex) { + ExtraCappedSQC cache = new ExtraCappedSQC(helper, endTex, sideTex, extraEndTex); + cache.buildPrototype(); + return cache; + } + + @Override + protected List buildPrototypeInternal() { + List quads = super.buildPrototypeInternal(); + buildExtraCapper(quads); + return quads; + } + + protected void buildExtraCapper(List list) { + helper.setTargetSprite(extraEndTex); + for (EnumFacing facing : EnumFacing.VALUES) { + int start = list.size(); + list.addAll(helper.visitTube(facing)); + extraCapperCoords.put(facing, new SubListAddress(start, list.size())); + } + } + + @Override + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, int argb) { + List quads = cache.getQuads(argb); + for (EnumFacing facing : EnumFacing.VALUES) { + if (GTUtility.evalMask(facing, connectionMask)) { + list.addAll(tubeCoords.get(facing).getSublist(quads)); + if (GTUtility.evalMask(facing, closedMask)) { + list.addAll(capperClosedCoords.get(facing).getSublist(quads)); + } else { + list.addAll(capperCoords.get(facing).getSublist(quads)); + list.addAll(extraCapperCoords.get(facing).getSublist(quads)); + } + } else { + list.addAll(coreCoords.get(facing).getSublist(quads)); + } + } + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java new file mode 100644 index 00000000000..611b5cb5ee1 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java @@ -0,0 +1,78 @@ +package gregtech.client.renderer.pipe.cache; + +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.quad.PipeQuadHelper; + +import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; + +import gregtech.client.renderer.pipe.util.SpriteInformation; + +import net.minecraft.client.renderer.block.model.BakedQuad; + +import net.minecraft.util.EnumFacing; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import org.jetbrains.annotations.NotNull; + +import java.util.EnumMap; +import java.util.List; + +@SideOnly(Side.CLIENT) +public class RestrictiveSQC extends BlockableSQC { + + protected final EnumMap restrictiveCoords = new EnumMap<>(EnumFacing.class); + + private final SpriteInformation restrictiveTex; + + protected RestrictiveSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, + SpriteInformation blockedTex, SpriteInformation restrictiveTex) { + super(helper, endTex, sideTex, blockedTex); + this.restrictiveTex = restrictiveTex; + } + + public static @NotNull RestrictiveSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, + SpriteInformation blockedTex, SpriteInformation restrictiveTex) { + RestrictiveSQC sqc = new RestrictiveSQC(helper, endTex, sideTex, blockedTex, restrictiveTex); + sqc.buildPrototype(); + return sqc; + } + + @Override + protected List buildPrototypeInternal() { + List quads = super.buildPrototypeInternal(); + buildRestrictive(quads); + return quads; + } + + protected void buildRestrictive(List list) { + helper.setTargetSprite(restrictiveTex); + for (EnumFacing facing : EnumFacing.VALUES) { + int start = list.size(); + list.addAll(helper.visitTube(facing)); + restrictiveCoords.put(facing, new SubListAddress(start, list.size())); + } + } + + @Override + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, int argb) { + List quads = cache.getQuads(argb); + for (EnumFacing facing : EnumFacing.VALUES) { + if (GTUtility.evalMask(facing, connectionMask)) { + list.addAll(tubeCoords.get(facing).getSublist(quads)); + list.addAll(restrictiveCoords.get(facing).getSublist(quads)); + if (GTUtility.evalMask(facing, closedMask)) { + list.addAll(capperClosedCoords.get(facing).getSublist(quads)); + } else { + list.addAll(capperCoords.get(facing).getSublist(quads)); + } + if (GTUtility.evalMask(facing, blockedMask)) { + list.addAll(blockedCoords.get(facing).getSublist(quads)); + } + } else { + list.addAll(coreCoords.get(facing).getSublist(quads)); + } + } + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java new file mode 100644 index 00000000000..35853be2491 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java @@ -0,0 +1,127 @@ +package gregtech.client.renderer.pipe.cache; + +import com.github.bsideup.jabel.Desugar; + +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.quad.PipeQuadHelper; + +import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; + +import gregtech.client.renderer.pipe.util.SpriteInformation; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraft.client.renderer.block.model.BakedQuad; + +import net.minecraft.util.EnumFacing; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import org.jetbrains.annotations.NotNull; + +import java.util.EnumMap; +import java.util.List; + +@SideOnly(Side.CLIENT) +public class StructureQuadCache { + + protected final PipeQuadHelper helper; + + protected ColorQuadCache cache; + + protected final EnumMap tubeCoords = new EnumMap<>(EnumFacing.class); + + protected final EnumMap coreCoords = new EnumMap<>(EnumFacing.class); + protected final EnumMap capperCoords = new EnumMap<>(EnumFacing.class); + protected final EnumMap capperClosedCoords = new EnumMap<>(EnumFacing.class); + + protected final SpriteInformation endTex; + protected final SpriteInformation sideTex; + + protected StructureQuadCache(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex) { + this.helper = helper; + this.endTex = endTex; + this.sideTex = sideTex; + } + + public static @NotNull StructureQuadCache create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex) { + StructureQuadCache cache = new StructureQuadCache(helper, endTex, sideTex); + cache.buildPrototype(); + return cache; + } + + protected void buildPrototype() { + this.cache = new ColorQuadCache(this.buildPrototypeInternal()); + } + + protected List buildPrototypeInternal() { + List quads = new ObjectArrayList<>(); + buildTube(quads); + buildCore(quads); + buildCapper(quads); + buildCapperClosed(quads); + return quads; + } + + protected void buildTube(List list) { + helper.setTargetSprite(sideTex); + for (EnumFacing facing : EnumFacing.VALUES) { + int start = list.size(); + list.addAll(helper.visitTube(facing)); + tubeCoords.put(facing, new SubListAddress(start, list.size())); + } + } + + protected void buildCore(List list) { + helper.setTargetSprite(endTex); + for (EnumFacing facing : EnumFacing.VALUES) { + int start = list.size(); + list.add(helper.visitCore(facing)); + coreCoords.put(facing, new SubListAddress(start, start + 1)); + } + } + + protected void buildCapper(List list) { + helper.setTargetSprite(endTex); + for (EnumFacing facing : EnumFacing.VALUES) { + int start = list.size(); + list.add(helper.visitCapper(facing)); + capperCoords.put(facing, new SubListAddress(start, start + 1)); + } + } + + protected void buildCapperClosed(List list) { + helper.setTargetSprite(sideTex); + for (EnumFacing facing : EnumFacing.VALUES) { + int start = list.size(); + list.add(helper.visitCapper(facing)); + capperClosedCoords.put(facing, new SubListAddress(start, start + 1)); + } + } + + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, int argb) { + List quads = cache.getQuads(argb); + for (EnumFacing facing : EnumFacing.VALUES) { + if (GTUtility.evalMask(facing, connectionMask)) { + list.addAll(tubeCoords.get(facing).getSublist(quads)); + if (GTUtility.evalMask(facing, closedMask)) { + list.addAll(capperClosedCoords.get(facing).getSublist(quads)); + } else { + list.addAll(capperCoords.get(facing).getSublist(quads)); + } + } else { + list.addAll(coreCoords.get(facing).getSublist(quads)); + } + } + } + + @Desugar + protected record SubListAddress(int startInclusive, int endExclusive) { + + public @NotNull List getSublist(@NotNull List list) { + return list.subList(startInclusive, endExclusive); + } + } + +} diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java new file mode 100644 index 00000000000..304c460d305 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -0,0 +1,234 @@ +package gregtech.client.renderer.pipe.quad; + +import gregtech.client.renderer.pipe.util.SpriteInformation; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.List; + +@SideOnly(Side.CLIENT) +public final class PipeQuadHelper { + + private static final VertexFormat FORMAT = DefaultVertexFormats.POSITION_TEX_COLOR_NORMAL; + + private final float thickness; + private final float x; + private final float y; + private final float z; + private final int argb; + private final float small; + private final float large; + private final UVMapper squareMapper; + private final UVMapper tallMapper; + private final UVMapper wideMapper; + + private RecolorableBakedQuad.Builder building; + + private SpriteInformation targetSprite; + + public PipeQuadHelper(float thickness, float x, float y, float z, int argb, float small, float large, + UVMapper squareMapper, UVMapper tallMapper, UVMapper wideMapper) { + this.thickness = thickness; + this.x = x; + this.y = y; + this.z = z; + this.argb = argb; + this.small = small; + this.large = large; + this.squareMapper = squareMapper; + this.tallMapper = tallMapper; + this.wideMapper = wideMapper; + } + + public static PipeQuadHelper create(float thickness, double x, double y, double z, + int argb) { + float small = 0.5f - thickness / 2; + float large = 0.5f + thickness / 2; + float small16 = small * 16; + float large16 = large * 16; + UVMapper squareMapper = createMapper(small16, small16, large16, large16); + UVMapper tallMapper = createMapper(large16, small16, 16, large16); + UVMapper wideMapper = createRotatedMapper(large16, small16, 16, large16); + return new PipeQuadHelper(thickness, (float) x, (float) y, (float) z, argb, small, large, squareMapper, + tallMapper, wideMapper); + } + + public static PipeQuadHelper create(float thickness) { + return create(thickness, 0, 0, 0, 0xFFFFFFFF); + } + + public void setTargetSprite(SpriteInformation sprite) { + this.targetSprite = sprite; + } + + public RecolorableBakedQuad visitCore(EnumFacing facing) { + return switch (facing.getAxis()) { + case X -> visitQuad(facing, 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, y + small, y + large, z + small, z + large, squareMapper); + case Y -> visitQuad(facing, x + small, x + large, 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, z + small, z + large, squareMapper); + case Z -> visitQuad(facing, x + small, x + large, y + small, y + large, 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, squareMapper); + }; + } + + public List visitTube(EnumFacing facing) { + List list = new ObjectArrayList<>(); + switch (facing.getAxis()) { + case X -> { + float x1; + float x2; + if (facing == EnumFacing.EAST) { + x1 = this.x + large; + x2 = 1; + } else { + x1 = this.x + small; + x2 = 0; + } + list.add(visitQuad(EnumFacing.UP, x1, x2, y + large, 0, z + small, z + large, wideMapper)); + list.add(visitQuad(EnumFacing.DOWN, x1, x2, y + small, 0, z + small, z + large, wideMapper)); + list.add(visitQuad(EnumFacing.SOUTH, x1, x2, y + small, y + large, z + large, 0, wideMapper)); + list.add(visitQuad(EnumFacing.NORTH, x1, x2, y + small, y + large, z + small, 0, wideMapper)); + } + case Y -> { + float y1; + float y2; + if (facing == EnumFacing.UP) { + y1 = this.y + large; + y2 = 1; + } else { + y1 = this.y + small; + y2 = 0; + } + list.add(visitQuad(EnumFacing.EAST, x + large, 0, y1, y2, z + small, z + large, tallMapper)); + list.add(visitQuad(EnumFacing.WEST, x + small, 0, y1, y2, z + small, z + large, tallMapper)); + list.add(visitQuad(EnumFacing.SOUTH, x + small, x + large, y1, y2, z + large, 0, wideMapper)); + list.add(visitQuad(EnumFacing.NORTH, x + small, x + large, y1, y2, z + small, 0, wideMapper)); + } + case Z -> { + float z1; + float z2; + if (facing == EnumFacing.SOUTH) { + z1 = this.z + large; + z2 = 1; + } else { + z1 = this.z + small; + z2 = 0; + } + list.add(visitQuad(EnumFacing.UP, x + small, x + large, y + large, 0, z1, z2, tallMapper)); + list.add(visitQuad(EnumFacing.DOWN, x + small, x + large, y + small, 0, z1, z2, tallMapper)); + list.add(visitQuad(EnumFacing.EAST, x + large, 0, y + small, y + large, z1, z2, tallMapper)); + list.add(visitQuad(EnumFacing.WEST, x + small, 0, y + small, y + large, z1, z2, tallMapper)); + } + } + return list; + } + + public RecolorableBakedQuad visitCapper(EnumFacing facing) { + return switch (facing.getAxis()) { + case X -> visitQuad(facing, 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, y + small, y + large, z + small, z + large, squareMapper); + case Y -> visitQuad(facing, x + small, x + large, 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, z + small, z + large, squareMapper); + case Z -> visitQuad(facing, x + small, x + large, y + small, y + large, 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, squareMapper); + }; + } + + public RecolorableBakedQuad visitQuad(EnumFacing normal, float x1, float x2, float y1, float y2, float z1, float z2, UVMapper mapper) { + building = new RecolorableBakedQuad.Builder(FORMAT); + switch (normal.getAxis()) { + case X -> { + visitVertex(normal, x1, y1, z1, mapper.map(UVCorner.VALUES[0], targetSprite.sprite())); + visitVertex(normal, x1, y1, z2, mapper.map(UVCorner.VALUES[1], targetSprite.sprite())); + visitVertex(normal, x1, y2, z2, mapper.map(UVCorner.VALUES[2], targetSprite.sprite())); + visitVertex(normal, x1, y2, z1, mapper.map(UVCorner.VALUES[3], targetSprite.sprite())); + } + case Y -> { + visitVertex(normal, x1, y1, z1, mapper.map(UVCorner.VALUES[0], targetSprite.sprite())); + visitVertex(normal, x1, y1, z2, mapper.map(UVCorner.VALUES[1], targetSprite.sprite())); + visitVertex(normal, x2, y1, z2, mapper.map(UVCorner.VALUES[2], targetSprite.sprite())); + visitVertex(normal, x2, y1, z1, mapper.map(UVCorner.VALUES[3], targetSprite.sprite())); + } + case Z -> { + visitVertex(normal, x1, y1, z1, mapper.map(UVCorner.VALUES[0], targetSprite.sprite())); + visitVertex(normal, x2, y1, z1, mapper.map(UVCorner.VALUES[1], targetSprite.sprite())); + visitVertex(normal, x2, y2, z1, mapper.map(UVCorner.VALUES[2], targetSprite.sprite())); + visitVertex(normal, x1, y2, z1, mapper.map(UVCorner.VALUES[3], targetSprite.sprite())); + } + } + building.setQuadOrientation(normal); + building.setTexture(targetSprite); + RecolorableBakedQuad quad = building.build(); + building = null; + return quad; + } + + private void visitVertex(EnumFacing normal, float x, float y, float z, UVMapper.UVPair pair) { + putVertex(building, FORMAT, normal, x, y, z, pair.u(), pair.v(), argb); + } + + public static UVMapper createMapper(double u1, double v1, double u2, double v2) { + return (corner, sprite) -> switch (corner) { + case UL -> UVMapper.uvPair(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)); + case UR -> UVMapper.uvPair(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)); + case DR -> UVMapper.uvPair(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)); + case DL -> UVMapper.uvPair(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)); + }; + } + + public static UVMapper createRotatedMapper(double u1, double v1, double u2, double v2) { + return (corner, sprite) -> switch (corner) { + case UR -> UVMapper.uvPair(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)); + case DR -> UVMapper.uvPair(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)); + case DL -> UVMapper.uvPair(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)); + case UL -> UVMapper.uvPair(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)); + }; + } + + @SuppressWarnings("SameParameterValue") + private static void putVertex(RecolorableBakedQuad.Builder consumer, VertexFormat format, EnumFacing normal, + float x, float y, float z, float u, float v, int argb) { + for (int e = 0; e < format.getElementCount(); e++) { + switch (format.getElement(e).getUsage()) { + case POSITION: + consumer.put(e, x, y, z, 1f); + break; + case COLOR: + float a = ((argb >> 24) & 0xFF) / 255f; // alpha + float r = ((argb >> 16) & 0xFF) / 255f; // red + float g = ((argb >> 8) & 0xFF) / 255f; // green + float b = ((argb) & 0xFF) / 255f; // blue + consumer.put(e, r, g, b, a); + break; + case NORMAL: + float offX = (float) normal.getXOffset(); + float offY = (float) normal.getYOffset(); + float offZ = (float) normal.getZOffset(); + consumer.put(e, offX, offY, offZ, 0f); + break; + case UV: + if (format.getElement(e).getIndex() == 0) + { + consumer.put(e, u, v, 0f, 1f); + break; + } + // else fallthrough to default + default: + consumer.put(e); + break; + } + } + } + + public static List createFrame(TextureAtlasSprite sprite) { + PipeQuadHelper helper = PipeQuadHelper.create(0.998f); + helper.setTargetSprite(new SpriteInformation(sprite, true)); + List list = new ObjectArrayList<>(); + for (EnumFacing facing : EnumFacing.VALUES) { + list.add(helper.visitCore(facing)); + } + return list; + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java new file mode 100644 index 00000000000..72b0df0902b --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java @@ -0,0 +1,188 @@ +package gregtech.client.renderer.pipe.quad; + +import gregtech.client.renderer.pipe.util.SpriteInformation; + +import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.client.renderer.vertex.VertexFormatElement; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import org.jetbrains.annotations.NotNull; + +@SideOnly(Side.CLIENT) +public class RecolorableBakedQuad extends UnpackedBakedQuad { + + private final SpriteInformation spriteInformation; + + public RecolorableBakedQuad(float[][][] unpackedData, int tint, EnumFacing orientation, + SpriteInformation texture, boolean applyDiffuseLighting, VertexFormat format) { + super(unpackedData, tint, orientation, texture.sprite(), applyDiffuseLighting, format); + this.spriteInformation = texture; + } + + public RecolorableBakedQuad withColor(int argb) { + if (!spriteInformation.colorable()) return this; + + float[][][] newData = new float[4][format.getElementCount()][]; + + float a = ((argb >> 24) & 0xFF) / 255f; // alpha + float r = ((argb >> 16) & 0xFF) / 255f; // red + float g = ((argb >> 8) & 0xFF) / 255f; // green + float b = ((argb) & 0xFF) / 255f; // blue + float[] array = new float[] {r, g, b, a}; + for (int v = 0; v < 4; v++) { + for (int e = 0; e < format.getElementCount(); e++) { + if (format.getElement(e).getUsage() == VertexFormatElement.EnumUsage.COLOR) { + newData[v][e] = array; + } else { + newData[v][e] = unpackedData[v][e]; + } + } + } + return new RecolorableBakedQuad(newData, this.tintIndex, this.face, this.spriteInformation, this.applyDiffuseLighting, this.format); + } + + public static class Builder { + private final VertexFormat format; + private final float[][][] unpackedData; + private int tint = -1; + private EnumFacing orientation; + private SpriteInformation texture; + private boolean applyDiffuseLighting = true; + + private int vertices = 0; + private int elements = 0; + private boolean full = false; + private boolean contractUVs = false; + + public Builder(VertexFormat format) + { + this.format = format; + unpackedData = new float[4][format.getElementCount()][4]; + } + + public @NotNull VertexFormat getVertexFormat() + { + return format; + } + + public void setContractUVs(boolean value) + { + this.contractUVs = value; + } + public void setQuadTint(int tint) + { + this.tint = tint; + } + + public void setQuadOrientation(@NotNull EnumFacing orientation) + { + this.orientation = orientation; + } + + public void setTexture(@NotNull SpriteInformation texture) + { + this.texture = texture; + } + + public void setApplyDiffuseLighting(boolean diffuse) + { + this.applyDiffuseLighting = diffuse; + } + + public void put(int element, float @NotNull ... data) + { + for(int i = 0; i < 4; i++) + { + if(i < data.length) + { + unpackedData[vertices][element][i] = data[i]; + } + else + { + unpackedData[vertices][element][i] = 0; + } + } + elements++; + if(elements == format.getElementCount()) + { + vertices++; + elements = 0; + } + if(vertices == 4) + { + full = true; + } + } + + public RecolorableBakedQuad build() { + if(!full) + { + throw new IllegalStateException("not enough data"); + } + if(texture == null) + { + throw new IllegalStateException("texture not set"); + } + if(contractUVs) + { + float tX = texture.sprite().getIconWidth() / (texture.sprite().getMaxU() - texture.sprite().getMinU()); + float tY = texture.sprite().getIconHeight() / (texture.sprite().getMaxV() - texture.sprite().getMinV()); + float tS = Math.max(tX, tY); + float ep = 1f / (tS * 0x100); + int uve = 0; + while(uve < format.getElementCount()) + { + VertexFormatElement e = format.getElement(uve); + if(e.getUsage() == VertexFormatElement.EnumUsage.UV && e.getIndex() == 0) + { + break; + } + uve++; + } + if(uve == format.getElementCount()) + { + throw new IllegalStateException("Can't contract UVs: format doesn't contain UVs"); + } + float[] uvc = new float[4]; + for(int v = 0; v < 4; v++) + { + for(int i = 0; i < 4; i++) + { + uvc[i] += unpackedData[v][uve][i] / 4; + } + } + for(int v = 0; v < 4; v++) + { + for (int i = 0; i < 4; i++) + { + float uo = unpackedData[v][uve][i]; + float eps = 1f / 0x100; + float un = uo * (1 - eps) + uvc[i] * eps; + float ud = uo - un; + float aud = ud; + if(aud < 0) aud = -aud; + if(aud < ep) // not moving a fraction of a pixel + { + float udc = uo - uvc[i]; + if(udc < 0) udc = -udc; + if(udc < 2 * ep) // center is closer than 2 fractions of a pixel, don't move too close + { + un = (uo + uvc[i]) / 2; + } + else // move at least by a fraction + { + un = uo + (ud < 0 ? ep : -ep); + } + } + unpackedData[v][uve][i] = un; + } + } + } + return new RecolorableBakedQuad(unpackedData, tint, orientation, texture, applyDiffuseLighting, format); + } + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java b/src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java new file mode 100644 index 00000000000..fcc4bf696a4 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java @@ -0,0 +1,14 @@ +package gregtech.client.renderer.pipe.quad; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +public enum UVCorner { + UL, + UR, + DR, + DL; + + public static final UVCorner[] VALUES = values(); +} diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java new file mode 100644 index 00000000000..9a11d40cfa3 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java @@ -0,0 +1,21 @@ +package gregtech.client.renderer.pipe.quad; + +import com.github.bsideup.jabel.Desugar; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +@FunctionalInterface +interface UVMapper { + + UVPair map(UVCorner corner, TextureAtlasSprite sprite); + + static UVPair uvPair(float u, float v) { + return new UVPair(u, v); + } + + @Desugar + record UVPair(float u, float v) {} +} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java new file mode 100644 index 00000000000..9c9f9d21acd --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java @@ -0,0 +1,17 @@ +package gregtech.client.renderer.pipe.util; + +public class ActivableCacheKey extends CacheKey { + + private final boolean active; + + public ActivableCacheKey(float thickness, boolean active) { + super(thickness); + this.active = active; + } + + public boolean isActive() { + return active; + } + + // activeness is merely a way to pass information onwards, it does not result in separate mappings. +} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java new file mode 100644 index 00000000000..ebf5303afb2 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java @@ -0,0 +1,47 @@ +package gregtech.client.renderer.pipe.util; + +import gregtech.client.renderer.pipe.AbstractPipeModel; + +import net.minecraft.util.IStringSerializable; + +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class CacheKey implements IStringSerializable { + + protected final float thickness; + + private final int hash; + + public CacheKey(float thickness) { + this.thickness = thickness; + this.hash = computeHash(); + } + + public float getThickness() { + return thickness; + } + + protected int computeHash() { + return Objects.hash(thickness); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (CacheKey) obj; + return Float.floatToIntBits(this.thickness) == Float.floatToIntBits(that.thickness); + } + + @Override + public final int hashCode() { + return hash; + } + + @Override + public @NotNull String getName() { + return String.valueOf(Float.floatToIntBits(thickness)); + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java b/src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java new file mode 100644 index 00000000000..eb251655170 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java @@ -0,0 +1,14 @@ +package gregtech.client.renderer.pipe.util; + +import gregtech.client.renderer.pipe.util.SpriteInformation; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +@FunctionalInterface +public interface PipeSpriteWoodClarifier { + + SpriteInformation getSprite(boolean isWoodVariant); +} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java new file mode 100644 index 00000000000..1e0324da16f --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java @@ -0,0 +1,11 @@ +package gregtech.client.renderer.pipe.util; + +import com.github.bsideup.jabel.Desugar; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@SideOnly(Side.CLIENT) +@Desugar +public record SpriteInformation(TextureAtlasSprite sprite, boolean colorable) {} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java new file mode 100644 index 00000000000..1ae793f767d --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java @@ -0,0 +1,34 @@ +package gregtech.client.renderer.pipe.util; + +import net.minecraft.client.renderer.texture.TextureAtlasSprite; + +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class SpriteInformationWrapper implements Supplier, Consumer, BiConsumer { + private SpriteInformation sprite; + + @Override + public void accept(TextureAtlasSprite sprite, Boolean colorable) { + accept(new SpriteInformation(sprite, colorable)); + } + + @Override + public void accept(SpriteInformation spriteInformation) { + this.sprite = spriteInformation; + } + + @Override + public SpriteInformation get() { + return this.sprite; + } + + public static SpriteInformationWrapper[] array(int size) { + SpriteInformationWrapper[] array = new SpriteInformationWrapper[size]; + for (int i = 0; i < size; i++) { + array[i] = new SpriteInformationWrapper(); + } + return array; + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java new file mode 100644 index 00000000000..8ebff9fd169 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java @@ -0,0 +1,40 @@ +package gregtech.client.renderer.pipe.util; + +import gregtech.client.renderer.pipe.PipeModel; + +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class WoodCacheKey extends CacheKey { + + private final boolean wood; + + public WoodCacheKey(float thickness, boolean wood) { + super(thickness); + this.wood = wood; + } + + public boolean isWood() { + return wood; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (WoodCacheKey) obj; + return Float.floatToIntBits(thickness) == Float.floatToIntBits(thickness) && + this.wood == that.wood; + } + + @Override + protected int computeHash() { + return Objects.hash(thickness, wood); + } + + @Override + public @NotNull String getName() { + return super.getName() + wood; + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/CableRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/CableRenderer.java similarity index 99% rename from src/main/java/gregtech/client/renderer/pipe/CableRenderer.java rename to src/main/java/gregtech/client/renderer/pipeold/CableRenderer.java index c45630f99c7..68ad587aa50 100644 --- a/src/main/java/gregtech/client/renderer/pipe/CableRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipeold/CableRenderer.java @@ -1,4 +1,4 @@ -package gregtech.client.renderer.pipe; +package gregtech.client.renderer.pipeold; import gregtech.api.graphnet.pipenetold.block.BlockPipe; import gregtech.api.graphnet.pipenetold.block.IPipeType; diff --git a/src/main/java/gregtech/client/renderer/pipe/FluidPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/FluidPipeRenderer.java similarity index 98% rename from src/main/java/gregtech/client/renderer/pipe/FluidPipeRenderer.java rename to src/main/java/gregtech/client/renderer/pipeold/FluidPipeRenderer.java index a7a78c63d8a..fe9df0bec8a 100644 --- a/src/main/java/gregtech/client/renderer/pipe/FluidPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipeold/FluidPipeRenderer.java @@ -1,4 +1,4 @@ -package gregtech.client.renderer.pipe; +package gregtech.client.renderer.pipeold; import gregtech.api.graphnet.pipenetold.block.BlockPipe; import gregtech.api.graphnet.pipenetold.block.IPipeType; diff --git a/src/main/java/gregtech/client/renderer/pipe/ItemPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/ItemPipeRenderer.java similarity index 98% rename from src/main/java/gregtech/client/renderer/pipe/ItemPipeRenderer.java rename to src/main/java/gregtech/client/renderer/pipeold/ItemPipeRenderer.java index f803229ae14..acee00a413f 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ItemPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipeold/ItemPipeRenderer.java @@ -1,4 +1,4 @@ -package gregtech.client.renderer.pipe; +package gregtech.client.renderer.pipeold; import gregtech.api.graphnet.pipenetold.block.BlockPipe; import gregtech.api.graphnet.pipenetold.block.IPipeType; diff --git a/src/main/java/gregtech/client/renderer/pipe/LaserPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/LaserPipeRenderer.java similarity index 99% rename from src/main/java/gregtech/client/renderer/pipe/LaserPipeRenderer.java rename to src/main/java/gregtech/client/renderer/pipeold/LaserPipeRenderer.java index 37f7c5b73c0..1ce9c0cfde2 100644 --- a/src/main/java/gregtech/client/renderer/pipe/LaserPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipeold/LaserPipeRenderer.java @@ -1,4 +1,4 @@ -package gregtech.client.renderer.pipe; +package gregtech.client.renderer.pipeold; import gregtech.api.graphnet.pipenetold.block.BlockPipe; import gregtech.api.graphnet.pipenetold.block.IPipeType; diff --git a/src/main/java/gregtech/client/renderer/pipe/OpticalPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/OpticalPipeRenderer.java similarity index 98% rename from src/main/java/gregtech/client/renderer/pipe/OpticalPipeRenderer.java rename to src/main/java/gregtech/client/renderer/pipeold/OpticalPipeRenderer.java index ddd4da6264e..3203c9fa989 100644 --- a/src/main/java/gregtech/client/renderer/pipe/OpticalPipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipeold/OpticalPipeRenderer.java @@ -1,4 +1,4 @@ -package gregtech.client.renderer.pipe; +package gregtech.client.renderer.pipeold; import gregtech.api.graphnet.pipenetold.block.BlockPipe; import gregtech.api.graphnet.pipenetold.block.IPipeType; diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/PipeRenderer.java similarity index 99% rename from src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java rename to src/main/java/gregtech/client/renderer/pipeold/PipeRenderer.java index 673dcb037c6..f14dfbbb440 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipeold/PipeRenderer.java @@ -1,4 +1,4 @@ -package gregtech.client.renderer.pipe; +package gregtech.client.renderer.pipeold; import gregtech.api.cover.CoverHolder; import gregtech.api.graphnet.pipenetold.block.BlockPipe; diff --git a/src/main/java/gregtech/client/renderer/texture/Textures.java b/src/main/java/gregtech/client/renderer/texture/Textures.java index c007a6b13d6..5bc9b44a507 100644 --- a/src/main/java/gregtech/client/renderer/texture/Textures.java +++ b/src/main/java/gregtech/client/renderer/texture/Textures.java @@ -7,6 +7,8 @@ import gregtech.client.renderer.CubeRendererState; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.cclop.UVMirror; +import gregtech.client.renderer.pipe.util.SpriteInformation; +import gregtech.client.renderer.pipe.util.SpriteInformationWrapper; import gregtech.client.renderer.texture.cube.AlignedOrientedOverlayRenderer; import gregtech.client.renderer.texture.cube.LDPipeOverlayRenderer; import gregtech.client.renderer.texture.cube.OrientedOverlayRenderer; @@ -44,6 +46,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import static gregtech.api.util.GTUtility.gregtechId; @@ -528,81 +531,88 @@ public class Textures { public static final ResourceLocation YELLOW_CAPE_TEXTURE = gregtechId("textures/capes/yellowcape.png"); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite RESTRICTIVE_OVERLAY; + public static final SpriteInformationWrapper WIRE = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_TINY; + public static final SpriteInformationWrapper INSULATION_FULL = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_SMALL; - @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_NORMAL; + public static final SpriteInformationWrapper[] INSULATION = SpriteInformationWrapper.array(5); + @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_LARGE; + public static final SpriteInformationWrapper RESTRICTIVE_OVERLAY = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_HUGE; + public static final SpriteInformationWrapper PIPE_TINY = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_QUADRUPLE; + public static final SpriteInformationWrapper PIPE_SMALL = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_NONUPLE; + public static final SpriteInformationWrapper PIPE_NORMAL = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_SIDE; - + public static final SpriteInformationWrapper PIPE_LARGE = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_SMALL_WOOD; + public static final SpriteInformationWrapper PIPE_HUGE = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_NORMAL_WOOD; + public static final SpriteInformationWrapper PIPE_QUADRUPLE = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_LARGE_WOOD; + public static final SpriteInformationWrapper PIPE_NONUPLE = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_SIDE_WOOD; + public static final SpriteInformationWrapper PIPE_SIDE = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite OPTICAL_PIPE_IN; + public static final SpriteInformationWrapper PIPE_SMALL_WOOD = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite OPTICAL_PIPE_SIDE; + public static final SpriteInformationWrapper PIPE_NORMAL_WOOD = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite OPTICAL_PIPE_SIDE_OVERLAY; + public static final SpriteInformationWrapper PIPE_LARGE_WOOD = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite OPTICAL_PIPE_SIDE_OVERLAY_ACTIVE; + public static final SpriteInformationWrapper PIPE_SIDE_WOOD = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite LASER_PIPE_IN; + public static final SpriteInformationWrapper OPTICAL_PIPE_IN = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite LASER_PIPE_SIDE; + public static final SpriteInformationWrapper OPTICAL_PIPE_SIDE = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite LASER_PIPE_OVERLAY; + public static final SpriteInformationWrapper OPTICAL_PIPE_SIDE_OVERLAY = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite LASER_PIPE_OVERLAY_EMISSIVE; + public static final SpriteInformationWrapper OPTICAL_PIPE_SIDE_OVERLAY_ACTIVE = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY; - @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UP; - @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DOWN; - @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_LEFT; - @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_RIGHT; - @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NU; + public static final SpriteInformationWrapper LASER_PIPE_IN = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_ND; + public static final SpriteInformationWrapper LASER_PIPE_SIDE = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NL; + public static final SpriteInformationWrapper LASER_PIPE_OVERLAY = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NR; - @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UD; - @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UL; - @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UR; - @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DL; - @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DR; + public static final SpriteInformationWrapper LASER_PIPE_OVERLAY_EMISSIVE = new SpriteInformationWrapper(); + +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY; @SideOnly(Side.CLIENT) - public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_LR; + public static final SpriteInformationWrapper PIPE_BLOCKED_OVERLAY_UP = new SpriteInformationWrapper(); +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DOWN; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_LEFT; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_RIGHT; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NU; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_ND; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NL; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NR; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UD; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UL; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UR; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DL; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DR; +// @SideOnly(Side.CLIENT) +// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_LR; @SideOnly(Side.CLIENT) public static ThreadLocal RENDER_STATE; @@ -624,53 +634,60 @@ public static void register(TextureMap textureMap) { iconRegister.registerIcons(textureMap); } - RESTRICTIVE_OVERLAY = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_restrictive")); - PIPE_TINY = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_tiny_in")); - PIPE_SMALL = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_small_in")); - PIPE_NORMAL = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_normal_in")); - PIPE_LARGE = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_large_in")); - PIPE_HUGE = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_huge_in")); - PIPE_QUADRUPLE = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_quadruple_in")); - PIPE_NONUPLE = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_nonuple_in")); - PIPE_SIDE = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_side")); - PIPE_SMALL_WOOD = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_small_in_wood")); - PIPE_NORMAL_WOOD = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_normal_in_wood")); - PIPE_LARGE_WOOD = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_large_in_wood")); - PIPE_SIDE_WOOD = textureMap.registerSprite(gregtechId("blocks/pipe/pipe_side_wood")); + WIRE.accept(textureMap.registerSprite(gregtechId("blocks/cable/wire")), true); + INSULATION_FULL.accept(textureMap.registerSprite(gregtechId("blocks/cable/insulation_full")), false); + for (int i = 0; i < INSULATION.length; i++) { + INSULATION[i].accept(textureMap.registerSprite(gregtechId("blocks/cable/insulation_" + i)), false); + } + + RESTRICTIVE_OVERLAY.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_restrictive")), false); + PIPE_TINY.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_tiny_in")), true); + PIPE_SMALL.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_small_in")), true); + PIPE_NORMAL.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_normal_in")), true); + PIPE_LARGE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_large_in")), true); + PIPE_HUGE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_huge_in")), true); + PIPE_QUADRUPLE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_quadruple_in")), true); + PIPE_NONUPLE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_nonuple_in")), true); + PIPE_SIDE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_side")), true); + PIPE_SMALL_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_small_in_wood")), true); + PIPE_NORMAL_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_normal_in_wood")), true); + PIPE_LARGE_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_large_in_wood")), true); + PIPE_SIDE_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_side_wood")), true); // Fluid Pipe Blocked overlay textures - PIPE_BLOCKED_OVERLAY = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked")); - PIPE_BLOCKED_OVERLAY_UP = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_up")); - PIPE_BLOCKED_OVERLAY_DOWN = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_down")); - PIPE_BLOCKED_OVERLAY_LEFT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_left")); - PIPE_BLOCKED_OVERLAY_RIGHT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_right")); - PIPE_BLOCKED_OVERLAY_NU = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nu")); - PIPE_BLOCKED_OVERLAY_ND = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nd")); - PIPE_BLOCKED_OVERLAY_NL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nl")); - PIPE_BLOCKED_OVERLAY_NR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nr")); - PIPE_BLOCKED_OVERLAY_UD = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ud")); - PIPE_BLOCKED_OVERLAY_UL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ul")); - PIPE_BLOCKED_OVERLAY_UR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ur")); - PIPE_BLOCKED_OVERLAY_DL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_dl")); - PIPE_BLOCKED_OVERLAY_DR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_dr")); - PIPE_BLOCKED_OVERLAY_LR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_lr")); - - OPTICAL_PIPE_IN = textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_in")); - OPTICAL_PIPE_SIDE = textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side")); - OPTICAL_PIPE_SIDE_OVERLAY = textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side_overlay")); - OPTICAL_PIPE_SIDE_OVERLAY_ACTIVE = textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side_overlay_active")); - - LASER_PIPE_SIDE = textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side")); - LASER_PIPE_IN = textureMap.registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_in")); - LASER_PIPE_OVERLAY = textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side_overlay")); - LASER_PIPE_OVERLAY_EMISSIVE = textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side_overlay_emissive")); +// PIPE_BLOCKED_OVERLAY = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked")); + PIPE_BLOCKED_OVERLAY_UP.accept(textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_up")), false); +// PIPE_BLOCKED_OVERLAY_DOWN = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_down")); +// PIPE_BLOCKED_OVERLAY_LEFT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_left")); +// PIPE_BLOCKED_OVERLAY_RIGHT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_right")); +// PIPE_BLOCKED_OVERLAY_NU = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nu")); +// PIPE_BLOCKED_OVERLAY_ND = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nd")); +// PIPE_BLOCKED_OVERLAY_NL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nl")); +// PIPE_BLOCKED_OVERLAY_NR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nr")); +// PIPE_BLOCKED_OVERLAY_UD = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ud")); +// PIPE_BLOCKED_OVERLAY_UL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ul")); +// PIPE_BLOCKED_OVERLAY_UR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ur")); +// PIPE_BLOCKED_OVERLAY_DL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_dl")); +// PIPE_BLOCKED_OVERLAY_DR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_dr")); +// PIPE_BLOCKED_OVERLAY_LR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_lr")); + + OPTICAL_PIPE_IN.accept(textureMap + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_in")), false); + OPTICAL_PIPE_SIDE.accept(textureMap + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side")), false); + OPTICAL_PIPE_SIDE_OVERLAY.accept(textureMap + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side_overlay")), true); + OPTICAL_PIPE_SIDE_OVERLAY_ACTIVE.accept(textureMap + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side_overlay_active")), true); + + LASER_PIPE_IN.accept(textureMap. + registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_in")), false); + LASER_PIPE_SIDE.accept(textureMap + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side")), false); + LASER_PIPE_OVERLAY.accept(textureMap + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side_overlay")), true); + LASER_PIPE_OVERLAY_EMISSIVE.accept(textureMap + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side_overlay_emissive")), true); for (MaterialIconSet iconSet : MaterialIconSet.ICON_SETS.values()) { textureMap.registerSprite(MaterialIconType.frameGt.getBlockTexturePath(iconSet)); diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index ca194d0ef72..36cdbb84005 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -1,5 +1,6 @@ package gregtech.common.blocks; +import gregtech.api.GTValues; import gregtech.api.GregTechAPI; import gregtech.api.block.machines.BlockMachine; import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; @@ -21,8 +22,6 @@ import gregtech.client.model.modelfactories.BakedModelHandler; import gregtech.client.renderer.handler.MetaTileEntityRenderer; import gregtech.client.renderer.handler.MetaTileEntityTESR; -import gregtech.client.renderer.pipe.LaserPipeRenderer; -import gregtech.client.renderer.pipe.OpticalPipeRenderer; import gregtech.common.ConfigHolder; import gregtech.common.blocks.explosive.BlockITNT; import gregtech.common.blocks.explosive.BlockPowderbarrel; @@ -40,6 +39,10 @@ import gregtech.common.items.MetaItems; import gregtech.common.pipelike.block.cable.CableBlock; import gregtech.common.pipelike.block.cable.CableStructure; +import gregtech.common.pipelike.block.laser.LaserPipeBlock; +import gregtech.common.pipelike.block.laser.LaserStructure; +import gregtech.common.pipelike.block.optical.OpticalPipeBlock; +import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.block.pipe.PipeBlock; import gregtech.common.pipelike.block.pipe.PipeStructure; import gregtech.common.pipelikeold.fluidpipe.longdistance.LDFluidPipeType; @@ -107,8 +110,8 @@ private MetaBlocks() {} public static BlockMachine MACHINE; public static final Map CABLES = new Object2ObjectOpenHashMap<>(); public static final Map MATERIAL_PIPES = new Object2ObjectOpenHashMap<>(); - public static final BlockOpticalPipe[] OPTICAL_PIPES = new BlockOpticalPipe[OpticalPipeType.values().length]; - public static final BlockLaserPipe[] LASER_PIPES = new BlockLaserPipe[OpticalPipeType.values().length]; + public static OpticalPipeBlock[] OPTICAL_PIPES; + public static LaserPipeBlock[] LASER_PIPES; public static BlockLongDistancePipe LD_ITEM_PIPE; public static BlockLongDistancePipe LD_FLUID_PIPE; @@ -205,15 +208,24 @@ public static void init() { } MATERIAL_PIPES.put(modid, pipes); } - for (OpticalPipeType type : OpticalPipeType.values()) { - OPTICAL_PIPES[type.ordinal()] = new BlockOpticalPipe(type); - OPTICAL_PIPES[type.ordinal()].setRegistryName(String.format("optical_pipe_%s", type.getName())); - OPTICAL_PIPES[type.ordinal()].setTranslationKey(String.format("optical_pipe_%s", type.getName())); + + Set structuresOptical = OpticalPipeBlock.gatherStructures(); + OPTICAL_PIPES = new OpticalPipeBlock[structuresOptical.size()]; + int i = 0; + for (OpticalStructure struct : structuresOptical) { + OpticalPipeBlock block = new OpticalPipeBlock(struct); + block.setRegistryName(GTValues.MODID, String.format("optical_pipe_%s", struct.getName())); + OPTICAL_PIPES[i] = block; + i++; } - for (LaserPipeType type : LaserPipeType.values()) { - LASER_PIPES[type.ordinal()] = new BlockLaserPipe(type); - LASER_PIPES[type.ordinal()].setRegistryName(String.format("laser_pipe_%s", type.getName())); - LASER_PIPES[type.ordinal()].setTranslationKey(String.format("laser_pipe_%s", type.getName())); + Set structuresLaser = LaserPipeBlock.gatherStructures(); + LASER_PIPES = new LaserPipeBlock[structuresOptical.size()]; + i = 0; + for (LaserStructure struct : structuresLaser) { + LaserPipeBlock block = new LaserPipeBlock(struct); + block.setRegistryName(GTValues.MODID, String.format("laser_pipe_%s", struct.getName())); + LASER_PIPES[i] = block; + i++; } LD_ITEM_PIPE = new BlockLongDistancePipe(LDItemPipeType.INSTANCE); @@ -426,15 +438,19 @@ public static void registerItemModels() { ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(MACHINE), stack -> MetaTileEntityRenderer.MODEL_LOCATION); for (MaterialRegistry registry : GregTechAPI.materialManager.getRegistries()) { - for (CableBlock cable : CABLES.get(registry.getModid())) cable.onModelRegister(); - for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) pipe.onModelRegister(); + for (CableBlock cable : CABLES.get(registry.getModid())) + ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(cable), + stack -> cable.getStructure().getModel().getLoc()); + for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) + ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(pipe), + stack -> pipe.getStructure().getModel().getLoc()); } - for (BlockOpticalPipe pipe : OPTICAL_PIPES) + for (OpticalPipeBlock pipe : OPTICAL_PIPES) ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(pipe), - stack -> OpticalPipeRenderer.INSTANCE.getModelLocation()); - for (BlockLaserPipe pipe : LASER_PIPES) + stack -> pipe.getStructure().getModel().getLoc()); + for (LaserPipeBlock pipe : LASER_PIPES) ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(pipe), - stack -> LaserPipeRenderer.INSTANCE.getModelLocation()); + stack -> pipe.getStructure().getModel().getLoc()); registerItemModel(BOILER_CASING); registerItemModel(METAL_CASING); @@ -523,31 +539,22 @@ private static void registerItemModelWithOverride(Block block, Map, public static void registerStateMappers() { ModelLoader.setCustomStateMapper(MACHINE, new SimpleStateMapper(MetaTileEntityRenderer.MODEL_LOCATION)); - IStateMapper normalStateMapper; for (MaterialRegistry registry : GregTechAPI.materialManager.getRegistries()) { - // TODO rendering -// normalStateMapper = new SimpleStateMapper(CableRenderer.INSTANCE.getModelLocation()); -// for (BlockCable cable : CABLES.get(registry.getModid())) { -// ModelLoader.setCustomStateMapper(cable, normalStateMapper); -// } -// normalStateMapper = new SimpleStateMapper(FluidPipeRenderer.INSTANCE.getModelLocation()); -// for (BlockFluidPipe pipe : FLUID_PIPES.get(registry.getModid())) { -// ModelLoader.setCustomStateMapper(pipe, normalStateMapper); -// } -// normalStateMapper = new SimpleStateMapper(ItemPipeRenderer.INSTANCE.getModelLocation()); -// for (BlockItemPipe pipe : ITEM_PIPES.get(registry.getModid())) { -// ModelLoader.setCustomStateMapper(pipe, normalStateMapper); -// } + for (CableBlock cable : CABLES.get(registry.getModid())) { + ModelLoader.setCustomStateMapper(cable, new SimpleStateMapper(cable.getStructure().getModel().getLoc())); + } + for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) { + ModelLoader.setCustomStateMapper(pipe, new SimpleStateMapper(pipe.getStructure().getModel().getLoc())); + } } - normalStateMapper = new SimpleStateMapper(OpticalPipeRenderer.INSTANCE.getModelLocation()); - for (BlockOpticalPipe pipe : OPTICAL_PIPES) { - ModelLoader.setCustomStateMapper(pipe, normalStateMapper); + for (OpticalPipeBlock pipe : OPTICAL_PIPES) { + ModelLoader.setCustomStateMapper(pipe, new SimpleStateMapper(pipe.getStructure().getModel().getLoc())); } - normalStateMapper = new SimpleStateMapper(LaserPipeRenderer.INSTANCE.getModelLocation()); - for (BlockLaserPipe pipe : LASER_PIPES) { - ModelLoader.setCustomStateMapper(pipe, normalStateMapper); + for (LaserPipeBlock pipe : LASER_PIPES) { + ModelLoader.setCustomStateMapper(pipe, new SimpleStateMapper(pipe.getStructure().getModel().getLoc())); } + IStateMapper normalStateMapper; normalStateMapper = new SimpleStateMapper(BlockSurfaceRock.MODEL_LOCATION); for (BlockSurfaceRock surfaceRock : SURFACE_ROCK_BLOCKS) { ModelLoader.setCustomStateMapper(surfaceRock, normalStateMapper); diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index 7c8631ccbe2..aa6c809ef94 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -57,10 +57,4 @@ public void partialBurn(IBlockState state, World world, BlockPos pos) { world.setBlockState(pos, newBlock.getStateFromMeta(this.getMetaFromState(state))); } } - - // TODO rendering - @Override - protected Pair getParticleTexture(World world, BlockPos blockPos) { - return null; - } } diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java index 5edc4cf0405..59dd4ea2023 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java @@ -1,56 +1,67 @@ package gregtech.common.pipelike.block.cable; +import com.github.bsideup.jabel.Desugar; + import gregtech.api.graphnet.pipenet.physical.IInsulatable; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.unification.ore.OrePrefix; +import gregtech.client.renderer.pipe.AbstractPipeModel; +import gregtech.client.renderer.pipe.CableModel; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.function.Consumer; +@Desugar public record CableStructure(String name, int material, int costFactor, OrePrefix ore, @Nullable CableStructure partialBurnStructure, @Nullable Integer partialBurnThreshold, - float renderThickness) implements IPipeMaterialStructure, IInsulatable { + float renderThickness, AbstractPipeModel model) implements IPipeMaterialStructure, IInsulatable { public static final int INSULATION_BURN_TEMP = 1000; public static final CableStructure WIRE_SINGLE = - new CableStructure("wire_single", 1, 2, OrePrefix.wireGtSingle, null, null, 0.125f); + new CableStructure("wire_single", 1, 2, OrePrefix.wireGtSingle, null, null, 0.125f, CableModel.INSTANCE); public static final CableStructure WIRE_DOUBLE = - new CableStructure("wire_double", 2, 2, OrePrefix.wireGtDouble, null, null, 0.25f); + new CableStructure("wire_double", 2, 2, OrePrefix.wireGtDouble, null, null, 0.25f, CableModel.INSTANCE); public static final CableStructure WIRE_QUADRUPLE = - new CableStructure("wire_quadruple", 4, 3, OrePrefix.wireGtQuadruple, null, null, 0.375f); + new CableStructure("wire_quadruple", 4, 3, OrePrefix.wireGtQuadruple, null, null, 0.375f, CableModel.INSTANCE); public static final CableStructure WIRE_OCTAL = - new CableStructure("wire_octal", 8, 3, OrePrefix.wireGtOctal, null, null, 0.5f); + new CableStructure("wire_octal", 8, 3, OrePrefix.wireGtOctal, null, null, 0.5f, CableModel.INSTANCE); public static final CableStructure WIRE_HEX = - new CableStructure("wire_hex", 16, 3, OrePrefix.wireGtHex, null, null, 0.75f); + new CableStructure("wire_hex", 16, 3, OrePrefix.wireGtHex, null, null, 0.75f, CableModel.INSTANCE); public static final CableStructure CABLE_SINGLE = - new CableStructure("cable_single", 1, 1, OrePrefix.cableGtSingle, WIRE_SINGLE, INSULATION_BURN_TEMP, 0.25f); + new CableStructure("cable_single", 1, 1, OrePrefix.cableGtSingle, WIRE_SINGLE, INSULATION_BURN_TEMP, 0.25f, CableModel.INSULATED_INSTANCES[0]); public static final CableStructure CABLE_DOUBLE = - new CableStructure("cable_double", 2, 1, OrePrefix.cableGtDouble, WIRE_DOUBLE, INSULATION_BURN_TEMP, 0.375f); + new CableStructure("cable_double", 2, 1, OrePrefix.cableGtDouble, WIRE_DOUBLE, INSULATION_BURN_TEMP, 0.375f, CableModel.INSULATED_INSTANCES[1]); public static final CableStructure CABLE_QUADRUPLE = - new CableStructure("cable_quadruple", 4, 1, OrePrefix.cableGtQuadruple, WIRE_QUADRUPLE, INSULATION_BURN_TEMP, 0.5f); + new CableStructure("cable_quadruple", 4, 1, OrePrefix.cableGtQuadruple, WIRE_QUADRUPLE, INSULATION_BURN_TEMP, 0.5f, CableModel.INSULATED_INSTANCES[2]); public static final CableStructure CABLE_OCTAL = - new CableStructure("cable_octal", 8, 1, OrePrefix.cableGtOctal, WIRE_OCTAL, INSULATION_BURN_TEMP, 0.75f); + new CableStructure("cable_octal", 8, 1, OrePrefix.cableGtOctal, WIRE_OCTAL, INSULATION_BURN_TEMP, 0.75f, CableModel.INSULATED_INSTANCES[3]); public static final CableStructure CABLE_HEX = - new CableStructure("cable_hex", 16, 1, OrePrefix.cableGtHex, WIRE_HEX, INSULATION_BURN_TEMP, 1f); + new CableStructure("cable_hex", 16, 1, OrePrefix.cableGtHex, WIRE_HEX, INSULATION_BURN_TEMP, 1f, CableModel.INSULATED_INSTANCES[4]); @Override public @NotNull String getName() { - return this.name(); + return name; } @Override public OrePrefix getOrePrefix() { - return this.ore(); + return ore; } @Override public float getRenderThickness() { - return renderThickness(); + return renderThickness; + } + + @Override + public AbstractPipeModel getModel() { + return model; } @Override @@ -60,7 +71,7 @@ public boolean isPaintable() { @Override public boolean isInsulated() { - return partialBurnStructure() != null; + return partialBurnStructure != null; } public static void registerDefaultStructures(Consumer register) { diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java new file mode 100644 index 00000000000..70c0be612be --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java @@ -0,0 +1,44 @@ +package gregtech.common.pipelike.block.laser; + +import gregtech.api.graphnet.gather.GatherStructuresEvent; +import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; +import gregtech.api.graphnet.pipenet.physical.IBurnable; +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.items.toolitem.ToolClasses; +import gregtech.api.items.toolitem.ToolHelper; +import gregtech.common.pipelike.block.optical.OpticalStructure; +import gregtech.common.pipelike.handlers.LaserNetHandler; +import gregtech.common.pipelike.handlers.OpticalNetHandler; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.MinecraftForge; + +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +public class LaserPipeBlock extends WorldPipeBlock implements IBurnable { + + public LaserPipeBlock(LaserStructure structure) { + super(structure); + setHarvestLevel(ToolClasses.WIRE_CUTTER, 1); + } + + public static Set gatherStructures() { + GatherStructuresEvent event = new GatherStructuresEvent<>(LaserStructure.class); + MinecraftForge.EVENT_BUS.post(event); + return event.getGathered(); + } + + @Override + public boolean isPipeTool(@NotNull ItemStack stack) { + return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); + } + + @Override + protected @NotNull IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos) { + return LaserNetHandler.INSTANCE; + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java new file mode 100644 index 00000000000..0c17c0f75be --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java @@ -0,0 +1,48 @@ +package gregtech.common.pipelike.block.laser; + +import com.github.bsideup.jabel.Desugar; + +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.AbstractPipeModel; +import gregtech.client.renderer.pipe.ActivablePipeModel; + +import net.minecraft.util.EnumFacing; + +import org.jetbrains.annotations.NotNull; + +@Desugar +public record LaserStructure(String name, float renderThickness, ActivablePipeModel model) implements IPipeStructure { + + public static final LaserStructure INSTANCE = new LaserStructure("standard", 0.375f, ActivablePipeModel.LASER); + + @Override + public boolean canConnectTo(EnumFacing side, byte connectionMask) { + for (EnumFacing facing : EnumFacing.VALUES) { + if (GTUtility.evalMask(facing, connectionMask)) { + return facing.getOpposite() == side; + } + } + return true; + } + + @Override + public @NotNull String getName() { + return name; + } + + @Override + public float getRenderThickness() { + return renderThickness; + } + + @Override + public boolean isPaintable() { + return true; + } + + @Override + public AbstractPipeModel getModel() { + return model; + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java new file mode 100644 index 00000000000..3a762494506 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java @@ -0,0 +1,43 @@ +package gregtech.common.pipelike.block.optical; + +import gregtech.api.graphnet.gather.GatherStructuresEvent; +import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; +import gregtech.api.graphnet.pipenet.physical.IBurnable; +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.items.toolitem.ToolClasses; +import gregtech.api.items.toolitem.ToolHelper; + +import gregtech.common.pipelike.handlers.OpticalNetHandler; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraftforge.common.MinecraftForge; + +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +public class OpticalPipeBlock extends WorldPipeBlock implements IBurnable { + + public OpticalPipeBlock(OpticalStructure structure) { + super(structure); + setHarvestLevel(ToolClasses.WIRE_CUTTER, 1); + } + + public static Set gatherStructures() { + GatherStructuresEvent event = new GatherStructuresEvent<>(OpticalStructure.class); + MinecraftForge.EVENT_BUS.post(event); + return event.getGathered(); + } + + @Override + public boolean isPipeTool(@NotNull ItemStack stack) { + return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); + } + + @Override + protected @NotNull IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos) { + return OpticalNetHandler.INSTANCE; + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java new file mode 100644 index 00000000000..661d865ee3f --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java @@ -0,0 +1,50 @@ +package gregtech.common.pipelike.block.optical; + +import com.github.bsideup.jabel.Desugar; + +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.AbstractPipeModel; +import gregtech.client.renderer.pipe.ActivablePipeModel; + +import net.minecraft.util.EnumFacing; + +import org.jetbrains.annotations.NotNull; + +@Desugar +public record OpticalStructure(String name, float renderThickness, ActivablePipeModel model) implements IPipeStructure { + + public static final OpticalStructure INSTANCE = new OpticalStructure("standard", 0.375f, ActivablePipeModel.OPTICAL); + + @Override + public boolean canConnectTo(EnumFacing side, byte connectionMask) { + byte connectionCount = 0; + for (EnumFacing facing : EnumFacing.VALUES) { + if (GTUtility.evalMask(facing, connectionMask)) { + connectionCount++; + } + if (connectionCount > 1) return false; + } + return true; + } + + @Override + public @NotNull String getName() { + return name; + } + + @Override + public float getRenderThickness() { + return renderThickness; + } + + @Override + public boolean isPaintable() { + return true; + } + + @Override + public AbstractPipeModel getModel() { + return model; + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java index 78c39715248..61d99eedf85 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java @@ -37,10 +37,4 @@ public static Set gatherStructures() { MinecraftForge.EVENT_BUS.post(event); return event.getGathered(); } - - // TODO rendering - @Override - protected Pair getParticleTexture(World world, BlockPos blockPos) { - return null; - } } diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java index 671d2e32bbb..751ab0b25c4 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java @@ -1,50 +1,77 @@ package gregtech.common.pipelike.block.pipe; +import com.github.bsideup.jabel.Desugar; + import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.unification.ore.OrePrefix; -import gregtech.common.pipelike.block.cable.CableStructure; +import gregtech.client.renderer.pipe.AbstractPipeModel; +import gregtech.client.renderer.pipe.PipeItemModel; +import gregtech.client.renderer.pipe.PipeModel; + +import gregtech.client.renderer.pipe.util.WoodCacheKey; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; -public record PipeStructure(String name, int material, int channelCount, boolean restrictive, OrePrefix ore, float renderThickness) +@Desugar +public record PipeStructure(String name, int material, int channelCount, boolean restrictive, OrePrefix ore, + float renderThickness, PipeModel model) implements IPipeMaterialStructure { - public static final PipeStructure TINY = new PipeStructure("tiny", 1, 1, false, OrePrefix.pipeTiny, 0.25f); - public static final PipeStructure SMALL = new PipeStructure("small", 2, 1, false, OrePrefix.pipeSmall, 0.375f); - public static final PipeStructure NORMAL = new PipeStructure("normal", 6, 1, false, OrePrefix.pipeNormal, 0.5f); - public static final PipeStructure LARGE = new PipeStructure("large", 12, 1, false, OrePrefix.pipeLarge, 0.75f); - public static final PipeStructure HUGE = new PipeStructure("huge", 24, 1, false, OrePrefix.pipeHuge, 0.875f); + public static final PipeStructure TINY = + new PipeStructure("tiny", 1, 1, false, OrePrefix.pipeTiny, 0.25f, PipeModel.INSTANCES[0]); + public static final PipeStructure SMALL = + new PipeStructure("small", 2, 1, false, OrePrefix.pipeSmall, 0.375f, PipeModel.INSTANCES[1]); + public static final PipeStructure NORMAL = + new PipeStructure("normal", 6, 1, false, OrePrefix.pipeNormal, 0.5f, PipeModel.INSTANCES[2]); + public static final PipeStructure LARGE = + new PipeStructure("large", 12, 1, false, OrePrefix.pipeLarge, 0.75f, PipeModel.INSTANCES[3]); + public static final PipeStructure HUGE = + new PipeStructure("huge", 24, 1, false, OrePrefix.pipeHuge, 0.875f, PipeModel.INSTANCES[4]); // TODO adjust quadruple and nonuple thicknesses to 0.5f and 0.75f respectively, and update textures accordingly - public static final PipeStructure QUADRUPLE = new PipeStructure("quadruple", 8, 4, false, OrePrefix.pipeQuadruple, 0.95f); - public static final PipeStructure NONUPLE = new PipeStructure("nonuple", 18, 9, false, OrePrefix.pipeNonuple, 0.95f); - - - public static final PipeStructure TINY_RESTRICTIVE = new PipeStructure("tiny_restrictive", 1, 1, true, OrePrefix.pipeTinyRestrictive, 0.25f); - public static final PipeStructure SMALL_RESTRICTIVE = new PipeStructure("small_restrictive", 2, 1, true, OrePrefix.pipeSmallRestrictive, 0.375f); - public static final PipeStructure NORMAL_RESTRICTIVE = new PipeStructure("normal_restrictive", 6, 1, true, OrePrefix.pipeNormalRestrictive, 0.5f); - public static final PipeStructure LARGE_RESTRICTIVE = new PipeStructure("large_restrictive", 12, 1, true, OrePrefix.pipeLargeRestrictive, 0.75f); - public static final PipeStructure HUGE_RESTRICTIVE = new PipeStructure("huge_restrictive", 24, 1, true, OrePrefix.pipeHugeRestrictive, 0.875f); - - public static final PipeStructure QUADRUPLE_RESTRICTIVE = new PipeStructure("quadruple_restrictive", 8, 4, true, OrePrefix.pipeQuadrupleRestrictive, 0.95f); - public static final PipeStructure NONUPLE_RESTRICTIVE = new PipeStructure("nonuple_restrictive", 18, 9, true, OrePrefix.pipeNonupleRestrictive, 0.95f); + public static final PipeStructure QUADRUPLE = + new PipeStructure("quadruple", 8, 4, false, OrePrefix.pipeQuadruple, 0.95f, PipeModel.INSTANCES[5]); + public static final PipeStructure NONUPLE = + new PipeStructure("nonuple", 18, 9, false, OrePrefix.pipeNonuple, 0.95f, PipeModel.INSTANCES[6]); + + + public static final PipeStructure TINY_RESTRICTIVE = + new PipeStructure("tiny_restrictive", 1, 1, true, OrePrefix.pipeTinyRestrictive, 0.25f, PipeModel.RESTRICTIVE_INSTANCES[0]); + public static final PipeStructure SMALL_RESTRICTIVE = + new PipeStructure("small_restrictive", 2, 1, true, OrePrefix.pipeSmallRestrictive, 0.375f, PipeModel.RESTRICTIVE_INSTANCES[1]); + public static final PipeStructure NORMAL_RESTRICTIVE = + new PipeStructure("normal_restrictive", 6, 1, true, OrePrefix.pipeNormalRestrictive, 0.5f, PipeModel.RESTRICTIVE_INSTANCES[2]); + public static final PipeStructure LARGE_RESTRICTIVE = + new PipeStructure("large_restrictive", 12, 1, true, OrePrefix.pipeLargeRestrictive, 0.75f, PipeModel.RESTRICTIVE_INSTANCES[3]); + public static final PipeStructure HUGE_RESTRICTIVE = + new PipeStructure("huge_restrictive", 24, 1, true, OrePrefix.pipeHugeRestrictive, 0.875f, PipeModel.RESTRICTIVE_INSTANCES[4]); + + public static final PipeStructure QUADRUPLE_RESTRICTIVE = + new PipeStructure("quadruple_restrictive", 8, 4, true, OrePrefix.pipeQuadrupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[5]); + public static final PipeStructure NONUPLE_RESTRICTIVE = + new PipeStructure("nonuple_restrictive", 18, 9, true, OrePrefix.pipeNonupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[6]); @Override public @NotNull String getName() { - return this.name(); + return name; } @Override public OrePrefix getOrePrefix() { - return this.ore(); + return ore; } @Override public float getRenderThickness() { - return this.renderThickness(); + return renderThickness; + } + + @Override + public AbstractPipeModel getModel() { + return model; } @Override diff --git a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java new file mode 100644 index 00000000000..cc6dfc54bbf --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java @@ -0,0 +1,45 @@ +package gregtech.common.pipelike.handlers; + +import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.common.pipelike.block.laser.LaserStructure; +import gregtech.common.pipelike.block.optical.OpticalStructure; +import gregtech.common.pipelike.net.laser.WorldLaserNet; +import gregtech.common.pipelike.net.optical.WorldOpticalNet; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.util.Collection; +import java.util.Collections; + +public class LaserNetHandler implements IPipeNetNodeHandler { + + public static final LaserNetHandler INSTANCE = new LaserNetHandler(); + + @Override + public void addToNets(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof LaserStructure) { + WorldLaserNet.getWorldNet(world).getOrCreateNode(pos); + } + } + + @Override + public Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof LaserStructure) { + WorldPipeNetNode node = WorldLaserNet.getWorldNet(world).getNode(pos); + if (node != null) return Collections.singletonList(node); + } + return Collections.emptyList(); + } + + @Override + public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof LaserStructure) { + WorldLaserNet net = WorldLaserNet.getWorldNet(world); + WorldPipeNetNode node = net.getNode(pos); + if (node != null) net.removeNode(node); + } + } +} diff --git a/src/main/java/gregtech/common/pipelike/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/MaterialEnergyProperties.java similarity index 97% rename from src/main/java/gregtech/common/pipelike/properties/MaterialEnergyProperties.java rename to src/main/java/gregtech/common/pipelike/handlers/MaterialEnergyProperties.java index 1f4657f214b..6fc5229c39b 100644 --- a/src/main/java/gregtech/common/pipelike/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/MaterialEnergyProperties.java @@ -1,10 +1,9 @@ -package gregtech.common.pipelike.properties; +package gregtech.common.pipelike.handlers; import gregtech.api.GTValues; import gregtech.api.fluids.FluidBuilder; import gregtech.api.fluids.store.FluidStorageKeys; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.pipenet.logic.EnumLossFunction; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; @@ -29,8 +28,6 @@ import gregtech.common.pipelike.net.energy.VoltageLimitLogic; import gregtech.common.pipelike.net.energy.WorldEnergyNet; -import it.unimi.dsi.fastutil.floats.Float2ObjectArrayMap; - import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -39,8 +36,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Map; - import static gregtech.api.unification.material.info.MaterialFlags.GENERATE_FOIL; import static gregtech.api.unification.material.info.MaterialFlags.NO_UNIFICATION; @@ -72,6 +67,10 @@ public MaterialEnergyProperties(long voltageLimit, long amperageLimit, long loss this.superconductorCriticalTemperature = superconductorCriticalTemperature; } + public long getVoltageLimit() { + return voltageLimit; + } + public static MaterialEnergyProperties createT(long voltageLimit, long amperageLimit, long lossPerAmp, int temperatureLimit) { return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, temperatureLimit, 0); @@ -133,9 +132,9 @@ public void verifyProperty(MaterialProperties properties) { @Override public void addToNet(World world, BlockPos pos, IPipeStructure structure) { - if (structure instanceof CableStructure cable) { + if (structure instanceof CableStructure) { WorldPipeNetNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); - mutateData(node.getData(), cable); + mutateData(node.getData(), structure); } else if (structure instanceof PipeStructure pipe) { long amperage = amperageLimit * pipe.material() / 2; if (amperage == 0) return; // skip pipes that are too small diff --git a/src/main/java/gregtech/common/pipelike/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/MaterialFluidProperties.java similarity index 92% rename from src/main/java/gregtech/common/pipelike/properties/MaterialFluidProperties.java rename to src/main/java/gregtech/common/pipelike/handlers/MaterialFluidProperties.java index a5839d901c7..3934c4bd05f 100644 --- a/src/main/java/gregtech/common/pipelike/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/MaterialFluidProperties.java @@ -1,11 +1,9 @@ -package gregtech.common.pipelike.properties; +package gregtech.common.pipelike.handlers; -import gregtech.api.GTValues; import gregtech.api.fluids.FluidBuilder; import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.fluids.store.FluidStorageKeys; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.logic.NetLogicData; @@ -21,17 +19,10 @@ import gregtech.api.unification.material.properties.PropertyKey; -import gregtech.common.pipelike.block.cable.CableStructure; import gregtech.common.pipelike.block.pipe.PipeStructure; -import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; -import gregtech.common.pipelike.net.energy.VoltageLimitLogic; - -import gregtech.common.pipelike.net.energy.WorldEnergyNet; import gregtech.common.pipelike.net.fluid.WorldFluidNet; -import it.unimi.dsi.fastutil.objects.Object2BooleanMap; -import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.util.math.BlockPos; @@ -144,9 +135,9 @@ public void verifyProperty(MaterialProperties properties) { @Override public void addToNet(World world, BlockPos pos, IPipeStructure structure) { - if (structure instanceof PipeStructure pipe) { + if (structure instanceof PipeStructure) { WorldPipeNetNode node = WorldFluidNet.getWorldNet(world).getOrCreateNode(pos); - mutateData(node.getData(), pipe); + mutateData(node.getData(), structure); } } diff --git a/src/main/java/gregtech/common/pipelike/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/MaterialItemProperties.java similarity index 75% rename from src/main/java/gregtech/common/pipelike/properties/MaterialItemProperties.java rename to src/main/java/gregtech/common/pipelike/handlers/MaterialItemProperties.java index b799ee6a1f8..3b4f804ecc0 100644 --- a/src/main/java/gregtech/common/pipelike/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/MaterialItemProperties.java @@ -1,19 +1,11 @@ -package gregtech.common.pipelike.properties; +package gregtech.common.pipelike.handlers; -import gregtech.api.fluids.FluidBuilder; -import gregtech.api.fluids.FluidConstants; -import gregtech.api.fluids.FluidState; -import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.fluids.store.FluidStorageKeys; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; -import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.unification.material.properties.FluidProperty; import gregtech.api.unification.material.properties.MaterialProperties; import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; @@ -21,27 +13,21 @@ import gregtech.common.pipelike.net.item.WorldItemNet; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraftforge.fluids.Fluid; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.EnumSet; -import java.util.Set; - public class MaterialItemProperties implements PipeNetProperties.IPipeNetMaterialProperty { public static final String KEY = "item"; - private final long baseThroughput; + private final long baseItemsPer5Ticks; private final float priority; - public MaterialItemProperties(long baseThroughput, float priority) { - this.baseThroughput = baseThroughput; + public MaterialItemProperties(long baseItemsPer5Ticks, float priority) { + this.baseItemsPer5Ticks = baseItemsPer5Ticks; this.priority = priority; } public static MaterialItemProperties create(long baseThroughput) { @@ -62,16 +48,16 @@ public void verifyProperty(MaterialProperties properties) { @Override public void addToNet(World world, BlockPos pos, IPipeStructure structure) { - if (structure instanceof PipeStructure pipe) { + if (structure instanceof PipeStructure) { WorldPipeNetNode node = WorldItemNet.getWorldNet(world).getOrCreateNode(pos); - mutateData(node.getData(), pipe); + mutateData(node.getData(), structure); } } @Override public void mutateData(NetLogicData data, IPipeStructure structure) { if (structure instanceof PipeStructure pipe) { - long throughput = baseThroughput * pipe.material(); + long throughput = baseItemsPer5Ticks * pipe.material(); double weight = priority * (pipe.restrictive() ? 100d : 1d) * pipe.channelCount() / pipe.material(); data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(weight)) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)); diff --git a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java new file mode 100644 index 00000000000..f42ca541e1a --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java @@ -0,0 +1,44 @@ +package gregtech.common.pipelike.handlers; + +import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; + +import gregtech.common.pipelike.block.optical.OpticalStructure; +import gregtech.common.pipelike.net.optical.WorldOpticalNet; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.util.Collection; +import java.util.Collections; + +public class OpticalNetHandler implements IPipeNetNodeHandler { + + public static final OpticalNetHandler INSTANCE = new OpticalNetHandler(); + + @Override + public void addToNets(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof OpticalStructure) { + WorldOpticalNet.getWorldNet(world).getOrCreateNode(pos); + } + } + + @Override + public Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof OpticalStructure) { + WorldPipeNetNode node = WorldOpticalNet.getWorldNet(world).getNode(pos); + if (node != null) return Collections.singletonList(node); + } + return Collections.emptyList(); + } + + @Override + public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) { + if (structure instanceof OpticalStructure) { + WorldOpticalNet net = WorldOpticalNet.getWorldNet(world); + WorldPipeNetNode node = net.getNode(pos); + if (node != null) net.removeNode(node); + } + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 51d6e28de96..3c2c070bee1 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -69,6 +69,6 @@ public Iterator getPaths(WorldPipeNetNode node, IPredicate @Override public @NotNull NetFlowEdge getNewEdge() { - return new NetFlowEdge(5, 4); + return new NetFlowEdge(2, 5); } } diff --git a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java new file mode 100644 index 00000000000..01d3d2a1ba4 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java @@ -0,0 +1,54 @@ +package gregtech.common.pipelike.net.laser; + +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.graphnet.alg.SinglePathAlgorithm; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; + +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; + +public class WorldLaserNet extends WorldPipeNet implements BasicWorldPipeNetPath.Provider { + + public static final Capability[] CAPABILITIES = new Capability[] { GregtechTileCapabilities.CAPABILITY_LASER }; + + private static final String DATA_ID_BASE = "gregtech.world_laser_net"; + + public static WorldLaserNet getWorldNet(World world) { + final String DATA_ID = getDataID(DATA_ID_BASE, world); + WorldLaserNet net = (WorldLaserNet) world.loadData(WorldLaserNet.class, DATA_ID); + if (net == null) { + net = new WorldLaserNet(DATA_ID); + world.setData(DATA_ID, net); + } + return net; + } + + public WorldLaserNet(String name) { + super(name, false, SinglePathAlgorithm::new); + } + + @Override + public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, long queryTick) { + return backer.getPaths(node, 0, BasicWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); + } + + @Override + public Capability[] getTargetCapabilities() { + return CAPABILITIES; + } + + @Override + public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { + return null; // TODO + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java new file mode 100644 index 00000000000..85d79183ad3 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -0,0 +1,60 @@ +package gregtech.common.pipelike.net.optical; + +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; +import gregtech.api.graphnet.alg.ShortestPathsAlgorithm; +import gregtech.api.graphnet.alg.SinglePathAlgorithm; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import gregtech.common.pipelike.net.item.WorldItemNet; + +import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; + +import net.minecraftforge.items.CapabilityItemHandler; + +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; + +public class WorldOpticalNet extends WorldPipeNet implements BasicWorldPipeNetPath.Provider { + + public static final Capability[] CAPABILITIES = new Capability[] { GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER, GregtechTileCapabilities.CAPABILITY_DATA_ACCESS }; + + private static final String DATA_ID_BASE = "gregtech.world_optical_net"; + + public static WorldOpticalNet getWorldNet(World world) { + final String DATA_ID = getDataID(DATA_ID_BASE, world); + WorldOpticalNet net = (WorldOpticalNet) world.loadData(WorldOpticalNet.class, DATA_ID); + if (net == null) { + net = new WorldOpticalNet(DATA_ID); + world.setData(DATA_ID, net); + } + return net; + } + + public WorldOpticalNet(String name) { + super(name, false, SinglePathAlgorithm::new); + } + + @Override + public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, long queryTick) { + return backer.getPaths(node, 0, BasicWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); + } + + @Override + public Capability[] getTargetCapabilities() { + return CAPABILITIES; + } + + @Override + public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { + return null; // TODO + } +} diff --git a/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java b/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java index 3bdf2706209..1baec90e87c 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java @@ -11,8 +11,8 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.util.GTUtility; -import gregtech.client.renderer.pipe.CableRenderer; -import gregtech.client.renderer.pipe.PipeRenderer; +import gregtech.client.renderer.pipeold.CableRenderer; +import gregtech.client.renderer.pipeold.PipeRenderer; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.pipelikeold.cable.net.WorldEnergyNet; import gregtech.common.pipelikeold.cable.tile.TileEntityCable; diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java index 902212116cf..1f41fac4562 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java @@ -12,8 +12,8 @@ import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.util.EntityDamageUtil; -import gregtech.client.renderer.pipe.FluidPipeRenderer; -import gregtech.client.renderer.pipe.PipeRenderer; +import gregtech.client.renderer.pipeold.FluidPipeRenderer; +import gregtech.client.renderer.pipeold.PipeRenderer; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.pipelikeold.fluidpipe.net.WorldFluidPipeNet; import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java b/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java index 4488683e40c..9d2e55b6f43 100644 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java @@ -8,8 +8,8 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.unification.material.registry.MaterialRegistry; -import gregtech.client.renderer.pipe.ItemPipeRenderer; -import gregtech.client.renderer.pipe.PipeRenderer; +import gregtech.client.renderer.pipeold.ItemPipeRenderer; +import gregtech.client.renderer.pipeold.PipeRenderer; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.pipelikeold.itempipe.net.WorldItemPipeNet; import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipe; diff --git a/src/main/java/gregtech/common/pipelikeold/laser/BlockLaserPipe.java b/src/main/java/gregtech/common/pipelikeold/laser/BlockLaserPipe.java index 93342f9a892..b2fc95f24d4 100644 --- a/src/main/java/gregtech/common/pipelikeold/laser/BlockLaserPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/laser/BlockLaserPipe.java @@ -7,7 +7,7 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.client.renderer.pipe.LaserPipeRenderer; +import gregtech.client.renderer.pipeold.LaserPipeRenderer; import gregtech.client.utils.BloomEffectUtil; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.pipelikeold.laser.net.WorldLaserPipeNet; diff --git a/src/main/java/gregtech/common/pipelikeold/optical/BlockOpticalPipe.java b/src/main/java/gregtech/common/pipelikeold/optical/BlockOpticalPipe.java index 8dc1f64b2c3..11480e42a8c 100644 --- a/src/main/java/gregtech/common/pipelikeold/optical/BlockOpticalPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/optical/BlockOpticalPipe.java @@ -7,7 +7,7 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.client.renderer.pipe.OpticalPipeRenderer; +import gregtech.client.renderer.pipeold.OpticalPipeRenderer; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.pipelikeold.optical.net.WorldOpticalPipeNet; import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; diff --git a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java index 9ab25c9414e..7d15798cd13 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java @@ -10,7 +10,7 @@ import crafttweaker.annotations.ZenRegister; -import gregtech.common.pipelike.properties.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.MaterialEnergyProperties; import stanhebben.zenscript.annotations.Optional; import stanhebben.zenscript.annotations.ZenExpansion; diff --git a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java index 87e6d848a61..5ace606c37d 100644 --- a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java @@ -22,7 +22,7 @@ import com.cleanroommc.groovyscript.api.GroovyBlacklist; import com.cleanroommc.groovyscript.api.GroovyLog; -import gregtech.common.pipelike.properties.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.MaterialEnergyProperties; import static gregtech.integration.groovy.GroovyScriptModule.checkFrozen; diff --git a/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java index e5bbbc7a408..f9c9c1828c0 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java @@ -19,7 +19,7 @@ import gregtech.common.items.MetaItems; import gregtech.common.items.behaviors.AbstractMaterialPartBehavior; -import gregtech.common.pipelike.properties.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.MaterialEnergyProperties; import net.minecraft.item.EnumDyeColor; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java index e88b76afba5..db16e5dafce 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java @@ -5,13 +5,12 @@ import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; -import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.unification.stack.UnificationEntry; import com.google.common.collect.ImmutableMap; -import gregtech.common.pipelike.properties.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.MaterialEnergyProperties; import org.apache.commons.lang3.ArrayUtils; diff --git a/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java index 651e9a84fff..90ffd7957e3 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java @@ -12,7 +12,7 @@ import com.google.common.collect.ImmutableMap; -import gregtech.common.pipelike.properties.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.MaterialEnergyProperties; import java.util.Map; @@ -108,7 +108,7 @@ public static void generateCableCovering(OrePrefix wirePrefix, Material material int cableAmount = (int) (wirePrefix.getMaterialAmount(material) * 2 / GTValues.M); OrePrefix cablePrefix = OrePrefix.getPrefix("cable" + wirePrefix.name().substring(4)); - int voltageTier = GTUtility.getTierByVoltage(property.getVoltage()); + int voltageTier = GTUtility.getTierByVoltage(property.getVoltageLimit()); int insulationAmount = INSULATION_AMOUNT.get(cablePrefix); // Generate hand-crafting recipes for ULV and LV cables diff --git a/src/main/resources/assets/gregtech/textures/blocks/cable/insulation_5.png b/src/main/resources/assets/gregtech/textures/blocks/cable/insulation_full.png similarity index 100% rename from src/main/resources/assets/gregtech/textures/blocks/cable/insulation_5.png rename to src/main/resources/assets/gregtech/textures/blocks/cable/insulation_full.png From aa8053fa00123e26ff72dbc85f3232b9a59c2675 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 27 Jul 2024 01:26:33 -0600 Subject: [PATCH 079/157] Complete rewrite pt6 --- .../api/capability/GregtechDataCodes.java | 3 +- .../capability/GregtechTileCapabilities.java | 19 +-- .../api/capability/IDataAccessHatch.java | 36 ----- .../api/capability/ILaserContainer.java | 5 +- .../gregtech/api/capability/ILaserRelay.java | 12 ++ .../capability/IOpticalComputationHatch.java | 7 - .../IOpticalComputationProvider.java | 70 -------- .../IOpticalComputationReceiver.java | 11 -- .../capability/IOpticalDataAccessHatch.java | 9 -- .../capability/SimpleCapabilityManager.java | 6 +- .../capability/data/IComputationConsumer.java | 15 ++ .../data/IComputationDataAccess.java | 11 ++ .../capability/data/IComputationProvider.java | 24 +++ .../api/capability/data/IDataAccess.java | 50 ++++++ .../api/capability/data/IHatchDataAccess.java | 11 ++ .../capability/data/IStandardDataAccess.java | 11 ++ .../data/query/ComputationQuery.java | 63 ++++++++ .../data/query/DataAccessFormat.java | 42 +++++ .../data/query/DataQueryFormat.java | 14 ++ .../data/query/DataQueryObject.java | 29 ++++ .../capability/data/query/IBridgeable.java | 9 ++ .../data/query/IComputationQuery.java | 8 + .../data/query/RecipeDataQuery.java | 32 ++++ .../impl/ComputationRecipeLogic.java | 27 ++-- .../impl/LaserContainerHandler.java | 15 +- .../tile/PipeActivableTileEntity.java | 24 ++- .../pipenet/physical/tile/PipeTileEntity.java | 4 + .../multiblock/MultiblockAbility.java | 17 +- .../multiblock/MultiblockDisplayText.java | 2 +- .../java/gregtech/api/util/GTUtility.java | 6 + .../metatileentities/MetaTileEntities.java | 2 +- .../MetaTileEntityActiveTransformer.java | 11 +- .../electric/MetaTileEntityAssemblyLine.java | 16 +- .../electric/MetaTileEntityDataBank.java | 3 +- .../multi/electric/MetaTileEntityHPCA.java | 20 ++- .../electric/MetaTileEntityNetworkSwitch.java | 153 ++---------------- .../MetaTileEntityPowerSubstation.java | 8 +- .../MetaTileEntityResearchStation.java | 30 ++-- .../MetaTileEntityComputationHatch.java | 123 +++++--------- .../MetaTileEntityDataAccessHatch.java | 31 ++-- .../MetaTileEntityLaserHatch.java | 27 ++-- .../MetaTileEntityOpticalDataHatch.java | 74 +++------ .../storage/MetaTileEntityCreativeEnergy.java | 4 +- .../common/pipelike/net/SlowActiveWalker.java | 78 +++++++++ .../net/energy/EnergyCapabilityObject.java | 9 +- .../net/laser/LaserCapabilityObject.java | 90 +++++++++++ .../pipelike/net/laser/WorldLaserNet.java | 2 +- .../net/optical/DataCapabilityObject.java | 98 +++++++++++ .../pipelike/net/optical/WorldOpticalNet.java | 8 +- .../laser/net/LaserNetHandler.java | 18 +-- .../laser/tile/TileEntityLaserPipe.java | 6 +- .../optical/net/OpticalNetHandler.java | 15 +- .../optical/tile/TileEntityOpticalPipe.java | 20 +-- .../provider/LaserContainerInfoProvider.java | 10 +- 54 files changed, 869 insertions(+), 579 deletions(-) delete mode 100644 src/main/java/gregtech/api/capability/IDataAccessHatch.java create mode 100644 src/main/java/gregtech/api/capability/ILaserRelay.java delete mode 100644 src/main/java/gregtech/api/capability/IOpticalComputationHatch.java delete mode 100644 src/main/java/gregtech/api/capability/IOpticalComputationProvider.java delete mode 100644 src/main/java/gregtech/api/capability/IOpticalComputationReceiver.java delete mode 100644 src/main/java/gregtech/api/capability/IOpticalDataAccessHatch.java create mode 100644 src/main/java/gregtech/api/capability/data/IComputationConsumer.java create mode 100644 src/main/java/gregtech/api/capability/data/IComputationDataAccess.java create mode 100644 src/main/java/gregtech/api/capability/data/IComputationProvider.java create mode 100644 src/main/java/gregtech/api/capability/data/IDataAccess.java create mode 100644 src/main/java/gregtech/api/capability/data/IHatchDataAccess.java create mode 100644 src/main/java/gregtech/api/capability/data/IStandardDataAccess.java create mode 100644 src/main/java/gregtech/api/capability/data/query/ComputationQuery.java create mode 100644 src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java create mode 100644 src/main/java/gregtech/api/capability/data/query/DataQueryFormat.java create mode 100644 src/main/java/gregtech/api/capability/data/query/DataQueryObject.java create mode 100644 src/main/java/gregtech/api/capability/data/query/IBridgeable.java create mode 100644 src/main/java/gregtech/api/capability/data/query/IComputationQuery.java create mode 100644 src/main/java/gregtech/api/capability/data/query/RecipeDataQuery.java create mode 100644 src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java create mode 100644 src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java create mode 100644 src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java diff --git a/src/main/java/gregtech/api/capability/GregtechDataCodes.java b/src/main/java/gregtech/api/capability/GregtechDataCodes.java index 38a459c13f6..8a31ad902dc 100644 --- a/src/main/java/gregtech/api/capability/GregtechDataCodes.java +++ b/src/main/java/gregtech/api/capability/GregtechDataCodes.java @@ -68,8 +68,7 @@ public static int assignId() { public static final int UPDATE_COVER_DATA_PIPE = assignId(); public static final int COVER_ATTACHED_PIPE = assignId(); public static final int COVER_REMOVED_PIPE = assignId(); - public static final int PIPE_OPTICAL_ACTIVE = assignId(); - public static final int PIPE_LASER_ACTIVE = assignId(); + public static final int PIPE_ACTIVE = assignId(); public static final int CABLE_TEMPERATURE = assignId(); public static final int UPDATE_PIPE_LOGIC = assignId(); diff --git a/src/main/java/gregtech/api/capability/GregtechTileCapabilities.java b/src/main/java/gregtech/api/capability/GregtechTileCapabilities.java index 170ec74984f..1af7b4a17e6 100644 --- a/src/main/java/gregtech/api/capability/GregtechTileCapabilities.java +++ b/src/main/java/gregtech/api/capability/GregtechTileCapabilities.java @@ -1,5 +1,6 @@ package gregtech.api.capability; +import gregtech.api.capability.data.IDataAccess; import gregtech.api.capability.impl.AbstractRecipeLogic; import gregtech.api.cover.CoverHolder; import gregtech.api.metatileentity.multiblock.IMaintenance; @@ -7,8 +8,6 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; -import org.jetbrains.annotations.ApiStatus; - public class GregtechTileCapabilities { @CapabilityInject(IWorkable.class) @@ -32,17 +31,9 @@ public class GregtechTileCapabilities { @CapabilityInject(IMaintenance.class) public static Capability CAPABILITY_MAINTENANCE = null; - @CapabilityInject(IDataAccessHatch.class) - public static Capability CAPABILITY_DATA_ACCESS = null; - - @CapabilityInject(ILaserContainer.class) - public static Capability CAPABILITY_LASER = null; - - @CapabilityInject(IOpticalComputationProvider.class) - public static Capability CAPABILITY_COMPUTATION_PROVIDER = null; + @CapabilityInject(IDataAccess.class) + public static Capability CAPABILITY_DATA_ACCESS = null; - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "2.9") - @CapabilityInject(IOpticalComputationProvider.class) - public static Capability CABABILITY_COMPUTATION_PROVIDER = null; + @CapabilityInject(ILaserRelay.class) + public static Capability CAPABILITY_LASER = null; } diff --git a/src/main/java/gregtech/api/capability/IDataAccessHatch.java b/src/main/java/gregtech/api/capability/IDataAccessHatch.java deleted file mode 100644 index ff5ec3d2f26..00000000000 --- a/src/main/java/gregtech/api/capability/IDataAccessHatch.java +++ /dev/null @@ -1,36 +0,0 @@ -package gregtech.api.capability; - -import gregtech.api.recipes.Recipe; - -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Collection; - -public interface IDataAccessHatch { - - /** - * If passed a {@code seen} context, you must use {@link #isRecipeAvailable(Recipe, Collection)} to prevent - * infinite recursion - * - * @param recipe the recipe to check - * @return if the recipe is available for use - */ - default boolean isRecipeAvailable(@NotNull Recipe recipe) { - Collection list = new ArrayList<>(); - list.add(this); - return isRecipeAvailable(recipe, list); - } - - /** - * @param recipe the recipe to check - * @param seen the hatches already checked - * @return if the recipe is available for use - */ - boolean isRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen); - - /** - * @return true if this Data Access Hatch is creative or not - */ - boolean isCreative(); -} diff --git a/src/main/java/gregtech/api/capability/ILaserContainer.java b/src/main/java/gregtech/api/capability/ILaserContainer.java index 4f051cd8a8e..60d9a6a347a 100644 --- a/src/main/java/gregtech/api/capability/ILaserContainer.java +++ b/src/main/java/gregtech/api/capability/ILaserContainer.java @@ -1,6 +1,3 @@ package gregtech.api.capability; -/** - * It is its own separate interface to make piping work easier - */ -public interface ILaserContainer extends IEnergyContainer {} +public interface ILaserContainer extends ILaserRelay, IEnergyContainer {} diff --git a/src/main/java/gregtech/api/capability/ILaserRelay.java b/src/main/java/gregtech/api/capability/ILaserRelay.java new file mode 100644 index 00000000000..c31cdc1caed --- /dev/null +++ b/src/main/java/gregtech/api/capability/ILaserRelay.java @@ -0,0 +1,12 @@ +package gregtech.api.capability; + +public interface ILaserRelay { + + /** + * Receive a laser pulse. + * @param laserVoltage the voltage of the laser. + * @param laserAmperage the amperage of the laser. + * @return how much amperage was received. + */ + long receiveLaser(long laserVoltage, long laserAmperage); +} diff --git a/src/main/java/gregtech/api/capability/IOpticalComputationHatch.java b/src/main/java/gregtech/api/capability/IOpticalComputationHatch.java deleted file mode 100644 index c7256994652..00000000000 --- a/src/main/java/gregtech/api/capability/IOpticalComputationHatch.java +++ /dev/null @@ -1,7 +0,0 @@ -package gregtech.api.capability; - -public interface IOpticalComputationHatch extends IOpticalComputationProvider { - - /** If this hatch transmits or receives CWU/t. */ - boolean isTransmitter(); -} diff --git a/src/main/java/gregtech/api/capability/IOpticalComputationProvider.java b/src/main/java/gregtech/api/capability/IOpticalComputationProvider.java deleted file mode 100644 index a30c2219bc7..00000000000 --- a/src/main/java/gregtech/api/capability/IOpticalComputationProvider.java +++ /dev/null @@ -1,70 +0,0 @@ -package gregtech.api.capability; - -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * MUST be implemented on any multiblock which uses - * Transmitter Computation Hatches in its structure. - */ -public interface IOpticalComputationProvider { - - /** - * Request some amount of CWU/t (Compute Work Units per tick) from this Machine. - * Implementors should expect these requests to occur each tick that computation is required. - * - * @param cwut Maximum amount of CWU/t requested. - * @return The amount of CWU/t that could be supplied. - */ - default int requestCWUt(int cwut, boolean simulate) { - Collection list = new ArrayList<>(); - list.add(this); - return requestCWUt(cwut, simulate, list); - } - - /** - * Request some amount of CWU/t (Compute Work Units per tick) from this Machine. - * Implementors should expect these requests to occur each tick that computation is required. - * - * @param cwut Maximum amount of CWU/t requested. - * @param seen The Optical Computation Providers already checked - * @return The amount of CWU/t that could be supplied. - */ - int requestCWUt(int cwut, boolean simulate, @NotNull Collection seen); - - /** - * The maximum of CWU/t that this computation provider can provide. - */ - default int getMaxCWUt() { - Collection list = new ArrayList<>(); - list.add(this); - return getMaxCWUt(list); - } - - /** - * The maximum of CWU/t that this computation provider can provide. - * - * @param seen The Optical Computation Providers already checked - */ - int getMaxCWUt(@NotNull Collection seen); - - /** - * Whether this Computation Provider can "Bridge" with other Computation Providers. - * Checked by machines like the Network Switch. - */ - default boolean canBridge() { - Collection list = new ArrayList<>(); - list.add(this); - return canBridge(list); - } - - /** - * Whether this Computation Provider can "Bridge" with other Computation Providers. - * Checked by machines like the Network Switch. - * - * @param seen The Optical Computation Providers already checked - */ - boolean canBridge(@NotNull Collection seen); -} diff --git a/src/main/java/gregtech/api/capability/IOpticalComputationReceiver.java b/src/main/java/gregtech/api/capability/IOpticalComputationReceiver.java deleted file mode 100644 index 231ad946643..00000000000 --- a/src/main/java/gregtech/api/capability/IOpticalComputationReceiver.java +++ /dev/null @@ -1,11 +0,0 @@ -package gregtech.api.capability; - -import gregtech.api.capability.impl.ComputationRecipeLogic; - -/** - * Used in conjunction with {@link ComputationRecipeLogic}. - */ -public interface IOpticalComputationReceiver { - - IOpticalComputationProvider getComputationProvider(); -} diff --git a/src/main/java/gregtech/api/capability/IOpticalDataAccessHatch.java b/src/main/java/gregtech/api/capability/IOpticalDataAccessHatch.java deleted file mode 100644 index 3caa747a8b5..00000000000 --- a/src/main/java/gregtech/api/capability/IOpticalDataAccessHatch.java +++ /dev/null @@ -1,9 +0,0 @@ -package gregtech.api.capability; - -public interface IOpticalDataAccessHatch extends IDataAccessHatch { - - /** - * @return if this hatch transmits data through cables - */ - boolean isTransmitter(); -} diff --git a/src/main/java/gregtech/api/capability/SimpleCapabilityManager.java b/src/main/java/gregtech/api/capability/SimpleCapabilityManager.java index 8aad39dc29c..d7a1035932d 100644 --- a/src/main/java/gregtech/api/capability/SimpleCapabilityManager.java +++ b/src/main/java/gregtech/api/capability/SimpleCapabilityManager.java @@ -1,5 +1,6 @@ package gregtech.api.capability; +import gregtech.api.capability.data.IDataAccess; import gregtech.api.capability.impl.AbstractRecipeLogic; import gregtech.api.cover.CoverHolder; import gregtech.api.metatileentity.multiblock.IMaintenance; @@ -46,11 +47,10 @@ public static void init() { registerCapabilityWithNoDefault(IMaintenance.class); registerCapabilityWithNoDefault(IMultipleRecipeMaps.class); registerCapabilityWithNoDefault(AbstractRecipeLogic.class); - registerCapabilityWithNoDefault(IDataAccessHatch.class); - registerCapabilityWithNoDefault(IOpticalComputationProvider.class); + registerCapabilityWithNoDefault(IDataAccess.class); registerCapabilityWithNoDefault(HardwareProvider.class); registerCapabilityWithNoDefault(ConverterTrait.class); - registerCapabilityWithNoDefault(ILaserContainer.class); + registerCapabilityWithNoDefault(ILaserRelay.class); // internal capabilities CapabilityManager.INSTANCE.register(GTWorldGenCapability.class, GTWorldGenCapability.STORAGE, diff --git a/src/main/java/gregtech/api/capability/data/IComputationConsumer.java b/src/main/java/gregtech/api/capability/data/IComputationConsumer.java new file mode 100644 index 00000000000..19f73509290 --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/IComputationConsumer.java @@ -0,0 +1,15 @@ +package gregtech.api.capability.data; + +/** + * Used for {@link gregtech.api.capability.impl.ComputationRecipeLogic} + */ +public interface IComputationConsumer { + + /** + * Called to supply CWU. + * @param requested the requested CWU + * @param simulate whether to simulate the request + * @return the amount of CWU supplied. + */ + long supplyCWU(long requested, boolean simulate); +} diff --git a/src/main/java/gregtech/api/capability/data/IComputationDataAccess.java b/src/main/java/gregtech/api/capability/data/IComputationDataAccess.java new file mode 100644 index 00000000000..f97bbce4406 --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/IComputationDataAccess.java @@ -0,0 +1,11 @@ +package gregtech.api.capability.data; + +import gregtech.api.capability.data.query.DataAccessFormat; + +public interface IComputationDataAccess extends IHatchDataAccess { + + @Override + default DataAccessFormat getFormat() { + return DataAccessFormat.COMPUTATION; + } +} diff --git a/src/main/java/gregtech/api/capability/data/IComputationProvider.java b/src/main/java/gregtech/api/capability/data/IComputationProvider.java new file mode 100644 index 00000000000..2a47ce7a7ed --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/IComputationProvider.java @@ -0,0 +1,24 @@ +package gregtech.api.capability.data; + +public interface IComputationProvider { + + /** + * Returns whether this provider supports bridging. If false, CWU will not be requested through + * network switches with multiple inputs. + * @return whether bridging is supported. + */ + boolean supportsBridging(); + + /** + * Called to supply CWU to a requester. + * @param requested the requested CWU + * @param simulate whether to simulate the request + * @return the amount of CWU supplied. + */ + long supplyCWU(long requested, boolean simulate); + + /** + * @return the maximum CWU that can be supplied in a single tick. + */ + long maxCWUt(); +} diff --git a/src/main/java/gregtech/api/capability/data/IDataAccess.java b/src/main/java/gregtech/api/capability/data/IDataAccess.java new file mode 100644 index 00000000000..d236a5e8312 --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/IDataAccess.java @@ -0,0 +1,50 @@ +package gregtech.api.capability.data; + +import gregtech.api.capability.data.query.DataAccessFormat; +import gregtech.api.capability.data.query.DataQueryObject; + +import org.jetbrains.annotations.NotNull; + +public interface IDataAccess { + + /** + * Queries this {@link IDataAccess} with the specified query. + * @param queryObject the object representing the query. Can be cached in a weak set created by + * {@link gregtech.api.util.GTUtility#createWeakHashSet()} in order to prevent endless recursion. + * @return if the query has been cancelled + */ + boolean accessData(@NotNull DataQueryObject queryObject); + + /** + * @return the {@link DataAccessFormat} this {@link IDataAccess} uses. + */ + DataAccessFormat getFormat(); + + /** + * @param queryObject a query object + * @return whether this {@link IDataAccess} supports the query object. + */ + default boolean supportsQuery(@NotNull DataQueryObject queryObject) { + return getFormat().supportsFormat(queryObject.getFormat()); + } + + /** + * Provides standardized logic for querying a collection of {@link IDataAccess}es. + * @param accesses the {@link IDataAccess}es to query. + * @param query the object representing the query. + * @return if the query has been cancelled + */ + static boolean accessDatas(@NotNull Iterable accesses, + @NotNull DataQueryObject query) { + boolean walk = false; + boolean cancelled = false; + for (IDataAccess access : accesses) { + query.setShouldTriggerWalker(false); + cancelled = access.accessData(query); + if (!walk) walk = query.shouldTriggerWalker(); + if (cancelled) break; + } + query.setShouldTriggerWalker(walk); + return cancelled; + } +} diff --git a/src/main/java/gregtech/api/capability/data/IHatchDataAccess.java b/src/main/java/gregtech/api/capability/data/IHatchDataAccess.java new file mode 100644 index 00000000000..5c0332a9c45 --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/IHatchDataAccess.java @@ -0,0 +1,11 @@ +package gregtech.api.capability.data; + +import gregtech.api.capability.data.IDataAccess; + +public interface IHatchDataAccess extends IDataAccess { + + /** + * @return if this hatch transmits data through cables + */ + boolean isTransmitter(); +} diff --git a/src/main/java/gregtech/api/capability/data/IStandardDataAccess.java b/src/main/java/gregtech/api/capability/data/IStandardDataAccess.java new file mode 100644 index 00000000000..02dfb6400ae --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/IStandardDataAccess.java @@ -0,0 +1,11 @@ +package gregtech.api.capability.data; + +import gregtech.api.capability.data.query.DataAccessFormat; + +public interface IStandardDataAccess extends IHatchDataAccess { + + @Override + default DataAccessFormat getFormat() { + return DataAccessFormat.STANDARD; + } +} diff --git a/src/main/java/gregtech/api/capability/data/query/ComputationQuery.java b/src/main/java/gregtech/api/capability/data/query/ComputationQuery.java new file mode 100644 index 00000000000..e28640d3c96 --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/query/ComputationQuery.java @@ -0,0 +1,63 @@ +package gregtech.api.capability.data.query; + +import gregtech.api.capability.data.IComputationProvider; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import java.util.Set; + +public class ComputationQuery extends DataQueryObject implements IComputationQuery { + + private final Set providers; + + private boolean bridged = false; + private boolean foundUnbridgeable = false; + + public ComputationQuery() { + providers = new ObjectOpenHashSet<>(); + } + + @Override + public DataQueryFormat getFormat() { + return DataQueryFormat.COMPUTATION; + } + + @Override + public void setBridged() { + this.bridged = true; + } + + public boolean foundUnbridgeable() { + return foundUnbridgeable; + } + + @Override + public void registerProvider(IComputationProvider provider) { + if (bridged && !provider.supportsBridging()) { + foundUnbridgeable = true; + return; + } + providers.add(provider); + } + + public Set getProviders() { + return providers; + } + + public long requestCWU(long amount, boolean simulate) { + long remaining = amount; + for (IComputationProvider provider : getProviders()) { + remaining -= provider.supplyCWU(remaining, simulate); + if (remaining <= 0) return amount; + } + return amount - remaining; + } + + public long maxCWUt() { + long amount = 0; + for (IComputationProvider provider : getProviders()) { + amount += provider.maxCWUt(); + } + return amount; + } +} diff --git a/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java b/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java new file mode 100644 index 00000000000..61f0a0736c9 --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java @@ -0,0 +1,42 @@ +package gregtech.api.capability.data.query; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.Contract; + +import java.util.Set; + +public final class DataAccessFormat { + + public static final DataAccessFormat STANDARD = create(DataQueryFormat.RECIPE); + public static final DataAccessFormat COMPUTATION = create(DataQueryFormat.COMPUTATION); + + public static final DataAccessFormat UNIVERSAL = new DataAccessFormat(null); + + private final Set supportedFormats; + + public static DataAccessFormat create(DataQueryFormat... allowedFormats) { + return new DataAccessFormat(new ObjectOpenHashSet<>(allowedFormats)); + } + + private DataAccessFormat(Set supportedFormats) { + this.supportedFormats = supportedFormats; + } + + @Contract("_ -> this") + public DataAccessFormat support(DataQueryFormat format) { + if (supportedFormats != null) this.supportedFormats.add(format); + return this; + } + + @Contract("_ -> this") + public DataAccessFormat notSupport(DataQueryFormat format) { + if (supportedFormats != null) this.supportedFormats.remove(format); + return this; + } + + public boolean supportsFormat(DataQueryFormat format) { + if (supportedFormats == null) return true; + else return supportedFormats.contains(format); + } + +} diff --git a/src/main/java/gregtech/api/capability/data/query/DataQueryFormat.java b/src/main/java/gregtech/api/capability/data/query/DataQueryFormat.java new file mode 100644 index 00000000000..5603aa3d5a7 --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/query/DataQueryFormat.java @@ -0,0 +1,14 @@ +package gregtech.api.capability.data.query; + +public final class DataQueryFormat { + + public static final DataQueryFormat RECIPE = create(); + public static final DataQueryFormat COMPUTATION = create(); + + @SuppressWarnings("InstantiationOfUtilityClass") + public static DataQueryFormat create() { + return new DataQueryFormat(); + } + + private DataQueryFormat() {} +} diff --git a/src/main/java/gregtech/api/capability/data/query/DataQueryObject.java b/src/main/java/gregtech/api/capability/data/query/DataQueryObject.java new file mode 100644 index 00000000000..441c98fcb99 --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/query/DataQueryObject.java @@ -0,0 +1,29 @@ +package gregtech.api.capability.data.query; + +public abstract class DataQueryObject { + + private static int ID = 0; + + private final int id; + + private boolean shouldTriggerWalker = false; + + public DataQueryObject() { + this.id = ID++; + } + + public void setShouldTriggerWalker(boolean shouldTriggerWalker) { + this.shouldTriggerWalker = shouldTriggerWalker; + } + + public boolean shouldTriggerWalker() { + return shouldTriggerWalker; + } + + public abstract DataQueryFormat getFormat(); + + @Override + public int hashCode() { + return id; + } +} diff --git a/src/main/java/gregtech/api/capability/data/query/IBridgeable.java b/src/main/java/gregtech/api/capability/data/query/IBridgeable.java new file mode 100644 index 00000000000..58377243441 --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/query/IBridgeable.java @@ -0,0 +1,9 @@ +package gregtech.api.capability.data.query; + +public interface IBridgeable { + + /** + * Called when a query has traversed a multiblock with more than one reception point and continued onward. + */ + void setBridged(); +} diff --git a/src/main/java/gregtech/api/capability/data/query/IComputationQuery.java b/src/main/java/gregtech/api/capability/data/query/IComputationQuery.java new file mode 100644 index 00000000000..ec80e2db9dd --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/query/IComputationQuery.java @@ -0,0 +1,8 @@ +package gregtech.api.capability.data.query; + +import gregtech.api.capability.data.IComputationProvider; + +public interface IComputationQuery extends IBridgeable{ + + void registerProvider(IComputationProvider provider); +} diff --git a/src/main/java/gregtech/api/capability/data/query/RecipeDataQuery.java b/src/main/java/gregtech/api/capability/data/query/RecipeDataQuery.java new file mode 100644 index 00000000000..ffb05a10079 --- /dev/null +++ b/src/main/java/gregtech/api/capability/data/query/RecipeDataQuery.java @@ -0,0 +1,32 @@ +package gregtech.api.capability.data.query; + +import gregtech.api.recipes.Recipe; + +public class RecipeDataQuery extends DataQueryObject { + + private final Recipe recipe; + + private boolean found = false; + + public RecipeDataQuery(Recipe recipe) { + this.recipe = recipe; + } + + @Override + public DataQueryFormat getFormat() { + return DataQueryFormat.RECIPE; + } + + public Recipe getRecipe() { + return recipe; + } + + public void setFound() { + this.found = true; + this.setShouldTriggerWalker(true); + } + + public boolean isFound() { + return found; + } +} diff --git a/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java index ffd91c5d3ff..ea84f98c663 100644 --- a/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java @@ -1,7 +1,6 @@ package gregtech.api.capability.impl; -import gregtech.api.capability.IOpticalComputationProvider; -import gregtech.api.capability.IOpticalComputationReceiver; +import gregtech.api.capability.data.IComputationConsumer; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.recipeproperties.ComputationProperty; @@ -14,7 +13,7 @@ /** * Recipe Logic for multiblocks that require computation. * Used with RecipeMaps that contain recipes using the {@link ComputationProperty}. - * The Multiblock holding this logic must implement {@link IOpticalComputationProvider}. + * The Multiblock holding this logic must implement {@link IComputationConsumer}. */ public class ComputationRecipeLogic extends MultiblockRecipeLogic { @@ -30,18 +29,14 @@ public class ComputationRecipeLogic extends MultiblockRecipeLogic { private boolean hasNotEnoughComputation; private int currentDrawnCWUt; - public ComputationRecipeLogic(RecipeMapMultiblockController metaTileEntity, ComputationType type) { + public ComputationRecipeLogic(T metaTileEntity, ComputationType type) { super(metaTileEntity); this.type = type; - if (!(metaTileEntity instanceof IOpticalComputationReceiver)) { - throw new IllegalArgumentException("MetaTileEntity must be instanceof IOpticalComputationReceiver"); - } } @NotNull - public IOpticalComputationProvider getComputationProvider() { - IOpticalComputationReceiver controller = (IOpticalComputationReceiver) metaTileEntity; - return controller.getComputationProvider(); + public IComputationConsumer getComputationProvider() { + return (IComputationConsumer) getMetaTileEntity(); } @Override @@ -52,9 +47,9 @@ public boolean checkRecipe(@NotNull Recipe recipe) { if (!recipe.hasProperty(ComputationProperty.getInstance())) { return true; } - IOpticalComputationProvider provider = getComputationProvider(); + IComputationConsumer provider = getComputationProvider(); int recipeCWUt = recipe.getProperty(ComputationProperty.getInstance(), 0); - return provider.requestCWUt(recipeCWUt, true) >= recipeCWUt; + return provider.supplyCWU(recipeCWUt, true) >= recipeCWUt; } @Override @@ -74,18 +69,18 @@ protected void updateRecipeProgress() { if (canRecipeProgress && drawEnergy(recipeEUt, true)) { drawEnergy(recipeEUt, false); - IOpticalComputationProvider provider = getComputationProvider(); - int availableCWUt = provider.requestCWUt(Integer.MAX_VALUE, true); + IComputationConsumer provider = getComputationProvider(); + int availableCWUt = (int) provider.supplyCWU(Integer.MAX_VALUE, true); if (availableCWUt >= recipeCWUt) { // carry on as normal this.hasNotEnoughComputation = false; if (isDurationTotalCWU) { // draw as much CWU as possible, and increase progress by this amount - currentDrawnCWUt = provider.requestCWUt(availableCWUt, false); + currentDrawnCWUt = (int) provider.supplyCWU(availableCWUt, false); progressTime += currentDrawnCWUt; } else { // draw only the recipe CWU/t, and increase progress by 1 - provider.requestCWUt(recipeCWUt, false); + provider.supplyCWU(recipeCWUt, false); progressTime++; } if (progressTime > maxProgressTime) { diff --git a/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java b/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java index 1665374a43d..6142d18ad82 100644 --- a/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java +++ b/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java @@ -3,6 +3,7 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IEnergyContainer; import gregtech.api.capability.ILaserContainer; +import gregtech.api.capability.ILaserRelay; import gregtech.api.metatileentity.MetaTileEntity; import net.minecraft.tileentity.TileEntity; @@ -26,6 +27,13 @@ public static LaserContainerHandler receiverContainer(MetaTileEntity tileEntity, return new LaserContainerHandler(tileEntity, maxCapacity, maxInputVoltage, maxInputAmperage, 0L, 0L); } + @Override + public long receiveLaser(long laserVoltage, long laserAmperage) { + long allowedAmps = getEnergyCanBeInserted() / laserVoltage; + addEnergy(laserVoltage * allowedAmps); + return allowedAmps; + } + @Override public T getCapability(Capability capability) { if (capability == GregtechTileCapabilities.CAPABILITY_LASER) { @@ -56,11 +64,10 @@ public void update() { EnumFacing oppositeSide = side.getOpposite(); if (tileEntity != null && tileEntity.hasCapability(GregtechTileCapabilities.CAPABILITY_LASER, oppositeSide)) { - IEnergyContainer energyContainer = tileEntity + ILaserRelay relay = tileEntity .getCapability(GregtechTileCapabilities.CAPABILITY_LASER, oppositeSide); - if (energyContainer == null || !energyContainer.inputsEnergy(oppositeSide)) continue; - amperesUsed += energyContainer.acceptEnergyFromNetwork(oppositeSide, outputVoltage, - outputAmperes - amperesUsed); + if (relay == null) continue; + amperesUsed += relay.receiveLaser(outputVoltage, outputAmperes - amperesUsed); if (amperesUsed == outputAmperes) break; } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java index 227537c3ded..bd204ad187a 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java @@ -1,11 +1,15 @@ package gregtech.api.graphnet.pipenet.physical.tile; +import gregtech.api.capability.GregtechDataCodes; import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.client.renderer.pipe.ActivablePipeModel; +import net.minecraft.network.PacketBuffer; import net.minecraftforge.common.property.IExtendedBlockState; +import org.jetbrains.annotations.NotNull; + public class PipeActivableTileEntity extends PipeTileEntity implements IActivable { private boolean active; @@ -16,7 +20,11 @@ public PipeActivableTileEntity(WorldPipeBlock block) { @Override public void setActive(boolean active) { - this.active = active; + if (this.active != active) { + this.active = active; + writeCustomData(GregtechDataCodes.PIPE_ACTIVE, buf -> buf.writeBoolean(active)); + markDirty(); + } } @Override @@ -28,4 +36,18 @@ public boolean isActive() { public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { return super.getRenderInformation(state).withProperty(ActivablePipeModel.ACTIVE_PROPERTY, isActive()); } + + @Override + public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { + super.receiveCustomData(discriminator, buf); + if (discriminator == GregtechDataCodes.PIPE_ACTIVE) { + boolean active = buf.readBoolean(); + if (this.active != active) { + this.active = active; + scheduleRenderUpdate(); + } + } + } + + // do not save activeness to nbt, it should go away on world save & load. } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 962c7508007..f541fa22825 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -515,14 +515,18 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { } else if (discriminator == UPDATE_CONNECTIONS) { this.connectionMask = buf.readByte(); this.renderMask = buf.readByte(); + scheduleRenderUpdate(); } else if (discriminator == UPDATE_BLOCKED_CONNECTIONS) { this.blockedMask = buf.readByte(); + scheduleRenderUpdate(); } else if (discriminator == UPDATE_FRAME_MATERIAL) { String name = buf.readString(255); if (name.equals("")) this.frameMaterial = null; else this.frameMaterial = GregTechAPI.materialManager.getMaterial(name); + scheduleRenderUpdate(); } else if (discriminator == UPDATE_PAINT) { this.paintingColor = buf.readInt(); + scheduleRenderUpdate(); } else { this.getCoverHolder().readCustomData(discriminator, buf); } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockAbility.java b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockAbility.java index 4c23893823c..88167fc910e 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockAbility.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockAbility.java @@ -1,6 +1,9 @@ package gregtech.api.metatileentity.multiblock; import gregtech.api.capability.*; +import gregtech.api.capability.data.IComputationDataAccess; +import gregtech.api.capability.data.IDataAccess; +import gregtech.api.capability.data.IStandardDataAccess; import gregtech.api.metatileentity.MetaTileEntity; import net.minecraftforge.fluids.IFluidTank; @@ -58,18 +61,18 @@ public class MultiblockAbility { public static final MultiblockAbility PASSTHROUGH_HATCH = new MultiblockAbility<>( "passthrough_hatch"); - public static final MultiblockAbility DATA_ACCESS_HATCH = new MultiblockAbility<>( + public static final MultiblockAbility DATA_ACCESS_HATCH = new MultiblockAbility<>( "data_access_hatch"); - public static final MultiblockAbility OPTICAL_DATA_RECEPTION = new MultiblockAbility<>( + public static final MultiblockAbility OPTICAL_DATA_RECEPTION = new MultiblockAbility<>( "optical_data_reception"); - public static final MultiblockAbility OPTICAL_DATA_TRANSMISSION = new MultiblockAbility<>( + public static final MultiblockAbility OPTICAL_DATA_TRANSMISSION = new MultiblockAbility<>( "optical_data_transmission"); - public static final MultiblockAbility INPUT_LASER = new MultiblockAbility<>("input_laser"); - public static final MultiblockAbility OUTPUT_LASER = new MultiblockAbility<>("output_laser"); + public static final MultiblockAbility LASER_RECEPTION = new MultiblockAbility<>("laser_reception"); + public static final MultiblockAbility LASER_TRANSMISSION = new MultiblockAbility<>("laser_transmission"); - public static final MultiblockAbility COMPUTATION_DATA_RECEPTION = new MultiblockAbility<>( + public static final MultiblockAbility COMPUTATION_DATA_RECEPTION = new MultiblockAbility<>( "computation_data_reception"); - public static final MultiblockAbility COMPUTATION_DATA_TRANSMISSION = new MultiblockAbility<>( + public static final MultiblockAbility COMPUTATION_DATA_TRANSMISSION = new MultiblockAbility<>( "computation_data_transmission"); public static final MultiblockAbility HPCA_COMPONENT = new MultiblockAbility<>( diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockDisplayText.java b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockDisplayText.java index 8cacd124e56..03e94f844a4 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockDisplayText.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockDisplayText.java @@ -197,7 +197,7 @@ public Builder addEnergyProductionAmpsLine(long maxVoltage, int amperage) { *
* Added if the structure is formed and if the max CWU/t is greater than zero. */ - public Builder addComputationUsageLine(int maxCWUt) { + public Builder addComputationUsageLine(long maxCWUt) { if (!isStructureFormed) return this; if (maxCWUt > 0) { ITextComponent computation = TextComponentUtil.stringWithColor(TextFormatting.AQUA, diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index a4367b9255c..693d80500af 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -67,11 +67,13 @@ import org.jetbrains.annotations.Nullable; import java.util.AbstractList; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Random; import java.util.Set; +import java.util.WeakHashMap; import java.util.function.BooleanSupplier; import java.util.function.DoubleSupplier; import java.util.function.Function; @@ -931,4 +933,8 @@ public static int[] convertARGBtoArray(int argb) { public static boolean evalMask(@NotNull EnumFacing facing, byte mask) { return (mask & (1 << facing.ordinal())) > 0; } + + public static Set createWeakHashSet() { + return Collections.newSetFromMap(new WeakHashMap<>()); + } } diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java index 4f8201e52d6..0ed7b91661c 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java @@ -1254,7 +1254,7 @@ public static void registerMetaTileEntities( } public static T registerMetaTileEntity(int id, T sampleMetaTileEntity) { - if (sampleMetaTileEntity instanceof IMultiblockAbilityPart abilityPart) { + if (sampleMetaTileEntity instanceof IMultiblockAbilityPart abilityPart) { MultiblockAbility.registerMultiblockAbility(abilityPart.getAbility(), sampleMetaTileEntity); } if (sampleMetaTileEntity instanceof MultiblockControllerBase && Mods.JustEnoughItems.isModLoaded()) { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java index 059ec0264a7..d66cbb56001 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java @@ -4,6 +4,8 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; import gregtech.api.capability.IEnergyContainer; +import gregtech.api.capability.ILaserRelay; +import gregtech.api.capability.ILaserContainer; import gregtech.api.capability.impl.EnergyContainerList; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; @@ -41,6 +43,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.math.BigInteger; import java.util.ArrayList; import java.util.List; @@ -80,8 +83,8 @@ protected void formStructure(PatternMatchContext context) { List powerOutput = new ArrayList<>(getAbilities(MultiblockAbility.OUTPUT_ENERGY)); powerOutput.addAll(getAbilities(MultiblockAbility.SUBSTATION_OUTPUT_ENERGY)); - powerInput.addAll(getAbilities(MultiblockAbility.INPUT_LASER)); - powerOutput.addAll(getAbilities(MultiblockAbility.OUTPUT_LASER)); + powerInput.addAll(getAbilities(MultiblockAbility.LASER_RECEPTION)); + powerOutput.addAll(getAbilities(MultiblockAbility.LASER_TRANSMISSION)); // Invalidate the structure if there is not at least one output and one input if (powerInput.isEmpty() || powerOutput.isEmpty()) { @@ -118,8 +121,8 @@ private TraceabilityPredicate getHatchPredicates() { .or(abilities(MultiblockAbility.OUTPUT_ENERGY).setPreviewCount(2)) .or(abilities(MultiblockAbility.SUBSTATION_INPUT_ENERGY).setPreviewCount(1)) .or(abilities(MultiblockAbility.SUBSTATION_OUTPUT_ENERGY).setPreviewCount(1)) - .or(abilities(MultiblockAbility.INPUT_LASER).setPreviewCount(1)) - .or(abilities(MultiblockAbility.OUTPUT_LASER).setPreviewCount(1)); + .or(abilities(MultiblockAbility.LASER_RECEPTION).setPreviewCount(1)) + .or(abilities(MultiblockAbility.LASER_TRANSMISSION).setPreviewCount(1)); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java index 4432cd61a21..027acd17680 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java @@ -2,7 +2,7 @@ import gregtech.api.GTValues; import gregtech.api.capability.GregtechDataCodes; -import gregtech.api.capability.IDataAccessHatch; +import gregtech.api.capability.data.IDataAccess; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; @@ -17,6 +17,7 @@ import gregtech.api.recipes.recipeproperties.ResearchProperty; import gregtech.api.util.GTUtility; import gregtech.api.util.RelativeDirection; +import gregtech.api.capability.data.query.RecipeDataQuery; import gregtech.client.particle.GTLaserBeamParticle; import gregtech.client.particle.GTParticleManager; import gregtech.client.renderer.ICubeRenderer; @@ -150,7 +151,7 @@ protected Function multiblockPartSorter() { public ICubeRenderer getBaseTexture(IMultiblockPart sourcePart) { if (sourcePart != null) { // part rendering - if (sourcePart instanceof IDataAccessHatch) { + if (sourcePart instanceof IDataAccess) { return Textures.GRATE_CASING_STEEL_FRONT; } else { return Textures.SOLID_STEEL_CASING; @@ -357,14 +358,13 @@ public boolean checkRecipe(@NotNull Recipe recipe, boolean consumeIfSuccess) { isRecipeAvailable(getAbilities(MultiblockAbility.OPTICAL_DATA_RECEPTION), recipe); } - private static boolean isRecipeAvailable(@NotNull Iterable hatches, + private static boolean isRecipeAvailable(@NotNull Iterable hatches, @NotNull Recipe recipe) { - for (IDataAccessHatch hatch : hatches) { - // creative hatches do not need to check, they always have the recipe - if (hatch.isCreative()) return true; - + RecipeDataQuery query = new RecipeDataQuery(recipe); + for (IDataAccess hatch : hatches) { // hatches need to have the recipe available - if (hatch.isRecipeAvailable(recipe)) return true; + hatch.accessData(query); + if (query.isFound()) return true; } return false; } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDataBank.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDataBank.java index 5b52829f001..9e55072a4a3 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDataBank.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDataBank.java @@ -2,6 +2,7 @@ import gregtech.api.GTValues; import gregtech.api.capability.*; +import gregtech.api.capability.data.IDataAccess; import gregtech.api.capability.impl.EnergyContainerList; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; @@ -196,7 +197,7 @@ private static IBlockState getFrontState() { public ICubeRenderer getBaseTexture(IMultiblockPart sourcePart) { if (sourcePart != null) { // part rendering - if (sourcePart instanceof IDataAccessHatch) { + if (sourcePart instanceof IDataAccess) { return Textures.COMPUTER_CASING; } else { return Textures.HIGH_POWER_CASING; diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java index 06f8286d8ff..7e61044b8ff 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java @@ -2,6 +2,7 @@ import gregtech.api.GTValues; import gregtech.api.capability.*; +import gregtech.api.capability.data.IComputationProvider; import gregtech.api.capability.impl.EnergyContainerList; import gregtech.api.capability.impl.FluidTankList; import gregtech.api.gui.GuiTextures; @@ -65,7 +66,7 @@ import java.util.function.Supplier; public class MetaTileEntityHPCA extends MultiblockWithDisplayBase - implements IOpticalComputationProvider, IControllable, IProgressBarMultiblock { + implements IComputationProvider, IControllable, IProgressBarMultiblock { private static final double IDLE_TEMPERATURE = 200; private static final double DAMAGE_TEMPERATURE = 1000; @@ -110,22 +111,19 @@ public void invalidateStructure() { } @Override - public int requestCWUt(int cwut, boolean simulate, @NotNull Collection seen) { - seen.add(this); - return isActive() && isWorkingEnabled() && !hasNotEnoughEnergy ? hpcaHandler.allocateCWUt(cwut, simulate) : 0; + public long supplyCWU(long requested, boolean simulate) { + return isActive() && isWorkingEnabled() && !hasNotEnoughEnergy ? + hpcaHandler.allocateCWUt((int) Math.min(Integer.MAX_VALUE, requested), simulate) : 0; } @Override - public int getMaxCWUt(@NotNull Collection seen) { - seen.add(this); - return isActive() && isWorkingEnabled() ? hpcaHandler.getMaxCWUt() : 0; + public boolean supportsBridging() { + return hpcaHandler.hasHPCABridge(); } @Override - public boolean canBridge(@NotNull Collection seen) { - seen.add(this); - // don't show a problem if the structure is not yet formed - return !isStructureFormed() || hpcaHandler.hasHPCABridge(); + public long maxCWUt() { + return isActive() && isWorkingEnabled() ? hpcaHandler.getMaxCWUt() : 0; } @Override diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java index fc49827d51b..7b89e941084 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java @@ -1,9 +1,7 @@ package gregtech.common.metatileentities.multi.electric; import gregtech.api.GTValues; -import gregtech.api.capability.IOpticalComputationHatch; -import gregtech.api.capability.IOpticalComputationProvider; -import gregtech.api.capability.IOpticalComputationReceiver; +import gregtech.api.capability.data.IDataAccess; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; @@ -14,6 +12,7 @@ import gregtech.api.pattern.PatternMatchContext; import gregtech.api.util.TextComponentUtil; import gregtech.api.util.TextFormattingUtil; +import gregtech.api.capability.data.query.ComputationQuery; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.common.blocks.BlockComputerCasing; @@ -26,23 +25,21 @@ import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; +import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import java.util.Set; -public class MetaTileEntityNetworkSwitch extends MetaTileEntityDataBank implements IOpticalComputationProvider { +public class MetaTileEntityNetworkSwitch extends MetaTileEntityDataBank { private static final int EUT_PER_HATCH = GTValues.VA[GTValues.IV]; - private final MultipleComputationHandler computationHandler = new MultipleComputationHandler(); + private long nextQueryTick; + private ComputationQuery query; public MetaTileEntityNetworkSwitch(ResourceLocation metaTileEntityId) { super(metaTileEntityId); @@ -63,39 +60,11 @@ protected int calculateEnergyUsage() { @Override protected void formStructure(PatternMatchContext context) { super.formStructure(context); - computationHandler.onStructureForm( - getAbilities(MultiblockAbility.COMPUTATION_DATA_RECEPTION), - getAbilities(MultiblockAbility.COMPUTATION_DATA_TRANSMISSION)); } @Override public void invalidateStructure() { super.invalidateStructure(); - computationHandler.reset(); - } - - @Override - protected int getEnergyUsage() { - return isStructureFormed() ? computationHandler.getEUt() : 0; - } - - @Override - public int requestCWUt(int cwut, boolean simulate, @NotNull Collection seen) { - seen.add(this); - return isActive() && !hasNotEnoughEnergy ? computationHandler.requestCWUt(cwut, simulate, seen) : 0; - } - - @Override - public int getMaxCWUt(@NotNull Collection seen) { - seen.add(this); - return isStructureFormed() ? computationHandler.getMaxCWUt(seen) : 0; - } - - // allows chaining Network Switches together - @Override - public boolean canBridge(@NotNull Collection seen) { - seen.add(this); - return true; } @Override @@ -153,119 +122,27 @@ protected void addDisplayText(List textList) { "gregtech.multiblock.idling", "gregtech.multiblock.data_bank.providing") .addEnergyUsageExactLine(getEnergyUsage()) - .addComputationUsageLine(computationHandler.getMaxCWUtForDisplay()) + .addComputationUsageLine(queryConnected().maxCWUt()) .addWorkingStatusLine(); } @Override protected void addWarningText(List textList) { super.addWarningText(textList); - if (isStructureFormed() && computationHandler.hasNonBridgingConnections()) { + if (isStructureFormed() && queryConnected().foundUnbridgeable()) { textList.add(TextComponentUtil.translationWithColor( TextFormatting.YELLOW, "gregtech.multiblock.computation.non_bridging.detailed")); } } - /** Handles computation load across multiple receivers and to multiple transmitters. */ - private static class MultipleComputationHandler implements IOpticalComputationProvider, - IOpticalComputationReceiver { - - // providers in the NS provide distributable computation to the NS - private final Set providers = new ObjectOpenHashSet<>(); - // transmitters in the NS give computation to other multis - private final Set transmitters = new ObjectOpenHashSet<>(); - - private int EUt; - - private void onStructureForm(Collection providers, - Collection transmitters) { - reset(); - this.providers.addAll(providers); - this.transmitters.addAll(transmitters); - this.EUt = (providers.size() + transmitters.size()) * EUT_PER_HATCH; - } - - private void reset() { - providers.clear(); - transmitters.clear(); - EUt = 0; - } - - @Override - public int requestCWUt(int cwut, boolean simulate, @NotNull Collection seen) { - if (seen.contains(this)) return 0; - // The max CWU/t that this Network Switch can provide, combining all its inputs. - seen.add(this); - Collection bridgeSeen = new ArrayList<>(seen); - int allocatedCWUt = 0; - for (var provider : providers) { - if (!provider.canBridge(bridgeSeen)) continue; - int allocated = provider.requestCWUt(cwut, simulate, seen); - allocatedCWUt += allocated; - cwut -= allocated; - if (cwut == 0) break; - } - return allocatedCWUt; - } - - public int getMaxCWUtForDisplay() { - Collection seen = new ArrayList<>(); - // The max CWU/t that this Network Switch can provide, combining all its inputs. - seen.add(this); - Collection bridgeSeen = new ArrayList<>(seen); - int maximumCWUt = 0; - for (var provider : providers) { - if (!provider.canBridge(bridgeSeen)) continue; - maximumCWUt += provider.getMaxCWUt(seen); - } - return maximumCWUt; - } - - public int getMaxCWUt(@NotNull Collection seen) { - if (seen.contains(this)) return 0; - // The max CWU/t that this Network Switch can provide, combining all its inputs. - seen.add(this); - Collection bridgeSeen = new ArrayList<>(seen); - int maximumCWUt = 0; - for (var provider : providers) { - if (!provider.canBridge(bridgeSeen)) continue; - maximumCWUt += provider.getMaxCWUt(seen); - } - return maximumCWUt; - } - - @Override - public boolean canBridge(@NotNull Collection seen) { - if (seen.contains(this)) return false; - seen.add(this); - for (var provider : providers) { - if (provider.canBridge(seen)) { - return true; - } - } - return false; - } - - /** The EU/t cost of this Network Switch given the attached providers and transmitters. */ - private int getEUt() { - return EUt; - } - - /** Test if any of the provider hatches do not allow bridging */ - private boolean hasNonBridgingConnections() { - Collection seen = new ArrayList<>(); - for (var provider : providers) { - if (!provider.canBridge(seen)) { - return true; - } - } - return false; - } - - @Override - public IOpticalComputationProvider getComputationProvider() { - return this; + private ComputationQuery queryConnected() { + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + if (tick >= nextQueryTick) { + this.query = new ComputationQuery(); + IDataAccess.accessDatas(getAbilities(MultiblockAbility.COMPUTATION_DATA_RECEPTION), query); + this.nextQueryTick = tick + 10; } + return this.query; } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPowerSubstation.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPowerSubstation.java index 7814f3dccc9..7fe597a9a66 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPowerSubstation.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPowerSubstation.java @@ -101,13 +101,13 @@ protected void formStructure(PatternMatchContext context) { List inputs = new ArrayList<>(); inputs.addAll(getAbilities(MultiblockAbility.INPUT_ENERGY)); inputs.addAll(getAbilities(MultiblockAbility.SUBSTATION_INPUT_ENERGY)); - inputs.addAll(getAbilities(MultiblockAbility.INPUT_LASER)); + inputs.addAll(getAbilities(MultiblockAbility.LASER_RECEPTION)); this.inputHatches = new EnergyContainerList(inputs); List outputs = new ArrayList<>(); outputs.addAll(getAbilities(MultiblockAbility.OUTPUT_ENERGY)); outputs.addAll(getAbilities(MultiblockAbility.SUBSTATION_OUTPUT_ENERGY)); - outputs.addAll(getAbilities(MultiblockAbility.OUTPUT_LASER)); + outputs.addAll(getAbilities(MultiblockAbility.LASER_TRANSMISSION)); this.outputHatches = new EnergyContainerList(outputs); List parts = new ArrayList<>(); @@ -236,9 +236,9 @@ protected BlockPattern createStructurePattern() { .where('X', states(getCasingState()).setMinGlobalLimited(MIN_CASINGS) .or(maintenancePredicate()) .or(abilities(MultiblockAbility.INPUT_ENERGY, MultiblockAbility.SUBSTATION_INPUT_ENERGY, - MultiblockAbility.INPUT_LASER).setMinGlobalLimited(1)) + MultiblockAbility.LASER_RECEPTION).setMinGlobalLimited(1)) .or(abilities(MultiblockAbility.OUTPUT_ENERGY, MultiblockAbility.SUBSTATION_OUTPUT_ENERGY, - MultiblockAbility.OUTPUT_LASER).setMinGlobalLimited(1))) + MultiblockAbility.LASER_TRANSMISSION).setMinGlobalLimited(1))) .where('G', states(getGlassState())) .where('B', BATTERY_PREDICATE.get()) .build(); diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java index 17fafd955ae..2cb741a778c 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java @@ -1,10 +1,9 @@ package gregtech.common.metatileentities.multi.electric; import gregtech.api.GTValues; +import gregtech.api.capability.data.IComputationConsumer; +import gregtech.api.capability.data.IDataAccess; import gregtech.api.capability.IObjectHolder; -import gregtech.api.capability.IOpticalComputationHatch; -import gregtech.api.capability.IOpticalComputationProvider; -import gregtech.api.capability.IOpticalComputationReceiver; import gregtech.api.capability.impl.ComputationRecipeLogic; import gregtech.api.capability.impl.ItemHandlerList; import gregtech.api.metatileentity.MetaTileEntity; @@ -20,6 +19,7 @@ import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMaps; import gregtech.api.util.GTUtility; +import gregtech.api.capability.data.query.ComputationQuery; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.common.ConfigHolder; @@ -45,10 +45,8 @@ import java.util.Collections; import java.util.List; -public class MetaTileEntityResearchStation extends RecipeMapMultiblockController - implements IOpticalComputationReceiver { +public class MetaTileEntityResearchStation extends RecipeMapMultiblockController implements IComputationConsumer { - private IOpticalComputationProvider computationProvider; private IObjectHolder objectHolder; public MetaTileEntityResearchStation(ResourceLocation metaTileEntityId) { @@ -64,21 +62,12 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { @Override protected void formStructure(PatternMatchContext context) { super.formStructure(context); - List providers = getAbilities(MultiblockAbility.COMPUTATION_DATA_RECEPTION); - if (providers != null && providers.size() >= 1) { - computationProvider = providers.get(0); - } List holders = getAbilities(MultiblockAbility.OBJECT_HOLDER); if (holders != null && holders.size() >= 1) { objectHolder = holders.get(0); // cannot set in initializeAbilities since super() calls it before setting the objectHolder field here this.inputInventory = new ItemHandlerList(Collections.singletonList(objectHolder.getAsHandler())); } - - // should never happen, but would rather do this than have an obscure NPE - if (computationProvider == null || objectHolder == null) { - invalidateStructure(); - } } // force object holder to be facing the controller @@ -97,7 +86,6 @@ public ComputationRecipeLogic getRecipeMapWorkable() { @Override public void invalidateStructure() { - computationProvider = null; // recheck the ability to make sure it wasn't the one broken List holders = getAbilities(MultiblockAbility.OBJECT_HOLDER); if (holders != null && holders.size() >= 1 && holders.get(0) == objectHolder) { @@ -108,8 +96,14 @@ public void invalidateStructure() { } @Override - public IOpticalComputationProvider getComputationProvider() { - return computationProvider; + public long supplyCWU(long requested, boolean simulate) { + return queryConnected().requestCWU(requested, simulate); + } + + private ComputationQuery queryConnected() { + ComputationQuery query = new ComputationQuery(); + IDataAccess.accessDatas(getAbilities(MultiblockAbility.COMPUTATION_DATA_RECEPTION), query); + return query; } public IObjectHolder getObjectHolder() { diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java index 6d250a712e5..3f9859ce3d6 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java @@ -2,19 +2,22 @@ import gregtech.api.GTValues; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.IOpticalComputationHatch; -import gregtech.api.capability.IOpticalComputationProvider; -import gregtech.api.gui.ModularUI; +import gregtech.api.capability.data.IComputationDataAccess; +import gregtech.api.capability.data.IComputationProvider; +import gregtech.api.capability.data.IDataAccess; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.util.GTLog; +import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; +import gregtech.api.util.GTUtility; +import gregtech.api.capability.data.query.DataQueryObject; +import gregtech.api.capability.data.query.IBridgeable; +import gregtech.api.capability.data.query.IComputationQuery; import gregtech.client.renderer.texture.Textures; import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.client.resources.I18n; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; @@ -28,14 +31,16 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; import java.util.List; +import java.util.Set; -public class MetaTileEntityComputationHatch extends MetaTileEntityMultiblockPart implements - IMultiblockAbilityPart, IOpticalComputationHatch { +public class MetaTileEntityComputationHatch extends MetaTileEntityMultiblockPart implements IMultiblockAbilityPart, + IComputationDataAccess { private final boolean isTransmitter; + private final Set recentQueries = GTUtility.createWeakHashSet(); + public MetaTileEntityComputationHatch(ResourceLocation metaTileEntityId, boolean isTransmitter) { super(metaTileEntityId, GTValues.ZPM); this.isTransmitter = isTransmitter; @@ -52,91 +57,39 @@ public boolean isTransmitter() { } @Override - public int requestCWUt(int cwut, boolean simulate, @NotNull Collection seen) { - seen.add(this); - var controller = getController(); - if (controller == null || !controller.isStructureFormed()) return 0; - if (isTransmitter()) { - // Ask the Multiblock controller, which *should* be an IOpticalComputationProvider - if (controller instanceof IOpticalComputationProvider provider) { - return provider.requestCWUt(cwut, simulate, seen); + public boolean accessData(@NotNull DataQueryObject queryObject) { + if (!supportsQuery(queryObject) || !recentQueries.add(queryObject)) return false; + if (isAttachedToMultiBlock()) { + if (isTransmitter()) { + MultiblockControllerBase controller = getController(); + if (!controller.isActive()) return false; + + if (controller instanceof IComputationProvider provider && queryObject instanceof IComputationQuery cq) { + cq.registerProvider(provider); + } + List reception = controller.getAbilities(MultiblockAbility.COMPUTATION_DATA_RECEPTION); + if (queryObject instanceof IBridgeable bridgeable && reception.size() > 1) { + bridgeable.setBridged(); + } + return IDataAccess.accessDatas(reception, queryObject); } else { - GTLog.logger.error("Computation Transmission Hatch could not request CWU/t from its controller!"); - return 0; - } - } else { - // Ask the attached Transmitter hatch, if it exists - IOpticalComputationProvider provider = getOpticalNetProvider(); - if (provider == null) return 0; - return provider.requestCWUt(cwut, simulate, seen); - } - } + TileEntity tileEntity = getNeighbor(getFrontFacing()); + if (tileEntity == null) return false; - @Override - public int getMaxCWUt(@NotNull Collection seen) { - seen.add(this); - var controller = getController(); - if (controller == null || !controller.isStructureFormed()) return 0; - if (isTransmitter()) { - // Ask the Multiblock controller, which *should* be an IOpticalComputationProvider - if (controller instanceof IOpticalComputationProvider provider) { - return provider.getMaxCWUt(seen); - } else { - GTLog.logger.error("Computation Transmission Hatch could not get maximum CWU/t from its controller!"); - return 0; + IDataAccess cap = tileEntity.getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, + getFrontFacing().getOpposite()); + return cap != null && cap.accessData(queryObject); } - } else { - // Ask the attached Transmitter hatch, if it exists - IOpticalComputationProvider provider = getOpticalNetProvider(); - if (provider == null) return 0; - return provider.getMaxCWUt(seen); - } - } - - @Override - public boolean canBridge(@NotNull Collection seen) { - seen.add(this); - var controller = getController(); - // return true here so that unlinked hatches don't cause problems in multis like the Network Switch - if (controller == null || !controller.isStructureFormed()) return true; - if (isTransmitter()) { - // Ask the Multiblock controller, which *should* be an IOpticalComputationProvider - if (controller instanceof IOpticalComputationProvider provider) { - return provider.canBridge(seen); - } else { - GTLog.logger.error("Computation Transmission Hatch could not test bridge status of its controller!"); - return false; - } - } else { - // Ask the attached Transmitter hatch, if it exists - IOpticalComputationProvider provider = getOpticalNetProvider(); - if (provider == null) return true; // nothing found, so don't report a problem, just pass quietly - return provider.canBridge(seen); } + return false; } - @Nullable - private IOpticalComputationProvider getOpticalNetProvider() { - TileEntity tileEntity = getNeighbor(getFrontFacing()); - if (tileEntity == null) return null; - - if (tileEntity instanceof TileEntityOpticalPipe) { - return tileEntity.getCapability(GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER, - getFrontFacing().getOpposite()); - } - return null; - } @Override protected boolean openGUIOnRightClick() { return false; } - @Override - protected ModularUI createUI(EntityPlayer entityPlayer) { - return null; - } - @Override public boolean canPartShare() { return false; @@ -152,20 +105,20 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, } @Override - public MultiblockAbility getAbility() { + public MultiblockAbility getAbility() { return isTransmitter() ? MultiblockAbility.COMPUTATION_DATA_TRANSMISSION : MultiblockAbility.COMPUTATION_DATA_RECEPTION; } @Override - public void registerAbilities(List abilityList) { + public void registerAbilities(List abilityList) { abilityList.add(this); } @Override public T getCapability(Capability capability, EnumFacing side) { - if (side == getFrontFacing() && capability == GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER) { - return GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER.cast(this); + if (capability == GregtechTileCapabilities.CAPABILITY_DATA_ACCESS) { + return GregtechTileCapabilities.CAPABILITY_DATA_ACCESS.cast(this); } return super.getCapability(capability, side); } diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java index a50acc06ba0..2778e521187 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java @@ -1,7 +1,7 @@ package gregtech.common.metatileentities.multi.multiblockpart; import gregtech.api.GTValues; -import gregtech.api.capability.IDataAccessHatch; +import gregtech.api.capability.data.IDataAccess; import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; @@ -18,6 +18,9 @@ import gregtech.api.util.AssemblyLineManager; import gregtech.api.util.ItemStackHashStrategy; import gregtech.api.util.LocalizationUtils; +import gregtech.api.capability.data.query.DataAccessFormat; +import gregtech.api.capability.data.query.DataQueryObject; +import gregtech.api.capability.data.query.RecipeDataQuery; import gregtech.client.renderer.texture.Textures; import gregtech.client.utils.TooltipHelper; import gregtech.common.ConfigHolder; @@ -46,8 +49,8 @@ import java.util.*; public class MetaTileEntityDataAccessHatch extends MetaTileEntityMultiblockNotifiablePart - implements IMultiblockAbilityPart, IDataAccessHatch, - IDataInfoProvider { + implements IMultiblockAbilityPart, IDataAccess, + IDataInfoProvider { private final Set recipes; private final boolean isCreative; @@ -61,7 +64,7 @@ public MetaTileEntityDataAccessHatch(ResourceLocation metaTileEntityId, int tier @Override public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { - return new MetaTileEntityDataAccessHatch(metaTileEntityId, getTier(), isCreative()); + return new MetaTileEntityDataAccessHatch(metaTileEntityId, getTier(), isCreative); } @Override @@ -147,14 +150,20 @@ private void rebuildData(boolean isDataBank) { } @Override - public boolean isRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { - seen.add(this); - return recipes.contains(recipe); + public boolean accessData(@NotNull DataQueryObject queryObject) { + if (!supportsQuery(queryObject)) return false; + if (queryObject instanceof RecipeDataQuery query) { + if (isCreative || recipes.contains(query.getRecipe())) { + query.setFound(); + return true; + } + } + return false; } @Override - public boolean isCreative() { - return this.isCreative; + public DataAccessFormat getFormat() { + return DataAccessFormat.STANDARD; } @Override @@ -208,12 +217,12 @@ public boolean canPartShare() { } @Override - public MultiblockAbility getAbility() { + public MultiblockAbility getAbility() { return MultiblockAbility.DATA_ACCESS_HATCH; } @Override - public void registerAbilities(List abilityList) { + public void registerAbilities(List abilityList) { abilityList.add(this); } diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityLaserHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityLaserHatch.java index 76acce75c33..6934ab46916 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityLaserHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityLaserHatch.java @@ -1,6 +1,7 @@ package gregtech.common.metatileentities.multi.multiblockpart; import gregtech.api.GTValues; +import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserContainer; import gregtech.api.capability.impl.LaserContainerHandler; import gregtech.api.gui.ModularUI; @@ -36,17 +37,17 @@ public class MetaTileEntityLaserHatch extends MetaTileEntityMultiblockPart implements IMultiblockAbilityPart, IDataInfoProvider { - private final boolean isOutput; + private final boolean isTransmitter; private final int tier; private final int amperage; private final ILaserContainer buffer; - public MetaTileEntityLaserHatch(ResourceLocation metaTileEntityId, boolean isOutput, int tier, int amperage) { + public MetaTileEntityLaserHatch(ResourceLocation metaTileEntityId, boolean isTransmitter, int tier, int amperage) { super(metaTileEntityId, tier); - this.isOutput = isOutput; + this.isTransmitter = isTransmitter; this.tier = tier; this.amperage = amperage; - if (isOutput) { + if (isTransmitter) { this.buffer = LaserContainerHandler.emitterContainer(this, GTValues.V[tier] * 64L * amperage, GTValues.V[tier], amperage); ((LaserContainerHandler) this.buffer).setSideOutputCondition(s -> s == getFrontFacing()); @@ -59,12 +60,7 @@ public MetaTileEntityLaserHatch(ResourceLocation metaTileEntityId, boolean isOut @Override public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { - return new MetaTileEntityLaserHatch(metaTileEntityId, isOutput, tier, amperage); - } - - @Override - protected ModularUI createUI(EntityPlayer entityPlayer) { - return null; + return new MetaTileEntityLaserHatch(metaTileEntityId, isTransmitter, tier, amperage); } @Override @@ -74,7 +70,7 @@ protected boolean openGUIOnRightClick() { @Override public MultiblockAbility getAbility() { - return isOutput ? MultiblockAbility.OUTPUT_LASER : MultiblockAbility.INPUT_LASER; + return isTransmitter ? MultiblockAbility.LASER_TRANSMISSION : MultiblockAbility.LASER_RECEPTION; } @Override @@ -86,7 +82,7 @@ public void registerAbilities(List abilityList) { public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { super.renderMetaTileEntity(renderState, translation, pipeline); if (shouldRenderOverlay()) { - if (isOutput) { + if (isTransmitter) { Textures.LASER_SOURCE.renderSided(getFrontFacing(), renderState, translation, pipeline); } else { Textures.LASER_TARGET.renderSided(getFrontFacing(), renderState, translation, pipeline); @@ -97,11 +93,11 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, @Override public void addInformation(ItemStack stack, @Nullable World world, @NotNull List tooltip, boolean advanced) { - tooltip.add(I18n.format(isOutput ? "gregtech.machine.laser_hatch.source.tooltip1" : + tooltip.add(I18n.format(isTransmitter ? "gregtech.machine.laser_hatch.source.tooltip1" : "gregtech.machine.laser_hatch.target.tooltip1")); tooltip.add(I18n.format("gregtech.machine.laser_hatch.tooltip2")); - if (isOutput) { + if (isTransmitter) { tooltip.add(I18n.format("gregtech.universal.tooltip.voltage_out", V[tier], VN[tier])); tooltip.add(I18n.format("gregtech.universal.tooltip.amperage_out_till", amperage)); } else { @@ -121,6 +117,9 @@ public List getDataInfo() { @Override public T getCapability(Capability capability, EnumFacing side) { + if (side == getFrontFacing() && capability == GregtechTileCapabilities.CAPABILITY_LASER) { + return GregtechTileCapabilities.CAPABILITY_LASER.cast(this.buffer); + } return super.getCapability(capability, side); } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java index ba1d589b12e..5bea9628ed7 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java @@ -2,20 +2,20 @@ import gregtech.api.GTValues; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.IDataAccessHatch; -import gregtech.api.capability.IOpticalDataAccessHatch; -import gregtech.api.gui.ModularUI; +import gregtech.api.capability.data.IDataAccess; +import gregtech.api.capability.data.IStandardDataAccess; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; -import gregtech.api.recipes.Recipe; +import gregtech.api.util.GTUtility; +import gregtech.api.capability.data.query.DataQueryObject; +import gregtech.api.capability.data.query.IBridgeable; import gregtech.client.renderer.texture.Textures; import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.client.resources.I18n; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; @@ -29,11 +29,14 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; import java.util.List; +import java.util.Set; public class MetaTileEntityOpticalDataHatch extends MetaTileEntityMultiblockNotifiablePart implements - IMultiblockAbilityPart, IOpticalDataAccessHatch { + IMultiblockAbilityPart, + IStandardDataAccess { + + private final Set recentQueries = GTUtility.createWeakHashSet(); private final boolean isTransmitter; @@ -47,11 +50,6 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { return new MetaTileEntityOpticalDataHatch(metaTileEntityId, this.isTransmitter); } - @Override - protected ModularUI createUI(EntityPlayer entityPlayer) { - return null; - } - @Override protected boolean openGUIOnRightClick() { return false; @@ -61,56 +59,36 @@ protected boolean openGUIOnRightClick() { public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, IVertexOperation[] pipeline) { super.renderMetaTileEntity(renderState, translation, pipeline); if (shouldRenderOverlay()) { - if (isTransmitter()) { - Textures.OPTICAL_DATA_ACCESS_HATCH.renderSided(getFrontFacing(), renderState, translation, pipeline); - } else { - Textures.OPTICAL_DATA_ACCESS_HATCH.renderSided(getFrontFacing(), renderState, translation, pipeline); - } + Textures.OPTICAL_DATA_ACCESS_HATCH.renderSided(getFrontFacing(), renderState, translation, pipeline); } } @Override - public boolean isRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { - seen.add(this); + public boolean accessData(@NotNull DataQueryObject queryObject) { + if (!supportsQuery(queryObject) || !recentQueries.add(queryObject)) return false; if (isAttachedToMultiBlock()) { if (isTransmitter()) { MultiblockControllerBase controller = getController(); if (!controller.isActive()) return false; - return isRecipeAvailable(controller.getAbilities(MultiblockAbility.DATA_ACCESS_HATCH), seen, recipe) || - isRecipeAvailable(controller.getAbilities(MultiblockAbility.OPTICAL_DATA_RECEPTION), seen, - recipe); + if (IDataAccess.accessDatas(controller.getAbilities(MultiblockAbility.DATA_ACCESS_HATCH), queryObject)) return true; + + List reception = controller.getAbilities(MultiblockAbility.OPTICAL_DATA_RECEPTION); + if (queryObject instanceof IBridgeable bridgeable && reception.size() > 1) { + bridgeable.setBridged(); + } + return IDataAccess.accessDatas(reception, queryObject); } else { TileEntity tileEntity = getNeighbor(getFrontFacing()); if (tileEntity == null) return false; - - if (tileEntity instanceof TileEntityOpticalPipe) { - IDataAccessHatch cap = tileEntity.getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, - getFrontFacing().getOpposite()); - return cap != null && cap.isRecipeAvailable(recipe, seen); - } - } - } - return false; - } - - private static boolean isRecipeAvailable(@NotNull Iterable hatches, - @NotNull Collection seen, - @NotNull Recipe recipe) { - for (IDataAccessHatch hatch : hatches) { - if (seen.contains(hatch)) continue; - if (hatch.isRecipeAvailable(recipe, seen)) { - return true; + IDataAccess cap = tileEntity.getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, + getFrontFacing().getOpposite()); + return cap != null && cap.accessData(queryObject); } } return false; } - @Override - public boolean isCreative() { - return false; - } - @Override public boolean isTransmitter() { return this.isTransmitter; @@ -123,19 +101,19 @@ public boolean canPartShare() { @Override public T getCapability(Capability capability, EnumFacing side) { - if (side == getFrontFacing() && capability == GregtechTileCapabilities.CAPABILITY_DATA_ACCESS) { + if (capability == GregtechTileCapabilities.CAPABILITY_DATA_ACCESS) { return GregtechTileCapabilities.CAPABILITY_DATA_ACCESS.cast(this); } return super.getCapability(capability, side); } @Override - public MultiblockAbility getAbility() { + public MultiblockAbility getAbility() { return isTransmitter() ? MultiblockAbility.OPTICAL_DATA_TRANSMISSION : MultiblockAbility.OPTICAL_DATA_RECEPTION; } @Override - public void registerAbilities(@NotNull List abilityList) { + public void registerAbilities(@NotNull List abilityList) { abilityList.add(this); } diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java index c9504523592..dc3c5ae8ea9 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java @@ -6,7 +6,7 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; import gregtech.api.capability.IEnergyContainer; -import gregtech.api.capability.ILaserContainer; +import gregtech.api.capability.ILaserRelay; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.ClickButtonWidget; @@ -48,7 +48,7 @@ import static gregtech.api.capability.GregtechDataCodes.UPDATE_ACTIVE; import static gregtech.api.capability.GregtechDataCodes.UPDATE_IO_SPEED; -public class MetaTileEntityCreativeEnergy extends MetaTileEntity implements ILaserContainer, IControllable { +public class MetaTileEntityCreativeEnergy extends MetaTileEntity implements ILaserRelay, IControllable { private long voltage = 0; private int amps = 1; diff --git a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java new file mode 100644 index 00000000000..1541f875fcd --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java @@ -0,0 +1,78 @@ +package gregtech.common.pipelike.net; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.path.AbstractNetPath; +import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; +import gregtech.api.util.TaskScheduler; +import gregtech.api.util.function.Task; + +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class SlowActiveWalker implements Task { + + public static void dispatch(World world, AbstractNetPath path, int delay) { + dispatch(world, path, delay, 1, 1); + } + + + public static void dispatch(World world, AbstractNetPath path, int delay, int stepSize, int activeLength) { + TaskScheduler.scheduleTask(world, new SlowActiveWalker(path, delay, stepSize, activeLength)); + } + + private final List path; + private final int lastStep; + private int index = 0; + + private final int delay; + private final int stepSize; + private final int activeLength; + private int counter; + + + protected SlowActiveWalker(AbstractNetPath path, int delay, int stepSize, int activeLength) { + this.path = path.getOrderedNodes(); + this.delay = delay; + this.stepSize = stepSize; + this.activeLength = activeLength; + this.lastStep = this.path.size() + activeLength - 1; + this.step(getSafe(-stepSize), getSafe(0)); + } + + @Override + public boolean run() { + counter++; + if (counter >= delay) { + counter = 0; + for (int i = 0; i < stepSize; i++) { + index++; + this.step(getSafe(index - activeLength), getSafe(index)); + if (index >= lastStep) return false; + } + } + return true; + } + + protected @Nullable WorldPipeNetNode getSafe(int index) { + if (index >= path.size()) return null; + else if (index < 0) return null; + else return path.get(index); + } + + protected void step(@Nullable WorldPipeNetNode previous, @Nullable WorldPipeNetNode next) { + if (previous != null) activate(previous, false); + if (next != null) activate(next, true); + } + + protected void activate(@NotNull WorldPipeNetNode node, boolean active) { + if (node.getTileEntity() instanceof PipeActivableTileEntity activable) { + activable.setActive(active); + } + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 644e73f76af..7d25190e5cf 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -34,7 +34,6 @@ public class EnergyCapabilityObject implements IPipeCapabilityObject, IEnergyContainer { private final WorldPipeNet net; - private final FlowWorldPipeNetPath.Provider provider; private @Nullable PipeTileEntity tile; private final EnumMap internalBuffers = new EnumMap<>(EnumFacing.class); @@ -42,9 +41,7 @@ public class EnergyCapabilityObject implements IPipeCapabilityObject, IEnergyCon private boolean transferring = false; public EnergyCapabilityObject(@NotNull N net, WorldPipeNetNode node) { - // eh, duplicate references so what this.net = net; - this.provider = net; for (EnumFacing facing : EnumFacing.VALUES) { AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); edge.setData(NetLogicData.union(node.getData(), (NetLogicData) null)); @@ -52,6 +49,10 @@ public EnergyCapability } } + private FlowWorldPipeNetPath.Provider getProvider() { + return (FlowWorldPipeNetPath.Provider) net; + } + @Override public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { if (tile == null || this.transferring) return 0; @@ -89,7 +90,7 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage private Iterator getPaths(EnergyTraverseData data) { assert tile != null; - return provider.getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), data.getQueryTick()); + return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), data.getQueryTick()); } @Nullable diff --git a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java new file mode 100644 index 00000000000..18997cd2536 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java @@ -0,0 +1,90 @@ +package gregtech.common.pipelike.net.laser; + +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.capability.ILaserRelay; +import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import gregtech.common.pipelike.net.SlowActiveWalker; + +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.Capability; + +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; + +public class LaserCapabilityObject implements IPipeCapabilityObject, ILaserRelay { + + private final WorldPipeNet net; + private @Nullable PipeTileEntity tile; + + private boolean transmitting; + + public LaserCapabilityObject(@NotNull N net) { + this.net = net; + } + + private BasicWorldPipeNetPath.Provider getProvider() { + return (BasicWorldPipeNetPath.Provider) net; + } + + @Override + public void setTile(@Nullable PipeTileEntity tile) { + this.tile = tile; + } + + private Iterator getPaths() { + assert tile != null; + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + return getProvider().getPaths(net.getNode(tile.getPos()), IPredicateTestObject.INSTANCE, null, tick); + } + + @Override + public long receiveLaser(long laserVoltage, long laserAmperage) { + if (tile == null || transmitting) return 0; + transmitting = true; + + long available = laserAmperage; + for (Iterator it = getPaths(); it.hasNext(); ) { + BasicWorldPipeNetPath path = it.next(); + WorldPipeNetNode destination = path.getTargetNode(); + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + ILaserRelay laser = capability.getValue() + .getCapability(GregtechTileCapabilities.CAPABILITY_LASER, capability.getKey().getOpposite()); + if (laser != null) { + long transmitted = laser.receiveLaser(laserVoltage, laserAmperage); + if (transmitted > 0) { + SlowActiveWalker.dispatch(tile.getWorld(), path, 1, 2, 2); + available -= transmitted; + if (available <= 0) return laserAmperage; + } + } + } + } + transmitting = false; + + return laserAmperage - available; + } + + @Override + public Capability[] getCapabilities() { + return WorldLaserNet.CAPABILITIES; + } + + @Override + public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { + if (capability == GregtechTileCapabilities.CAPABILITY_LASER) { + return GregtechTileCapabilities.CAPABILITY_LASER.cast(this); + } + return null; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java index 01d3d2a1ba4..d04f9bce2ae 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java @@ -49,6 +49,6 @@ public Capability[] getTargetCapabilities() { @Override public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return null; // TODO + return new IPipeCapabilityObject[] { new LaserCapabilityObject(this) }; } } diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java new file mode 100644 index 00000000000..4f276e8c858 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -0,0 +1,98 @@ +package gregtech.common.pipelike.net.optical; + +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.capability.data.IDataAccess; +import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import gregtech.api.util.GTUtility; +import gregtech.api.capability.data.query.DataAccessFormat; +import gregtech.api.capability.data.query.DataQueryObject; +import gregtech.common.pipelike.net.SlowActiveWalker; + +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.Capability; + +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; +import java.util.Set; + +public class DataCapabilityObject implements IPipeCapabilityObject, IDataAccess { + + private final WorldPipeNet net; + + private @Nullable PipeTileEntity tile; + + private final Set recentQueries = GTUtility.createWeakHashSet(); + + public DataCapabilityObject(@NotNull N net) { + this.net = net; + } + + private BasicWorldPipeNetPath.Provider getProvider() { + return (BasicWorldPipeNetPath.Provider) net; + } + + @Override + public void setTile(@Nullable PipeTileEntity tile) { + this.tile = tile; + } + + @Override + public boolean accessData(@NotNull DataQueryObject queryObject) { + if (tile == null) return false; + // if the add call fails (because the object already exists in the set) then do not recurse + if (!recentQueries.add(queryObject)) return false; + + for (Iterator it = getPaths(); it.hasNext(); ) { + BasicWorldPipeNetPath path = it.next(); + WorldPipeNetNode destination = path.getTargetNode(); + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + IDataAccess access = capability.getValue() + .getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, capability.getKey().getOpposite()); + if (access != null) { + queryObject.setShouldTriggerWalker(false); + boolean cancelled = access.accessData(queryObject); + if (queryObject.shouldTriggerWalker()) { + SlowActiveWalker.dispatch(tile.getWorld(), path, 1); + } + if (cancelled) return true; + } + } + } + return false; + } + + @Override + public DataAccessFormat getFormat() { + return DataAccessFormat.UNIVERSAL; + } + + private Iterator getPaths() { + assert tile != null; + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + return getProvider().getPaths(net.getNode(tile.getPos()), IPredicateTestObject.INSTANCE, null, tick); + } + + @Override + public Capability[] getCapabilities() { + return WorldOpticalNet.CAPABILITIES; + } + + @Override + public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { + if (capability == GregtechTileCapabilities.CAPABILITY_DATA_ACCESS) { + return GregtechTileCapabilities.CAPABILITY_DATA_ACCESS.cast(this); + } + return null; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java index 85d79183ad3..d2e87e3ea7a 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -11,20 +11,16 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.common.pipelike.net.item.WorldItemNet; - import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.items.CapabilityItemHandler; - import org.jetbrains.annotations.Nullable; import java.util.Iterator; public class WorldOpticalNet extends WorldPipeNet implements BasicWorldPipeNetPath.Provider { - public static final Capability[] CAPABILITIES = new Capability[] { GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER, GregtechTileCapabilities.CAPABILITY_DATA_ACCESS }; + public static final Capability[] CAPABILITIES = new Capability[] { GregtechTileCapabilities.CAPABILITY_DATA_ACCESS }; private static final String DATA_ID_BASE = "gregtech.world_optical_net"; @@ -55,6 +51,6 @@ public Capability[] getTargetCapabilities() { @Override public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return null; // TODO + return new IPipeCapabilityObject[] { new DataCapabilityObject(this) }; } } diff --git a/src/main/java/gregtech/common/pipelikeold/laser/net/LaserNetHandler.java b/src/main/java/gregtech/common/pipelikeold/laser/net/LaserNetHandler.java index 15b5382714b..20a4ad6daab 100644 --- a/src/main/java/gregtech/common/pipelikeold/laser/net/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/laser/net/LaserNetHandler.java @@ -1,7 +1,7 @@ package gregtech.common.pipelikeold.laser.net; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.ILaserContainer; +import gregtech.api.capability.ILaserRelay; import gregtech.api.graphnet.pipenetold.IPipeNetHandler; import gregtech.api.graphnet.NetGroup; import gregtech.api.graphnet.pipenetold.PipeNetNode; @@ -20,7 +20,7 @@ import java.util.Iterator; import java.util.Map; -public class LaserNetHandler implements ILaserContainer, IPipeNetHandler { +public class LaserNetHandler implements ILaserRelay, IPipeNetHandler { private final WorldLaserPipeNet net; private final TileEntityLaserPipe pipe; @@ -55,7 +55,7 @@ private void setPipesActive() { } @Nullable - private ILaserContainer getInnerContainer() { + private ILaserRelay getInnerContainer() { if (net == null || pipe.isInvalid() || facing == null) { return null; } @@ -72,7 +72,7 @@ private ILaserContainer getInnerContainer() { @Override public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { - ILaserContainer handler = getInnerContainer(); + ILaserRelay handler = getInnerContainer(); if (handler == null) return 0; setPipesActive(); return handler.acceptEnergyFromNetwork(side, voltage, amperage, simulate); @@ -80,21 +80,21 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage @Override public boolean inputsEnergy(EnumFacing side) { - ILaserContainer handler = getInnerContainer(); + ILaserRelay handler = getInnerContainer(); if (handler == null) return false; return handler.inputsEnergy(side); } @Override public boolean outputsEnergy(EnumFacing side) { - ILaserContainer handler = getInnerContainer(); + ILaserRelay handler = getInnerContainer(); if (handler == null) return false; return handler.outputsEnergy(side); } @Override public long changeEnergy(long amount) { - ILaserContainer handler = getInnerContainer(); + ILaserRelay handler = getInnerContainer(); if (handler == null) return 0; setPipesActive(); return handler.changeEnergy(amount); @@ -102,14 +102,14 @@ public long changeEnergy(long amount) { @Override public long getEnergyStored() { - ILaserContainer handler = getInnerContainer(); + ILaserRelay handler = getInnerContainer(); if (handler == null) return 0; return handler.getEnergyStored(); } @Override public long getEnergyCapacity() { - ILaserContainer handler = getInnerContainer(); + ILaserRelay handler = getInnerContainer(); if (handler == null) return 0; return handler.getEnergyCapacity(); } diff --git a/src/main/java/gregtech/common/pipelikeold/laser/tile/TileEntityLaserPipe.java b/src/main/java/gregtech/common/pipelikeold/laser/tile/TileEntityLaserPipe.java index 15275d1b9b3..0f5750628ae 100644 --- a/src/main/java/gregtech/common/pipelikeold/laser/tile/TileEntityLaserPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/laser/tile/TileEntityLaserPipe.java @@ -2,7 +2,7 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.ILaserContainer; +import gregtech.api.capability.ILaserRelay; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; @@ -28,7 +28,7 @@ public class TileEntityLaserPipe extends TileEntityPipeBase handlers = new EnumMap<>(EnumFacing.class); // the LaserNetHandler can only be created on the server, so we have an empty placeholder for the client - private final ILaserContainer clientCapability = new DefaultLaserContainer(); + private final ILaserRelay clientCapability = new DefaultLaserContainer(); private LaserNetHandler defaultHandler; private int ticksActive = 0; @@ -192,7 +192,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { } } - private static class DefaultLaserContainer implements ILaserContainer { + private static class DefaultLaserContainer implements ILaserRelay { @Override public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { diff --git a/src/main/java/gregtech/common/pipelikeold/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelikeold/optical/net/OpticalNetHandler.java index 22fc06a8275..3a573419825 100644 --- a/src/main/java/gregtech/common/pipelikeold/optical/net/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/optical/net/OpticalNetHandler.java @@ -1,9 +1,8 @@ package gregtech.common.pipelikeold.optical.net; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.IDataAccessHatch; -import gregtech.api.capability.IOpticalComputationProvider; -import gregtech.api.capability.IOpticalDataAccessHatch; +import gregtech.api.capability.data.IDataAccess; +import gregtech.api.capability.data.IHatchDataAccess; import gregtech.api.graphnet.pipenetold.IPipeNetHandler; import gregtech.api.graphnet.NetGroup; import gregtech.api.graphnet.pipenetold.PipeNetNode; @@ -24,7 +23,7 @@ import java.util.Iterator; import java.util.Map; -public class OpticalNetHandler implements IDataAccessHatch, IOpticalComputationProvider, IPipeNetHandler { +public class OpticalNetHandler implements IDataAccess, IOpticalComputationProvider, IPipeNetHandler { private final TileEntityOpticalPipe pipe; private final EnumFacing facing; @@ -49,7 +48,7 @@ public EnumFacing getFacing() { } @Override - public boolean isRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { + public boolean isRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { boolean isAvailable = traverseRecipeAvailable(recipe, seen); if (isAvailable) setPipesActive(); return isAvailable; @@ -93,7 +92,7 @@ private boolean isNetInvalidForTraversal() { return net == null || pipe.isInvalid() || facing == null; } - private boolean traverseRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { + private boolean traverseRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { if (isNetInvalidForTraversal()) return false; Iterator> inv = net.getPaths(this.pipe); @@ -103,9 +102,9 @@ private boolean traverseRecipeAvailable(@NotNull Recipe recipe, @NotNull Collect if (connecteds.size() != 1) return false; EnumFacing facing = connecteds.keySet().iterator().next(); - IDataAccessHatch access = connecteds.get(facing).getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, + IDataAccess access = connecteds.get(facing).getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, facing.getOpposite()); - if (!(access instanceof IOpticalDataAccessHatch hatch) || seen.contains(hatch)) return false; + if (!(access instanceof IHatchDataAccess hatch) || seen.contains(hatch)) return false; if (hatch.isTransmitter()) { return hatch.isRecipeAvailable(recipe, seen); diff --git a/src/main/java/gregtech/common/pipelikeold/optical/tile/TileEntityOpticalPipe.java b/src/main/java/gregtech/common/pipelikeold/optical/tile/TileEntityOpticalPipe.java index 494caefe1b6..164b1bf3a1b 100644 --- a/src/main/java/gregtech/common/pipelikeold/optical/tile/TileEntityOpticalPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/optical/tile/TileEntityOpticalPipe.java @@ -2,13 +2,12 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.IDataAccessHatch; -import gregtech.api.capability.IOpticalComputationProvider; +import gregtech.api.capability.data.IDataAccess; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.api.recipes.Recipe; import gregtech.api.util.TaskScheduler; +import gregtech.api.capability.data.query.DataQueryObject; import gregtech.common.pipelikeold.optical.OpticalPipeProperties; import gregtech.common.pipelikeold.optical.OpticalPipeType; import gregtech.common.pipelikeold.optical.net.OpticalNetHandler; @@ -29,7 +28,7 @@ public class TileEntityOpticalPipe extends TileEntityPipeBase handlers = new EnumMap<>(EnumFacing.class); // the OpticalNetHandler can only be created on the server, so we have an empty placeholder for the client - private final IDataAccessHatch clientDataHandler = new DefaultDataHandler(); + private final IDataAccess clientDataHandler = new DefaultDataHandler(); private final IOpticalComputationProvider clientComputationHandler = new DefaultComputationHandler(); private OpticalNetHandler defaultHandler; @@ -143,7 +142,7 @@ public void setActive(boolean active, int duration) { } if (stateChanged) { - writeCustomData(GregtechDataCodes.PIPE_OPTICAL_ACTIVE, buf -> { + writeCustomData(GregtechDataCodes.PIPE_ACTIVE, buf -> { buf.writeBoolean(this.isActive); }); notifyBlockUpdate(); @@ -154,21 +153,16 @@ public void setActive(boolean active, int duration) { @Override public void receiveCustomData(int discriminator, PacketBuffer buf) { super.receiveCustomData(discriminator, buf); - if (discriminator == GregtechDataCodes.PIPE_OPTICAL_ACTIVE) { + if (discriminator == GregtechDataCodes.PIPE_ACTIVE) { this.isActive = buf.readBoolean(); scheduleRenderUpdate(); } } - private static class DefaultDataHandler implements IDataAccessHatch { + private static class DefaultDataHandler implements IDataAccess { @Override - public boolean isRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { - return false; - } - - @Override - public boolean isCreative() { + public boolean accessData(@NotNull DataQueryObject queryObject) { return false; } } diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java index 404bf223680..9b2148a8e88 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java @@ -2,7 +2,7 @@ import gregtech.api.GTValues; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.ILaserContainer; +import gregtech.api.capability.ILaserRelay; import gregtech.api.util.TextFormattingUtil; import net.minecraft.entity.player.EntityPlayer; @@ -14,21 +14,21 @@ import mcjty.theoneprobe.api.NumberFormat; import org.jetbrains.annotations.NotNull; -public class LaserContainerInfoProvider extends CapabilityInfoProvider { +public class LaserContainerInfoProvider extends CapabilityInfoProvider { @NotNull @Override - protected Capability getCapability() { + protected Capability getCapability() { return GregtechTileCapabilities.CAPABILITY_LASER; } @Override - protected boolean allowDisplaying(@NotNull ILaserContainer capability) { + protected boolean allowDisplaying(@NotNull ILaserRelay capability) { return !capability.isOneProbeHidden(); } @Override - protected void addProbeInfo(ILaserContainer capability, IProbeInfo probeInfo, EntityPlayer player, + protected void addProbeInfo(ILaserRelay capability, IProbeInfo probeInfo, EntityPlayer player, TileEntity tileEntity, IProbeHitData data) { long maxStorage = capability.getEnergyCapacity(); if (maxStorage == 0) return; // do not add empty max storage progress bar From e406f6bf7fe55bb50557d22eb40be0cf3daf981f Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 27 Jul 2024 18:35:41 -0600 Subject: [PATCH 080/157] Complete rewrite pt7 --- .../api/capability/IPropertyFluidFilter.java | 52 +-- .../capability/impl/PropertyFluidFilter.java | 24 +- .../java/gregtech/api/fluids/FluidState.java | 9 + .../graphnet/gather/GTGraphGatherables.java | 14 + .../gather/GatherPredicatesEvent.java | 4 +- .../api/graphnet/pipenet/NodeLossCache.java | 78 ++++ .../api/graphnet/pipenet/NodeLossResult.java | 23 +- .../pipenet/logic/TemperatureLogic.java | 40 +- .../graphnet/pipenet/physical/IBurnable.java | 1 - .../graphnet/pipenet/physical/IFreezable.java | 17 + .../physical/block/WorldPipeBlock.java | 3 + .../pipenet/physical/tile/PipeTileEntity.java | 62 +++ .../predicate/test/FluidTestObject.java | 4 + .../predicate/test/ItemTestObject.java | 14 + .../traverse/IEqualizableTraverseData.java | 2 +- .../traverse/IRoundRobinTraverseData.java | 3 +- .../api/graphnet/traverse/ITraverseData.java | 15 +- .../graphnet/traverse/TraverseHelpers.java | 22 +- .../traverse/util/CompositeLossOperator.java | 22 + .../traverse/util/FlowConsumptionStack.java | 2 +- .../traverse/util/IdentityLossOperator.java | 17 - .../traverse/util/MultLossOperator.java | 13 + .../traverse/util/ReversibleLossOperator.java | 13 + .../items/metaitem/FilteredFluidStats.java | 6 +- .../api/unification/material/Material.java | 33 +- .../material/materials/ElementMaterials.java | 16 +- .../materials/FirstDegreeMaterials.java | 2 +- .../materials/OrganicChemistryMaterials.java | 2 +- .../materials/SecondDegreeMaterials.java | 4 +- .../properties/FluidPipeProperties.java | 386 ------------------ .../properties/ItemPipeProperties.java | 115 ------ .../properties/PipeNetProperties.java | 42 +- .../material/properties/PropertyKey.java | 6 - .../material/properties/WoodProperty.java | 12 +- .../java/gregtech/api/util/GTUtility.java | 46 ++- .../java/gregtech/api/util/TaskScheduler.java | 15 + .../java/gregtech/common/CommonProxy.java | 10 +- .../common/creativetab/GTCreativeTabs.java | 2 +- .../java/gregtech/common/items/MetaItem1.java | 39 +- .../multi/MetaTileEntityMultiblockTank.java | 2 +- .../storage/MetaTileEntityCreativeEnergy.java | 23 +- .../storage/MetaTileEntityDrum.java | 22 +- .../pipelike/block/laser/LaserPipeBlock.java | 2 +- .../pipelike/block/laser/LaserStructure.java | 8 + .../block/optical/OpticalPipeBlock.java | 2 +- .../block/optical/OpticalStructure.java | 8 + .../common/pipelike/block/pipe/PipeBlock.java | 3 +- .../pipelike/block/pipe/PipeStructure.java | 1 - .../pipelike/handlers/LaserNetHandler.java | 2 +- .../pipelike/handlers/OpticalNetHandler.java | 2 +- .../MaterialEnergyProperties.java | 6 +- .../MaterialFluidProperties.java | 61 ++- .../MaterialItemProperties.java | 16 +- .../net/energy/EnergyCapabilityObject.java | 12 +- .../net/energy/EnergyTraverseData.java | 20 +- .../net/energy/SuperconductorLogic.java | 2 +- .../net/fluid/ContainmentFailure.java | 154 +++++++ .../net/fluid/FluidCapabilityObject.java | 159 ++++++++ .../net/fluid/FluidContainmentLogic.java | 143 +++++++ .../pipelike/net/fluid/FluidTraverseData.java | 159 ++++++++ .../pipelike/net/fluid/WorldFluidNet.java | 2 +- .../net/item/ItemCapabilityObject.java | 166 ++++++++ .../pipelike/net/item/ItemTraverseData.java | 67 +++ .../pipelike/net/item/WorldItemNet.java | 2 +- .../pipelikeold/fluidpipe/BlockFluidPipe.java | 1 - .../pipelikeold/fluidpipe/FluidPipeType.java | 1 - .../fluidpipe/ItemBlockFluidPipe.java | 1 - .../fluidpipe/net/FluidNetHandler.java | 1 - .../fluidpipe/net/WorldFluidPipeNet.java | 1 - .../fluidpipe/tile/TileEntityFluidPipe.java | 1 - .../pipelikeold/itempipe/BlockItemPipe.java | 1 - .../itempipe/ItemBlockItemPipe.java | 1 - .../pipelikeold/itempipe/ItemPipeType.java | 1 - .../itempipe/net/ItemNetHandler.java | 1 - .../itempipe/net/WorldItemPipeNet.java | 1 - .../itempipe/tile/TileEntityItemPipe.java | 1 - .../material/CTMaterialBuilder.java | 11 +- .../material/MaterialPropertyExpansion.java | 110 ++--- .../recipe/MetaItemBracketHandler.java | 40 +- .../groovy/GroovyScriptModule.java | 45 +- .../groovy/MaterialPropertyExpansion.java | 98 +++-- .../integration/jei/basic/MaterialTree.java | 3 +- .../provider/LaserContainerInfoProvider.java | 21 +- .../debug/DebugPipeNetInfoProvider.java | 33 +- .../loaders/recipe/CircuitRecipes.java | 2 +- .../loaders/recipe/ComponentRecipes.java | 34 +- .../loaders/recipe/ComputerRecipes.java | 4 +- .../loaders/recipe/CraftingComponent.java | 50 +-- .../loaders/recipe/CraftingRecipeLoader.java | 4 +- .../loaders/recipe/MachineRecipeLoader.java | 2 +- .../loaders/recipe/MetaTileEntityLoader.java | 98 ++--- .../MetaTileEntityMachineRecipeLoader.java | 56 +-- .../chemistry/AssemblerRecipeLoader.java | 4 +- .../recipe/handlers/PartsRecipeHandler.java | 2 +- .../recipe/handlers/PipeRecipeHandler.java | 86 ++-- .../recipe/handlers/WireCombiningHandler.java | 2 +- .../recipe/handlers/WireRecipeHandler.java | 2 +- .../resources/assets/gregtech/lang/en_us.lang | 2 +- 98 files changed, 1884 insertions(+), 1071 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/IFreezable.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/util/CompositeLossOperator.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverse/util/IdentityLossOperator.java delete mode 100644 src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java delete mode 100644 src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java rename src/main/java/gregtech/common/pipelike/handlers/{ => properties}/MaterialEnergyProperties.java (97%) rename src/main/java/gregtech/common/pipelike/handlers/{ => properties}/MaterialFluidProperties.java (73%) rename src/main/java/gregtech/common/pipelike/handlers/{ => properties}/MaterialItemProperties.java (81%) create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java create mode 100644 src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java create mode 100644 src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java diff --git a/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java b/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java index 1b97a5a3e2a..1b74b239e02 100644 --- a/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java +++ b/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java @@ -1,5 +1,6 @@ package gregtech.api.capability; +import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.AttributedFluid; import gregtech.api.fluids.attribute.FluidAttribute; @@ -30,29 +31,21 @@ public interface IPropertyFluidFilter extends IFilter { @Override default boolean test(@NotNull FluidStack stack) { Fluid fluid = stack.getFluid(); - if (fluid.getTemperature() < CRYOGENIC_FLUID_THRESHOLD && !isCryoProof()) return false; + if (fluid.getTemperature() < getMinFluidTemperature()) return false; - if (fluid instanceof AttributedFluid attributedFluid) { - FluidState state = attributedFluid.getState(); - if (!canContain(state)) return false; + FluidState state = FluidState.inferState(stack); + if (!canContain(state)) return false; + if (fluid instanceof AttributedFluid attributedFluid) { for (FluidAttribute attribute : attributedFluid.getAttributes()) { if (!canContain(attribute)) { return false; } } - - // plasma ignores temperature requirements - if (state == FluidState.PLASMA) return true; - } else { - if (fluid.isGaseous() && !canContain(FluidState.GAS)) { - return false; - } - if (!canContain(FluidState.LIQUID)) { - return false; - } } + // plasma ignores temperature requirements + if (state == FluidState.PLASMA) return true; return fluid.getTemperature() <= getMaxFluidTemperature(); } @@ -73,14 +66,6 @@ default int getPriority() { */ boolean canContain(@NotNull FluidAttribute attribute); - /** - * Set the container as able to contain an attribute - * - * @param attribute the attribute to change containment status for - * @param canContain whether the attribute can be contained - */ - void setCanContain(@NotNull FluidAttribute attribute, boolean canContain); - @NotNull @UnmodifiableView Collection<@NotNull FluidAttribute> getContainedAttributes(); @@ -94,14 +79,15 @@ default int getPriority() { */ default void appendTooltips(@NotNull List tooltip, boolean showToolsInfo, boolean showTemperatureInfo) { if (TooltipHelper.isShiftDown()) { - if (showTemperatureInfo) + if (showTemperatureInfo) { tooltip.add(I18n.format("gregtech.fluid_pipe.max_temperature", getMaxFluidTemperature())); + tooltip.add(I18n.format("gregtech.fluid_pipe.min_temperature", getMinFluidTemperature())); + } if (isGasProof()) tooltip.add(I18n.format("gregtech.fluid_pipe.gas_proof")); else tooltip.add(I18n.format("gregtech.fluid_pipe.not_gas_proof")); if (isPlasmaProof()) tooltip.add(I18n.format("gregtech.fluid_pipe.plasma_proof")); - if (isCryoProof()) tooltip.add(I18n.format("gregtech.fluid_pipe.cryo_proof")); getContainedAttributes().forEach(a -> a.appendContainerTooltips(tooltip)); - } else if (isGasProof() || isCryoProof() || isPlasmaProof() || !getContainedAttributes().isEmpty()) { + } else if (isGasProof() || isPlasmaProof() || !getContainedAttributes().isEmpty()) { if (showToolsInfo) { tooltip.add(I18n.format("gregtech.tooltip.tool_fluid_hold_shift")); } else { @@ -120,17 +106,23 @@ default void appendTooltips(@NotNull List tooltip, boolean showToolsInfo /** * This is always checked, regardless of the contained fluid being a {@link AttributedFluid} or not * - * @return whether this filter allows gases + * @return the minimum allowed temperature for a fluid */ - boolean isGasProof(); + int getMinFluidTemperature(); /** - * @return whether this filter allows cryogenic fluids + * This is always checked, regardless of the contained fluid being a {@link AttributedFluid} or not + * + * @return whether this filter allows gases */ - boolean isCryoProof(); + default boolean isGasProof() { + return canContain(FluidState.GAS); + } /** * @return whether this filter allows plasmas */ - boolean isPlasmaProof(); + default boolean isPlasmaProof() { + return canContain(FluidState.PLASMA); + } } diff --git a/src/main/java/gregtech/api/capability/impl/PropertyFluidFilter.java b/src/main/java/gregtech/api/capability/impl/PropertyFluidFilter.java index deb8e12d8d3..d8cd07812d6 100644 --- a/src/main/java/gregtech/api/capability/impl/PropertyFluidFilter.java +++ b/src/main/java/gregtech/api/capability/impl/PropertyFluidFilter.java @@ -17,19 +17,18 @@ public class PropertyFluidFilter implements IPropertyFluidFilter { private final Object2BooleanMap containmentPredicate = new Object2BooleanOpenHashMap<>(); private final int maxFluidTemperature; + private final int minFluidTemperature; private final boolean gasProof; - private final boolean cryoProof; private final boolean plasmaProof; - public PropertyFluidFilter(int maxFluidTemperature, + public PropertyFluidFilter(int maxFluidTemperature, int minFluidTemperature, boolean gasProof, boolean acidProof, - boolean cryoProof, boolean plasmaProof) { this.maxFluidTemperature = maxFluidTemperature; + this.minFluidTemperature = minFluidTemperature; this.gasProof = gasProof; if (acidProof) setCanContain(FluidAttributes.ACID, true); - this.cryoProof = cryoProof; this.plasmaProof = plasmaProof; } @@ -47,7 +46,6 @@ public boolean canContain(@NotNull FluidAttribute attribute) { return containmentPredicate.getBoolean(attribute); } - @Override public void setCanContain(@NotNull FluidAttribute attribute, boolean canContain) { containmentPredicate.put(attribute, canContain); } @@ -63,13 +61,13 @@ public int getMaxFluidTemperature() { } @Override - public boolean isGasProof() { - return this.gasProof; + public int getMinFluidTemperature() { + return minFluidTemperature; } @Override - public boolean isCryoProof() { - return this.cryoProof; + public boolean isGasProof() { + return this.gasProof; } @Override @@ -79,12 +77,12 @@ public boolean isPlasmaProof() { @Override public String toString() { - return "SimplePropertyFluidFilter{" + - "maxFluidTemperature=" + maxFluidTemperature + + return "PropertyFluidFilter{" + + "containmentPredicate=" + containmentPredicate + + ", maxFluidTemperature=" + maxFluidTemperature + + ", minFluidTemperature=" + minFluidTemperature + ", gasProof=" + gasProof + - ", cryoProof=" + cryoProof + ", plasmaProof=" + plasmaProof + - ", containmentPredicate=" + containmentPredicate + '}'; } } diff --git a/src/main/java/gregtech/api/fluids/FluidState.java b/src/main/java/gregtech/api/fluids/FluidState.java index 02cad14303c..90d856c7eb6 100644 --- a/src/main/java/gregtech/api/fluids/FluidState.java +++ b/src/main/java/gregtech/api/fluids/FluidState.java @@ -1,5 +1,9 @@ package gregtech.api.fluids; +import gregtech.api.fluids.attribute.AttributedFluid; + +import net.minecraftforge.fluids.FluidStack; + import org.jetbrains.annotations.NotNull; public enum FluidState { @@ -17,4 +21,9 @@ public enum FluidState { public @NotNull String getTranslationKey() { return this.translationKey; } + + public static FluidState inferState(FluidStack stack) { + if (stack.getFluid() instanceof AttributedFluid fluid) return fluid.getState(); + else return stack.getFluid().isGaseous(stack) ? GAS : LIQUID; + } } diff --git a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java index b1112098dae..7d4b5d7a8dd 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java +++ b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java @@ -4,7 +4,10 @@ import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.INetLogicEntry; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.predicate.ShutterPredicate; import gregtech.common.pipelike.block.cable.CableStructure; +import gregtech.common.pipelike.block.laser.LaserStructure; +import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.block.pipe.PipeStructure; import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; import gregtech.api.graphnet.logic.MultiNetCountLogic; @@ -13,6 +16,7 @@ import gregtech.api.graphnet.predicate.IEdgePredicate; +import gregtech.common.pipelike.net.energy.SuperconductorLogic; import gregtech.common.pipelike.net.energy.VoltageLimitLogic; import net.minecraftforge.common.MinecraftForge; @@ -48,6 +52,7 @@ public final class GTGraphGatherables { @SubscribeEvent public static void gatherPredicates(GatherPredicatesEvent event) { + event.registerPredicate(ShutterPredicate.INSTANCE); } @SubscribeEvent @@ -58,6 +63,7 @@ public static void gatherLogics(GatherLogicsEvent event) { event.registerLogic(MultiNetCountLogic.INSTANCE); event.registerLogic(LossAbsoluteLogic.INSTANCE); event.registerLogic(VoltageLimitLogic.INSTANCE); + event.registerLogic(SuperconductorLogic.INSTANCE); event.registerLogic(TemperatureLogic.INSTANCE); } @@ -71,5 +77,13 @@ public static void gatherStructures(GatherStructuresEvent event) { GatherStructuresEvent cast = (GatherStructuresEvent) event; CableStructure.registerDefaultStructures(cast::registerMaterialStructure); } + if (event.getStructure() == OpticalStructure.class) { + GatherStructuresEvent cast = (GatherStructuresEvent) event; + OpticalStructure.registerDefaultStructures(cast::registerMaterialStructure); + } + if (event.getStructure() == LaserStructure.class) { + GatherStructuresEvent cast = (GatherStructuresEvent) event; + LaserStructure.registerDefaultStructures(cast::registerMaterialStructure); + } } } diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java index e90f4e9e46e..94dddb838b6 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java +++ b/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java @@ -15,7 +15,7 @@ public class GatherPredicatesEvent extends Event { GatherPredicatesEvent() {} - public void registerSupplier(String name, Supplier> supplier) { - gathered.put(name, supplier); + public void registerPredicate(IEdgePredicate predicate) { + gathered.put(predicate.getName(), predicate::getNew); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java new file mode 100644 index 00000000000..200e9f623c0 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java @@ -0,0 +1,78 @@ +package gregtech.api.graphnet.pipenet; + +import com.github.bsideup.jabel.Desugar; + +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.traverse.ITraverseData; +import gregtech.api.util.TaskScheduler; +import gregtech.api.util.function.Task; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.world.World; + +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.WeakHashMap; + +public class NodeLossCache implements Task { + + private static final WeakHashMap CACHE = new WeakHashMap<>(); + + public static void registerLossResult(Key key, NodeLossResult result) { + NodeLossCache existing = CACHE.get(key.node().getNet()); + if (existing == null) { + existing = new NodeLossCache(key.node().getNet().getWorld()); + CACHE.put(key.node().getNet(), existing); + } + existing.registerResult(key, result); + } + + public static @Nullable NodeLossResult getLossResult(Key key) { + NodeLossCache existing = CACHE.get(key.node().getNet()); + if (existing == null) { + existing = new NodeLossCache(key.node().getNet().getWorld()); + CACHE.put(key.node().getNet(), existing); + } + return existing.getResult(key); + } + + private final Map cache = new Object2ObjectOpenHashMap<>(); + + + private NodeLossCache(World world) { + TaskScheduler.scheduleTask(world, TaskScheduler.weakTask(this)); + } + + public void registerResult(Key key, NodeLossResult result) { + cache.put(key, result); + } + + public @Nullable NodeLossResult getResult(Key key) { + return cache.get(key); + } + + + @Override + public boolean run() { + if (cache.isEmpty()) return true; + for (var result : cache.entrySet()) { + result.getValue().triggerPostAction(result.getKey().node()); + } + cache.clear(); + return true; + } + + public static Key key(WorldPipeNetNode node, IPredicateTestObject testObject, SimulatorKey simulator) { + return new Key(node, testObject, simulator); + } + + public static Key key(WorldPipeNetNode node, ITraverseData data) { + return new Key(node, data.getTestObject(), data.getSimulatorKey()); + } + + @Desugar + public record Key(WorldPipeNetNode node, IPredicateTestObject testObject, SimulatorKey simulator) {} +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java index 41c5ef2999f..6f1849ace68 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java @@ -1,17 +1,18 @@ package gregtech.api.graphnet.pipenet; +import gregtech.api.graphnet.traverse.util.CompositeLossOperator; import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; -import net.minecraft.util.Tuple; - +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.function.Consumer; -import java.util.function.UnaryOperator; public final class NodeLossResult { + public static final NodeLossResult IDENTITY = new NodeLossResult(null, ReversibleLossOperator.IDENTITY); + private final @Nullable Consumer postAction; private final @NotNull ReversibleLossOperator lossFunction; @@ -20,10 +21,26 @@ public NodeLossResult(@Nullable Consumer postAction, @NotNull this.lossFunction = lossFunction; } + @Contract("!null, !null -> new; !null, null -> param1; null, !null -> param2; null, null -> null") + public static NodeLossResult combine(@Nullable NodeLossResult a, @Nullable NodeLossResult b) { + if (a == null) return b; + if (b == null) return a; + Consumer postAction = a.postAction; + if (b.postAction != null) { + if (postAction == null) postAction = b.postAction; + else postAction = postAction.andThen(b.postAction); + } + return new NodeLossResult(postAction, new CompositeLossOperator(a.lossFunction, b.lossFunction)); + } + public boolean hasPostAction() { return postAction != null; } + public Consumer getPostAction() { + return postAction; + } + public void triggerPostAction(WorldPipeNetNode node) { if (postAction == null) return; this.postAction.accept(node); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index 97b4334c2c8..a67a7a552dc 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -9,6 +9,7 @@ import gregtech.api.graphnet.pipenet.physical.IBurnable; +import gregtech.api.graphnet.pipenet.physical.IFreezable; import gregtech.api.graphnet.traverse.util.CompleteLossOperator; import gregtech.api.graphnet.traverse.util.MultLossOperator; @@ -19,6 +20,7 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -96,9 +98,33 @@ public TemperatureLogic getNew() { return new TemperatureLogic(); } + public boolean isOverMaximum(int temperature) { + return temperature > getTemperatureMaximum(); + } + + public boolean isOverPartialBurnThreshold(int temperature) { + return getPartialBurnTemperature() != null && temperature > getPartialBurnTemperature(); + } + + public boolean isUnderMinimum(int temperature) { + return temperature < getTemperatureMinimum(); + } + @Nullable public NodeLossResult getLossResult(long tick) { - if (getTemperature(tick) > getTemperatureMaximum()) { + int temp = getTemperature(tick); + if (isUnderMinimum(temp)) { + return new NodeLossResult(n -> { + World world = n.getNet().getWorld(); + BlockPos pos = n.getEquivalencyData(); + IBlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof IFreezable freezable) { + freezable.fullyFreeze(state, world, pos); + } else { + world.setBlockToAir(pos); + } + }, CompleteLossOperator.INSTANCE); + } else if (isOverMaximum(temp)) { return new NodeLossResult(n -> { World world = n.getNet().getWorld(); BlockPos pos = n.getEquivalencyData(); @@ -109,7 +135,7 @@ public NodeLossResult getLossResult(long tick) { world.setBlockToAir(pos); } }, CompleteLossOperator.INSTANCE); - } else if (getPartialBurnTemperature() != null && getTemperature(tick) > getPartialBurnTemperature()) { + } else if (isOverPartialBurnThreshold(temp)) { return new NodeLossResult(n -> { World world = n.getNet().getWorld(); BlockPos pos = n.getEquivalencyData(); @@ -117,7 +143,7 @@ public NodeLossResult getLossResult(long tick) { if (state.getBlock() instanceof IBurnable burnable) { burnable.partialBurn(state, world, pos); } - }, new MultLossOperator(0.5)); + }, MultLossOperator.TENTHS[5]); } else { return null; } @@ -133,6 +159,14 @@ public void applyThermalEnergy(float energy, long tick) { this.energy += energy; } + public void moveTowardsTemperature(int temperature, long tick, float mult, boolean safe) { + if (safe) { + temperature = MathHelper.clamp(temperature, getTemperatureMinimum() + 1, getTemperatureMaximum() - 1); + } + int temp = getTemperature(tick); + applyThermalEnergy(mult * (temperature - temp), tick); + } + public int getTemperature(long tick) { restoreTemperature(tick); return (int) (this.energy / this.thermalMass) + DEFAULT_TEMPERATURE; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java index 9c0e527fb51..51cf8739ddd 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java @@ -20,6 +20,5 @@ default void partialBurn(IBlockState state, World world, BlockPos pos) {} default void fullyBurn(IBlockState state, World world, BlockPos pos) { assert Blocks.FIRE != null; world.setBlockState(pos, Blocks.FIRE.getDefaultState()); - world.setBlockToAir(pos); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IFreezable.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IFreezable.java new file mode 100644 index 00000000000..88c45cabfe7 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IFreezable.java @@ -0,0 +1,17 @@ +package gregtech.api.graphnet.pipenet.physical; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public interface IFreezable { + + /** + * Called when the block should be fully frozen. + */ + default void fullyFreeze(IBlockState state, World world, BlockPos pos) { + assert Blocks.FROSTED_ICE != null; + world.setBlockState(pos, Blocks.FROSTED_ICE.getDefaultState()); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java index 3ca8ea1e76b..bcda0498ee8 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java @@ -1,5 +1,6 @@ package gregtech.api.graphnet.pipenet.physical.block; +import gregtech.api.GTValues; import gregtech.api.block.BuiltInRenderBlock; import gregtech.api.cover.Cover; @@ -35,6 +36,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.NonNullList; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -43,6 +45,7 @@ import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraft.world.WorldServer; import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fml.common.FMLCommonHandler; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index f541fa22825..d91a50f73a4 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -1,5 +1,6 @@ package gregtech.api.graphnet.pipenet.physical.tile; +import gregtech.api.GTValues; import gregtech.api.GregTechAPI; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; @@ -22,20 +23,27 @@ import gregtech.common.blocks.MetaBlocks; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.SoundEvents; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ITickable; import net.minecraft.util.NonNullList; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.property.IExtendedBlockState; @@ -48,8 +56,10 @@ import org.jetbrains.annotations.Nullable; import java.util.EnumMap; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import static gregtech.api.capability.GregtechDataCodes.*; @@ -87,6 +97,9 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick private final int offset = (int) (Math.random() * 20); + private long nextDamageTime = 0; + private long nextSoundTime = 0; + public PipeTileEntity(WorldPipeBlock block) { this.block = block; } @@ -565,6 +578,20 @@ public boolean isOverheatParticleAlive() { return overheatParticle != null && overheatParticle.isAlive(); } + public void spawnParticles(EnumFacing direction, EnumParticleTypes particleType, int particleCount) { + if (getWorld() instanceof WorldServer server) { + server.spawnParticle(particleType, + getPos().getX() + 0.5, + getPos().getY() + 0.5, + getPos().getZ() + 0.5, + particleCount, + direction.getXOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, + direction.getYOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, + direction.getZOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, + 0.1); + } + } + // misc overrides // @Override @@ -623,4 +650,39 @@ public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { .withProperty(AbstractPipeModel.FRAME_MATERIAL_PROPERTY, frameMaterial) .withProperty(AbstractPipeModel.FRAME_MASK_PROPERTY, frameMask); } + + public void dealAreaDamage(int size, Consumer damageFunction) { + long timer = getOffsetTimer(); + if (timer >= this.nextDamageTime) { + List entities = getWorld().getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(getPos()).grow(size)); + entities.forEach(damageFunction); + this.nextDamageTime = timer + 20; + } + } + + public void playLossSound() { + long timer = getOffsetTimer(); + if (timer >= this.nextSoundTime) { + getWorld().playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); + this.nextSoundTime = timer + 20; + } + } + + public void visuallyExplode() { + getWorld().createExplosion(null, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, + 1.0f + GTValues.RNG.nextFloat(), false); + } + + public void setNeighborsToFire() { + for (EnumFacing side : EnumFacing.VALUES) { + if (!GTValues.RNG.nextBoolean()) continue; + BlockPos blockPos = getPos().offset(side); + IBlockState blockState = getWorld().getBlockState(blockPos); + if (blockState.getBlock().isAir(blockState, getWorld(), blockPos) || + blockState.getBlock().isFlammable(getWorld(), blockPos, side.getOpposite())) { + getWorld().setBlockState(blockPos, Blocks.FIRE.getDefaultState()); + } + } + } } diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java index 87ca1818007..16b44dea78e 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java @@ -20,6 +20,10 @@ public FluidStack recombine() { return new FluidStack(fluid, 1, tag); } + public FluidStack recombine(int amount) { + return new FluidStack(fluid, amount, tag); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java index 4e1661a6e85..f56e2883af1 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java @@ -4,6 +4,8 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import org.jetbrains.annotations.Range; + import java.util.Objects; public class ItemTestObject implements IPredicateTestObject { @@ -12,16 +14,28 @@ public class ItemTestObject implements IPredicateTestObject { public final int meta; public final NBTTagCompound tag; + public final int stackLimit; + public ItemTestObject(ItemStack stack) { item = stack.getItem(); meta = stack.getMetadata(); tag = stack.getTagCompound(); + stackLimit = stack.getMaxStackSize(); } public ItemStack recombine() { return new ItemStack(item, 1, meta, tag); } + public ItemStack recombine(int amount) { + assert amount < getStackLimit() && amount > 0; + return new ItemStack(item, amount, meta, tag); + } + + public int getStackLimit() { + return stackLimit; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java index 1fbfaf5cb1b..6ec10b99fb1 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java @@ -9,7 +9,7 @@ public interface IEqualizableTraverseData> { @@ -20,7 +19,7 @@ public interface IRoundRobinTraverseData> { /** * Called before walking the next path. Should reset per-path logics to prepare. + * * @param path the next path + * @param flow how much flow can be provided to the path. * @return whether the path should be skipped */ - boolean prepareForPathWalk(P path); + boolean prepareForPathWalk(P path, long flow); /** * Reports that the traverse is traversing to a node, for additional logic to be run. @@ -55,4 +57,15 @@ public interface ITraverseData> { default long getFlowLimit(AbstractNetFlowEdge edge) { return edge.getFlowLimit(this.getTestObject(), this.getGraphNet(), this.getQueryTick(), this.getSimulatorKey()); } + + /** + * Allows for consuming more than just the edge flow limits on a consumption event. Must always consume the correct + * amount of edge flow or things will break. + * @param edge the edge to consume along. + * @param targetNode the target node of the edge. + * @param consumption the amount to consume from the edge's flow limit. + */ + default void consumeFlowLimit(AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { + edge.consumeFlowLimit(this.getTestObject(), this.getGraphNet(), consumption, this.getQueryTick(), this.getSimulatorKey()); + } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index c0d96228ad7..d0af0461db8 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -18,8 +18,6 @@ import java.util.ArrayDeque; import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.function.BiConsumer; @@ -51,7 +49,7 @@ public static pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); long pathFlow = availableFlow; P path = paths.next(); - if (data.prepareForPathWalk(path)) continue; + if (data.prepareForPathWalk(path, pathFlow)) continue; List nodes = path.getOrderedNodes(); List edges = path.getOrderedEdges(); @@ -71,7 +69,7 @@ public static consumeFlowLimit(edge, data, flow), data.traverseToNode(targetNode, pathFlow)); + stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); if (pathFlow <= 0) continue pathloop; @@ -87,10 +85,6 @@ public static data, long consumption) { - edge.consumeFlowLimit(data.getTestObject(), data.getGraphNet(), consumption, data.getQueryTick(), data.getSimulatorKey()); - } - /** * Provides logic for traversing a net that simply finds the lowest weight path that it can traverse, * and then traverses it. Optionally supports flow, in which case overflows will be reported @@ -116,7 +110,7 @@ public static , D List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); long pathFlow = isFlow ? availableFlow : 1; P path = paths.next(); - if (data.prepareForPathWalk(path)) continue; + if (data.prepareForPathWalk(path, pathFlow)) continue; List nodes = path.getOrderedNodes(); List edges = path.getOrderedEdges(); @@ -148,7 +142,7 @@ public static , D if (finalOverflow > 0) overflowListener.accept(targetNode, finalOverflow); }); } - stack.add(flow -> consumeFlowLimit(flowEdge, data, flow), data.traverseToNode(targetNode, pathFlow)); + stack.add(flow -> data.consumeFlowLimit(flowEdge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); } @@ -251,7 +245,7 @@ public static nodes = path.getOrderedNodes(); List edges = path.getOrderedEdges(); @@ -271,7 +265,7 @@ public static consumeFlowLimit(edge, data, flow), data.traverseToNode(targetNode, pathFlow)); + stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); if (pathFlow <= 0) continue pathloop; @@ -389,7 +383,7 @@ private static pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); long pathFlow = flowIn; - data.prepareForPathWalk(path); + data.prepareForPathWalk(path, pathFlow); List nodes = path.getOrderedNodes(); List edges = path.getOrderedEdges(); @@ -409,7 +403,7 @@ private static consumeFlowLimit(edge, data, flow), data.traverseToNode(targetNode, pathFlow)); + stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); if (pathFlow <= 0) return 0; diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/CompositeLossOperator.java b/src/main/java/gregtech/api/graphnet/traverse/util/CompositeLossOperator.java new file mode 100644 index 00000000000..979116b379c --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/util/CompositeLossOperator.java @@ -0,0 +1,22 @@ +package gregtech.api.graphnet.traverse.util; + +public class CompositeLossOperator implements ReversibleLossOperator { + + private final ReversibleLossOperator first; + private final ReversibleLossOperator second; + + public CompositeLossOperator(ReversibleLossOperator first, ReversibleLossOperator second) { + this.first = first; + this.second = second; + } + + @Override + public double applyLoss(double value) { + return second.applyLoss(first.applyLoss(value)); + } + + @Override + public double undoLoss(double value) { + return first.undoLoss(second.undoLoss(value)); + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java b/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java index 04a5b5ad6f7..49bfb6dad72 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java +++ b/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java @@ -14,7 +14,7 @@ public class FlowConsumptionStack { private final ReversibleLossOperator initialOperator; public FlowConsumptionStack() { - this.initialOperator = IdentityLossOperator.INSTANCE; + this.initialOperator = ReversibleLossOperator.IDENTITY; } public FlowConsumptionStack(ReversibleLossOperator initialOperator) { diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/IdentityLossOperator.java b/src/main/java/gregtech/api/graphnet/traverse/util/IdentityLossOperator.java deleted file mode 100644 index b0f8d105566..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverse/util/IdentityLossOperator.java +++ /dev/null @@ -1,17 +0,0 @@ -package gregtech.api.graphnet.traverse.util; - -public class IdentityLossOperator implements ReversibleLossOperator { - public static final IdentityLossOperator INSTANCE = new IdentityLossOperator(); - - private IdentityLossOperator() {} - - @Override - public double applyLoss(double value) { - return value; - } - - @Override - public double undoLoss(double value) { - return value; - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java b/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java index 8b43231f425..1bfc018e6bb 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java @@ -2,6 +2,19 @@ public class MultLossOperator implements ReversibleLossOperator { + public static final MultLossOperator[] TENTHS = new MultLossOperator[10]; + + public static final MultLossOperator[] EIGHTHS = new MultLossOperator[8]; + + static { + for (int i = 1; i < 10; i++) { + TENTHS[i] = new MultLossOperator(0.1d * i); + } + for (int i = 1; i < 8; i++) { + EIGHTHS[i] = new MultLossOperator(0.125d * i); + } + } + private final double mult; public MultLossOperator(double mult) { diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/ReversibleLossOperator.java b/src/main/java/gregtech/api/graphnet/traverse/util/ReversibleLossOperator.java index b6d860bd402..7f3cc05aa56 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/ReversibleLossOperator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/util/ReversibleLossOperator.java @@ -2,6 +2,19 @@ public interface ReversibleLossOperator { + ReversibleLossOperator IDENTITY = new ReversibleLossOperator() { + + @Override + public double applyLoss(double value) { + return value; + } + + @Override + public double undoLoss(double value) { + return value; + } + }; + double applyLoss(double value); double undoLoss(double value); diff --git a/src/main/java/gregtech/api/items/metaitem/FilteredFluidStats.java b/src/main/java/gregtech/api/items/metaitem/FilteredFluidStats.java index 75bfaae996b..d06ac6846ac 100644 --- a/src/main/java/gregtech/api/items/metaitem/FilteredFluidStats.java +++ b/src/main/java/gregtech/api/items/metaitem/FilteredFluidStats.java @@ -26,10 +26,10 @@ public FilteredFluidStats(int capacity, boolean allowPartialFill, @Nullable IFil this.filter = filter; } - public FilteredFluidStats(int capacity, int maxFluidTemperature, boolean gasProof, boolean acidProof, - boolean cryoProof, boolean plasmaProof, boolean allowPartialFill) { + public FilteredFluidStats(int capacity, int maxFluidTemperature, int minFluidTemperature, boolean gasProof, boolean acidProof, + boolean plasmaProof, boolean allowPartialFill) { this(capacity, allowPartialFill, - new PropertyFluidFilter(maxFluidTemperature, gasProof, acidProof, cryoProof, plasmaProof)); + new PropertyFluidFilter(maxFluidTemperature, minFluidTemperature, gasProof, acidProof, plasmaProof)); } @Override diff --git a/src/main/java/gregtech/api/unification/material/Material.java b/src/main/java/gregtech/api/unification/material/Material.java index ef61dc804fa..d8dada085fb 100644 --- a/src/main/java/gregtech/api/unification/material/Material.java +++ b/src/main/java/gregtech/api/unification/material/Material.java @@ -3,6 +3,7 @@ import gregtech.api.GregTechAPI; import gregtech.api.fluids.FluidBuilder; import gregtech.api.fluids.FluidState; +import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.fluids.store.FluidStorageKey; import gregtech.api.fluids.store.FluidStorageKeys; import gregtech.api.unification.Element; @@ -18,7 +19,11 @@ import gregtech.api.util.LocalizationUtils; import gregtech.api.util.SmallDigits; -import gregtech.common.pipelike.handlers.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; + +import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; + +import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; import net.minecraft.enchantment.Enchantment; import net.minecraft.util.ResourceLocation; @@ -1064,19 +1069,33 @@ public Builder cableProperties(long voltage, long amperage, long loss, int meltT return this; } - public Builder fluidPipeProperties(int maxTemp, int throughput, boolean gasProof) { - return fluidPipeProperties(maxTemp, throughput, gasProof, false, false, false); + public Builder fluidPipeProperties(int maxTemp, long throughput, boolean gasProof) { + getOrCreatePipeNetProperties().setProperty(MaterialFluidProperties.createMax(throughput, maxTemp).setContain(FluidState.GAS, gasProof)); + return this; + } + + public Builder fluidPipeProperties(int maxTemp, long throughput, boolean gasProof, float priority) { + getOrCreatePipeNetProperties().setProperty(MaterialFluidProperties.createMax(throughput, maxTemp, priority).setContain(FluidState.GAS, gasProof)); + return this; } public Builder fluidPipeProperties(int maxTemp, int throughput, boolean gasProof, boolean acidProof, - boolean cryoProof, boolean plasmaProof) { - properties.setProperty(PropertyKey.FLUID_PIPE, - new FluidPipeProperties(maxTemp, throughput, gasProof, acidProof, cryoProof, plasmaProof)); + boolean plasmaProof) { + getOrCreatePipeNetProperties().setProperty(MaterialFluidProperties.createMax(throughput, maxTemp).setContain(FluidState.GAS, gasProof) + .setContain(FluidAttributes.ACID, acidProof).setContain(FluidState.PLASMA, plasmaProof)); + return this; + } + + public Builder fluidPipeProperties(int maxTemp, int minTemp, int throughput, boolean gasProof, boolean acidProof, + boolean plasmaProof) { + getOrCreatePipeNetProperties().setProperty(new MaterialFluidProperties(throughput, maxTemp, minTemp) + .setContain(FluidState.GAS, gasProof).setContain(FluidAttributes.ACID, acidProof) + .setContain(FluidState.PLASMA, plasmaProof)); return this; } public Builder itemPipeProperties(int priority, float stacksPerSec) { - properties.setProperty(PropertyKey.ITEM_PIPE, new ItemPipeProperties(priority, stacksPerSec)); + getOrCreatePipeNetProperties().setProperty(new MaterialItemProperties((long) (stacksPerSec * 16), priority)); return this; } diff --git a/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java b/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java index 8d4af1f4fa7..b93b70ed7e0 100644 --- a/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java @@ -168,7 +168,7 @@ public static void register() { .flags(EXT_METAL, GENERATE_ROTOR, GENERATE_DOUBLE_PLATE) .element(Elements.Cr) .rotorStats(12.0f, 3.0f, 512) - .fluidPipeProperties(2180, 35, true, true, false, false) + .fluidPipeProperties(2180, 104, 35, true, true, false) .blast(1700, GasTier.LOW) .build(); @@ -302,7 +302,7 @@ public static void register() { GENERATE_DOUBLE_PLATE) .element(Elements.Au) .cableProperties(V[HV], 3, 2) - .fluidPipeProperties(1671, 25, true, true, false, false) + .fluidPipeProperties(1671, 25, true, true, false) .build(); Hafnium = new Material.Builder(42, gregtechId("hafnium")) @@ -366,7 +366,7 @@ public static void register() { .flags(EXT2_METAL, GENERATE_DOUBLE_PLATE, GENERATE_FINE_WIRE, GENERATE_GEAR, GENERATE_FRAME) .element(Elements.Ir) .rotorStats(7.0f, 3.0f, 2560) - .fluidPipeProperties(3398, 250, true, false, true, false) + .fluidPipeProperties(3398, 5, 250, true, false, false) .blast(b -> b .temp(4500, GasTier.HIGH) .blastStats(VA[IV], 1100) @@ -835,7 +835,7 @@ public static void register() { .toolStats(ToolProperty.Builder.of(8.0F, 6.0F, 1536, 3) .enchantability(14).build()) .rotorStats(7.0f, 3.0f, 1600) - .fluidPipeProperties(2426, 150, true, true, false, false) + .fluidPipeProperties(2426, 150, true, true, false) .blast(b -> b .temp(1941, GasTier.MID) .blastStats(VA[HV], 1500) @@ -858,7 +858,7 @@ public static void register() { .element(Elements.W) .rotorStats(7.0f, 3.0f, 2560) .cableProperties(V[IV], 2, 2) - .fluidPipeProperties(4618, 50, true, true, false, true) + .fluidPipeProperties(4618, 50, true, true, true) .blast(b -> b .temp(3600, GasTier.MID) .blastStats(VA[EV], 1800) @@ -929,7 +929,7 @@ public static void register() { .element(Elements.Nq) .rotorStats(6.0f, 4.0f, 1280) .cableProperties(V[ZPM], 2, 2) - .fluidPipeProperties(3776, 200, true, false, true, true) + .fluidPipeProperties(3776, 3, 200, true, false, true) .blast(b -> b .temp(5000, GasTier.HIGH) .blastStats(VA[IV], 600) @@ -971,7 +971,7 @@ public static void register() { .toolStats(ToolProperty.Builder.of(180.0F, 100.0F, 65535, 6) .attackSpeed(0.5F).enchantability(33).magnetic().unbreakable().build()) .rotorStats(24.0f, 12.0f, 655360) - .fluidPipeProperties(100_000, 5000, true, true, true, true) + .fluidPipeProperties(100_000, 1, 5000, true, true, true) .build(); Tritanium = new Material.Builder(128, gregtechId("tritanium")) @@ -993,7 +993,7 @@ public static void register() { .element(Elements.Dr) .toolStats(ToolProperty.Builder.of(14.0F, 12.0F, 8192, 5) .attackSpeed(0.3F).enchantability(33).magnetic().build()) - .fluidPipeProperties(9625, 500, true, true, true, true) + .fluidPipeProperties(9625, 1, 500, true, true, true) .build(); Trinium = new Material.Builder(130, gregtechId("trinium")) diff --git a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java index 034644e69c7..fb395f10262 100644 --- a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java @@ -599,7 +599,7 @@ public static void register() { .toolStats(ToolProperty.Builder.of(7.0F, 5.0F, 1024, 3) .enchantability(14).build()) .rotorStats(7.0f, 4.0f, 480) - .fluidPipeProperties(2428, 75, true, true, true, false) + .fluidPipeProperties(2428, 59, 75, true, true, false) .blast(b -> b.temp(1700, GasTier.LOW).blastStats(VA[HV], 1100)) .build(); diff --git a/src/main/java/gregtech/api/unification/material/materials/OrganicChemistryMaterials.java b/src/main/java/gregtech/api/unification/material/materials/OrganicChemistryMaterials.java index de2bdf4a703..91a23b873cb 100644 --- a/src/main/java/gregtech/api/unification/material/materials/OrganicChemistryMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/OrganicChemistryMaterials.java @@ -143,7 +143,7 @@ public static void register() { .color(0x646464) .flags(STD_METAL, GENERATE_FRAME, GENERATE_FOIL) .components(Carbon, 2, Fluorine, 4) - .fluidPipeProperties(600, 100, true, true, false, false) + .fluidPipeProperties(600, 100, true, true, false) .build(); Sugar = new Material.Builder(1017, gregtechId("sugar")) diff --git a/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java index aff4da9ac1f..27403478bcd 100644 --- a/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java @@ -122,7 +122,7 @@ public static void register() { .toolStats(ToolProperty.Builder.of(9.0F, 7.0F, 2048, 4) .enchantability(14).build()) .rotorStats(8.0f, 4.0f, 2560) - .fluidPipeProperties(3587, 225, true, true, false, false) + .fluidPipeProperties(3587, 225, true, true, false) .cableProperties(V[IV], 3, 2) .blast(b -> b .temp(4000, GasTier.MID) @@ -290,7 +290,7 @@ public static void register() { .toolStats(ToolProperty.Builder.of(3.0F, 3.0F, 1536, 3) .attackSpeed(-0.2F).enchantability(5).build()) .rotorStats(7.0f, 3.0f, 1920) - .fluidPipeProperties(2073, 50, true, true, false, false) + .fluidPipeProperties(2073, 50, true, true, false) .blast(1453, GasTier.LOW) .build(); diff --git a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java deleted file mode 100644 index 22d0ed7646d..00000000000 --- a/src/main/java/gregtech/api/unification/material/properties/FluidPipeProperties.java +++ /dev/null @@ -1,386 +0,0 @@ -package gregtech.api.unification.material.properties; - -import gregtech.api.GTValues; -import gregtech.api.capability.IPropertyFluidFilter; -import gregtech.api.fluids.FluidConstants; -import gregtech.api.fluids.FluidState; -import gregtech.api.fluids.attribute.AttributedFluid; -import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.fluids.attribute.FluidAttributes; -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.NodeLossResult; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.util.EntityDamageUtil; -import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; - -import net.minecraft.init.Blocks; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.WorldServer; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidStack; - -import it.unimi.dsi.fastutil.objects.Object2BooleanMap; -import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.UnmodifiableView; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; - -public class FluidPipeProperties implements IMaterialProperty, IPropertyFluidFilter, - IPipeNetData { - - private final Object2BooleanMap containmentPredicate = new Object2BooleanOpenHashMap<>(); - - private int throughput; - private int tanks; - - private int maxFluidTemperature; - private boolean gasProof; - private boolean cryoProof; - private boolean plasmaProof; - - public FluidPipeProperties(int maxFluidTemperature, int throughput, boolean gasProof, boolean acidProof, - boolean cryoProof, boolean plasmaProof) { - this(maxFluidTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof, 1); - } - - /** - * Should only be called from - * {@link gregtech.common.pipelikeold.fluidpipe.FluidPipeType#modifyProperties(FluidPipeProperties)} - */ - public FluidPipeProperties(int maxFluidTemperature, int throughput, boolean gasProof, boolean acidProof, - boolean cryoProof, boolean plasmaProof, int tanks) { - this.maxFluidTemperature = maxFluidTemperature; - this.throughput = throughput; - this.gasProof = gasProof; - if (acidProof) setCanContain(FluidAttributes.ACID, true); - this.cryoProof = cryoProof; - this.plasmaProof = plasmaProof; - this.tanks = tanks; - } - - /** - * Default property constructor. - */ - public FluidPipeProperties() { - this(300, 1, false, false, false, false); - } - - @Override - public void verifyProperty(MaterialProperties properties) { - if (!properties.hasProperty(PropertyKey.WOOD)) { - properties.ensureSet(PropertyKey.INGOT, true); - } - - if (properties.hasProperty(PropertyKey.ITEM_PIPE)) { - throw new IllegalStateException( - "Material " + properties.getMaterial() + - " has both Fluid and Item Pipe Property, which is not allowed!"); - } - } - - public int getTanks() { - return tanks; - } - - @Override - public double getWeightFactor() { - float factor = 100f / this.throughput; - return factor * factor; - } - - public int getThroughput() { - return throughput; - } - - public void setThroughput(int throughput) { - this.throughput = throughput; - } - - @Override - public int getMaxFluidTemperature() { - return maxFluidTemperature; - } - - public void setMaxFluidTemperature(int maxFluidTemperature) { - this.maxFluidTemperature = maxFluidTemperature; - } - - @Override - public boolean canContain(@NotNull FluidState state) { - return switch (state) { - case LIQUID -> true; - case GAS -> gasProof; - case PLASMA -> plasmaProof; - }; - } - - @Override - public boolean canContain(@NotNull FluidAttribute attribute) { - return containmentPredicate.getBoolean(attribute); - } - - @Override - public void setCanContain(@NotNull FluidAttribute attribute, boolean canContain) { - this.containmentPredicate.put(attribute, canContain); - } - - @Override - public @NotNull @UnmodifiableView Collection<@NotNull FluidAttribute> getContainedAttributes() { - return containmentPredicate.keySet(); - } - - public boolean isGasProof() { - return gasProof; - } - - public void setGasProof(boolean gasProof) { - this.gasProof = gasProof; - } - - public boolean isAcidProof() { - return canContain(FluidAttributes.ACID); - } - - public boolean isCryoProof() { - return cryoProof; - } - - public void setCryoProof(boolean cryoProof) { - this.cryoProof = cryoProof; - } - - public boolean isPlasmaProof() { - return plasmaProof; - } - - public void setPlasmaProof(boolean plasmaProof) { - this.plasmaProof = plasmaProof; - } - - @Override - public int getChannelMaxCount() { - return this.tanks; - } - - public NodeLossResult determineFluidPassthroughResult(@NotNull FluidStack stack, World world, BlockPos pos) { - Fluid fluid = stack.getFluid(); - - boolean burning = this.getMaxFluidTemperature() < fluid.getTemperature(stack); - boolean leaking = !this.isGasProof() && fluid.isGaseous(stack); - boolean shattering = !this.isCryoProof() && fluid.getTemperature() < FluidConstants.CRYOGENIC_FLUID_THRESHOLD; - boolean corroding = false; - boolean melting = false; - - if (fluid instanceof AttributedFluid attributedFluid) { - FluidState state = attributedFluid.getState(); - if (!this.canContain(state)) { - leaking = state == FluidState.GAS; - melting = state == FluidState.PLASMA; - } - - // carrying plasmas which are too hot when plasma proof does not burn pipes - if (burning && state == FluidState.PLASMA && this.canContain(FluidState.PLASMA)) { - burning = false; - } - - for (FluidAttribute attribute : attributedFluid.getAttributes()) { - if (!this.canContain(attribute)) { - // corrodes if the pipe can't handle the attribute, even if it's not an acid - corroding = true; - } - } - } - - if (burning || leaking || corroding || shattering || melting) { - return determineDestroyPipeResults(stack, burning, leaking, corroding, shattering, melting, world, pos); - } else return new NodeLossResult(n -> {}, 1d); - } - - public NodeLossResult determineDestroyPipeResults(FluidStack stack, boolean isBurning, boolean isLeaking, - boolean isCorroding, boolean isShattering, - boolean isMelting, World world, BlockPos pos) { - List particleActions = new ObjectArrayList<>(); - Consumer damageAction = tile -> {}; - Runnable destructionAction = () -> {}; - double mult = 1; - - if (isLeaking) { - particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, - EnumParticleTypes.SMOKE_NORMAL, 7 + GTValues.RNG.nextInt(2))); - - // voids 10% - mult *= 0.9; - - // apply heat damage in area surrounding the pipe - damageAction = tile -> tile.dealAreaDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, - stack.getFluid().getTemperature(stack), 2.0F, 10)); - - // chance to do a small explosion - if (GTValues.RNG.nextInt(isBurning ? 3 : 7) == 0) { - destructionAction = () -> world.setBlockToAir(pos); - if (!world.isRemote) { - particleActions.add(() -> ((WorldServer) world).spawnParticle(EnumParticleTypes.SMOKE_LARGE, - pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 10, 0.2, 0.2, 0.2, 0.0)); - } - particleActions - .add(() -> world.createExplosion(null, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, - 1.0f + GTValues.RNG.nextFloat(), false)); - } - } - - if (isCorroding) { - particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, - EnumParticleTypes.CRIT_MAGIC, 3 + GTValues.RNG.nextInt(2))); - - // voids 25% - mult *= 0.75; - - // apply chemical damage in area surrounding the pipe - damageAction = tile -> tile.dealAreaDamage(1, entity -> EntityDamageUtil.applyChemicalDamage(entity, 2)); - - // 1/10 chance to void everything and destroy the pipe - if (GTValues.RNG.nextInt(10) == 0) { - mult = 0; - destructionAction = () -> world.setBlockToAir(pos); - } - } - - if (isBurning || isMelting) { - particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, - EnumParticleTypes.FLAME, (isMelting ? 7 : 3) + GTValues.RNG.nextInt(2))); - - // voids 75% - mult *= 0.25; - - // 1/4 chance to burn everything around it - if (GTValues.RNG.nextInt(4) == 0) { - TileEntityFluidPipe.setNeighboursToFire(world, pos); - } - - // apply heat damage in area surrounding the pipe - damageAction = tile -> tile.dealAreaDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, - stack.getFluid().getTemperature(stack), 2.0F, 10)); - - // 1/10 chance to void everything and burn the pipe - if (GTValues.RNG.nextInt(10) == 0) { - mult = 0; - destructionAction = () -> world.setBlockState(pos, Blocks.FIRE.getDefaultState()); - } - } - - if (isShattering) { - particleActions.add(() -> TileEntityFluidPipe.spawnParticles(world, pos, EnumFacing.UP, - EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2))); - - // voids 75% - mult *= 0.75; - - // apply frost damage in area surrounding the pipe - damageAction = tile -> tile.dealAreaDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, - stack.getFluid().getTemperature(stack), 2.0F, 10)); - - // 1/10 chance to void everything and freeze the pipe - if (GTValues.RNG.nextInt(10) == 0) { - mult = 0; - destructionAction = () -> world.setBlockState(pos, Blocks.ICE.getDefaultState()); - } - } - Runnable finalDestructionAction = destructionAction; - Consumer finalDamageAction = damageAction; - return new NodeLossResult(nodeG -> { - // only do 'extra' actions if the node already holds its MTE. - // don't go fetch it from the world as this 9 times out of 10 means loading a chunk unnecessarily. - IPipeTile tile = nodeG.getHeldMTEUnsafe(); - if (tile instanceof TileEntityFluidPipe pipe) { - pipe.playLossSound(); - particleActions.forEach(Runnable::run); - finalDamageAction.accept(pipe); - } - finalDestructionAction.run(); - }, mult); - } - - @Override - public FluidPipeProperties getSumData(List datas) { - int maxFluidTemperature = this.getMaxFluidTemperature(); - int throughput = this.getThroughput(); - boolean gasProof = this.isGasProof(); - boolean acidProof = this.isAcidProof(); - boolean cryoProof = this.isCryoProof(); - boolean plasmaProof = this.isPlasmaProof(); - for (FluidPipeProperties data : datas) { - maxFluidTemperature = Math.min(maxFluidTemperature, data.getMaxFluidTemperature()); - throughput = Math.min(throughput, data.getThroughput()); - gasProof &= data.isGasProof(); - acidProof &= data.isAcidProof(); - cryoProof &= data.isCryoProof(); - plasmaProof &= data.isPlasmaProof(); - } - return new FluidPipeProperties(maxFluidTemperature, throughput, gasProof, acidProof, cryoProof, plasmaProof); - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tagCompound = new NBTTagCompound(); - tagCompound.setInteger("max_temperature", this.getMaxFluidTemperature()); - tagCompound.setInteger("throughput", this.getThroughput()); - tagCompound.setBoolean("gas_proof", this.isGasProof()); - tagCompound.setBoolean("acid_proof", this.isAcidProof()); - tagCompound.setBoolean("cryo_proof", this.isCryoProof()); - tagCompound.setBoolean("plasma_proof", this.isPlasmaProof()); - tagCompound.setInteger("channels", this.getTanks()); - return tagCompound; - } - - @Override - public void deserializeNBT(NBTTagCompound tagCompound) { - maxFluidTemperature = tagCompound.getInteger("max_temperature"); - throughput = tagCompound.getInteger("throughput"); - gasProof = tagCompound.getBoolean("gas_proof"); - if (tagCompound.getBoolean("acid_proof")) setCanContain(FluidAttributes.ACID, true); - cryoProof = tagCompound.getBoolean("cryo_proof"); - plasmaProof = tagCompound.getBoolean("plasma_proof"); - tanks = tagCompound.getInteger("channels"); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof FluidPipeProperties that)) return false; - return getThroughput() == that.getThroughput() && - getTanks() == that.getTanks() && - getMaxFluidTemperature() == that.getMaxFluidTemperature() && - isGasProof() == that.isGasProof() && - isCryoProof() == that.isCryoProof() && - isPlasmaProof() == that.isPlasmaProof() && - containmentPredicate.equals(that.containmentPredicate); - } - - @Override - public int hashCode() { - return Objects.hash(getThroughput(), getTanks(), getMaxFluidTemperature(), gasProof, cryoProof, plasmaProof, - containmentPredicate); - } - - @Override - public String toString() { - return "FluidPipeProperties{" + - "throughput=" + throughput + - ", tanks=" + tanks + - ", maxFluidTemperature=" + maxFluidTemperature + - ", gasProof=" + gasProof + - ", cryoProof=" + cryoProof + - ", plasmaProof=" + plasmaProof + - ", containmentPredicate=" + containmentPredicate + - '}'; - } -} diff --git a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java b/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java deleted file mode 100644 index 22e4fbcc448..00000000000 --- a/src/main/java/gregtech/api/unification/material/properties/ItemPipeProperties.java +++ /dev/null @@ -1,115 +0,0 @@ -package gregtech.api.unification.material.properties; - -import gregtech.api.graphnet.pipenetold.IPipeNetData; - -import java.util.List; -import java.util.Objects; - -public class ItemPipeProperties implements IMaterialProperty, IPipeNetData { - - /** - * Items will try to take the path with the lowest priority - */ - private int priority; - - /** - * rate in stacks per sec - */ - private float transferRate; - - public ItemPipeProperties(int priority, float transferRate) { - this.priority = priority; - this.transferRate = transferRate; - } - - /** - * Default property constructor. - */ - public ItemPipeProperties() { - this(1, 0.25f); - } - - /** - * Retrieves the priority of the item pipe - * - * @return The item pipe priority - */ - public int getPriority() { - return priority; - } - - /** - * Sets the Priority of the item pipe - */ - public void setPriority(int priority) { - this.priority = priority; - } - - /** - * Retrieve the transfer rate of the item pipe - * - * @return The transfer rate of the item pipe - */ - public float getTransferRate() { - return transferRate; - } - - /** - * Sets the transfer rate of the item pipe - * - * @param transferRate The transfer rate - */ - public void setTransferRate(float transferRate) { - this.transferRate = transferRate; - } - - @Override - public void verifyProperty(MaterialProperties properties) { - if (!properties.hasProperty(PropertyKey.WOOD)) { - properties.ensureSet(PropertyKey.INGOT, true); - } - - if (properties.hasProperty(PropertyKey.FLUID_PIPE)) { - throw new IllegalStateException( - "Material " + properties.getMaterial() + - " has both Fluid and Item Pipe Property, which is not allowed!"); - } - } - - @Override - public double getWeightFactor() { - // 200 the magic number is dead ;-; - return priority; - } - - @Override - public ItemPipeProperties getSumData(List datas) { - float transferRate = this.getTransferRate(); - int priority = this.getPriority(); - for (ItemPipeProperties data : datas) { - transferRate = Math.min(transferRate, data.getTransferRate()); - priority += data.getPriority(); - } - return new ItemPipeProperties(priority, transferRate); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ItemPipeProperties that)) return false; - return priority == that.priority && Float.compare(that.transferRate, transferRate) == 0; - } - - @Override - public int hashCode() { - return Objects.hash(priority, transferRate); - } - - @Override - public String toString() { - return "ItemPipeProperties{" + - "priority=" + priority + - ", transferRate=" + transferRate + - '}'; - } -} diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index 91f313e02c2..aa1799d42fc 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -6,17 +6,11 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.ore.IOreRegistrationHandler; - -import gregtech.api.unification.ore.OrePrefix; -import gregtech.api.util.function.TriConsumer; - import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.util.IStringSerializable; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -26,26 +20,28 @@ import java.util.List; import java.util.Map; -import static gregtech.api.unification.material.info.MaterialFlags.NO_UNIFICATION; - public class PipeNetProperties implements IMaterialProperty, IPipeNetNodeHandler { - protected final Map properties = new Object2ObjectOpenHashMap<>(); + protected final Map, IPipeNetMaterialProperty> properties = new Object2ObjectOpenHashMap<>(); public void setProperty(IPipeNetMaterialProperty property) { - this.properties.put(property.getName(), property); + this.properties.put(property.getKey(), property); + } + + public boolean hasProperty(IPipeNetMaterialProperty.MaterialPropertyKey key) { + return this.properties.containsKey(key); } - public boolean hasProperty(String propertyName) { - return this.properties.containsKey(propertyName); + public Collection getRegisteredProperties() { + return properties.values(); } - public T getProperty(String propertyName) { - return (T) this.properties.get(propertyName); + public T getProperty(IPipeNetMaterialProperty.MaterialPropertyKey key) { + return key.cast(this.properties.get(key)); } - public void removeProperty(String propertyName) { - this.properties.remove(propertyName); + public void removeProperty(IPipeNetMaterialProperty.MaterialPropertyKey key) { + this.properties.remove(key); } public boolean generatesStructure(IPipeStructure structure) { @@ -86,7 +82,7 @@ public void verifyProperty(MaterialProperties properties) { } } - public interface IPipeNetMaterialProperty extends IMaterialProperty, IStringSerializable { + public interface IPipeNetMaterialProperty extends IMaterialProperty { void addToNet(World world, BlockPos pos, IPipeStructure structure); @@ -98,5 +94,15 @@ public interface IPipeNetMaterialProperty extends IMaterialProperty, IStringSeri void removeFromNet(World world, BlockPos pos, IPipeStructure structure); boolean generatesStructure(IPipeStructure structure); + + MaterialPropertyKey getKey(); + + class MaterialPropertyKey { + + T cast(IPipeNetMaterialProperty property) { + return (T) property; + } + } } + } diff --git a/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java b/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java index 273caab6dbd..8577c41f89f 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java +++ b/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java @@ -17,12 +17,6 @@ public class PropertyKey { // Empty property used to allow property-less Materials without removing base type enforcement public static final PropertyKey EMPTY = new PropertyKey<>("empty", EmptyProperty.class); - - public static final PropertyKey FLUID_PIPE = new PropertyKey<>("fluid_pipe", - FluidPipeProperties.class); - public static final PropertyKey ITEM_PIPE = new PropertyKey<>("item_pipe", - ItemPipeProperties.class); - private final String key; private final Class type; diff --git a/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java b/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java index 7f38703d67b..4cb6202f169 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java +++ b/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java @@ -2,6 +2,7 @@ import gregtech.api.unification.material.info.MaterialFlags; import gregtech.api.unification.ore.OrePrefix; +import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; public class WoodProperty implements IMaterialProperty { @@ -10,11 +11,12 @@ public void verifyProperty(MaterialProperties properties) { properties.ensureSet(PropertyKey.DUST); properties.getMaterial().addFlags(MaterialFlags.FLAMMABLE); - if (properties.hasProperty(PropertyKey.FLUID_PIPE)) { - OrePrefix.pipeTinyFluid.setIgnored(properties.getMaterial()); - OrePrefix.pipeHugeFluid.setIgnored(properties.getMaterial()); - OrePrefix.pipeQuadrupleFluid.setIgnored(properties.getMaterial()); - OrePrefix.pipeNonupleFluid.setIgnored(properties.getMaterial()); + PipeNetProperties netProperties = properties.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (netProperties != null && netProperties.hasProperty(MaterialFluidProperties.KEY)) { + OrePrefix.pipeTiny.setIgnored(properties.getMaterial()); + OrePrefix.pipeHuge.setIgnored(properties.getMaterial()); + OrePrefix.pipeQuadruple.setIgnored(properties.getMaterial()); + OrePrefix.pipeNonuple.setIgnored(properties.getMaterial()); } } } diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 693d80500af..de2e1ad55a5 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -19,6 +19,9 @@ import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.ore.OrePrefix; +import it.unimi.dsi.fastutil.bytes.ByteArrayList; +import it.unimi.dsi.fastutil.bytes.ByteList; + import net.minecraft.block.BlockRedstoneWire; import net.minecraft.block.BlockSnow; import net.minecraft.block.material.MapColor; @@ -67,7 +70,9 @@ import org.jetbrains.annotations.Nullable; import java.util.AbstractList; +import java.util.BitSet; import java.util.Collections; +import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -930,10 +935,47 @@ public static int[] convertARGBtoArray(int argb) { } @Contract(pure = true) - public static boolean evalMask(@NotNull EnumFacing facing, byte mask) { - return (mask & (1 << facing.ordinal())) > 0; + public static boolean evalMask(@NotNull Enum anEnum, byte mask) { + return (mask & (1L << anEnum.ordinal())) > 0; + } + + @Contract(pure = true) + public static boolean evalMask(@NotNull Enum anEnum, @NotNull BitSet mask) { + return mask.get(anEnum.ordinal()); + } + + @Contract(pure = true) + @NotNull + public static > EnumSet maskToSet(@NotNull Class enumClass, byte mask) { + EnumSet set = EnumSet.noneOf(enumClass); + for (T anEnum : enumClass.getEnumConstants()) { + if (evalMask(anEnum, mask)) set.add(anEnum); + } + return set; + } + + @Contract(pure = true) + @NotNull + public static > EnumSet maskToSet(@NotNull Class enumClass, @NotNull BitSet mask) { + EnumSet set = EnumSet.noneOf(enumClass); + for (T anEnum : enumClass.getEnumConstants()) { + if (evalMask(anEnum, mask)) set.add(anEnum); + } + return set; } + @Contract(pure = true) + @NotNull + public static BitSet setToMask(@NotNull EnumSet enumSet) { + BitSet mask = new BitSet(); + for (Enum anEnum : enumSet) { + mask.set(anEnum.ordinal()); + } + return mask; + } + + @Contract(pure = true, value = "->new") + @NotNull public static Set createWeakHashSet() { return Collections.newSetFromMap(new WeakHashMap<>()); } diff --git a/src/main/java/gregtech/api/util/TaskScheduler.java b/src/main/java/gregtech/api/util/TaskScheduler.java index 6cf63029be5..2400491d466 100644 --- a/src/main/java/gregtech/api/util/TaskScheduler.java +++ b/src/main/java/gregtech/api/util/TaskScheduler.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -72,4 +73,18 @@ public static void onWorldTick(TickEvent.WorldTickEvent event) { } } } + + public static Task weakTask(Task task) { + return new Task() { + + private final WeakReference ref = new WeakReference<>(task); + + @Override + public boolean run() { + Task task = this.ref.get(); + if (task == null) return false; + else return task.run(); + } + }; + } } diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index bcb3fdf0da8..0e80780e5cb 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -26,6 +26,8 @@ import gregtech.common.items.MetaItems; import gregtech.common.items.ToolItems; import gregtech.common.pipelike.block.cable.CableBlock; +import gregtech.common.pipelike.block.laser.LaserPipeBlock; +import gregtech.common.pipelike.block.optical.OpticalPipeBlock; import gregtech.common.pipelike.block.pipe.PipeBlock; import gregtech.common.pipelikeold.cable.BlockCable; import gregtech.common.pipelikeold.cable.ItemBlockCable; @@ -94,8 +96,8 @@ public static void registerBlocks(RegistryEvent.Register event) { for (CableBlock cable : CABLES.get(materialRegistry.getModid())) registry.register(cable); for (PipeBlock cable : MATERIAL_PIPES.get(materialRegistry.getModid())) registry.register(cable); } - for (BlockOpticalPipe pipe : OPTICAL_PIPES) registry.register(pipe); - for (BlockLaserPipe pipe : LASER_PIPES) registry.register(pipe); + for (OpticalPipeBlock pipe : OPTICAL_PIPES) registry.register(pipe); + for (LaserPipeBlock pipe : LASER_PIPES) registry.register(pipe); registry.register(LD_ITEM_PIPE); registry.register(LD_FLUID_PIPE); @@ -210,8 +212,8 @@ public static void registerItems(RegistryEvent.Register event) { for (PipeBlock cable : MATERIAL_PIPES.get(materialRegistry.getModid())) registry.register(createItemBlock(cable, ItemPipeBlock::new)); } - for (BlockOpticalPipe pipe : OPTICAL_PIPES) registry.register(createItemBlock(pipe, ItemBlockOpticalPipe::new)); - for (BlockLaserPipe pipe : LASER_PIPES) registry.register(createItemBlock(pipe, ItemBlockLaserPipe::new)); + for (OpticalPipeBlock pipe : OPTICAL_PIPES) registry.register(createItemBlock(pipe, ItemPipeBlock::new)); + for (LaserPipeBlock pipe : LASER_PIPES) registry.register(createItemBlock(pipe, ItemPipeBlock::new)); registry.register(createItemBlock(LD_ITEM_PIPE, ItemBlock::new)); registry.register(createItemBlock(LD_FLUID_PIPE, ItemBlock::new)); diff --git a/src/main/java/gregtech/common/creativetab/GTCreativeTabs.java b/src/main/java/gregtech/common/creativetab/GTCreativeTabs.java index 95d308dde3e..180c3c0cf36 100644 --- a/src/main/java/gregtech/common/creativetab/GTCreativeTabs.java +++ b/src/main/java/gregtech/common/creativetab/GTCreativeTabs.java @@ -20,7 +20,7 @@ public final class GTCreativeTabs { public static final BaseCreativeTab TAB_GREGTECH_CABLES = new BaseCreativeTab(GTValues.MODID + ".cables", () -> OreDictUnifier.get(OrePrefix.cableGtDouble, Materials.Aluminium), true); public static final BaseCreativeTab TAB_GREGTECH_PIPES = new BaseCreativeTab(GTValues.MODID + ".pipes", - () -> OreDictUnifier.get(OrePrefix.pipeNormalFluid, Materials.Aluminium), true); + () -> OreDictUnifier.get(OrePrefix.pipeNormal, Materials.Aluminium), true); public static final BaseCreativeTab TAB_GREGTECH_TOOLS = new BaseCreativeTab(GTValues.MODID + ".tools", () -> ToolItems.HARD_HAMMER.get(Materials.Aluminium), true); public static final BaseCreativeTab TAB_GREGTECH_MATERIALS = new BaseCreativeTab(GTValues.MODID + ".materials", diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index 23c6f54c761..1a29afdeb9b 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -60,6 +60,7 @@ import gregtech.common.items.behaviors.monitorplugin.FakeGuiPluginBehavior; import gregtech.common.items.behaviors.monitorplugin.OnlinePicPluginBehavior; import gregtech.common.items.behaviors.monitorplugin.TextPluginBehavior; +import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; import gregtech.core.sound.GTSoundEvents; import net.minecraft.client.resources.I18n; @@ -192,53 +193,63 @@ public void registerSubItems() { // Fluid Cells: ID 78-88 FLUID_CELL = addItem(78, "fluid_cell") - .addComponents(new FilteredFluidStats(1000, 1800, true, false, false, false, false), + .addComponents(new FilteredFluidStats(1000, 1800, 121, true, false, false, false), new ItemFluidContainer()) .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); FLUID_CELL_UNIVERSAL = addItem(79, "fluid_cell.universal") - .addComponents(new FilteredFluidStats(1000, 1800, true, false, false, false, true), + .addComponents(new FilteredFluidStats(1000, 1800, 121, true, false, false, true), new ItemFluidContainer()) .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); + MaterialFluidProperties properties = Materials.Steel.getProperty(PropertyKey.PIPENET_PROPERTIES).getProperty(MaterialFluidProperties.KEY); + FLUID_CELL_LARGE_STEEL = addItem(80, "large_fluid_cell.steel") - .addComponents(new FilteredFluidStats(8000, - Materials.Steel.getProperty(PropertyKey.FLUID_PIPE).getMaxFluidTemperature(), true, false, - false, false, true), new ItemFluidContainer()) + .addComponents(new FilteredFluidStats(8000, properties.getMaxFluidTemperature(), + properties.getMinFluidTemperature(), true, false, + false, true), new ItemFluidContainer()) .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, M * 4))) // ingot * 4 .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); + properties = Materials.Aluminium.getProperty(PropertyKey.PIPENET_PROPERTIES).getProperty(MaterialFluidProperties.KEY); + FLUID_CELL_LARGE_ALUMINIUM = addItem(81, "large_fluid_cell.aluminium") .addComponents(new FilteredFluidStats(32000, - Materials.Aluminium.getProperty(PropertyKey.FLUID_PIPE).getMaxFluidTemperature(), true, false, - false, false, true), new ItemFluidContainer()) + properties.getMaxFluidTemperature(), properties.getMinFluidTemperature(), true, false, + false, true), new ItemFluidContainer()) .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Aluminium, M * 4))) // ingot * 4 .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); + properties = Materials.StainlessSteel.getProperty(PropertyKey.PIPENET_PROPERTIES).getProperty(MaterialFluidProperties.KEY); + FLUID_CELL_LARGE_STAINLESS_STEEL = addItem(82, "large_fluid_cell.stainless_steel") .addComponents(new FilteredFluidStats(64000, - Materials.StainlessSteel.getProperty(PropertyKey.FLUID_PIPE).getMaxFluidTemperature(), true, - true, true, false, true), new ItemFluidContainer()) + properties.getMaxFluidTemperature(), properties.getMinFluidTemperature(), true, + true, false, true), new ItemFluidContainer()) .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.StainlessSteel, M * 6))) // ingot * 6 .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); + properties = Materials.Titanium.getProperty(PropertyKey.PIPENET_PROPERTIES).getProperty(MaterialFluidProperties.KEY); + FLUID_CELL_LARGE_TITANIUM = addItem(83, "large_fluid_cell.titanium") .addComponents(new FilteredFluidStats(128000, - Materials.Titanium.getProperty(PropertyKey.FLUID_PIPE).getMaxFluidTemperature(), true, true, - false, false, true), new ItemFluidContainer()) + properties.getMaxFluidTemperature(), properties.getMinFluidTemperature(), true, true, + false, true), new ItemFluidContainer()) .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Titanium, M * 6))) // ingot * 6 .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); + properties = Materials.TungstenSteel.getProperty(PropertyKey.PIPENET_PROPERTIES).getProperty(MaterialFluidProperties.KEY); + FLUID_CELL_LARGE_TUNGSTEN_STEEL = addItem(84, "large_fluid_cell.tungstensteel") .addComponents(new FilteredFluidStats(512000, - Materials.TungstenSteel.getProperty(PropertyKey.FLUID_PIPE).getMaxFluidTemperature(), true, - true, false, false, true), new ItemFluidContainer()) + properties.getMaxFluidTemperature(), properties.getMinFluidTemperature(), true, + true, false, true), new ItemFluidContainer()) .setMaxStackSize(32) .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.TungstenSteel, M * 8))) // ingot * 8 .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); FLUID_CELL_GLASS_VIAL = addItem(85, "fluid_cell.glass_vial") - .addComponents(new FilteredFluidStats(1000, 1200, false, true, false, false, true), + .addComponents(new FilteredFluidStats(1000, 1200, 213, false, true, false, true), new ItemFluidContainer()) .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Glass, M / 4))) // small dust .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); diff --git a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityMultiblockTank.java b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityMultiblockTank.java index eeabc2cd762..7a595eeeb2c 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityMultiblockTank.java +++ b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityMultiblockTank.java @@ -60,7 +60,7 @@ protected void initializeInventory() { FilteredFluidHandler tank = new FilteredFluidHandler(capacity); if (!isMetal) { - tank.setFilter(new PropertyFluidFilter(340, false, false, false, false)); + tank.setFilter(new PropertyFluidFilter(340, 121, false, false, false)); } this.exportFluids = this.importFluids = new FluidTankList(true, tank); diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java index dc3c5ae8ea9..6444be9b295 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java @@ -6,6 +6,7 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; import gregtech.api.capability.IEnergyContainer; +import gregtech.api.capability.ILaserContainer; import gregtech.api.capability.ILaserRelay; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; @@ -48,7 +49,7 @@ import static gregtech.api.capability.GregtechDataCodes.UPDATE_ACTIVE; import static gregtech.api.capability.GregtechDataCodes.UPDATE_IO_SPEED; -public class MetaTileEntityCreativeEnergy extends MetaTileEntity implements ILaserRelay, IControllable { +public class MetaTileEntityCreativeEnergy extends MetaTileEntity implements ILaserContainer, IControllable { private long voltage = 0; private int amps = 1; @@ -197,12 +198,15 @@ public void update() { IEnergyContainer container = tile.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, opposite); // Try to get laser capability - if (container == null) - container = tile.getCapability(GregtechTileCapabilities.CAPABILITY_LASER, opposite); - - if (container == null || !container.inputsEnergy(opposite) || container.getEnergyCanBeInserted() == 0) - continue; - ampsUsed += container.acceptEnergyFromNetwork(opposite, voltage, amps - ampsUsed); + if (container == null) { + ILaserRelay relay = tile.getCapability(GregtechTileCapabilities.CAPABILITY_LASER, opposite); + if (relay != null) { + ampsUsed += relay.receiveLaser(voltage, amps - ampsUsed); + } + } else { + if (!container.inputsEnergy(opposite) || container.getEnergyCanBeInserted() == 0) continue; + ampsUsed += container.acceptEnergyFromNetwork(opposite, voltage, amps - ampsUsed); + } if (ampsUsed >= amps) break; } @@ -233,6 +237,11 @@ public void readFromNBT(NBTTagCompound data) { super.readFromNBT(data); } + @Override + public long receiveLaser(long laserVoltage, long laserAmperage) { + return acceptEnergyFromNetwork(null, laserVoltage, laserAmperage); + } + @Override public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { if (source || !active || ampsReceived >= amps) { diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java index 7a5ef5b4d38..a3795288cc8 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java @@ -3,18 +3,19 @@ import gregtech.api.capability.IPropertyFluidFilter; import gregtech.api.capability.impl.FilteredFluidHandler; import gregtech.api.capability.impl.GTFluidHandlerItemStack; -import gregtech.api.gui.ModularUI; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.recipes.ModHandler; import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.properties.FluidPipeProperties; +import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; import gregtech.client.utils.TooltipHelper; +import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; + import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; @@ -85,7 +86,7 @@ public boolean hasFrontFacing() { protected void initializeInventory() { if (this.material == null) return; // call before field initialization, should be called later with fields set super.initializeInventory(); - IPropertyFluidFilter filter = this.material.getProperty(PropertyKey.FLUID_PIPE); + IPropertyFluidFilter filter = getFluidProperty(); if (filter == null) { throw new IllegalArgumentException( String.format("Material %s requires FluidPipeProperty for Drums", material)); @@ -93,6 +94,12 @@ protected void initializeInventory() { this.fluidInventory = this.fluidTank = new FilteredFluidHandler(tankSize).setFilter(filter); } + private @Nullable MaterialFluidProperties getFluidProperty() { + PipeNetProperties properties = this.material.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (properties != null) return properties.getProperty(MaterialFluidProperties.KEY); + else return null; + } + @Override public void initFromItemStackData(NBTTagCompound itemStack) { super.initFromItemStackData(itemStack); @@ -243,8 +250,8 @@ public int getDefaultPaintingColor() { @SideOnly(Side.CLIENT) public void addInformation(ItemStack stack, @Nullable World player, List tooltip, boolean advanced) { tooltip.add(I18n.format("gregtech.universal.tooltip.fluid_storage_capacity", tankSize)); - FluidPipeProperties pipeProperties = material.getProperty(PropertyKey.FLUID_PIPE); - pipeProperties.appendTooltips(tooltip, true, true); + MaterialFluidProperties pipeProperties = getFluidProperty(); + if (pipeProperties != null) pipeProperties.appendTooltips(tooltip, true, true); if (TooltipHelper.isShiftDown()) { tooltip.add(I18n.format("gregtech.tool_action.screwdriver.access_covers")); @@ -267,11 +274,6 @@ public boolean showToolUsages() { return false; } - @Override - protected ModularUI createUI(EntityPlayer entityPlayer) { - return null; - } - @Override public NBTTagCompound writeToNBT(NBTTagCompound data) { super.writeToNBT(data); diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java index 70c0be612be..a5f1c40f6f2 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java @@ -19,7 +19,7 @@ import java.util.Set; -public class LaserPipeBlock extends WorldPipeBlock implements IBurnable { +public class LaserPipeBlock extends WorldPipeBlock { public LaserPipeBlock(LaserStructure structure) { super(structure); diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java index 0c17c0f75be..432ffa3c3d5 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java @@ -7,10 +7,14 @@ import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.client.renderer.pipe.ActivablePipeModel; +import gregtech.common.pipelike.block.optical.OpticalStructure; + import net.minecraft.util.EnumFacing; import org.jetbrains.annotations.NotNull; +import java.util.function.Consumer; + @Desugar public record LaserStructure(String name, float renderThickness, ActivablePipeModel model) implements IPipeStructure { @@ -45,4 +49,8 @@ public boolean isPaintable() { public AbstractPipeModel getModel() { return model; } + + public static void registerDefaultStructures(Consumer register) { + register.accept(INSTANCE); + } } diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java index 3a762494506..49f3d2a94a6 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java @@ -18,7 +18,7 @@ import java.util.Set; -public class OpticalPipeBlock extends WorldPipeBlock implements IBurnable { +public class OpticalPipeBlock extends WorldPipeBlock { public OpticalPipeBlock(OpticalStructure structure) { super(structure); diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java index 661d865ee3f..21b06e40680 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java @@ -7,10 +7,14 @@ import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.client.renderer.pipe.ActivablePipeModel; +import gregtech.common.pipelike.block.cable.CableStructure; + import net.minecraft.util.EnumFacing; import org.jetbrains.annotations.NotNull; +import java.util.function.Consumer; + @Desugar public record OpticalStructure(String name, float renderThickness, ActivablePipeModel model) implements IPipeStructure { @@ -47,4 +51,8 @@ public boolean isPaintable() { public AbstractPipeModel getModel() { return model; } + + public static void registerDefaultStructures(Consumer register) { + register.accept(INSTANCE); + } } diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java index 61d99eedf85..76e3c13b980 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java @@ -3,6 +3,7 @@ import gregtech.api.graphnet.gather.GatherStructuresEvent; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.IBurnable; +import gregtech.api.graphnet.pipenet.physical.IFreezable; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; @@ -26,7 +27,7 @@ import java.util.Set; -public class PipeBlock extends PipeMaterialBlock implements IBurnable { +public class PipeBlock extends PipeMaterialBlock implements IBurnable, IFreezable { public PipeBlock(PipeStructure structure, MaterialRegistry registry) { super(structure, registry); diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java index 751ab0b25c4..ddcc6bbf058 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java @@ -31,7 +31,6 @@ public record PipeStructure(String name, int material, int channelCount, boolean public static final PipeStructure HUGE = new PipeStructure("huge", 24, 1, false, OrePrefix.pipeHuge, 0.875f, PipeModel.INSTANCES[4]); - // TODO adjust quadruple and nonuple thicknesses to 0.5f and 0.75f respectively, and update textures accordingly public static final PipeStructure QUADRUPLE = new PipeStructure("quadruple", 8, 4, false, OrePrefix.pipeQuadruple, 0.95f, PipeModel.INSTANCES[5]); public static final PipeStructure NONUPLE = diff --git a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java index cc6dfc54bbf..d79ab7d1562 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java @@ -14,7 +14,7 @@ import java.util.Collection; import java.util.Collections; -public class LaserNetHandler implements IPipeNetNodeHandler { +public final class LaserNetHandler implements IPipeNetNodeHandler { public static final LaserNetHandler INSTANCE = new LaserNetHandler(); diff --git a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java index f42ca541e1a..a4907c6599c 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java @@ -13,7 +13,7 @@ import java.util.Collection; import java.util.Collections; -public class OpticalNetHandler implements IPipeNetNodeHandler { +public final class OpticalNetHandler implements IPipeNetNodeHandler { public static final OpticalNetHandler INSTANCE = new OpticalNetHandler(); diff --git a/src/main/java/gregtech/common/pipelike/handlers/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java similarity index 97% rename from src/main/java/gregtech/common/pipelike/handlers/MaterialEnergyProperties.java rename to src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 6fc5229c39b..3a9bc6a2aff 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -1,4 +1,4 @@ -package gregtech.common.pipelike.handlers; +package gregtech.common.pipelike.handlers.properties; import gregtech.api.GTValues; import gregtech.api.fluids.FluidBuilder; @@ -41,7 +41,7 @@ public final class MaterialEnergyProperties implements PipeNetProperties.IPipeNetMaterialProperty { - public static final String KEY = "energy"; + public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>(); private final long voltageLimit; private final long amperageLimit; @@ -101,7 +101,7 @@ public boolean isSuperconductor() { } @Override - public @NotNull String getName() { + public MaterialPropertyKey getKey() { return KEY; } diff --git a/src/main/java/gregtech/common/pipelike/handlers/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java similarity index 73% rename from src/main/java/gregtech/common/pipelike/handlers/MaterialFluidProperties.java rename to src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index 3934c4bd05f..414797c68ed 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -1,5 +1,6 @@ -package gregtech.common.pipelike.handlers; +package gregtech.common.pipelike.handlers.properties; +import gregtech.api.capability.IPropertyFluidFilter; import gregtech.api.fluids.FluidBuilder; import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; @@ -13,14 +14,20 @@ import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.FluidProperty; +import gregtech.api.unification.material.properties.IMaterialProperty; import gregtech.api.unification.material.properties.MaterialProperties; import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.unification.ore.IOreRegistrationHandler; +import gregtech.api.unification.ore.OrePrefix; +import gregtech.api.util.function.TriConsumer; import gregtech.common.pipelike.block.pipe.PipeStructure; +import gregtech.common.pipelike.net.fluid.FluidContainmentLogic; import gregtech.common.pipelike.net.fluid.WorldFluidNet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; @@ -31,13 +38,17 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; +import java.util.Collection; import java.util.EnumSet; import java.util.Set; -public class MaterialFluidProperties implements PipeNetProperties.IPipeNetMaterialProperty { +import static gregtech.api.unification.material.info.MaterialFlags.NO_UNIFICATION; - public static final String KEY = "fluid"; +public final class MaterialFluidProperties implements PipeNetProperties.IPipeNetMaterialProperty, IPropertyFluidFilter { + + public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>(); private final Set containableAttributes = new ObjectOpenHashSet<>(); private final EnumSet containableStates = EnumSet.of(FluidState.LIQUID); @@ -55,6 +66,10 @@ public MaterialFluidProperties(long baseThroughput, int maxFluidTemperature, int this.priority = priority; } + public MaterialFluidProperties(long baseThroughput, int maxFluidTemperature, int minFluidTemperature) { + this(baseThroughput, maxFluidTemperature, minFluidTemperature, 2048f / baseThroughput); + } + public static MaterialFluidProperties createMax(long baseThroughput, int maxFluidTemperature) { return createMax(baseThroughput, maxFluidTemperature, 2048f / baseThroughput); } @@ -79,36 +94,61 @@ public static MaterialFluidProperties create(long baseThroughput, float priority return new MaterialFluidProperties(baseThroughput, 0, 0, priority); } - public MaterialFluidProperties contains(FluidState state) { + public MaterialFluidProperties setContain(FluidState state, boolean canContain) { + if (canContain) contain(state); + else notContain(state); + return this; + } + + public MaterialFluidProperties setContain(FluidAttribute attribute, boolean canContain) { + if (canContain) contain(attribute); + else notContain(attribute); + return this; + } + + public MaterialFluidProperties contain(FluidState state) { this.containableStates.add(state); return this; } - public MaterialFluidProperties contains(FluidAttribute attribute) { + public MaterialFluidProperties contain(FluidAttribute attribute) { this.containableAttributes.add(attribute); return this; } - public MaterialFluidProperties notContains(FluidState state) { + public MaterialFluidProperties notContain(FluidState state) { this.containableStates.remove(state); return this; } - public MaterialFluidProperties notContains(FluidAttribute attribute) { + public MaterialFluidProperties notContain(FluidAttribute attribute) { this.containableAttributes.remove(attribute); return this; } - public boolean canContain(FluidState state) { + public boolean canContain(@NotNull FluidState state) { return this.containableStates.contains(state); } - public boolean canContain(FluidAttribute attribute) { + public boolean canContain(@NotNull FluidAttribute attribute) { return this.containableAttributes.contains(attribute); } @Override - public @NotNull String getName() { + public @NotNull @UnmodifiableView Collection<@NotNull FluidAttribute> getContainedAttributes() { + return containableAttributes; + } + + public int getMaxFluidTemperature() { + return maxFluidTemperature; + } + + public int getMinFluidTemperature() { + return minFluidTemperature; + } + + @Override + public MaterialPropertyKey getKey() { return KEY; } @@ -149,6 +189,7 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { double weight = priority * (pipe.restrictive() ? 100d : 1d) * pipe.channelCount() / pipe.material(); data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(weight)) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)) + .setLogicEntry(FluidContainmentLogic.INSTANCE.getWith(containableStates, containableAttributes)) .setLogicEntry(TemperatureLogic.INSTANCE .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), maxFluidTemperature, minFluidTemperature, 50 * pipe.material(), null)); diff --git a/src/main/java/gregtech/common/pipelike/handlers/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java similarity index 81% rename from src/main/java/gregtech/common/pipelike/handlers/MaterialItemProperties.java rename to src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index 3b4f804ecc0..e607c58ac73 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -1,4 +1,4 @@ -package gregtech.common.pipelike.handlers; +package gregtech.common.pipelike.handlers.properties; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.logic.NetLogicData; @@ -6,9 +6,14 @@ import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.properties.IMaterialProperty; import gregtech.api.unification.material.properties.MaterialProperties; import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.unification.ore.IOreRegistrationHandler; +import gregtech.api.unification.ore.OrePrefix; +import gregtech.api.util.function.TriConsumer; import gregtech.common.pipelike.block.pipe.PipeStructure; import gregtech.common.pipelike.net.item.WorldItemNet; @@ -16,12 +21,13 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class MaterialItemProperties implements PipeNetProperties.IPipeNetMaterialProperty { +import static gregtech.api.unification.material.info.MaterialFlags.NO_UNIFICATION; - public static final String KEY = "item"; +public final class MaterialItemProperties implements PipeNetProperties.IPipeNetMaterialProperty { + + public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>(); private final long baseItemsPer5Ticks; private final float priority; @@ -35,7 +41,7 @@ public static MaterialItemProperties create(long baseThroughput) { } @Override - public @NotNull String getName() { + public MaterialPropertyKey getKey() { return KEY; } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 7d25190e5cf..543b86a447a 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -63,10 +63,13 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); AbstractNetFlowEdge internalBuffer = this.internalBuffers.get(side); - long limit = internalBuffer.getFlowLimit(IPredicateTestObject.INSTANCE, net, tick, simulator); - if (limit <= 0) return 0; + long availableAmperage = amperage; + if (internalBuffer != null) { + long limit = internalBuffer.getFlowLimit(IPredicateTestObject.INSTANCE, net, tick, simulator); + if (limit <= 0) return 0; - long availableAmperage = Math.min(amperage, limit); + availableAmperage = Math.min(amperage, limit); + } EnergyTraverseData data = new EnergyTraverseData(net, IPredicateTestObject.INSTANCE, simulator, tick, voltage, tile.getPos(), side); @@ -74,10 +77,9 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage if (availableAmperage > 0) { availableAmperage -= TraverseHelpers.traverseDumb(data, getPaths(data), data::handleOverflow, availableAmperage); } - data.runPostActions(); long accepted = amperage - availableAmperage; - internalBuffer.consumeFlowLimit(IPredicateTestObject.INSTANCE, net, accepted, tick, simulator); + if (internalBuffer != null) internalBuffer.consumeFlowLimit(IPredicateTestObject.INSTANCE, net, accepted, tick, simulator); if (!simulate) { EnergyGroupData group = getEnergyData(); if (group != null) { diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index 68442d79c96..a5283bb6b6c 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -4,6 +4,7 @@ import gregtech.api.capability.IEnergyContainer; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.NodeLossCache; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.NodeLossResult; @@ -12,7 +13,6 @@ import gregtech.api.graphnet.traverse.AbstractTraverseData; import gregtech.api.graphnet.traverse.util.FlatLossOperator; -import gregtech.api.graphnet.traverse.util.IdentityLossOperator; import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; import gregtech.api.util.GTUtility; @@ -27,8 +27,6 @@ public class EnergyTraverseData extends AbstractTraverseData { - private final Object2ObjectOpenHashMap lossCache; - private final Object2ObjectOpenHashMap overVoltageInformation; private final long startVoltage; @@ -40,7 +38,6 @@ public class EnergyTraverseData extends AbstractTraverseData(); this.overVoltageInformation = new Object2ObjectOpenHashMap<>(); this.startVoltage = startVoltage; this.sourcePos = sourcePos; @@ -48,7 +45,8 @@ public EnergyTraverseData(IGraphNet net, IPredicateTestObject testObject, Simula } @Override - public boolean prepareForPathWalk(FlowWorldPipeNetPath path) { + public boolean prepareForPathWalk(FlowWorldPipeNetPath path, long flow) { + if (flow <= 0) return true; this.pathVoltage = startVoltage; this.overVoltageInformation.clear(); this.overVoltageInformation.trim(10); @@ -64,8 +62,8 @@ public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowRea new OverVoltageInformation(voltage, flowReachingNode)); } - - NodeLossResult result = lossCache.get(node); + NodeLossCache.Key key = NodeLossCache.key(node, this); + NodeLossResult result = NodeLossCache.getLossResult(key); if (result != null) { return result.getLossFunction(); } else { @@ -75,11 +73,11 @@ public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowRea if (node.getData().getLogicEntryDefaultable(SuperconductorLogic.INSTANCE) .canSuperconduct(temperatureLogic == null ? TemperatureLogic.DEFAULT_TEMPERATURE : temperatureLogic.getTemperature(getQueryTick()))) { - return IdentityLossOperator.INSTANCE; + return ReversibleLossOperator.IDENTITY; } return new FlatLossOperator(node.getData().getLogicEntryDefaultable(LossAbsoluteLogic.INSTANCE).getValue()); } - if (result.hasPostAction()) lossCache.put(node, result); + if (result.hasPostAction()) NodeLossCache.registerLossResult(key, result); return result.getLossFunction(); } } @@ -117,10 +115,6 @@ public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachin return accepted; } - public void runPostActions() { - lossCache.forEach((k, v) -> v.triggerPostAction(k)); - } - private static int calculateHeatV(long amperage, long voltage, long maxVoltage) { return (int) (amperage * (Math.log1p(Math.log((double) voltage / maxVoltage)) * 45 + 36.5)); } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java index 7b8afe4bfd7..2832f6d32d4 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java @@ -8,7 +8,7 @@ public class SuperconductorLogic extends AbstractIntLogicData temp; } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java b/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java new file mode 100644 index 00000000000..aace8fff048 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java @@ -0,0 +1,154 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.GTValues; +import gregtech.api.fluids.FluidState; +import gregtech.api.fluids.attribute.FluidAttribute; +import gregtech.api.fluids.attribute.FluidAttributes; +import gregtech.api.graphnet.pipenet.NodeLossResult; + +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.graphnet.traverse.util.MultLossOperator; +import gregtech.api.util.EntityDamageUtil; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.ResourceLocation; + +import net.minecraftforge.fluids.FluidStack; + +import org.jetbrains.annotations.NotNull; + +import java.util.EnumMap; +import java.util.Map; + +@FunctionalInterface +public interface ContainmentFailure { + + ContainmentFailure FALLBACK = stack -> NodeLossResult.IDENTITY; + + EnumMap STATE_FAILURES = new EnumMap<>(FluidState.class); + + Map ATTRIBUTE_FAILURES = new Object2ObjectOpenHashMap<>(); + + static void registerFailure(FluidState state, ContainmentFailure failure) { + STATE_FAILURES.put(state, failure); + } + + static void registerFailure(FluidAttribute attribute, ContainmentFailure failure) { + ATTRIBUTE_FAILURES.put(attribute.getResourceLocation(), failure); + } + + static @NotNull ContainmentFailure getFailure(FluidState state) { + return STATE_FAILURES.getOrDefault(state, FALLBACK); + } + + static @NotNull ContainmentFailure getFailure(FluidAttribute attribute) { + return ATTRIBUTE_FAILURES.getOrDefault(attribute.getResourceLocation(), FALLBACK); + } + + static @NotNull ContainmentFailure getFailure(ResourceLocation attribute) { + return ATTRIBUTE_FAILURES.getOrDefault(attribute, FALLBACK); + } + + @NotNull NodeLossResult computeLossResult(FluidStack fluid); + + static void init() { + registerFailure(FluidState.GAS, stack -> { + if (GTValues.RNG.nextInt(8) == 0) { + return new NodeLossResult(node -> { + PipeTileEntity tile = node.getTileEntityNoLoading(); + if (tile != null) { + tile.playLossSound(); + tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.SMOKE_NORMAL, 7 + GTValues.RNG.nextInt(2)); + tile.dealAreaDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + stack.getFluid().getTemperature(stack), 1, 10)); + } + }, MultLossOperator.TENTHS[9]); + } else { + return new NodeLossResult(node -> { + node.getNet().getWorld().setBlockToAir(node.getEquivalencyData()); + PipeTileEntity tile = node.getTileEntityNoLoading(); + if (tile != null) { + tile.playLossSound(); + tile.visuallyExplode(); + tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, 9 + GTValues.RNG.nextInt(3)); + tile.dealAreaDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + stack.getFluid().getTemperature(stack), 1.5f, 15)); + } + }, MultLossOperator.TENTHS[2]); + } + }); + registerFailure(FluidState.LIQUID, stack -> new NodeLossResult(node -> { + PipeTileEntity tile = node.getTileEntityNoLoading(); + if (tile != null) { + tile.playLossSound(); + for (EnumFacing facing : EnumFacing.HORIZONTALS) { + int particles = GTValues.RNG.nextInt(5); + if (particles != 0) { + tile.spawnParticles(facing, EnumParticleTypes.DRIP_WATER, particles); + } + } + tile.dealAreaDamage(1, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + stack.getFluid().getTemperature(stack), 2f, 20)); + } + }, MultLossOperator.TENTHS[6])); + registerFailure(FluidState.PLASMA, stack -> { + if (GTValues.RNG.nextInt(4) == 0) { + return new NodeLossResult(node -> { + PipeTileEntity tile = node.getTileEntityNoLoading(); + if (tile != null) { + tile.playLossSound(); + tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.SMOKE_NORMAL, 1 + GTValues.RNG.nextInt(2)); + tile.dealAreaDamage(3, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + stack.getFluid().getTemperature(stack), 1, 25)); + } + }, MultLossOperator.TENTHS[8]); + } else { + return new NodeLossResult(node -> { + node.getNet().getWorld().setBlockToAir(node.getEquivalencyData()); + PipeTileEntity tile = node.getTileEntityNoLoading(); + if (tile != null) { + tile.playLossSound(); + tile.visuallyExplode(); + tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, 3 + GTValues.RNG.nextInt(3)); + tile.dealAreaDamage(3, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + stack.getFluid().getTemperature(stack), 1.5f, 30)); + } + }, MultLossOperator.TENTHS[2]); + } + }); + registerFailure(FluidAttributes.ACID, stack -> { + if (GTValues.RNG.nextInt(10) == 0) { + return new NodeLossResult(node -> { + PipeTileEntity tile = node.getTileEntityNoLoading(); + if (tile != null) { + tile.playLossSound(); + boolean gaseous = stack.getFluid().isGaseous(stack); + tile.spawnParticles(gaseous ? EnumFacing.UP : EnumFacing.DOWN, EnumParticleTypes.CRIT_MAGIC, + 3 + GTValues.RNG.nextInt(2)); + tile.dealAreaDamage(gaseous ? 2 : 1, entity -> + EntityDamageUtil.applyChemicalDamage(entity, gaseous ? 2 : 3)); + } + }, MultLossOperator.TENTHS[9]); + } else { + return new NodeLossResult(node -> { + node.getNet().getWorld().setBlockToAir(node.getEquivalencyData()); + PipeTileEntity tile = node.getTileEntityNoLoading(); + if (tile != null) { + tile.playLossSound(); + boolean gaseous = stack.getFluid().isGaseous(stack); + for (EnumFacing facing : EnumFacing.HORIZONTALS) { + tile.spawnParticles(facing, EnumParticleTypes.CRIT_MAGIC, 3 + GTValues.RNG.nextInt(2)); + } + tile.spawnParticles(gaseous ? EnumFacing.UP : EnumFacing.DOWN, EnumParticleTypes.CRIT_MAGIC, + 6 + GTValues.RNG.nextInt(4)); + tile.dealAreaDamage(gaseous ? 2 : 1, entity -> + EntityDamageUtil.applyChemicalDamage(entity, gaseous ? 3 : 4)); + } + }, MultLossOperator.EIGHTHS[6]); + } + }); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java new file mode 100644 index 00000000000..ff69322b486 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -0,0 +1,159 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.traverse.TraverseHelpers; +import gregtech.common.pipelike.net.energy.EnergyTraverseData; +import gregtech.common.pipelike.net.energy.WorldEnergyNet; +import gregtech.common.pipelikeold.cable.net.EnergyGroupData; + +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumMap; +import java.util.Iterator; + +public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler { + + private static final IFluidTankProperties[] EMPTY = new IFluidTankProperties[0]; + + private final WorldPipeNet net; + private @Nullable PipeTileEntity tile; + + private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); + + private boolean transferring = false; + + public FluidCapabilityObject(@NotNull N net, WorldPipeNetNode node) { + this.net = net; + for (EnumFacing facing : EnumFacing.VALUES) { + AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); + edge.setData(NetLogicData.union(node.getData(), (NetLogicData) null)); + wrappers.put(facing, new Wrapper(facing, edge)); + } + } + + private FlowWorldPipeNetPath.Provider getProvider() { + return (FlowWorldPipeNetPath.Provider) net; + } + + private Iterator getPaths(FluidTraverseData data) { + assert tile != null; + return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), data.getQueryTick()); + } + + @Override + public void setTile(@Nullable PipeTileEntity tile) { + this.tile = tile; + } + + @Override + public Capability[] getCapabilities() { + return WorldEnergyNet.CAPABILITIES; + } + + @Override + public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { + if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { + return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(facing == null ? this : wrappers.get(facing)); + } + return null; + } + + @Override + public int fill(FluidStack resource, boolean doFill) { + return fill(resource, doFill, null); + } + + public int fill(FluidStack resource, boolean doFill, EnumFacing side) { + if (tile == null || this.transferring) return 0; + this.transferring = true; + + SimulatorKey simulator = null; + if (!doFill) simulator = SimulatorKey.getNewSimulatorInstance(); + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + + FluidTestObject testObject = new FluidTestObject(resource); + + AbstractNetFlowEdge internalBuffer = this.wrappers.get(side).getBuffer(); + long allowed = resource.amount; + if (internalBuffer != null) { + long limit = internalBuffer.getFlowLimit(testObject, net, tick, simulator); + if (limit <= 0) return 0; + allowed = Math.min(limit, allowed); + } + + FluidTraverseData data = new FluidTraverseData(net, testObject, simulator, tick, tile.getPos(), side); + long accepted = TraverseHelpers.traverseFlood(data, getPaths(data), allowed); + + if (internalBuffer != null) internalBuffer.consumeFlowLimit(testObject, net, accepted, tick, simulator); + this.transferring = false; + return (int) accepted; + } + + @Override + public IFluidTankProperties[] getTankProperties() { + return EMPTY; + } + + @Override + public FluidStack drain(int maxDrain, boolean doDrain) { + return null; + } + + @Override + public FluidStack drain(FluidStack resource, boolean doDrain) { + return null; + } + + protected class Wrapper implements IFluidHandler { + + private final EnumFacing facing; + private final AbstractNetFlowEdge buffer; + + public Wrapper(EnumFacing facing, AbstractNetFlowEdge buffer) { + this.facing = facing; + this.buffer = buffer; + } + + public AbstractNetFlowEdge getBuffer() { + return buffer; + } + + @Override + public IFluidTankProperties[] getTankProperties() { + return EMPTY; + } + + @Override + public int fill(FluidStack resource, boolean doFill) { + return FluidCapabilityObject.this.fill(resource, doFill, facing); + } + + @Override + public FluidStack drain(FluidStack resource, boolean doDrain) { + return null; + } + + @Override + public FluidStack drain(int maxDrain, boolean doDrain) { + return null; + } + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java new file mode 100644 index 00000000000..d5a5523481a --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java @@ -0,0 +1,143 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.fluids.FluidState; +import gregtech.api.fluids.attribute.FluidAttribute; +import gregtech.api.graphnet.logic.INetLogicEntry; + +import gregtech.api.util.GTUtility; +import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.nbt.NBTTagByte; +import net.minecraft.nbt.NBTTagByteArray; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagInt; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; +import net.minecraft.network.PacketBuffer; + +import net.minecraft.util.ResourceLocation; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.BitSet; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.Set; + +public class FluidContainmentLogic implements INetLogicEntry { + + public static final FluidContainmentLogic INSTANCE = new FluidContainmentLogic().contain(FluidState.LIQUID); + + private final Set containableAttributes = new ObjectOpenHashSet<>(); + private @NotNull EnumSet containableStates = EnumSet.noneOf(FluidState.class); + + public FluidContainmentLogic getWith(Collection states, Collection attributes) { + FluidContainmentLogic logic = getNew(); + logic.containableStates.addAll(states); + for (FluidAttribute attribute : attributes) { + logic.contain(attribute); + } + return logic; + } + + private FluidContainmentLogic() {} + + public FluidContainmentLogic contain(FluidState state) { + this.containableStates.add(state); + return this; + } + + public FluidContainmentLogic contain(FluidAttribute attribute) { + this.containableAttributes.add(attribute.getResourceLocation()); + return this; + } + + public FluidContainmentLogic notContain(FluidState state) { + this.containableStates.remove(state); + return this; + } + + public FluidContainmentLogic notContain(FluidAttribute attribute) { + this.containableAttributes.remove(attribute.getResourceLocation()); + return this; + } + + public boolean contains(FluidState state) { + return this.containableStates.contains(state); + } + + public boolean contains(FluidAttribute attribute) { + return this.containableAttributes.contains(attribute.getResourceLocation()); + } + + @Override + public @NotNull String getName() { + return "FluidContainment"; + } + + @Override + public @Nullable FluidContainmentLogic union(INetLogicEntry other) { + if (other instanceof FluidContainmentLogic logic) { + if (this.containableAttributes.equals(logic.containableAttributes) && + this.containableStates.equals(logic.containableStates)) { + return this; + } else { + FluidContainmentLogic returnable = getNew(); + returnable.containableStates = EnumSet.copyOf(this.containableStates); + returnable.containableStates.retainAll(logic.containableStates); + returnable.containableAttributes.addAll(this.containableAttributes); + returnable.containableAttributes.retainAll(logic.containableAttributes); + return returnable; + } + } + return this; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + NBTTagList list = new NBTTagList(); + for (ResourceLocation loc : containableAttributes) { + list.appendTag(new NBTTagString(loc.toString())); + } + tag.setTag("Attributes", list); + tag.setByteArray("States", GTUtility.setToMask(containableStates).toByteArray()); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + NBTTagList list = nbt.getTagList("Attributes", 8); + for (int i = 0; i < list.tagCount(); i++) { + containableAttributes.add(new ResourceLocation(list.getStringTagAt(i))); + } + containableStates = GTUtility.maskToSet(FluidState.class, BitSet.valueOf(nbt.getByteArray("States"))); + } + + @Override + public FluidContainmentLogic getNew() { + return new FluidContainmentLogic(); + } + + @Override + public void encode(PacketBuffer buf, boolean fullChange) { + buf.writeVarInt(containableAttributes.size()); + for (ResourceLocation loc : containableAttributes) { + buf.writeString(loc.toString()); + } + buf.writeByteArray(GTUtility.setToMask(containableStates).toByteArray()); + } + + @Override + public void decode(PacketBuffer buf, boolean fullChange) { + int attributes = buf.readVarInt(); + for (int i = 0; i < attributes; i++) { + containableAttributes.add(new ResourceLocation(buf.readString(255))); + } + containableStates = GTUtility.maskToSet(FluidState.class, BitSet.valueOf(buf.readByteArray(255))); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java new file mode 100644 index 00000000000..cc0f83410b2 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -0,0 +1,159 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.GTValues; +import gregtech.api.fluids.FluidState; +import gregtech.api.fluids.attribute.AttributedFluid; +import gregtech.api.fluids.attribute.FluidAttribute; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.NodeLossCache; +import gregtech.api.graphnet.pipenet.NodeLossResult; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.graphnet.traverse.AbstractTraverseData; +import gregtech.api.graphnet.traverse.util.MultLossOperator; +import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; +import gregtech.api.util.EntityDamageUtil; +import gregtech.api.util.GTUtility; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; + +import java.util.function.LongConsumer; + +public class FluidTraverseData extends AbstractTraverseData { + + public static final float TEMPERATURE_EFFECT = 0.005f; + + static { + ContainmentFailure.init(); + } + + private final BlockPos sourcePos; + private final EnumFacing inputFacing; + + private final Object2ObjectOpenHashMap temperatureUpdates = new Object2ObjectOpenHashMap<>(); + + public FluidTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing) { + super(net, testObject, simulator, queryTick); + this.sourcePos = sourcePos; + this.inputFacing = inputFacing; + } + + @Override + public FluidTestObject getTestObject() { + return (FluidTestObject) super.getTestObject(); + } + + @Override + public boolean prepareForPathWalk(FlowWorldPipeNetPath path, long flow) { + temperatureUpdates.clear(); + temperatureUpdates.trim(16); + return flow > 0; + } + + @Override + public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowReachingNode) { + NodeLossCache.Key key = NodeLossCache.key(node, this); + NodeLossResult result = NodeLossCache.getLossResult(key); + if (result != null) { + return result.getLossFunction(); + } else { + FluidStack stack = getTestObject().recombine(); + FluidContainmentLogic containmentLogic = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.INSTANCE); + FluidState state = FluidState.inferState(stack); + + TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + if (temperatureLogic != null) { + result = temperatureLogic.getLossResult(getQueryTick()); + int fluidTemp = stack.getFluid().getTemperature(stack); + boolean gaseous = stack.getFluid().isGaseous(stack); + // prevent plasmas from melting valid pipes due to raw temperature + boolean temperatureSafe = state == FluidState.PLASMA && containmentLogic.contains(FluidState.PLASMA); + temperatureUpdates.put(node, l -> temperatureLogic.moveTowardsTemperature(fluidTemp, getQueryTick(), l * TEMPERATURE_EFFECT, temperatureSafe)); + if (temperatureLogic.isUnderMinimum(fluidTemp)) { + result = NodeLossResult.combine(result, new NodeLossResult(pipe -> { + PipeTileEntity tile = pipe.getTileEntityNoLoading(); + if (tile != null) { + tile.playLossSound(); + tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); + tile.dealAreaDamage(gaseous ? 2 : 1, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + fluidTemp, 2.0F, 10)); + } + }, MultLossOperator.EIGHTHS[2])); + } else if (temperatureLogic.isOverMaximum(fluidTemp)) { + result = NodeLossResult.combine(result, new NodeLossResult(GTValues.RNG.nextInt(4) == 0 ? pipe -> { + PipeTileEntity tile = pipe.getTileEntityNoLoading(); + if (tile != null) { + tile.playLossSound(); + tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); + tile.dealAreaDamage(gaseous ? 2 : 1, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + fluidTemp, 2.0F, 10)); + tile.setNeighborsToFire(); + } + } : pipe -> { + PipeTileEntity tile = pipe.getTileEntityNoLoading(); + if (tile != null) { + tile.playLossSound(); + tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); + tile.dealAreaDamage(gaseous ? 2 : 1, entity -> EntityDamageUtil.applyTemperatureDamage(entity, + fluidTemp, 2.0F, 10)); + } + }, MultLossOperator.EIGHTHS[2])); + } + } + + if (!containmentLogic.contains(state)) { + result = NodeLossResult.combine(result, ContainmentFailure.getFailure(state).computeLossResult(stack)); + } + + if (stack instanceof AttributedFluid fluid) { + for (FluidAttribute attribute : fluid.getAttributes()) { + if (!containmentLogic.contains(attribute)) { + result = NodeLossResult.combine(result, ContainmentFailure.getFailure(attribute).computeLossResult(stack)); + } + } + } + + if (result == null) return ReversibleLossOperator.IDENTITY; + NodeLossCache.registerLossResult(key, result); + return result.getLossFunction(); + } + } + + @Override + public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachingDestination) { + long availableFlow = flowReachingDestination; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) continue; // anti insert-to-our-source logic + + IFluidHandler container = capability.getValue() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + availableFlow -= container.fill( + getTestObject().recombine((int) Math.min(Integer.MAX_VALUE, availableFlow)), + getSimulatorKey() == null); + } + } + return flowReachingDestination - availableFlow; + } + + @Override + public void consumeFlowLimit(AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { + super.consumeFlowLimit(edge, targetNode, consumption); + temperatureUpdates.getOrDefault(targetNode, l -> {}).accept(consumption); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 55b70709a65..a997d9118cf 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -59,7 +59,7 @@ public Capability[] getTargetCapabilities() { @Override public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return new IPipeCapabilityObject[] { }; + return new IPipeCapabilityObject[] { new FluidCapabilityObject(this, node) }; } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java new file mode 100644 index 00000000000..dfc1c566ae6 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -0,0 +1,166 @@ +package gregtech.common.pipelike.net.item; + +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.graphnet.traverse.TraverseHelpers; +import gregtech.common.pipelike.net.energy.WorldEnergyNet; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fml.common.FMLCommonHandler; + +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumMap; +import java.util.Iterator; + +public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler { + + private final WorldPipeNet net; + private @Nullable PipeTileEntity tile; + + private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); + + private boolean transferring = false; + + public ItemCapabilityObject(@NotNull N net, WorldPipeNetNode node) { + this.net = net; + for (EnumFacing facing : EnumFacing.VALUES) { + AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); + edge.setData(NetLogicData.union(node.getData(), (NetLogicData) null)); + wrappers.put(facing, new Wrapper(facing, edge)); + } + } + + private FlowWorldPipeNetPath.Provider getProvider() { + return (FlowWorldPipeNetPath.Provider) net; + } + + private Iterator getPaths(ItemTraverseData data) { + assert tile != null; + return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), data.getQueryTick()); + } + + @Override + public void setTile(@Nullable PipeTileEntity tile) { + this.tile = tile; + } + + @Override + public Capability[] getCapabilities() { + return WorldEnergyNet.CAPABILITIES; + } + + @Override + public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { + if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { + return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(facing == null ? this : wrappers.get(facing)); + } + return null; + } + + public @NotNull ItemStack insertItem(@NotNull ItemStack stack, boolean simulate, EnumFacing side) { + if (tile == null || this.transferring) return stack; + this.transferring = true; + + SimulatorKey simulator = null; + if (simulate) simulator = SimulatorKey.getNewSimulatorInstance(); + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + + ItemTestObject testObject = new ItemTestObject(stack); + + AbstractNetFlowEdge internalBuffer = this.wrappers.get(side).getBuffer(); + int available = stack.getCount(); + if (internalBuffer != null) { + long limit = internalBuffer.getFlowLimit(testObject, net, tick, simulator); + if (limit <= 0) return stack; + available = (int) Math.min(limit, available); + } + + ItemTraverseData data = new ItemTraverseData(net, testObject, simulator, tick, tile.getPos(), side); + available = (int) TraverseHelpers.traverseFlood(data, getPaths(data), available); + + if (internalBuffer != null) + internalBuffer.consumeFlowLimit(testObject, net, stack.getCount() - available, tick, simulator); + this.transferring = false; + return testObject.recombine(available); + } + + @Override + public int getSlots() { + return 1; + } + + @Override + public @NotNull ItemStack getStackInSlot(int slot) { + return ItemStack.EMPTY; + } + + @Override + public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + return insertItem(stack, simulate, null); + } + + @Override + public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { + return ItemStack.EMPTY; + } + + @Override + public int getSlotLimit(int slot) { + return 64; + } + + protected class Wrapper implements IItemHandler { + + private final EnumFacing facing; + private final AbstractNetFlowEdge buffer; + + public Wrapper(EnumFacing facing, AbstractNetFlowEdge buffer) { + this.facing = facing; + this.buffer = buffer; + } + + public AbstractNetFlowEdge getBuffer() { + return buffer; + } + + @Override + public int getSlots() { + return 1; + } + + @Override + public @NotNull ItemStack getStackInSlot(int slot) { + return ItemStack.EMPTY; + } + + @Override + public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { + return ItemCapabilityObject.this.insertItem(stack, simulate, facing); + } + + @Override + public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { + return ItemStack.EMPTY; + } + + @Override + public int getSlotLimit(int slot) { + return 64; + } + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java new file mode 100644 index 00000000000..de252750808 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java @@ -0,0 +1,67 @@ +package gregtech.common.pipelike.net.item; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.graphnet.traverse.AbstractTraverseData; +import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; +import gregtech.api.util.GTUtility; + +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; + +public class ItemTraverseData extends AbstractTraverseData { + + private final BlockPos sourcePos; + private final EnumFacing inputFacing; + + public ItemTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing) { + super(net, testObject, simulator, queryTick); + this.sourcePos = sourcePos; + this.inputFacing = inputFacing; + } + + @Override + public ItemTestObject getTestObject() { + return (ItemTestObject) super.getTestObject(); + } + + @Override + public boolean prepareForPathWalk(FlowWorldPipeNetPath path, long flow) { + return flow > 0; + } + + @Override + public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowReachingNode) { + return ReversibleLossOperator.IDENTITY; + } + + @Override + public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachingDestination) { + long availableFlow = flowReachingDestination; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) continue; // anti insert-to-our-source logic + + IItemHandler container = capability.getValue() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + for (int i = 0; i < container.getSlots(); i++) { + int toInsert = (int) Math.min(Math.min(getTestObject().getStackLimit(), container.getSlotLimit(i)), availableFlow); + availableFlow -= toInsert - container.insertItem(i, getTestObject().recombine(toInsert), + getSimulatorKey() != null).getCount(); + + } + } + } + return flowReachingDestination - availableFlow; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 3c2c070bee1..8b473e35fe6 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -59,7 +59,7 @@ public Capability[] getTargetCapabilities() { @Override public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return new IPipeCapabilityObject[] { }; + return new IPipeCapabilityObject[] { new ItemCapabilityObject(this, node) }; } @Override diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java index 1f41fac4562..5474f265946 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java @@ -9,7 +9,6 @@ import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.util.EntityDamageUtil; import gregtech.client.renderer.pipeold.FluidPipeRenderer; diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/FluidPipeType.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/FluidPipeType.java index 8f85d012d03..a0dda3ff22d 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/FluidPipeType.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/FluidPipeType.java @@ -1,7 +1,6 @@ package gregtech.common.pipelikeold.fluidpipe; import gregtech.api.graphnet.pipenetold.block.material.IMaterialPipeType; -import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.unification.ore.OrePrefix; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/ItemBlockFluidPipe.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/ItemBlockFluidPipe.java index 4072b809931..115476c21f1 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/ItemBlockFluidPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/ItemBlockFluidPipe.java @@ -2,7 +2,6 @@ import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; import gregtech.api.graphnet.pipenetold.block.material.ItemBlockMaterialPipe; -import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.client.utils.TooltipHelper; import gregtech.common.ConfigHolder; diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java index 8b44ebf32eb..c4608916cd7 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java @@ -8,7 +8,6 @@ import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.covers.CoverFluidRegulator; import gregtech.common.covers.CoverPump; import gregtech.common.pipelikeold.fluidpipe.FluidPipeType; diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/WorldFluidPipeNet.java index 5d8cafa410f..2398a89787c 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/WorldFluidPipeNet.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/WorldFluidPipeNet.java @@ -6,7 +6,6 @@ import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.common.covers.CoverFluidFilter; import gregtech.common.covers.CoverPump; import gregtech.common.covers.FluidFilterMode; diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipe.java index f5087554440..346c1a84da0 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipe.java @@ -4,7 +4,6 @@ import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.util.TaskScheduler; import gregtech.common.pipelikeold.fluidpipe.FluidPipeType; import gregtech.common.pipelikeold.fluidpipe.net.FluidNetHandler; diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java b/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java index 9d2e55b6f43..56547560762 100644 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java @@ -6,7 +6,6 @@ import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.client.renderer.pipeold.ItemPipeRenderer; import gregtech.client.renderer.pipeold.PipeRenderer; diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/ItemBlockItemPipe.java b/src/main/java/gregtech/common/pipelikeold/itempipe/ItemBlockItemPipe.java index 2f88ae6269c..6c530bdb54f 100644 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/ItemBlockItemPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/ItemBlockItemPipe.java @@ -2,7 +2,6 @@ import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; import gregtech.api.graphnet.pipenetold.block.material.ItemBlockMaterialPipe; -import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.client.utils.TooltipHelper; import gregtech.common.ConfigHolder; diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/ItemPipeType.java b/src/main/java/gregtech/common/pipelikeold/itempipe/ItemPipeType.java index 9b129f97d47..a62043bd54f 100644 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/ItemPipeType.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/ItemPipeType.java @@ -1,7 +1,6 @@ package gregtech.common.pipelikeold.itempipe; import gregtech.api.graphnet.pipenetold.block.material.IMaterialPipeType; -import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.unification.ore.OrePrefix; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemNetHandler.java index 891b28b3d50..928aacebff7 100644 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemNetHandler.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemNetHandler.java @@ -5,7 +5,6 @@ import gregtech.api.graphnet.pipenetold.PipeNetPath; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.util.FacingPos; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.ItemStackHashStrategy; diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelikeold/itempipe/net/WorldItemPipeNet.java index 7fbd7688beb..1afc02c3073 100644 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/net/WorldItemPipeNet.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/net/WorldItemPipeNet.java @@ -4,7 +4,6 @@ import gregtech.api.graphnet.pipenetold.WorldPipeNetSimple; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.common.covers.CoverConveyor; import gregtech.common.covers.CoverItemFilter; import gregtech.common.covers.ItemFilterMode; diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipe.java b/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipe.java index 86a9548066c..e855ea6d275 100644 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipe.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipe.java @@ -3,7 +3,6 @@ import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.util.FacingPos; import gregtech.common.pipelikeold.itempipe.ItemPipeType; import gregtech.common.pipelikeold.itempipe.net.ItemNetHandler; diff --git a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java index f8c780b6aa7..25e1d5f626b 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java @@ -252,8 +252,15 @@ public CTMaterialBuilder fluidPipeProperties(int maxTemp, int throughput, boolea @ZenMethod public CTMaterialBuilder fluidPipeProperties(int maxTemp, int throughput, boolean gasProof, boolean acidProof, - boolean cryoProof, boolean plasmaProof) { - backingBuilder.fluidPipeProperties(maxTemp, throughput, gasProof, acidProof, cryoProof, plasmaProof); + boolean plasmaProof) { + backingBuilder.fluidPipeProperties(maxTemp, throughput, gasProof, acidProof, plasmaProof); + return this; + } + + @ZenMethod + public CTMaterialBuilder fluidPipeProperties(int maxTemp, int minTemp, int throughput, boolean gasProof, boolean acidProof, + boolean plasmaProof) { + backingBuilder.fluidPipeProperties(maxTemp, minTemp, throughput, gasProof, acidProof, plasmaProof); return this; } diff --git a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java index 7d15798cd13..88c8f3db0e3 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java @@ -1,7 +1,9 @@ package gregtech.integration.crafttweaker.material; import gregtech.api.fluids.FluidBuilder; +import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; +import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.fluids.store.FluidStorage; import gregtech.api.fluids.store.FluidStorageKeys; @@ -10,7 +12,11 @@ import crafttweaker.annotations.ZenRegister; -import gregtech.common.pipelike.handlers.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; + +import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; + +import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; import stanhebben.zenscript.annotations.Optional; import stanhebben.zenscript.annotations.ZenExpansion; @@ -38,11 +44,6 @@ public static boolean hasDust(Material m) { return m.hasProperty(PropertyKey.DUST); } - @ZenMethod - public static boolean hasFluidPipes(Material m) { - return m.hasProperty(PropertyKey.FLUID_PIPE); - } - @ZenMethod public static boolean hasFluid(Material m) { return m.hasProperty(PropertyKey.FLUID); @@ -58,11 +59,6 @@ public static boolean hasIngot(Material m) { return m.hasProperty(PropertyKey.INGOT); } - @ZenMethod - public static boolean hasItemPipes(Material m) { - return m.hasProperty(PropertyKey.ITEM_PIPE); - } - @ZenMethod public static boolean hasOre(Material m) { return m.hasProperty(PropertyKey.ORE); @@ -73,10 +69,22 @@ public static boolean hasTools(Material m) { return m.hasProperty(PropertyKey.TOOL); } + @ZenMethod + public static boolean hasFluidPipes(Material m) { + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + return properties != null && properties.hasProperty(MaterialFluidProperties.KEY); + } + + @ZenMethod + public static boolean hasItemPipes(Material m) { + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + return properties != null && properties.hasProperty(MaterialItemProperties.KEY); + } + @ZenMethod public static boolean hasWires(Material m) { - return m.hasProperty(PropertyKey.PIPENET_PROPERTIES) && - m.getProperty(PropertyKey.PIPENET_PROPERTIES).hasProperty(MaterialEnergyProperties.KEY); + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + return properties != null && properties.hasProperty(MaterialEnergyProperties.KEY); } //////////////////////////////////// @@ -124,28 +132,6 @@ public static void addDust(Material m, @Optional int harvestLevel, @Optional int } else m.setProperty(PropertyKey.DUST, new DustProperty(harvestLevel, burnTime)); } - @ZenMethod - public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof) { - addFluidPipes(m, maxFluidTemperature, throughput, gasProof, false, false, false); - } - - @ZenMethod - public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof, - boolean acidProof, boolean cryoProof, boolean plasmaProof) { - if (checkFrozen("add fluid pipes to a material")) return; - if (m.hasProperty(PropertyKey.FLUID_PIPE)) { - m.getProperty(PropertyKey.FLUID_PIPE).setMaxFluidTemperature(maxFluidTemperature); - m.getProperty(PropertyKey.FLUID_PIPE).setThroughput(throughput); - m.getProperty(PropertyKey.FLUID_PIPE).setGasProof(gasProof); - m.getProperty(PropertyKey.FLUID_PIPE).setCanContain(FluidAttributes.ACID, acidProof); - m.getProperty(PropertyKey.FLUID_PIPE).setCryoProof(cryoProof); - m.getProperty(PropertyKey.FLUID_PIPE).setPlasmaProof(plasmaProof); - } else { - m.setProperty(PropertyKey.FLUID_PIPE, new FluidPipeProperties(maxFluidTemperature, throughput, gasProof, - acidProof, cryoProof, plasmaProof)); - } - } - @ZenMethod public static void addFluid(Material m) { if (checkFrozen("add a Fluid to a material")) return; @@ -208,15 +194,6 @@ public static void addOre(Material m, @Optional int oreMultiplier, @Optional int } else m.setProperty(PropertyKey.ORE, new OreProperty(oreMultiplier, byproductMultiplier, emissive)); } - @ZenMethod - public static void addItemPipes(Material m, int priority, float transferRate) { - if (checkFrozen("add Item Pipes to a material")) return; - if (m.hasProperty(PropertyKey.ITEM_PIPE)) { - m.getProperty(PropertyKey.ITEM_PIPE).setPriority(priority); - m.getProperty(PropertyKey.ITEM_PIPE).setTransferRate(transferRate); - } else m.setProperty(PropertyKey.ITEM_PIPE, new ItemPipeProperties(priority, transferRate)); - } - @ZenMethod public static void addPlasma(Material m) { if (checkFrozen("add a Plasma to a material")) return; @@ -249,13 +226,52 @@ public static void addTools(Material m, float toolSpeed, float toolAttackDamage, .durabilityMultiplier(durabilityMultiplier).build()); } + @ZenMethod + public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof) { + addFluidPipes(m, maxFluidTemperature, throughput, gasProof, false, false); + } + + @ZenMethod + public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof, + boolean acidProof, boolean plasmaProof) { + addFluidPipes(m, maxFluidTemperature, FluidConstants.CRYOGENIC_FLUID_THRESHOLD + 1, throughput, gasProof, acidProof, plasmaProof); + } + + @ZenMethod + public static void addFluidPipes(Material m, int maxFluidTemperature, int minFluidTemperature, int throughput, boolean gasProof, + boolean acidProof, boolean plasmaProof) { + if (checkFrozen("add fluid pipes to a material")) return; + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (properties == null) { + properties = new PipeNetProperties(); + m.setProperty(PropertyKey.PIPENET_PROPERTIES, properties); + } + properties.setProperty(new MaterialFluidProperties(throughput, maxFluidTemperature, minFluidTemperature) + .setContain(FluidState.GAS, gasProof).setContain(FluidAttributes.ACID, acidProof) + .setContain(FluidState.PLASMA, plasmaProof)); + } + + @ZenMethod + public static void addItemPipes(Material m, int priority, float transferRate) { + if (checkFrozen("add Item Pipes to a material")) return; + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (properties == null) { + properties = new PipeNetProperties(); + m.setProperty(PropertyKey.PIPENET_PROPERTIES, properties); + } + properties.setProperty(new MaterialItemProperties((long) (transferRate * 16), priority)); + } + @ZenMethod public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock, @Optional int meltTemperature, @Optional int superconductorTemp) { if (checkFrozen("add Wires to a material")) return; - if (!m.hasProperty(PropertyKey.PIPENET_PROPERTIES)) { - m.setProperty(PropertyKey.PIPENET_PROPERTIES, new PipeNetProperties()); + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (properties == null) { + properties = new PipeNetProperties(); + m.setProperty(PropertyKey.PIPENET_PROPERTIES, properties); } - m.getProperty(PropertyKey.PIPENET_PROPERTIES).setProperty(new MaterialEnergyProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, superconductorTemp)); + properties.setProperty(new MaterialEnergyProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, + superconductorTemp)); } } diff --git a/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java b/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java index ddaab23ccdc..282fd1a6229 100644 --- a/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java +++ b/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java @@ -1,13 +1,20 @@ package gregtech.integration.crafttweaker.recipe; import gregtech.api.GregTechAPI; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.metaitem.MetaItem.MetaValueItem; import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.properties.PipeNetProperties; +import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.common.blocks.BlockCompressed; import gregtech.common.blocks.BlockFrame; import gregtech.common.blocks.MetaBlocks; +import gregtech.common.pipelike.block.cable.CableBlock; +import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; +import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; import gregtech.common.pipelikeold.cable.BlockCable; import gregtech.common.pipelikeold.fluidpipe.BlockFluidPipe; import gregtech.common.pipelikeold.itempipe.BlockItemPipe; @@ -79,19 +86,26 @@ public static void rebuildComponentRegistry() { for (MaterialRegistry registry : GregTechAPI.materialManager.getRegistries()) { String modid = registry.getModid(); Map map = metaBlockNames.computeIfAbsent(modid, (k) -> new Object2ObjectOpenHashMap<>()); - for (BlockCable cable : MetaBlocks.CABLES.get(modid)) { - for (Material material : cable.getEnabledMaterials()) { - map.put(cable.getPrefix().name + material.toCamelCaseString(), cable.getItem(material)); - } - } - for (BlockItemPipe cable : MetaBlocks.ITEM_PIPES.get(modid)) { - for (Material material : cable.getEnabledMaterials()) { - map.put(cable.getPrefix().name + material.toCamelCaseString(), cable.getItem(material)); - } - } - for (BlockFluidPipe cable : MetaBlocks.FLUID_PIPES.get(modid)) { - for (Material material : cable.getEnabledMaterials()) { - map.put(cable.getPrefix().name + material.toCamelCaseString(), cable.getItem(material)); + + for (Material material : registry) { + PipeNetProperties prop = material.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (prop == null) continue; + + for (PipeNetProperties.IPipeNetMaterialProperty property : prop.getRegisteredProperties()) { + // TODO this is awkward, surely there's a better solution? + if (property instanceof MaterialEnergyProperties) { + for (CableBlock cable : MetaBlocks.CABLES.get(modid)) { + String name = cable.getStructure().getOrePrefix().name + material.toCamelCaseString(); + ItemStack stack = cable.getItem(material); + map.put(name, stack); + } + } else if (property instanceof MaterialItemProperties || property instanceof MaterialFluidProperties) { + for (PipeMaterialBlock pipe : MetaBlocks.MATERIAL_PIPES.get(modid)) { + String name = pipe.getStructure().getOrePrefix().name + material.toCamelCaseString(); + ItemStack stack = pipe.getItem(material); + map.put(name, stack); + } + } } } metaBlockNames.put(modid, map); diff --git a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java index 53ae11ccf4d..b392b6dd796 100644 --- a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java +++ b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java @@ -3,6 +3,7 @@ import gregtech.api.GTValues; import gregtech.api.GregTechAPI; import gregtech.api.fluids.FluidBuilder; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.modules.GregTechModule; @@ -14,12 +15,18 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.event.MaterialEvent; import gregtech.api.unification.material.event.PostMaterialEvent; +import gregtech.api.unification.material.properties.PipeNetProperties; +import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.util.Mods; import gregtech.common.blocks.BlockCompressed; import gregtech.common.blocks.BlockFrame; import gregtech.common.blocks.MetaBlocks; +import gregtech.common.pipelike.block.cable.CableBlock; +import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; +import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; import gregtech.common.pipelikeold.cable.BlockCable; import gregtech.common.pipelikeold.fluidpipe.BlockFluidPipe; import gregtech.common.pipelikeold.itempipe.BlockItemPipe; @@ -190,25 +197,25 @@ public static void loadMetaItemBracketHandler() { String modid = registry.getModid(); Map map = metaItems.computeIfAbsent(modid, (k) -> new Object2ObjectOpenHashMap<>()); - for (BlockCable cable : MetaBlocks.CABLES.get(modid)) { - for (Material material : cable.getEnabledMaterials()) { - String name = cable.getPrefix().name + material.toCamelCaseString(); - ItemStack stack = cable.getItem(material); - map.put(name, stack); - } - } - for (BlockItemPipe pipe : MetaBlocks.ITEM_PIPES.get(modid)) { - for (Material material : pipe.getEnabledMaterials()) { - String name = pipe.getPrefix().name + material.toCamelCaseString(); - ItemStack stack = pipe.getItem(material); - map.put(name, stack); - } - } - for (BlockFluidPipe pipe : MetaBlocks.FLUID_PIPES.get(modid)) { - for (Material material : pipe.getEnabledMaterials()) { - String name = pipe.getPrefix().name + material.toCamelCaseString(); - ItemStack stack = pipe.getItem(material); - map.put(name, stack); + for (Material material : registry) { + PipeNetProperties prop = material.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (prop == null) continue; + + for (PipeNetProperties.IPipeNetMaterialProperty property : prop.getRegisteredProperties()) { + // TODO this is awkward, surely there's a better solution? + if (property instanceof MaterialEnergyProperties) { + for (CableBlock cable : MetaBlocks.CABLES.get(modid)) { + String name = cable.getStructure().getOrePrefix().name + material.toCamelCaseString(); + ItemStack stack = cable.getItem(material); + map.put(name, stack); + } + } else if (property instanceof MaterialItemProperties || property instanceof MaterialFluidProperties) { + for (PipeMaterialBlock pipe : MetaBlocks.MATERIAL_PIPES.get(modid)) { + String name = pipe.getStructure().getOrePrefix().name + material.toCamelCaseString(); + ItemStack stack = pipe.getItem(material); + map.put(name, stack); + } + } } } metaItems.put(modid, map); diff --git a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java index 5ace606c37d..282e5518bfe 100644 --- a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java @@ -1,6 +1,7 @@ package gregtech.integration.groovy; import gregtech.api.fluids.FluidBuilder; +import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.fluids.store.FluidStorageKey; @@ -8,11 +9,9 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.BlastProperty; import gregtech.api.unification.material.properties.DustProperty; -import gregtech.api.unification.material.properties.FluidPipeProperties; import gregtech.api.unification.material.properties.FluidProperty; import gregtech.api.unification.material.properties.GemProperty; import gregtech.api.unification.material.properties.IngotProperty; -import gregtech.api.unification.material.properties.ItemPipeProperties; import gregtech.api.unification.material.properties.OreProperty; import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; @@ -22,7 +21,9 @@ import com.cleanroommc.groovyscript.api.GroovyBlacklist; import com.cleanroommc.groovyscript.api.GroovyLog; -import gregtech.common.pipelike.handlers.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; +import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; import static gregtech.integration.groovy.GroovyScriptModule.checkFrozen; @@ -41,10 +42,6 @@ public static boolean hasDust(Material m) { return m.hasProperty(PropertyKey.DUST); } - public static boolean hasFluidPipes(Material m) { - return m.hasProperty(PropertyKey.FLUID_PIPE); - } - public static boolean hasFluid(Material m) { return m.hasProperty(PropertyKey.FLUID); } @@ -57,10 +54,6 @@ public static boolean hasIngot(Material m) { return m.hasProperty(PropertyKey.INGOT); } - public static boolean hasItemPipes(Material m) { - return m.hasProperty(PropertyKey.ITEM_PIPE); - } - public static boolean hasOre(Material m) { return m.hasProperty(PropertyKey.ORE); } @@ -69,9 +62,19 @@ public static boolean hasTools(Material m) { return m.hasProperty(PropertyKey.TOOL); } + public static boolean hasFluidPipes(Material m) { + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + return properties != null && properties.hasProperty(MaterialFluidProperties.KEY); + } + + public static boolean hasItemPipes(Material m) { + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + return properties != null && properties.hasProperty(MaterialItemProperties.KEY); + } + public static boolean hasWires(Material m) { - return m.hasProperty(PropertyKey.PIPENET_PROPERTIES) && - m.getProperty(PropertyKey.PIPENET_PROPERTIES).hasProperty(MaterialEnergyProperties.KEY); + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + return properties != null && properties.hasProperty(MaterialEnergyProperties.KEY); } //////////////////////////////////// @@ -149,26 +152,6 @@ public static void addWood(Material m) { } } - public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof) { - addFluidPipes(m, maxFluidTemperature, throughput, gasProof, false, false, false); - } - - public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof, - boolean acidProof, boolean cryoProof, boolean plasmaProof) { - if (checkFrozen("add fluid pipes to a material")) return; - if (m.hasProperty(PropertyKey.FLUID_PIPE)) { - m.getProperty(PropertyKey.FLUID_PIPE).setMaxFluidTemperature(maxFluidTemperature); - m.getProperty(PropertyKey.FLUID_PIPE).setThroughput(throughput); - m.getProperty(PropertyKey.FLUID_PIPE).setGasProof(gasProof); - m.getProperty(PropertyKey.FLUID_PIPE).setCanContain(FluidAttributes.ACID, acidProof); - m.getProperty(PropertyKey.FLUID_PIPE).setCryoProof(cryoProof); - m.getProperty(PropertyKey.FLUID_PIPE).setPlasmaProof(plasmaProof); - } else { - m.setProperty(PropertyKey.FLUID_PIPE, new FluidPipeProperties(maxFluidTemperature, throughput, gasProof, - acidProof, cryoProof, plasmaProof)); - } - } - @GroovyBlacklist private static void addFluidInternal(Material m, FluidStorageKey key, FluidBuilder builder) { if (checkFrozen("add a Fluid to a material")) return; @@ -264,14 +247,6 @@ public static void addOre(Material m, int oreMultiplier, int byproductMultiplier } else m.setProperty(PropertyKey.ORE, new OreProperty(oreMultiplier, byproductMultiplier, emissive)); } - public static void addItemPipes(Material m, int priority, float transferRate) { - if (checkFrozen("add Item Pipes to a material")) return; - if (m.hasProperty(PropertyKey.ITEM_PIPE)) { - m.getProperty(PropertyKey.ITEM_PIPE).setPriority(priority); - m.getProperty(PropertyKey.ITEM_PIPE).setTransferRate(transferRate); - } else m.setProperty(PropertyKey.ITEM_PIPE, new ItemPipeProperties(priority, transferRate)); - } - public static void addTools(Material m, ToolProperty.Builder builder) { addTools(m, builder.build()); } @@ -322,6 +297,38 @@ public static void addTools(Material m, float toolSpeed, float toolAttackDamage, .durabilityMultiplier(durabilityMultiplier)); } + public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof) { + addFluidPipes(m, maxFluidTemperature, throughput, gasProof, false, false); + } + + public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof, + boolean acidProof, boolean plasmaProof) { + addFluidPipes(m, maxFluidTemperature, FluidConstants.CRYOGENIC_FLUID_THRESHOLD + 1, throughput, gasProof, acidProof, plasmaProof); + } + + public static void addFluidPipes(Material m, int maxFluidTemperature, int minFluidTemperature, int throughput, boolean gasProof, + boolean acidProof, boolean plasmaProof) { + if (checkFrozen("add fluid pipes to a material")) return; + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (properties == null) { + properties = new PipeNetProperties(); + m.setProperty(PropertyKey.PIPENET_PROPERTIES, properties); + } + properties.setProperty(new MaterialFluidProperties(throughput, maxFluidTemperature, minFluidTemperature) + .setContain(FluidState.GAS, gasProof).setContain(FluidAttributes.ACID, acidProof) + .setContain(FluidState.PLASMA, plasmaProof)); + } + + public static void addItemPipes(Material m, int priority, float transferRate) { + if (checkFrozen("add Item Pipes to a material")) return; + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (properties == null) { + properties = new PipeNetProperties(); + m.setProperty(PropertyKey.PIPENET_PROPERTIES, properties); + } + properties.setProperty(new MaterialItemProperties((long) (transferRate * 16), priority)); + } + public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock) { addWires(m, voltage, baseAmperage, lossPerBlock, 0); } @@ -333,10 +340,13 @@ public static void addWires(Material m, long voltage, long baseAmperage, long lo public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock, int meltTemperature, int superconductorTemp) { if (checkFrozen("add Wires to a material")) return; - if (!m.hasProperty(PropertyKey.PIPENET_PROPERTIES)) { - m.setProperty(PropertyKey.PIPENET_PROPERTIES, new PipeNetProperties()); + PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (properties == null) { + properties = new PipeNetProperties(); + m.setProperty(PropertyKey.PIPENET_PROPERTIES, properties); } - m.getProperty(PropertyKey.PIPENET_PROPERTIES).setProperty(new MaterialEnergyProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, superconductorTemp)); + properties.setProperty(new MaterialEnergyProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, + superconductorTemp)); } public static void addCables(Material m, long voltage, long baseAmperage, long lossPerBlock) { diff --git a/src/main/java/gregtech/integration/jei/basic/MaterialTree.java b/src/main/java/gregtech/integration/jei/basic/MaterialTree.java index 82cc58d5dab..b7d5ed6aede 100644 --- a/src/main/java/gregtech/integration/jei/basic/MaterialTree.java +++ b/src/main/java/gregtech/integration/jei/basic/MaterialTree.java @@ -35,8 +35,7 @@ public class MaterialTree implements IRecipeWrapper { OrePrefix.wireFine, OrePrefix.frameGt, OrePrefix.round, - OrePrefix.pipeNormalFluid, - OrePrefix.pipeNormalItem, + OrePrefix.pipeNormal, OrePrefix.screw, OrePrefix.bolt, OrePrefix.gear, diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java index 9b2148a8e88..5ee259103de 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java @@ -2,6 +2,7 @@ import gregtech.api.GTValues; import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.capability.ILaserContainer; import gregtech.api.capability.ILaserRelay; import gregtech.api.util.TextFormattingUtil; @@ -24,19 +25,21 @@ protected Capability getCapability() { @Override protected boolean allowDisplaying(@NotNull ILaserRelay capability) { - return !capability.isOneProbeHidden(); + return capability instanceof ILaserContainer c && !c.isOneProbeHidden(); } @Override - protected void addProbeInfo(ILaserRelay capability, IProbeInfo probeInfo, EntityPlayer player, + protected void addProbeInfo(ILaserRelay cap, IProbeInfo probeInfo, EntityPlayer player, TileEntity tileEntity, IProbeHitData data) { - long maxStorage = capability.getEnergyCapacity(); - if (maxStorage == 0) return; // do not add empty max storage progress bar - probeInfo.progress(capability.getEnergyStored(), maxStorage, probeInfo.defaultProgressStyle() - .suffix(" / " + TextFormattingUtil.formatNumbers(maxStorage) + " EU") - .filledColor(0xFFEEE600) - .alternateFilledColor(0xFFEEE600) - .borderColor(0xFF555555).numberFormat(NumberFormat.COMMAS)); + if (cap instanceof ILaserContainer capability) { + long maxStorage = capability.getEnergyCapacity(); + if (maxStorage == 0) return; // do not add empty max storage progress bar + probeInfo.progress(capability.getEnergyStored(), maxStorage, probeInfo.defaultProgressStyle() + .suffix(" / " + TextFormattingUtil.formatNumbers(maxStorage) + " EU") + .filledColor(0xFFEEE600) + .alternateFilledColor(0xFFEEE600) + .borderColor(0xFF555555).numberFormat(NumberFormat.COMMAS)); + } } @Override diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java index e1150fc9fcf..a5d07770e3c 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java @@ -1,5 +1,6 @@ package gregtech.integration.theoneprobe.provider.debug; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.pipenetold.PipeNetNode; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; @@ -44,31 +45,13 @@ public void addProbeInfo(@NotNull ProbeMode mode, @NotNull IProbeInfo probeInfo, list.forEach(probeInfo::text); } } - if (tileEntity instanceof TileEntityPipeBase) { - IPipeTile pipeTile = (IPipeTile) tileEntity; - BlockPipe blockPipe = pipeTile.getPipeBlock(); - WorldPipeNetBase pipeNet = blockPipe.getWorldPipeNet(world); - if (pipeNet != null) { - probeInfo.text("Net: " + pipeNet.hashCode()); - probeInfo.text("WorldPipeNetNode Info: "); - StringBuilder builder = new StringBuilder(); - PipeNetNode node = pipeNet.getNode(data.getPos()); - if (node != null) { - builder.append("{") - .append("active: ").append(node.isActive) - .append(", mark: ").append(node.mark) - .append(", open: ").append(node.getOpenConnections()) - .append(", blocked: ").append(node.getBlockedConnections()) - .append("}"); - } - probeInfo.text(builder.toString()); - } - probeInfo.text("tile open: " + pipeTile.getConnections()); - // if (blockPipe instanceof BlockFluidPipe) { - // if (pipeTile instanceof TileEntityFluidPipeTickable) { - // probeInfo.text("tile active: " + ((TileEntityFluidPipeTickable) pipeTile).isActive()); - // } - // } + if (tileEntity instanceof PipeTileEntity pipeTile) { + String builder = "{" + + ", mark: " + pipeTile.getPaintingColor() + + ", open: " + pipeTile.getConnectionMask() + + ", blocked: " + pipeTile.getBlockedMask() + + "}"; + probeInfo.text(builder); } } } diff --git a/src/main/java/gregtech/loaders/recipe/CircuitRecipes.java b/src/main/java/gregtech/loaders/recipe/CircuitRecipes.java index 0d62958b37c..0031d81d33e 100644 --- a/src/main/java/gregtech/loaders/recipe/CircuitRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/CircuitRecipes.java @@ -1467,7 +1467,7 @@ private static void circuitRecipes() { CIRCUIT_ASSEMBLER_RECIPES.recipeBuilder().EUt(80000).duration(600) .input(WETWARE_CIRCUIT_BOARD) .input(STEM_CELLS, 16) - .input(pipeSmallFluid, Polybenzimidazole, 8) + .input(pipeSmall, Polybenzimidazole, 8) .input(plate, Electrum, 8) .input(foil, SiliconeRubber, 16) .input(bolt, HSSE, 8) diff --git a/src/main/java/gregtech/loaders/recipe/ComponentRecipes.java b/src/main/java/gregtech/loaders/recipe/ComponentRecipes.java index cb0828ab239..cbe06fc336d 100644 --- a/src/main/java/gregtech/loaders/recipe/ComponentRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/ComponentRecipes.java @@ -213,35 +213,35 @@ public static void register() { // Start--------------------------------------------------------------------------------------------------- ModHandler.addShapedRecipe(material.equals(Rubber), String.format("electric_pump_lv_%s", name), ELECTRIC_PUMP_LV.getStackForm(), "SXR", "dPw", "RMC", 'S', new UnificationEntry(screw, Tin), 'X', - new UnificationEntry(rotor, Tin), 'P', new UnificationEntry(pipeNormalFluid, Bronze), 'R', + new UnificationEntry(rotor, Tin), 'P', new UnificationEntry(pipeNormal, Bronze), 'R', new UnificationEntry(ring, material), 'C', new UnificationEntry(cableGtSingle, Tin), 'M', ELECTRIC_MOTOR_LV.getStackForm()); ModHandler.addShapedRecipe(material.equals(Rubber), String.format("electric_pump_mv_%s", name), ELECTRIC_PUMP_MV.getStackForm(), "SXR", "dPw", "RMC", 'S', new UnificationEntry(screw, Bronze), 'X', - new UnificationEntry(rotor, Bronze), 'P', new UnificationEntry(pipeNormalFluid, Steel), 'R', + new UnificationEntry(rotor, Bronze), 'P', new UnificationEntry(pipeNormal, Steel), 'R', new UnificationEntry(ring, material), 'C', new UnificationEntry(cableGtSingle, Copper), 'M', ELECTRIC_MOTOR_MV.getStackForm()); ModHandler.addShapedRecipe(material.equals(Rubber), String.format("electric_pump_hv_%s", name), ELECTRIC_PUMP_HV.getStackForm(), "SXR", "dPw", "RMC", 'S', new UnificationEntry(screw, Steel), 'X', - new UnificationEntry(rotor, Steel), 'P', new UnificationEntry(pipeNormalFluid, StainlessSteel), 'R', + new UnificationEntry(rotor, Steel), 'P', new UnificationEntry(pipeNormal, StainlessSteel), 'R', new UnificationEntry(ring, material), 'C', new UnificationEntry(cableGtSingle, Gold), 'M', ELECTRIC_MOTOR_HV.getStackForm()); ModHandler.addShapedRecipe(material.equals(Rubber), String.format("electric_pump_ev_%s", name), ELECTRIC_PUMP_EV.getStackForm(), "SXR", "dPw", "RMC", 'S', new UnificationEntry(screw, StainlessSteel), 'X', new UnificationEntry(rotor, StainlessSteel), 'P', - new UnificationEntry(pipeNormalFluid, Titanium), 'R', new UnificationEntry(ring, material), 'C', + new UnificationEntry(pipeNormal, Titanium), 'R', new UnificationEntry(ring, material), 'C', new UnificationEntry(cableGtSingle, Aluminium), 'M', ELECTRIC_MOTOR_EV.getStackForm()); if (!material.equals(Rubber)) ModHandler.addShapedRecipe(material.equals(SiliconeRubber), String.format("electric_pump_iv_%s", name), ELECTRIC_PUMP_IV.getStackForm(), "SXR", "dPw", "RMC", 'S', new UnificationEntry(screw, TungstenSteel), 'X', new UnificationEntry(rotor, TungstenSteel), - 'P', new UnificationEntry(pipeNormalFluid, TungstenSteel), 'R', + 'P', new UnificationEntry(pipeNormal, TungstenSteel), 'R', new UnificationEntry(ring, material), 'C', new UnificationEntry(cableGtSingle, Tungsten), 'M', ELECTRIC_MOTOR_IV.getStackForm()); ASSEMBLER_RECIPES.recipeBuilder() .input(cableGtSingle, Tin) - .input(pipeNormalFluid, Bronze) + .input(pipeNormal, Bronze) .input(screw, Tin) .input(rotor, Tin) .input(ring, materialEntry.getValue(), 2) @@ -251,7 +251,7 @@ public static void register() { ASSEMBLER_RECIPES.recipeBuilder() .input(cableGtSingle, Copper) - .input(pipeNormalFluid, Steel) + .input(pipeNormal, Steel) .input(screw, Bronze) .input(rotor, Bronze) .input(ring, materialEntry.getValue(), 2) @@ -261,7 +261,7 @@ public static void register() { ASSEMBLER_RECIPES.recipeBuilder() .input(cableGtSingle, Gold) - .input(pipeNormalFluid, StainlessSteel) + .input(pipeNormal, StainlessSteel) .input(screw, Steel) .input(rotor, Steel) .input(ring, materialEntry.getValue(), 2) @@ -271,7 +271,7 @@ public static void register() { ASSEMBLER_RECIPES.recipeBuilder() .input(cableGtSingle, Aluminium) - .input(pipeNormalFluid, Titanium) + .input(pipeNormal, Titanium) .input(screw, StainlessSteel) .input(rotor, StainlessSteel) .input(ring, materialEntry.getValue(), 2) @@ -282,7 +282,7 @@ public static void register() { if (!materialEntry.getValue().equals(Rubber)) ASSEMBLER_RECIPES.recipeBuilder() .input(cableGtSingle, Tungsten) - .input(pipeNormalFluid, TungstenSteel) + .input(pipeNormal, TungstenSteel) .input(screw, TungstenSteel) .input(rotor, TungstenSteel) .input(ring, materialEntry.getValue(), 2) @@ -342,7 +342,7 @@ public static void register() { ASSEMBLY_LINE_RECIPES.recipeBuilder() .input(ELECTRIC_MOTOR_LuV) - .input(pipeSmallFluid, NiobiumTitanium) + .input(pipeSmall, NiobiumTitanium) .input(plate, HSSS, 2) .input(screw, HSSS, 8) .input(ring, SiliconeRubber, 4) @@ -356,7 +356,7 @@ public static void register() { ASSEMBLY_LINE_RECIPES.recipeBuilder() .input(ELECTRIC_MOTOR_ZPM) - .input(pipeNormalFluid, Polybenzimidazole) + .input(pipeNormal, Polybenzimidazole) .input(plate, Osmiridium, 2) .input(screw, Osmiridium, 8) .input(ring, SiliconeRubber, 8) @@ -373,7 +373,7 @@ public static void register() { ASSEMBLY_LINE_RECIPES.recipeBuilder() .input(ELECTRIC_MOTOR_UV) - .input(pipeLargeFluid, Naquadah) + .input(pipeLarge, Naquadah) .input(plate, Tritanium, 2) .input(screw, Tritanium, 8) .input(ring, SiliconeRubber, 16) @@ -473,12 +473,12 @@ public static void register() { ModHandler.addShapedRecipe(true, "cover_item_voiding", COVER_ITEM_VOIDING.getStackForm(), "SDS", "dPw", " E ", 'S', new UnificationEntry(screw, Steel), 'D', COVER_ITEM_DETECTOR.getStackForm(), 'P', - new UnificationEntry(pipeNormalItem, Brass), 'E', Items.ENDER_PEARL); + new UnificationEntry(pipeNormal, Brass), 'E', Items.ENDER_PEARL); ASSEMBLER_RECIPES.recipeBuilder() .input(screw, Steel, 2) .inputs(COVER_ITEM_DETECTOR.getStackForm()) - .input(pipeNormalItem, Brass) + .input(pipeNormal, Brass) .input(Items.ENDER_PEARL) .outputs(COVER_ITEM_VOIDING.getStackForm()) .duration(100).EUt(VA[LV]).buildAndRegister(); @@ -491,12 +491,12 @@ public static void register() { ModHandler.addShapedRecipe(true, "cover_fluid_voiding", COVER_FLUID_VOIDING.getStackForm(), "SDS", "dPw", " E ", 'S', new UnificationEntry(screw, Steel), 'D', COVER_FLUID_DETECTOR.getStackForm(), 'P', - new UnificationEntry(pipeNormalFluid, Bronze), 'E', Items.ENDER_PEARL); + new UnificationEntry(pipeNormal, Bronze), 'E', Items.ENDER_PEARL); ASSEMBLER_RECIPES.recipeBuilder() .input(screw, Steel, 2) .inputs(COVER_FLUID_DETECTOR.getStackForm()) - .input(pipeNormalFluid, Bronze) + .input(pipeNormal, Bronze) .input(Items.ENDER_PEARL) .outputs(COVER_FLUID_VOIDING.getStackForm()) .duration(100).EUt(VA[LV]).buildAndRegister(); diff --git a/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java b/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java index 9b2fbca568d..2832ffc5510 100644 --- a/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java @@ -76,7 +76,7 @@ public static void init() { .input(frameGt, StainlessSteel) .input(ELECTRIC_MOTOR_IV, 2) .input(rotor, StainlessSteel, 2) - .input(pipeTinyFluid, StainlessSteel, 16) + .input(pipeTiny, StainlessSteel, 16) .input(plate, Copper, 16) .input(wireGtSingle, SamariumIronArsenicOxide) .outputs(COMPUTER_CASING.getItemVariant(BlockComputerCasing.CasingType.COMPUTER_HEAT_VENT, @@ -200,7 +200,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .inputs(COMPUTER_CASING.getItemVariant(BlockComputerCasing.CasingType.ADVANCED_COMPUTER_CASING)) .input(plate, Aluminium, 16) - .input(pipeTinyFluid, StainlessSteel, 16) + .input(pipeTiny, StainlessSteel, 16) .input(screw, StainlessSteel, 8) .output(HPCA_ACTIVE_COOLER_COMPONENT) .fluidInputs(PCBCoolant.getFluid(1000)) diff --git a/src/main/java/gregtech/loaders/recipe/CraftingComponent.java b/src/main/java/gregtech/loaders/recipe/CraftingComponent.java index f6c8898f9d9..7a58d032a68 100644 --- a/src/main/java/gregtech/loaders/recipe/CraftingComponent.java +++ b/src/main/java/gregtech/loaders/recipe/CraftingComponent.java @@ -369,29 +369,29 @@ public static void initializeComponents() { PIPE_NORMAL = new Component(Stream.of(new Object[][] { - { 0, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Bronze) }, - { 1, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Bronze) }, - { 2, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Steel) }, - { 3, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.StainlessSteel) }, - { 4, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Titanium) }, - { 5, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.TungstenSteel) }, - { 6, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.NiobiumTitanium) }, - { 7, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Iridium) }, - { 8, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Naquadah) }, + { 0, new UnificationEntry(OrePrefix.pipeNormal, Materials.Bronze) }, + { 1, new UnificationEntry(OrePrefix.pipeNormal, Materials.Bronze) }, + { 2, new UnificationEntry(OrePrefix.pipeNormal, Materials.Steel) }, + { 3, new UnificationEntry(OrePrefix.pipeNormal, Materials.StainlessSteel) }, + { 4, new UnificationEntry(OrePrefix.pipeNormal, Materials.Titanium) }, + { 5, new UnificationEntry(OrePrefix.pipeNormal, Materials.TungstenSteel) }, + { 6, new UnificationEntry(OrePrefix.pipeNormal, Materials.NiobiumTitanium) }, + { 7, new UnificationEntry(OrePrefix.pipeNormal, Materials.Iridium) }, + { 8, new UnificationEntry(OrePrefix.pipeNormal, Materials.Naquadah) }, }).collect(Collectors.toMap(data -> (Integer) data[0], data -> data[1]))); PIPE_LARGE = new Component(Stream.of(new Object[][] { - { 0, new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Bronze) }, - { 1, new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Bronze) }, - { 2, new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Steel) }, - { 3, new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.StainlessSteel) }, - { 4, new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Titanium) }, - { 5, new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.TungstenSteel) }, - { 6, new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.NiobiumTitanium) }, - { 7, new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Ultimet) }, - { 8, new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Naquadah) }, + { 0, new UnificationEntry(OrePrefix.pipeLarge, Materials.Bronze) }, + { 1, new UnificationEntry(OrePrefix.pipeLarge, Materials.Bronze) }, + { 2, new UnificationEntry(OrePrefix.pipeLarge, Materials.Steel) }, + { 3, new UnificationEntry(OrePrefix.pipeLarge, Materials.StainlessSteel) }, + { 4, new UnificationEntry(OrePrefix.pipeLarge, Materials.Titanium) }, + { 5, new UnificationEntry(OrePrefix.pipeLarge, Materials.TungstenSteel) }, + { 6, new UnificationEntry(OrePrefix.pipeLarge, Materials.NiobiumTitanium) }, + { 7, new UnificationEntry(OrePrefix.pipeLarge, Materials.Ultimet) }, + { 8, new UnificationEntry(OrePrefix.pipeLarge, Materials.Naquadah) }, }).collect(Collectors.toMap(data -> (Integer) data[0], data -> data[1]))); @@ -774,13 +774,13 @@ public static void initializeComponents() { { 0, new ItemStack(Blocks.GLASS, 1, GTValues.W) }, { 1, new ItemStack(Blocks.GLASS, 1, GTValues.W) }, { 2, new ItemStack(Blocks.GLASS, 1, GTValues.W) }, - { 3, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Polyethylene) }, - { 4, new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Polyethylene) }, - { 5, new UnificationEntry(OrePrefix.pipeHugeFluid, Materials.Polyethylene) }, - { 6, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Polytetrafluoroethylene) }, - { 7, new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Polytetrafluoroethylene) }, - { 8, new UnificationEntry(OrePrefix.pipeHugeFluid, Materials.Polytetrafluoroethylene) }, - { GTValues.FALLBACK, new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Polyethylene) }, + { 3, new UnificationEntry(OrePrefix.pipeNormal, Materials.Polyethylene) }, + { 4, new UnificationEntry(OrePrefix.pipeLarge, Materials.Polyethylene) }, + { 5, new UnificationEntry(OrePrefix.pipeHuge, Materials.Polyethylene) }, + { 6, new UnificationEntry(OrePrefix.pipeNormal, Materials.Polytetrafluoroethylene) }, + { 7, new UnificationEntry(OrePrefix.pipeLarge, Materials.Polytetrafluoroethylene) }, + { 8, new UnificationEntry(OrePrefix.pipeHuge, Materials.Polytetrafluoroethylene) }, + { GTValues.FALLBACK, new UnificationEntry(OrePrefix.pipeNormal, Materials.Polyethylene) }, }).collect(Collectors.toMap(data -> (Integer) data[0], data -> data[1]))); diff --git a/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java index 8b18ba7a811..8538b378bf8 100644 --- a/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/CraftingRecipeLoader.java @@ -173,7 +173,7 @@ private static void loadCraftingRecipes() { ModHandler.addShapedRecipe(true, "filter_casing_sterile", MetaBlocks.CLEANROOM_CASING.getItemVariant(BlockCleanroomCasing.CasingType.FILTER_CASING_STERILE, ConfigHolder.recipes.casingsPerCraft), - "BEB", "ISI", "MFR", 'B', new UnificationEntry(OrePrefix.pipeLargeFluid, Polybenzimidazole), 'E', + "BEB", "ISI", "MFR", 'B', new UnificationEntry(OrePrefix.pipeLarge, Polybenzimidazole), 'E', EMITTER_ZPM.getStackForm(), 'I', ITEM_FILTER.getStackForm(), 'S', BLACKLIGHT.getStackForm(), 'M', ELECTRIC_MOTOR_ZPM.getStackForm(), 'F', new UnificationEntry(OrePrefix.frameGt, Tritanium), 'R', new UnificationEntry(OrePrefix.rotor, NaquadahAlloy)); @@ -307,7 +307,7 @@ private static void loadCraftingRecipes() { 'C', new UnificationEntry(OrePrefix.circuit, Tier.LV), 'S', MetaItems.FLUID_CELL_LARGE_STEEL.getStackForm(), 'U', MetaItems.ELECTRIC_PUMP_LV.getStackForm(), 'R', new UnificationEntry(OrePrefix.rotor, Lead), 'I', - new UnificationEntry(OrePrefix.pipeSmallFluid, Potin)); + new UnificationEntry(OrePrefix.pipeSmall, Potin)); ModHandler.addShapedRecipe("electric_jetpack", MetaItems.ELECTRIC_JETPACK.getStackForm(), "xCd", "TBT", "I I", 'C', new UnificationEntry(OrePrefix.circuit, Tier.MV), 'T', MetaItems.POWER_THRUSTER.getStackForm(), 'B', MetaItems.BATTERY_MV_LITHIUM.getStackForm(), 'I', diff --git a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java index 67a29315718..41cfdcd587d 100644 --- a/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MachineRecipeLoader.java @@ -755,7 +755,7 @@ private static void registerAssemblerRecipes() { .inputs(MetaItems.FIELD_GENERATOR_IV.getStackForm(2)).inputs(MetaItems.ELECTRIC_PUMP_IV.getStackForm()) .inputs(MetaItems.NEUTRON_REFLECTOR.getStackForm(2)) .input(OrePrefix.circuit, MarkerMaterials.Tier.LuV, 4) - .input(OrePrefix.pipeSmallFluid, Materials.Naquadah, 4).input(OrePrefix.plate, Materials.Europium, 4) + .input(OrePrefix.pipeSmall, Materials.Naquadah, 4).input(OrePrefix.plate, Materials.Europium, 4) .fluidInputs(Materials.VanadiumGallium.getFluid(GTValues.L * 4)) .outputs(MetaBlocks.FUSION_CASING.getItemVariant(BlockFusionCasing.CasingType.FUSION_COIL)) .duration(100).cleanroom(CleanroomType.CLEANROOM).buildAndRegister(); diff --git a/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java b/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java index 192c35d1d16..61c1fbef6c8 100644 --- a/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MetaTileEntityLoader.java @@ -155,28 +155,28 @@ public static void init() { MetaBlocks.BOILER_CASING.getItemVariant(BRONZE_PIPE, ConfigHolder.recipes.casingsPerCraft), "PIP", "IFI", "PIP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'F', new UnificationEntry(OrePrefix.frameGt, Materials.Bronze), 'I', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Bronze)); + new UnificationEntry(OrePrefix.pipeNormal, Materials.Bronze)); ModHandler.addShapedRecipe(true, "casing_steel_pipe", MetaBlocks.BOILER_CASING.getItemVariant(STEEL_PIPE, ConfigHolder.recipes.casingsPerCraft), "PIP", "IFI", "PIP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'F', new UnificationEntry(OrePrefix.frameGt, Materials.Steel), 'I', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Steel)); + new UnificationEntry(OrePrefix.pipeNormal, Materials.Steel)); ModHandler.addShapedRecipe(true, "casing_titanium_pipe", MetaBlocks.BOILER_CASING.getItemVariant(TITANIUM_PIPE, ConfigHolder.recipes.casingsPerCraft), "PIP", "IFI", "PIP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Titanium), 'F', new UnificationEntry(OrePrefix.frameGt, Materials.Titanium), 'I', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Titanium)); + new UnificationEntry(OrePrefix.pipeNormal, Materials.Titanium)); ModHandler.addShapedRecipe(true, "casing_tungstensteel_pipe", MetaBlocks.BOILER_CASING.getItemVariant(TUNGSTENSTEEL_PIPE, ConfigHolder.recipes.casingsPerCraft), "PIP", "IFI", "PIP", 'P', new UnificationEntry(OrePrefix.plate, Materials.TungstenSteel), 'F', new UnificationEntry(OrePrefix.frameGt, Materials.TungstenSteel), 'I', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.TungstenSteel)); + new UnificationEntry(OrePrefix.pipeNormal, Materials.TungstenSteel)); ModHandler.addShapedRecipe(true, "casing_ptfe_pipe", MetaBlocks.BOILER_CASING.getItemVariant(POLYTETRAFLUOROETHYLENE_PIPE, ConfigHolder.recipes.casingsPerCraft), "PIP", "IFI", "PIP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Polytetrafluoroethylene), 'F', new UnificationEntry(OrePrefix.frameGt, Materials.Polytetrafluoroethylene), 'I', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Polytetrafluoroethylene)); + new UnificationEntry(OrePrefix.pipeNormal, Materials.Polytetrafluoroethylene)); ModHandler.addShapedRecipe(true, "casing_bronze_firebox", MetaBlocks.BOILER_FIREBOX_CASING.getItemVariant(BRONZE_FIREBOX, ConfigHolder.recipes.casingsPerCraft), "PSP", "SFS", "PSP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'F', @@ -404,7 +404,7 @@ public static void init() { ModHandler.addShapedRecipe(true, "passthrough_hatch_fluid", MetaTileEntities.PASSTHROUGH_HATCH_FLUID.getStackForm(), " C ", "GHG", " S ", 'C', MetaItems.ELECTRIC_PUMP_HV.getStackForm(), 'G', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Steel), 'H', + new UnificationEntry(OrePrefix.pipeSmall, Materials.Steel), 'H', MetaTileEntities.HULL[GTValues.HV].getStackForm(), 'S', MetaBlocks.TRANSPARENT_CASING.getItemVariant(BlockGlassCasing.CasingType.TEMPERED_GLASS)); @@ -444,85 +444,85 @@ public static void init() { ModHandler.addShapedRecipe(true, "steam_boiler_solar_bronze", MetaTileEntities.STEAM_BOILER_SOLAR_BRONZE.getStackForm(), "GGG", "SSS", "PMP", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_BRICKS_HULL), 'P', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'S', + new UnificationEntry(OrePrefix.pipeSmall, Materials.Bronze), 'S', new UnificationEntry(OrePrefix.plate, Materials.Silver), 'G', new ItemStack(Blocks.GLASS)); ModHandler.addShapedRecipe(true, "steam_boiler_solar_steel", MetaTileEntities.STEAM_BOILER_SOLAR_STEEL.getStackForm(), "GGG", "SSS", "PMP", 'M', MetaBlocks.STEAM_CASING.getItemVariant(STEEL_BRICKS_HULL), 'P', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Steel), 'S', + new UnificationEntry(OrePrefix.pipeSmall, Materials.Steel), 'S', new UnificationEntry(OrePrefix.plateDouble, Materials.Silver), 'G', new ItemStack(Blocks.GLASS)); ModHandler.addShapedRecipe(true, "steam_furnace_bronze", MetaTileEntities.STEAM_FURNACE_BRONZE.getStackForm(), "XXX", "XMX", "XFX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_BRICKS_HULL), 'X', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'F', OreDictNames.craftingFurnace); + new UnificationEntry(OrePrefix.pipeSmall, Materials.Bronze), 'F', OreDictNames.craftingFurnace); ModHandler.addShapedRecipe(true, "steam_furnace_steel", MetaTileEntities.STEAM_FURNACE_STEEL.getStackForm(), "XSX", "PMP", "XXX", 'M', MetaTileEntities.STEAM_FURNACE_BRONZE.getStackForm(), 'X', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.TinAlloy), 'S', + new UnificationEntry(OrePrefix.pipeSmall, Materials.TinAlloy), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'P', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron)); ModHandler.addShapedRecipe(true, "steam_macerator_bronze", MetaTileEntities.STEAM_MACERATOR_BRONZE.getStackForm(), "DXD", "XMX", "PXP", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), 'X', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'P', OreDictNames.craftingPiston, 'D', + new UnificationEntry(OrePrefix.pipeSmall, Materials.Bronze), 'P', OreDictNames.craftingPiston, 'D', new UnificationEntry(OrePrefix.gem, Materials.Diamond)); ModHandler.addShapedRecipe(true, "steam_macerator_steel", MetaTileEntities.STEAM_MACERATOR_STEEL.getStackForm(), "WSW", "PMP", "WWW", 'M', MetaTileEntities.STEAM_MACERATOR_BRONZE.getStackForm(), 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'P', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.TinAlloy)); + new UnificationEntry(OrePrefix.pipeSmall, Materials.TinAlloy)); ModHandler.addShapedRecipe(true, "steam_extractor_bronze", MetaTileEntities.STEAM_EXTRACTOR_BRONZE.getStackForm(), "XXX", "PMG", "XXX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), 'X', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'P', OreDictNames.craftingPiston, 'G', + new UnificationEntry(OrePrefix.pipeSmall, Materials.Bronze), 'P', OreDictNames.craftingPiston, 'G', new ItemStack(Blocks.GLASS)); ModHandler.addShapedRecipe(true, "steam_extractor_steel", MetaTileEntities.STEAM_EXTRACTOR_STEEL.getStackForm(), "PSP", "WMW", "PPP", 'M', MetaTileEntities.STEAM_EXTRACTOR_BRONZE.getStackForm(), 'P', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.TinAlloy), 'S', + new UnificationEntry(OrePrefix.pipeSmall, Materials.TinAlloy), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron)); ModHandler.addShapedRecipe(true, "steam_hammer_bronze", MetaTileEntities.STEAM_HAMMER_BRONZE.getStackForm(), "XPX", "XMX", "XAX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), 'X', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'P', OreDictNames.craftingPiston, 'A', + new UnificationEntry(OrePrefix.pipeSmall, Materials.Bronze), 'P', OreDictNames.craftingPiston, 'A', OreDictNames.craftingAnvil); ModHandler.addShapedRecipe(true, "steam_hammer_steel", MetaTileEntities.STEAM_HAMMER_STEEL.getStackForm(), "WSW", "PMP", "WWW", 'M', MetaTileEntities.STEAM_HAMMER_BRONZE.getStackForm(), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron), 'P', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.TinAlloy)); + new UnificationEntry(OrePrefix.pipeSmall, Materials.TinAlloy)); ModHandler.addShapedRecipe(true, "steam_compressor_bronze", MetaTileEntities.STEAM_COMPRESSOR_BRONZE.getStackForm(), "XXX", "PMP", "XXX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), 'X', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'P', OreDictNames.craftingPiston); + new UnificationEntry(OrePrefix.pipeSmall, Materials.Bronze), 'P', OreDictNames.craftingPiston); ModHandler.addShapedRecipe(true, "steam_compressor_steel", MetaTileEntities.STEAM_COMPRESSOR_STEEL.getStackForm(), "PSP", "WMW", "PPP", 'M', MetaTileEntities.STEAM_COMPRESSOR_BRONZE.getStackForm(), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron), 'P', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.TinAlloy)); + new UnificationEntry(OrePrefix.pipeSmall, Materials.TinAlloy)); ModHandler.addShapedRecipe(true, "steam_alloy_smelter_bronze", MetaTileEntities.STEAM_ALLOY_SMELTER_BRONZE.getStackForm(), "XXX", "FMF", "XXX", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_BRICKS_HULL), 'X', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'F', OreDictNames.craftingFurnace); + new UnificationEntry(OrePrefix.pipeSmall, Materials.Bronze), 'F', OreDictNames.craftingFurnace); ModHandler.addShapedRecipe(true, "steam_alloy_smelter_steel", MetaTileEntities.STEAM_ALLOY_SMELTER_STEEL.getStackForm(), "WSW", "WMW", "WPW", 'M', MetaTileEntities.STEAM_ALLOY_SMELTER_BRONZE.getStackForm(), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron), 'P', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.TinAlloy)); + new UnificationEntry(OrePrefix.pipeSmall, Materials.TinAlloy)); ModHandler.addShapedRecipe(true, "steam_rock_breaker_bronze", MetaTileEntities.STEAM_ROCK_BREAKER_BRONZE.getStackForm(), "PXP", "XMX", "DXD", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), 'X', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.Bronze), 'P', "craftingPiston", 'D', + new UnificationEntry(OrePrefix.pipeSmall, Materials.Bronze), 'P', "craftingPiston", 'D', new UnificationEntry(OrePrefix.gem, Materials.Diamond)); ModHandler.addShapedRecipe(true, "steam_rock_breaker_steel", MetaTileEntities.STEAM_ROCK_BREAKER_STEEL.getStackForm(), "WSW", "PMP", "WWW", 'M', MetaTileEntities.STEAM_ROCK_BREAKER_BRONZE.getStackForm(), 'W', new UnificationEntry(OrePrefix.plate, Materials.WroughtIron), 'S', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'P', - new UnificationEntry(OrePrefix.pipeSmallFluid, Materials.TinAlloy)); + new UnificationEntry(OrePrefix.pipeSmall, Materials.TinAlloy)); ModHandler.addShapedRecipe(true, "steam_miner", MetaTileEntities.STEAM_MINER.getStackForm(), "DSD", "SMS", "GSG", 'M', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), 'S', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Bronze), 'D', + new UnificationEntry(OrePrefix.pipeNormal, Materials.Bronze), 'D', new UnificationEntry(OrePrefix.gem, Materials.Diamond), 'G', new UnificationEntry(OrePrefix.gearSmall, Materials.Bronze)); @@ -550,7 +550,7 @@ public static void init() { new UnificationEntry(OrePrefix.cableGtSingle, Materials.Gold)); ModHandler.addShapedRecipe(true, "distillation_tower", MetaTileEntities.DISTILLATION_TOWER.getStackForm(), "CBC", "FMF", "CBC", 'M', MetaTileEntities.HULL[GTValues.HV].getStackForm(), 'B', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.StainlessSteel), 'C', + new UnificationEntry(OrePrefix.pipeLarge, Materials.StainlessSteel), 'C', new UnificationEntry(OrePrefix.circuit, Tier.EV), 'F', MetaItems.ELECTRIC_PUMP_HV); ModHandler.addShapedRecipe(true, "cracking_unit", MetaTileEntities.CRACKER.getStackForm(), "CEC", "PHP", "CEC", 'C', MetaBlocks.WIRE_COIL.getItemVariant(CUPRONICKEL), 'E', MetaItems.ELECTRIC_PUMP_HV, 'P', @@ -578,13 +578,13 @@ public static void init() { ConfigHolder.recipes.casingsPerCraft), "PhP", "RFR", "PwP", 'R', new UnificationEntry(OrePrefix.rotor, Materials.Titanium), 'F', MetaBlocks.METAL_CASING.getItemVariant(TITANIUM_STABLE), 'P', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Titanium)); + new UnificationEntry(OrePrefix.pipeNormal, Materials.Titanium)); ModHandler.addShapedRecipe(true, "extreme_engine_intake_casing", MetaBlocks.MULTIBLOCK_CASING.getItemVariant(MultiblockCasingType.EXTREME_ENGINE_INTAKE_CASING, ConfigHolder.recipes.casingsPerCraft), "PhP", "RFR", "PwP", 'R', new UnificationEntry(OrePrefix.rotor, Materials.TungstenSteel), 'F', MetaBlocks.METAL_CASING.getItemVariant(TUNGSTENSTEEL_ROBUST), 'P', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.TungstenSteel)); + new UnificationEntry(OrePrefix.pipeNormal, Materials.TungstenSteel)); ModHandler.addShapedRecipe(true, "multi_furnace", MetaTileEntities.MULTI_FURNACE.getStackForm(), "PPP", "ASA", "CAC", 'P', Blocks.FURNACE, 'A', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.HV), 'S', MetaBlocks.METAL_CASING.getItemVariant(INVAR_HEATPROOF), 'C', @@ -594,17 +594,17 @@ public static void init() { "PSP", "SAS", "CSC", 'S', new UnificationEntry(OrePrefix.gear, Materials.Steel), 'P', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.HV), 'A', MetaTileEntities.HULL[GTValues.HV].getStackForm(), 'C', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Steel)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.Steel)); ModHandler.addShapedRecipe(true, "large_gas_turbine", MetaTileEntities.LARGE_GAS_TURBINE.getStackForm(), "PSP", "SAS", "CSC", 'S', new UnificationEntry(OrePrefix.gear, Materials.StainlessSteel), 'P', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.EV), 'A', MetaTileEntities.HULL[GTValues.EV].getStackForm(), 'C', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.StainlessSteel)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.StainlessSteel)); ModHandler.addShapedRecipe(true, "large_plasma_turbine", MetaTileEntities.LARGE_PLASMA_TURBINE.getStackForm(), "PSP", "SAS", "CSC", 'S', new UnificationEntry(OrePrefix.gear, Materials.TungstenSteel), 'P', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.LuV), 'A', MetaTileEntities.HULL[GTValues.LuV].getStackForm(), 'C', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.TungstenSteel)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.TungstenSteel)); ModHandler.addShapedRecipe(true, "large_bronze_boiler", MetaTileEntities.LARGE_BRONZE_BOILER.getStackForm(), "PSP", "SAS", "PSP", 'P', new UnificationEntry(OrePrefix.cableGtSingle, Materials.Tin), 'S', @@ -634,7 +634,7 @@ public static void init() { MetaTileEntities.LARGE_CHEMICAL_REACTOR.getStackForm(), "CRC", "PMP", "CHC", 'C', new UnificationEntry(OrePrefix.circuit, Tier.HV), 'R', OreDictUnifier.get(OrePrefix.rotor, Materials.StainlessSteel), 'P', - OreDictUnifier.get(OrePrefix.pipeLargeFluid, Materials.Polytetrafluoroethylene), 'M', + OreDictUnifier.get(OrePrefix.pipeLarge, Materials.Polytetrafluoroethylene), 'M', MetaItems.ELECTRIC_MOTOR_HV.getStackForm(), 'H', MetaTileEntities.HULL[GTValues.HV].getStackForm()); ModHandler.addShapedRecipe(true, "power_substation", MetaTileEntities.POWER_SUBSTATION.getStackForm(), "LPL", @@ -654,7 +654,7 @@ public static void init() { MetaBlocks.METAL_CASING.getItemVariant(STEEL_SOLID)); ModHandler.addShapedRecipe(true, "steam_hatch", MetaTileEntities.STEAM_HATCH.getStackForm(), "BPB", "BTB", "BPB", 'B', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'P', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Steel), 'T', + new UnificationEntry(OrePrefix.pipeNormal, Materials.Steel), 'T', MetaTileEntities.STEEL_DRUM.getStackForm()); ModHandler.addShapedRecipe(true, "steam_input_bus", MetaTileEntities.STEAM_IMPORT_BUS.getStackForm(), "C", "H", 'H', MetaBlocks.STEAM_CASING.getItemVariant(STEEL_HULL), 'C', OreDictNames.chestWood); @@ -672,7 +672,7 @@ public static void init() { MetaBlocks.METAL_CASING.getItemVariant(BRONZE_BRICKS)); ModHandler.addShapedRecipe(true, "steam_hatch", MetaTileEntities.STEAM_HATCH.getStackForm(), "BPB", "BTB", "BPB", 'B', new UnificationEntry(OrePrefix.plate, Materials.Bronze), 'P', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Bronze), 'T', + new UnificationEntry(OrePrefix.pipeNormal, Materials.Bronze), 'T', MetaTileEntities.BRONZE_DRUM.getStackForm()); ModHandler.addShapedRecipe(true, "steam_input_bus", MetaTileEntities.STEAM_IMPORT_BUS.getStackForm(), "C", "H", 'H', MetaBlocks.STEAM_CASING.getItemVariant(BRONZE_HULL), 'C', OreDictNames.chestWood); @@ -683,14 +683,14 @@ public static void init() { ModHandler.addShapedRecipe(true, "processing_array", MetaTileEntities.PROCESSING_ARRAY.getStackForm(), "COC", "RHR", "CPC", 'C', new UnificationEntry(OrePrefix.circuit, Tier.IV), 'O', MetaItems.TOOL_DATA_STICK.getStackForm(), 'R', MetaItems.ROBOT_ARM_EV.getStackForm(), 'P', - OreDictUnifier.get(OrePrefix.pipeLargeFluid, Materials.StainlessSteel), 'H', + OreDictUnifier.get(OrePrefix.pipeLarge, Materials.StainlessSteel), 'H', MetaTileEntities.HULL[GTValues.EV].getStackForm()); ModHandler.addShapedRecipe(true, "advanced_processing_array", MetaTileEntities.ADVANCED_PROCESSING_ARRAY.getStackForm(), "RCR", "SPE", "HNH", 'R', MetaItems.ROBOT_ARM_LuV, 'C', new UnificationEntry(OrePrefix.circuit, Tier.ZPM), 'S', MetaItems.SENSOR_LuV, 'P', MetaTileEntities.PROCESSING_ARRAY.getStackForm(), 'E', MetaItems.EMITTER_LuV, 'H', new UnificationEntry(OrePrefix.plate, Materials.HSSE), 'N', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Naquadah)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.Naquadah)); // GENERATORS ModHandler.addShapedRecipe(true, "diesel_generator_lv", MetaTileEntities.COMBUSTION_GENERATOR[0].getStackForm(), @@ -733,19 +733,19 @@ public static void init() { 'R', new UnificationEntry(OrePrefix.rotor, Materials.Tin), 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.LV), 'W', new UnificationEntry(OrePrefix.cableGtSingle, Materials.Tin), 'P', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Bronze)); + new UnificationEntry(OrePrefix.pipeNormal, Materials.Bronze)); ModHandler.addShapedRecipe(true, "steam_turbine_mv", MetaTileEntities.STEAM_TURBINE[1].getStackForm(), "PCP", "RMR", "EWE", 'M', MetaTileEntities.HULL[GTValues.MV].getStackForm(), 'E', MetaItems.ELECTRIC_MOTOR_MV, 'R', new UnificationEntry(OrePrefix.rotor, Materials.Bronze), 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.MV), 'W', new UnificationEntry(OrePrefix.cableGtSingle, Materials.Copper), 'P', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Steel)); + new UnificationEntry(OrePrefix.pipeNormal, Materials.Steel)); ModHandler.addShapedRecipe(true, "steam_turbine_hv", MetaTileEntities.STEAM_TURBINE[2].getStackForm(), "PCP", "RMR", "EWE", 'M', MetaTileEntities.HULL[GTValues.HV].getStackForm(), 'E', MetaItems.ELECTRIC_MOTOR_HV, 'R', new UnificationEntry(OrePrefix.rotor, Materials.Steel), 'C', new UnificationEntry(OrePrefix.circuit, MarkerMaterials.Tier.HV), 'W', new UnificationEntry(OrePrefix.cableGtSingle, Materials.Gold), 'P', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.StainlessSteel)); + new UnificationEntry(OrePrefix.pipeNormal, Materials.StainlessSteel)); ModHandler.addShapedRecipe(true, "workbench_bronze", MetaTileEntities.WORKBENCH.getStackForm(), "CSC", "PWP", "PsP", 'C', OreDictNames.chestWood, 'W', new ItemStack(Blocks.CRAFTING_TABLE), 'S', @@ -758,12 +758,12 @@ public static void init() { ModHandler.addShapedRecipe(true, "primitive_pump", MetaTileEntities.PRIMITIVE_WATER_PUMP.getStackForm(), "RGS", "OWd", "CLC", 'R', new UnificationEntry(OrePrefix.ring, Materials.Iron), 'G', - new UnificationEntry(OrePrefix.pipeNormalFluid, Materials.Wood), 'S', + new UnificationEntry(OrePrefix.pipeNormal, Materials.Wood), 'S', new UnificationEntry(OrePrefix.screw, Materials.Iron), 'O', new UnificationEntry(OrePrefix.rotor, Materials.Iron), 'W', MetaBlocks.PLANKS.getItemVariant(BlockGregPlanks.BlockType.TREATED_PLANK), 'C', new ItemStack(Blocks.STONE_SLAB, 1, 3), 'L', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Wood)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.Wood)); ModHandler.addShapedRecipe(true, "pump_deck", MetaBlocks.STEAM_CASING.getItemVariant(PUMP_DECK, 2), "SWS", "dCh", 'S', new UnificationEntry(OrePrefix.screw, Materials.Iron), 'W', MetaBlocks.PLANKS.getItemVariant(BlockGregPlanks.BlockType.TREATED_PLANK), 'C', @@ -772,7 +772,7 @@ public static void init() { "CRC", 'S', new UnificationEntry(OrePrefix.screw, Materials.Iron), 'R', new UnificationEntry(OrePrefix.ring, Materials.Iron), 'P', MetaBlocks.PLANKS.getItemVariant(BlockGregPlanks.BlockType.TREATED_PLANK), 'L', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Wood), 'C', + new UnificationEntry(OrePrefix.pipeLarge, Materials.Wood), 'C', new ItemStack(Blocks.STONE_SLAB, 1, 3)); ModHandler.addShapedRecipe(true, "wood_multiblock_tank", MetaTileEntities.WOODEN_TANK.getStackForm(), " R ", @@ -975,31 +975,31 @@ public static void init() { // Hermetic Casings ModHandler.addShapedRecipe(true, "hermetic_casing_lv", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_LV), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Steel), 'F', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Polyethylene)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.Polyethylene)); ModHandler.addShapedRecipe(true, "hermetic_casing_mv", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_MV), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Aluminium), 'F', - new UnificationEntry(OrePrefix.pipeLargeItem, Materials.PolyvinylChloride)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.PolyvinylChloride)); ModHandler.addShapedRecipe(true, "hermetic_casing_hv", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_HV), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.StainlessSteel), 'F', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Polytetrafluoroethylene)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.Polytetrafluoroethylene)); ModHandler.addShapedRecipe(true, "hermetic_casing_ev", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_EV), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Titanium), 'F', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.StainlessSteel)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.StainlessSteel)); ModHandler.addShapedRecipe(true, "hermetic_casing_iv", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_IV), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.TungstenSteel), 'F', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Titanium)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.Titanium)); ModHandler.addShapedRecipe(true, "hermetic_casing_luv", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_LUV), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.RhodiumPlatedPalladium), 'F', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.TungstenSteel)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.TungstenSteel)); ModHandler.addShapedRecipe(true, "hermetic_casing_zpm", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_ZPM), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.NaquadahAlloy), 'F', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.NiobiumTitanium)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.NiobiumTitanium)); ModHandler.addShapedRecipe(true, "hermetic_casing_uv", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_UV), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Darmstadtium), 'F', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Naquadah)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.Naquadah)); ModHandler.addShapedRecipe(true, "hermetic_casing_max", MetaBlocks.HERMETIC_CASING.getItemVariant(HERMETIC_UHV), "PPP", "PFP", "PPP", 'P', new UnificationEntry(OrePrefix.plate, Materials.Neutronium), 'F', - new UnificationEntry(OrePrefix.pipeLargeFluid, Materials.Duranium)); + new UnificationEntry(OrePrefix.pipeLarge, Materials.Duranium)); // Super / Quantum Chests ModHandler.addShapedRecipe(true, "super_chest_lv", MetaTileEntities.QUANTUM_CHEST[0].getStackForm(), "CPC", diff --git a/src/main/java/gregtech/loaders/recipe/MetaTileEntityMachineRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MetaTileEntityMachineRecipeLoader.java index 39e12fe8af3..4d0551eed87 100644 --- a/src/main/java/gregtech/loaders/recipe/MetaTileEntityMachineRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MetaTileEntityMachineRecipeLoader.java @@ -44,7 +44,7 @@ public static void init() { // Quadruple Fluid Input Hatches ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[EV]) - .input(pipeQuadrupleFluid, Titanium) + .input(pipeQuadruple, Titanium) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_IMPORT_HATCH[0]) @@ -52,7 +52,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[IV]) - .input(pipeQuadrupleFluid, TungstenSteel) + .input(pipeQuadruple, TungstenSteel) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_IMPORT_HATCH[1]) @@ -60,7 +60,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[LuV]) - .input(pipeQuadrupleFluid, NiobiumTitanium) + .input(pipeQuadruple, NiobiumTitanium) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_IMPORT_HATCH[2]) @@ -68,7 +68,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[ZPM]) - .input(pipeQuadrupleFluid, Iridium) + .input(pipeQuadruple, Iridium) .fluidInputs(Polybenzimidazole.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_IMPORT_HATCH[3]) @@ -76,7 +76,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[UV]) - .input(pipeQuadrupleFluid, Naquadah) + .input(pipeQuadruple, Naquadah) .fluidInputs(Polybenzimidazole.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_IMPORT_HATCH[4]) @@ -84,7 +84,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[UHV]) - .input(pipeQuadrupleFluid, Neutronium) + .input(pipeQuadruple, Neutronium) .fluidInputs(Polybenzimidazole.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_IMPORT_HATCH[5]) @@ -93,7 +93,7 @@ public static void init() { // Nonuple Fluid Input Hatches ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[EV]) - .input(pipeNonupleFluid, Titanium) + .input(pipeNonuple, Titanium) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_IMPORT_HATCH[0]) @@ -101,7 +101,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[IV]) - .input(pipeNonupleFluid, TungstenSteel) + .input(pipeNonuple, TungstenSteel) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_IMPORT_HATCH[1]) @@ -109,7 +109,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[LuV]) - .input(pipeNonupleFluid, NiobiumTitanium) + .input(pipeNonuple, NiobiumTitanium) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_IMPORT_HATCH[2]) @@ -117,7 +117,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[ZPM]) - .input(pipeNonupleFluid, Iridium) + .input(pipeNonuple, Iridium) .fluidInputs(Polybenzimidazole.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_IMPORT_HATCH[3]) @@ -125,7 +125,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[UV]) - .input(pipeNonupleFluid, Naquadah) + .input(pipeNonuple, Naquadah) .fluidInputs(Polybenzimidazole.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_IMPORT_HATCH[4]) @@ -133,7 +133,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_IMPORT_HATCH[UHV]) - .input(pipeNonupleFluid, Neutronium) + .input(pipeNonuple, Neutronium) .fluidInputs(Polybenzimidazole.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_IMPORT_HATCH[5]) @@ -142,7 +142,7 @@ public static void init() { // Quadruple Fluid Output Hatches ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[EV]) - .input(pipeQuadrupleFluid, Titanium) + .input(pipeQuadruple, Titanium) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_EXPORT_HATCH[0]) @@ -150,7 +150,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[IV]) - .input(pipeQuadrupleFluid, TungstenSteel) + .input(pipeQuadruple, TungstenSteel) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_EXPORT_HATCH[1]) @@ -158,7 +158,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[LuV]) - .input(pipeQuadrupleFluid, NiobiumTitanium) + .input(pipeQuadruple, NiobiumTitanium) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_EXPORT_HATCH[2]) @@ -166,7 +166,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[ZPM]) - .input(pipeQuadrupleFluid, Iridium) + .input(pipeQuadruple, Iridium) .fluidInputs(Polybenzimidazole.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_EXPORT_HATCH[3]) @@ -174,7 +174,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[UV]) - .input(pipeQuadrupleFluid, Naquadah) + .input(pipeQuadruple, Naquadah) .fluidInputs(Polybenzimidazole.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_EXPORT_HATCH[4]) @@ -182,7 +182,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[UHV]) - .input(pipeQuadrupleFluid, Neutronium) + .input(pipeQuadruple, Neutronium) .fluidInputs(Polybenzimidazole.getFluid(L * 4)) .circuitMeta(4) .output(QUADRUPLE_EXPORT_HATCH[5]) @@ -191,7 +191,7 @@ public static void init() { // Nonuple Fluid Output Hatches ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[EV]) - .input(pipeNonupleFluid, Titanium) + .input(pipeNonuple, Titanium) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_EXPORT_HATCH[0]) @@ -199,7 +199,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[IV]) - .input(pipeNonupleFluid, TungstenSteel) + .input(pipeNonuple, TungstenSteel) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_EXPORT_HATCH[1]) @@ -207,7 +207,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[LuV]) - .input(pipeNonupleFluid, NiobiumTitanium) + .input(pipeNonuple, NiobiumTitanium) .fluidInputs(Polytetrafluoroethylene.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_EXPORT_HATCH[2]) @@ -215,7 +215,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[ZPM]) - .input(pipeNonupleFluid, Iridium) + .input(pipeNonuple, Iridium) .fluidInputs(Polybenzimidazole.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_EXPORT_HATCH[3]) @@ -223,7 +223,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[UV]) - .input(pipeNonupleFluid, Naquadah) + .input(pipeNonuple, Naquadah) .fluidInputs(Polybenzimidazole.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_EXPORT_HATCH[4]) @@ -231,7 +231,7 @@ public static void init() { ASSEMBLER_RECIPES.recipeBuilder() .input(FLUID_EXPORT_HATCH[UHV]) - .input(pipeNonupleFluid, Neutronium) + .input(pipeNonuple, Neutronium) .fluidInputs(Polybenzimidazole.getFluid(L * 9)) .circuitMeta(9) .output(NONUPLE_EXPORT_HATCH[5]) @@ -957,7 +957,7 @@ public static void init() { // Long Distance Pipes ASSEMBLER_RECIPES.recipeBuilder() - .input(pipeLargeItem, Tin, 2) + .input(pipeLarge, Tin, 2) .input(plate, Steel, 8) .input(gear, Steel, 2) .circuitMeta(1) @@ -966,7 +966,7 @@ public static void init() { .duration(400).EUt(16).buildAndRegister(); ASSEMBLER_RECIPES.recipeBuilder() - .input(pipeLargeFluid, Bronze, 2) + .input(pipeLarge, Bronze, 2) .input(plate, Steel, 8) .input(gear, Steel, 2) .circuitMeta(1) @@ -975,7 +975,7 @@ public static void init() { .duration(400).EUt(16).buildAndRegister(); ASSEMBLER_RECIPES.recipeBuilder() - .input(pipeLargeItem, Tin, 2) + .input(pipeLarge, Tin, 2) .input(plate, Steel, 8) .circuitMeta(2) .fluidInputs(SolderingAlloy.getFluid(L / 2)) @@ -983,7 +983,7 @@ public static void init() { .duration(600).EUt(24).buildAndRegister(); ASSEMBLER_RECIPES.recipeBuilder() - .input(pipeLargeFluid, Bronze, 2) + .input(pipeLarge, Bronze, 2) .input(plate, Steel, 8) .circuitMeta(2) .fluidInputs(SolderingAlloy.getFluid(L / 2)) diff --git a/src/main/java/gregtech/loaders/recipe/chemistry/AssemblerRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/chemistry/AssemblerRecipeLoader.java index 44be226b0c8..615416a68c7 100644 --- a/src/main/java/gregtech/loaders/recipe/chemistry/AssemblerRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/chemistry/AssemblerRecipeLoader.java @@ -64,14 +64,14 @@ public static void init() { // Other ASSEMBLER_RECIPES.recipeBuilder() .input(rotor, Titanium, 2) - .input(pipeNormalFluid, Titanium, 4) + .input(pipeNormal, Titanium, 4) .inputs(METAL_CASING.getItemVariant(TITANIUM_STABLE)) .outputs(MULTIBLOCK_CASING.getItemVariant(ENGINE_INTAKE_CASING, ConfigHolder.recipes.casingsPerCraft)) .duration(50).EUt(16).buildAndRegister(); ASSEMBLER_RECIPES.recipeBuilder() .input(rotor, TungstenSteel, 2) - .input(pipeNormalFluid, TungstenSteel, 4) + .input(pipeNormal, TungstenSteel, 4) .inputs(METAL_CASING.getItemVariant(TUNGSTENSTEEL_ROBUST)) .outputs(MULTIBLOCK_CASING.getItemVariant(EXTREME_ENGINE_INTAKE_CASING, ConfigHolder.recipes.casingsPerCraft)) diff --git a/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java index f9c9c1828c0..a90eaf14d9d 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java @@ -19,7 +19,7 @@ import gregtech.common.items.MetaItems; import gregtech.common.items.behaviors.AbstractMaterialPartBehavior; -import gregtech.common.pipelike.handlers.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; import net.minecraft.item.EnumDyeColor; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java index bd58e4263e8..54e271d2b09 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java @@ -5,63 +5,62 @@ import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; -import gregtech.api.unification.material.properties.FluidPipeProperties; -import gregtech.api.unification.material.properties.IMaterialProperty; -import gregtech.api.unification.material.properties.ItemPipeProperties; +import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.unification.ore.IOreRegistrationHandler; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.unification.stack.UnificationEntry; import gregtech.api.util.GTUtility; import gregtech.common.items.MetaItems; +import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; + +import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; + import net.minecraft.item.ItemStack; import com.google.common.base.CaseFormat; +import java.util.function.BiConsumer; + import static gregtech.api.GTValues.*; import static gregtech.api.recipes.RecipeMaps.ASSEMBLER_RECIPES; import static gregtech.api.unification.material.Materials.Glue; import static gregtech.api.unification.material.info.MaterialFlags.NO_SMASHING; +import static gregtech.api.unification.material.info.MaterialFlags.NO_UNIFICATION; import static gregtech.api.unification.ore.OrePrefix.plate; import static gregtech.api.unification.ore.OrePrefix.plateDouble; public class PipeRecipeHandler { public static void register() { - OrePrefix.pipeTinyFluid.addProcessingHandler(PropertyKey.FLUID_PIPE, PipeRecipeHandler::processPipeTiny); - OrePrefix.pipeSmallFluid.addProcessingHandler(PropertyKey.FLUID_PIPE, PipeRecipeHandler::processPipeSmall); - OrePrefix.pipeNormalFluid.addProcessingHandler(PropertyKey.FLUID_PIPE, PipeRecipeHandler::processPipeNormal); - OrePrefix.pipeLargeFluid.addProcessingHandler(PropertyKey.FLUID_PIPE, PipeRecipeHandler::processPipeLarge); - OrePrefix.pipeHugeFluid.addProcessingHandler(PropertyKey.FLUID_PIPE, PipeRecipeHandler::processPipeHuge); - - OrePrefix.pipeQuadrupleFluid.addProcessingHandler(PropertyKey.FLUID_PIPE, - PipeRecipeHandler::processPipeQuadruple); - OrePrefix.pipeNonupleFluid.addProcessingHandler(PropertyKey.FLUID_PIPE, PipeRecipeHandler::processPipeNonuple); - - OrePrefix.pipeTinyItem.addProcessingHandler(PropertyKey.ITEM_PIPE, PipeRecipeHandler::processPipeTiny); - OrePrefix.pipeSmallItem.addProcessingHandler(PropertyKey.ITEM_PIPE, PipeRecipeHandler::processPipeSmall); - OrePrefix.pipeNormalItem.addProcessingHandler(PropertyKey.ITEM_PIPE, PipeRecipeHandler::processPipeNormal); - OrePrefix.pipeLargeItem.addProcessingHandler(PropertyKey.ITEM_PIPE, PipeRecipeHandler::processPipeLarge); - OrePrefix.pipeHugeItem.addProcessingHandler(PropertyKey.ITEM_PIPE, PipeRecipeHandler::processPipeHuge); - - OrePrefix.pipeSmallRestrictive.addProcessingHandler(PropertyKey.ITEM_PIPE, - PipeRecipeHandler::processRestrictivePipe); - OrePrefix.pipeNormalRestrictive.addProcessingHandler(PropertyKey.ITEM_PIPE, - PipeRecipeHandler::processRestrictivePipe); - OrePrefix.pipeLargeRestrictive.addProcessingHandler(PropertyKey.ITEM_PIPE, - PipeRecipeHandler::processRestrictivePipe); - OrePrefix.pipeHugeRestrictive.addProcessingHandler(PropertyKey.ITEM_PIPE, - PipeRecipeHandler::processRestrictivePipe); + processStandard(OrePrefix.pipeTiny, OrePrefix.pipeTinyRestrictive, PipeRecipeHandler::processPipeTiny); + processStandard(OrePrefix.pipeSmall, OrePrefix.pipeSmallRestrictive, PipeRecipeHandler::processPipeSmall); + processStandard(OrePrefix.pipeNormal, OrePrefix.pipeNormalRestrictive, PipeRecipeHandler::processPipeNormal); + processStandard(OrePrefix.pipeLarge, OrePrefix.pipeLargeRestrictive, PipeRecipeHandler::processPipeLarge); + processStandard(OrePrefix.pipeHuge, OrePrefix.pipeHugeRestrictive, PipeRecipeHandler::processPipeHuge); + processStandard(OrePrefix.pipeQuadruple, OrePrefix.pipeQuadrupleRestrictive, PipeRecipeHandler::processPipeQuadruple); + processStandard(OrePrefix.pipeNonuple, OrePrefix.pipeNonupleRestrictive, PipeRecipeHandler::processPipeNonuple); } - private static void processRestrictivePipe(OrePrefix pipePrefix, Material material, ItemPipeProperties property) { - OrePrefix unrestrictive; - if (pipePrefix == OrePrefix.pipeSmallRestrictive) unrestrictive = OrePrefix.pipeSmallItem; - else if (pipePrefix == OrePrefix.pipeNormalRestrictive) unrestrictive = OrePrefix.pipeNormalItem; - else if (pipePrefix == OrePrefix.pipeLargeRestrictive) unrestrictive = OrePrefix.pipeLargeItem; - else if (pipePrefix == OrePrefix.pipeHugeRestrictive) unrestrictive = OrePrefix.pipeHugeItem; - else return; + private static void processStandard(OrePrefix pipePrefix, OrePrefix restrictivePrefix, BiConsumer processor) { + pipePrefix.addProcessingHandler(registrationHandler(processor)); + restrictivePrefix.addProcessingHandler(registrationHandler((o, m) -> processRestrictivePipe(o, m, pipePrefix))); + } + + public static IOreRegistrationHandler registrationHandler( + BiConsumer handler) { + return (orePrefix, material) -> { + if (material.hasFlag(NO_UNIFICATION)) return; + PipeNetProperties properties = material.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (properties != null && (properties.hasProperty(MaterialFluidProperties.KEY) || + properties.hasProperty(MaterialItemProperties.KEY))) { + handler.accept(orePrefix, material); + } + }; + } + private static void processRestrictivePipe(OrePrefix pipePrefix, Material material, OrePrefix unrestrictive) { RecipeMaps.ASSEMBLER_RECIPES.recipeBuilder() .input(unrestrictive, material) .input(OrePrefix.ring, Materials.Iron, 2) @@ -78,7 +77,7 @@ private static void processRestrictivePipe(OrePrefix pipePrefix, Material materi OreDictUnifier.get(OrePrefix.ring, Materials.Iron)); } - private static void processPipeTiny(OrePrefix pipePrefix, Material material, IMaterialProperty property) { + private static void processPipeTiny(OrePrefix pipePrefix, Material material) { ItemStack pipeStack = OreDictUnifier.get(pipePrefix, material); // Some pipes like wood do not have an ingot @@ -120,7 +119,7 @@ private static void processPipeTiny(OrePrefix pipePrefix, Material material, IMa } } - private static void processPipeSmall(OrePrefix pipePrefix, Material material, IMaterialProperty property) { + private static void processPipeSmall(OrePrefix pipePrefix, Material material) { ItemStack pipeStack = OreDictUnifier.get(pipePrefix, material); if (material.hasProperty(PropertyKey.INGOT)) { @@ -162,7 +161,7 @@ private static void processPipeSmall(OrePrefix pipePrefix, Material material, IM } } - private static void processPipeNormal(OrePrefix pipePrefix, Material material, IMaterialProperty property) { + private static void processPipeNormal(OrePrefix pipePrefix, Material material) { ItemStack pipeStack = OreDictUnifier.get(pipePrefix, material); if (material.hasProperty(PropertyKey.INGOT)) { @@ -204,7 +203,7 @@ private static void processPipeNormal(OrePrefix pipePrefix, Material material, I } } - private static void processPipeLarge(OrePrefix pipePrefix, Material material, IMaterialProperty property) { + private static void processPipeLarge(OrePrefix pipePrefix, Material material) { ItemStack pipeStack = OreDictUnifier.get(pipePrefix, material); if (material.hasProperty(PropertyKey.INGOT)) { @@ -245,7 +244,7 @@ private static void processPipeLarge(OrePrefix pipePrefix, Material material, IM } } - private static void processPipeHuge(OrePrefix pipePrefix, Material material, IMaterialProperty property) { + private static void processPipeHuge(OrePrefix pipePrefix, Material material) { ItemStack pipeStack = OreDictUnifier.get(pipePrefix, material); if (material.hasProperty(PropertyKey.INGOT)) { @@ -286,8 +285,9 @@ private static void processPipeHuge(OrePrefix pipePrefix, Material material, IMa } } - private static void processPipeQuadruple(OrePrefix pipePrefix, Material material, FluidPipeProperties property) { - ItemStack smallPipe = OreDictUnifier.get(OrePrefix.pipeSmallFluid, material); + private static void processPipeQuadruple(OrePrefix pipePrefix, Material material) { + // TODO should quadruple pipes be mode of normal pipes instead? + ItemStack smallPipe = OreDictUnifier.get(OrePrefix.pipeSmall, material); ItemStack quadPipe = OreDictUnifier.get(pipePrefix, material); ModHandler.addShapedRecipe(String.format("quadruple_%s_pipe", material.toString()), quadPipe, "XX", "XX", @@ -302,8 +302,8 @@ private static void processPipeQuadruple(OrePrefix pipePrefix, Material material .buildAndRegister(); } - private static void processPipeNonuple(OrePrefix pipePrefix, Material material, FluidPipeProperties property) { - ItemStack smallPipe = OreDictUnifier.get(OrePrefix.pipeSmallFluid, material); + private static void processPipeNonuple(OrePrefix pipePrefix, Material material) { + ItemStack smallPipe = OreDictUnifier.get(OrePrefix.pipeSmall, material); ItemStack nonuplePipe = OreDictUnifier.get(pipePrefix, material); ModHandler.addShapedRecipe(String.format("nonuple_%s_pipe", material.toString()), nonuplePipe, "XXX", "XXX", "XXX", diff --git a/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java index db16e5dafce..8ce9a432e08 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java @@ -10,7 +10,7 @@ import com.google.common.collect.ImmutableMap; -import gregtech.common.pipelike.handlers.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; import org.apache.commons.lang3.ArrayUtils; diff --git a/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java index 90ffd7957e3..44e4d3767eb 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java @@ -12,7 +12,7 @@ import com.google.common.collect.ImmutableMap; -import gregtech.common.pipelike.handlers.MaterialEnergyProperties; +import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; import java.util.Map; diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 78cbaeb9f2d..19210c952b4 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -5565,10 +5565,10 @@ gregtech.cable.superconductor=§d%s Superconductor gregtech.fluid_pipe.capacity=§9Capacity: §f%,d L gregtech.fluid_pipe.max_temperature=§cTemperature Limit: §f%,d K +gregtech.fluid_pipe.min_temperature=§6Can handle fluids below §f%,d K gregtech.fluid_pipe.channels=§eChannels: §f%d gregtech.fluid_pipe.gas_proof=§6Can handle Gases gregtech.fluid_pipe.acid_proof=§6Can handle Acids -gregtech.fluid_pipe.cryo_proof=§6Can handle Cryogenics gregtech.fluid_pipe.plasma_proof=§6Can handle all Plasmas gregtech.fluid_pipe.not_gas_proof=§4Gases may leak! From dab9fbfbe6d0a8b37460087bcb033eb501ca77c6 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 27 Jul 2024 20:33:45 -0600 Subject: [PATCH 081/157] Compilable edition --- .../api/block/machines/BlockMachine.java | 2 +- .../api/block/machines/MachineItemBlock.java | 15 +- .../gregtech/api/cover/CoverRayTracer.java | 8 +- .../pipenet/logic/TemperatureLogic.java | 5 +- .../pipenet/physical/IPipeStructure.java | 2 +- .../pipenet/physical/block/ItemPipeBlock.java | 1 + .../physical/block/WorldPipeBlock.java | 15 +- .../pipenet/physical/tile/PipeTileEntity.java | 7 +- .../api/graphnet/pipenetold/IPipeNetData.java | 15 - .../graphnet/pipenetold/IPipeNetHandler.java | 30 - .../api/graphnet/pipenetold/NetPath.java | 4 - .../graphnet/pipenetold/NodeLossResult.java | 20 - .../api/graphnet/pipenetold/PipeNetNode.java | 269 ------- .../api/graphnet/pipenetold/PipeNetPath.java | 117 --- .../graphnet/pipenetold/WorldPipeNetBase.java | 419 ----------- .../pipenetold/WorldPipeNetComplex.java | 52 -- .../pipenetold/WorldPipeNetSimple.java | 45 -- .../graphnet/pipenetold/block/BlockPipe.java | 680 ------------------ .../graphnet/pipenetold/block/IPipeType.java | 14 - .../pipenetold/block/ItemBlockPipe.java | 64 -- .../block/material/BlockMaterialPipe.java | 116 --- .../block/material/IMaterialPipeTile.java | 14 - .../block/material/IMaterialPipeType.java | 16 - .../block/material/ItemBlockMaterialPipe.java | 26 - .../material/TileEntityMaterialPipeBase.java | 109 --- .../block/simple/BlockSimplePipe.java | 44 -- .../longdist/LongDistanceNetwork.java | 11 +- .../predicate/FilteredEdgePredicate.java | 73 -- .../predicate/IShutteredEdgePredicate.java | 8 - .../predicate/ShutteredEdgePredicate.java | 50 -- .../graphnet/pipenetold/tile/IPipeTile.java | 111 --- .../tile/PipeCoverableImplementation.java | 300 -------- .../pipenetold/tile/TileEntityPipeBase.java | 617 ---------------- .../multiblock/MultiblockControllerBase.java | 6 +- .../java/gregtech/api/util/GTStringUtils.java | 8 +- .../renderer/pipeold/CableRenderer.java | 109 --- .../renderer/pipeold/FluidPipeRenderer.java | 69 -- .../renderer/pipeold/ItemPipeRenderer.java | 58 -- .../renderer/pipeold/LaserPipeRenderer.java | 103 --- .../renderer/pipeold/OpticalPipeRenderer.java | 57 -- .../client/renderer/pipeold/PipeRenderer.java | 577 --------------- .../client/utils/FacadeBlockAccess.java | 3 +- .../java/gregtech/common/CommonProxy.java | 10 - .../java/gregtech/common/EventHandlers.java | 4 +- .../gregtech/common/ToolEventHandlers.java | 19 +- .../gregtech/common/blocks/BlockFrame.java | 50 +- .../gregtech/common/blocks/MetaBlocks.java | 4 - .../common/command/CommandRecipeCheck.java | 45 +- .../gregtech/common/covers/CoverConveyor.java | 9 - .../common/covers/CoverRoboticArm.java | 17 +- .../gui/widget/monitor/WidgetCoverList.java | 4 +- .../items/behaviors/ColorSprayBehaviour.java | 6 +- .../items/behaviors/TricorderBehavior.java | 15 +- .../MetaTileEntityWorldAccelerator.java | 4 +- .../MetaTileEntityMonitorScreen.java | 6 +- .../MetaTileEntityComputationHatch.java | 1 - .../MetaTileEntityOpticalDataHatch.java | 1 - .../net/energy/EnergyCapabilityObject.java | 1 + .../net/fluid/FluidCapabilityObject.java | 3 - .../common/pipelikeold/cable/BlockCable.java | 204 ------ .../common/pipelikeold/cable/Insulation.java | 76 -- .../pipelikeold/cable/ItemBlockCable.java | 55 -- .../cable/net/EnergyNetHandler.java | 372 ---------- .../pipelikeold/cable/net/WorldEnergyNet.java | 75 -- .../cable/tile/AveragingPerTickCounter.java | 91 --- .../cable/tile/PerTickLongCounter.java | 58 -- .../cable/tile/TileEntityCable.java | 320 --------- .../cable/tile/TileEntityCableTickable.java | 18 - .../pipelikeold/fluidpipe/BlockFluidPipe.java | 184 ----- .../pipelikeold/fluidpipe/FluidPipeType.java | 74 -- .../fluidpipe/ItemBlockFluidPipe.java | 53 -- .../fluidpipe/net/FluidEdgePredicate.java | 38 - .../fluidpipe/net/FluidNetHandler.java | 287 -------- .../fluidpipe/net/WorldFluidPipeNet.java | 91 --- .../fluidpipe/tile/TileEntityFluidPipe.java | 205 ------ .../tile/TileEntityFluidPipeTickable.java | 16 - .../pipelikeold/itempipe/BlockItemPipe.java | 136 ---- .../itempipe/ItemBlockItemPipe.java | 55 -- .../pipelikeold/itempipe/ItemPipeType.java | 78 -- .../itempipe/net/ItemEdgePredicate.java | 38 - .../itempipe/net/ItemNetHandler.java | 518 ------------- .../itempipe/net/WorldItemPipeNet.java | 86 --- .../itempipe/tile/TileEntityItemPipe.java | 121 ---- .../tile/TileEntityItemPipeTickable.java | 16 - .../pipelikeold/laser/BlockLaserPipe.java | 151 ---- .../pipelikeold/laser/ItemBlockLaserPipe.java | 36 - .../laser/LaserPipeProperties.java | 15 - .../pipelikeold/laser/LaserPipeType.java | 30 - .../laser/net/LaserNetHandler.java | 131 ---- .../laser/net/WorldLaserPipeNet.java | 53 -- .../laser/tile/TileEntityLaserPipe.java | 232 ------ .../pipelikeold/optical/BlockOpticalPipe.java | 144 ---- .../optical/ItemBlockOpticalPipe.java | 34 - .../optical/OpticalPipeProperties.java | 15 - .../pipelikeold/optical/OpticalPipeType.java | 31 - .../optical/net/OpticalNetHandler.java | 149 ---- .../optical/net/WorldOpticalPipeNet.java | 54 -- .../optical/tile/TileEntityOpticalPipe.java | 187 ----- .../integration/RecipeCompatUtil.java | 9 +- .../recipe/MetaItemBracketHandler.java | 3 - .../groovy/GroovyScriptModule.java | 3 - .../debug/DebugPipeNetInfoProvider.java | 5 - 102 files changed, 115 insertions(+), 8900 deletions(-) delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetData.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetHandler.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/NetPath.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/NodeLossResult.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/PipeNetNode.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/PipeNetPath.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetComplex.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetSimple.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/block/BlockPipe.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/block/IPipeType.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/block/ItemBlockPipe.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/block/material/BlockMaterialPipe.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeTile.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeType.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/block/material/ItemBlockMaterialPipe.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/block/material/TileEntityMaterialPipeBase.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/block/simple/BlockSimplePipe.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/predicate/FilteredEdgePredicate.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/predicate/IShutteredEdgePredicate.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/predicate/ShutteredEdgePredicate.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/tile/IPipeTile.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/tile/PipeCoverableImplementation.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java delete mode 100644 src/main/java/gregtech/client/renderer/pipeold/CableRenderer.java delete mode 100644 src/main/java/gregtech/client/renderer/pipeold/FluidPipeRenderer.java delete mode 100644 src/main/java/gregtech/client/renderer/pipeold/ItemPipeRenderer.java delete mode 100644 src/main/java/gregtech/client/renderer/pipeold/LaserPipeRenderer.java delete mode 100644 src/main/java/gregtech/client/renderer/pipeold/OpticalPipeRenderer.java delete mode 100644 src/main/java/gregtech/client/renderer/pipeold/PipeRenderer.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/cable/Insulation.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/cable/ItemBlockCable.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/cable/net/WorldEnergyNet.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/cable/tile/AveragingPerTickCounter.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/cable/tile/PerTickLongCounter.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCable.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCableTickable.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/fluidpipe/FluidPipeType.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/fluidpipe/ItemBlockFluidPipe.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidEdgePredicate.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/fluidpipe/net/WorldFluidPipeNet.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipe.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipeTickable.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/itempipe/ItemBlockItemPipe.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/itempipe/ItemPipeType.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemEdgePredicate.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemNetHandler.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/itempipe/net/WorldItemPipeNet.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipe.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipeTickable.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/laser/BlockLaserPipe.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/laser/ItemBlockLaserPipe.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/laser/LaserPipeProperties.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/laser/LaserPipeType.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/laser/net/LaserNetHandler.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/laser/net/WorldLaserPipeNet.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/laser/tile/TileEntityLaserPipe.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/optical/BlockOpticalPipe.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/optical/ItemBlockOpticalPipe.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeProperties.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeType.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/optical/net/OpticalNetHandler.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/optical/net/WorldOpticalPipeNet.java delete mode 100644 src/main/java/gregtech/common/pipelikeold/optical/tile/TileEntityOpticalPipe.java diff --git a/src/main/java/gregtech/api/block/machines/BlockMachine.java b/src/main/java/gregtech/api/block/machines/BlockMachine.java index bf6ad133c20..6941bc2e53a 100644 --- a/src/main/java/gregtech/api/block/machines/BlockMachine.java +++ b/src/main/java/gregtech/api/block/machines/BlockMachine.java @@ -6,13 +6,13 @@ import gregtech.api.block.UnlistedStringProperty; import gregtech.api.cover.Cover; import gregtech.api.cover.IFacadeCover; +import gregtech.api.graphnet.pipenetold.IBlockAppearance; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; -import gregtech.api.graphnet.pipenetold.IBlockAppearance; import gregtech.api.util.GTUtility; import gregtech.api.util.Mods; import gregtech.client.renderer.handler.MetaTileEntityRenderer; diff --git a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java index cd4a76b33ac..09337217886 100644 --- a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java +++ b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java @@ -2,9 +2,9 @@ import gregtech.api.GTValues; import gregtech.api.GregTechAPI; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.metatileentity.ITieredMetaTileEntity; import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; import gregtech.api.util.GTUtility; import gregtech.api.util.LocalizationUtils; import gregtech.client.utils.TooltipHelper; @@ -20,6 +20,7 @@ import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; @@ -90,18 +91,8 @@ public boolean placeBlockAt(@NotNull ItemStack stack, @NotNull EntityPlayer play MetaTileEntity metaTileEntity = GTUtility.getMetaTileEntity(stack); // prevent rendering glitch before meta tile entity sync to client, but after block placement // set opaque property on the placing on block, instead during set of meta tile entity - boolean superVal = super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, + return super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, newState.withProperty(BlockMachine.OPAQUE, metaTileEntity == null || metaTileEntity.isOpaqueCube())); - if (superVal && !world.isRemote) { - BlockPos possiblePipe = pos.offset(side.getOpposite()); - Block block = world.getBlockState(possiblePipe).getBlock(); - if (block instanceof BlockPipepipe) { - if (pipe.canPipeConnectToBlock(world, possiblePipe, side.getOpposite(), world.getTileEntity(pos))) { - pipe.getPipeTileEntity(world, possiblePipe).setConnection(side, true, false); - } - } - } - return superVal; } @Nullable diff --git a/src/main/java/gregtech/api/cover/CoverRayTracer.java b/src/main/java/gregtech/api/cover/CoverRayTracer.java index ef9ec827ef6..b35ad4ec4b7 100644 --- a/src/main/java/gregtech/api/cover/CoverRayTracer.java +++ b/src/main/java/gregtech/api/cover/CoverRayTracer.java @@ -1,6 +1,6 @@ package gregtech.api.cover; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.util.GTUtility; import net.minecraft.entity.player.EntityPlayer; @@ -20,8 +20,8 @@ private CoverRayTracer() {} @NotNull EntityPlayer player) { // if the coverable view is from a blockpipe, use the proper raytrace method RayTraceResult result = coverableView.getWorld().getBlockState(coverableView.getPos()) - .getBlock() instanceof BlockPipepipe ? - pipe.getServerCollisionRayTrace(player, coverableView.getPos(), coverableView.getWorld()) : + .getBlock() instanceof WorldPipeBlock pipe ? + pipe.collisionRayTrace(player, coverableView.getWorld(), coverableView.getPos()) : RayTracer.retraceBlock(coverableView.getWorld(), player, coverableView.getPos()); if (result == null || result.typeOfHit != RayTraceResult.Type.BLOCK) { return null; @@ -36,8 +36,6 @@ private CoverRayTracer() {} return determineGridSideHit(result); } else if (rayTraceResult.cuboid6.data instanceof CoverSideData coverSideData) { return coverSideData.side; - } else if (rayTraceResult.cuboid6.data instanceof BlockPipe.PipeConnectionData pipeConnectionData) { - return pipeConnectionData.side; } else if (rayTraceResult.cuboid6.data instanceof PrimaryBoxData primaryBoxData) { return primaryBoxData.usePlacementGrid ? determineGridSideHit(result) : result.sideHit; } // unknown hit type, fall through diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index a67a7a552dc..faacf631b3f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -301,7 +301,10 @@ public void encode(PacketBuffer buf, boolean fullChange) { buf.writeVarInt(this.thermalMass); this.temperatureLossFunction.encode(buf); buf.writeVarInt(this.functionPriority); - buf.writeVarInt(Objects.requireNonNullElse(this.partialBurnTemperature, -1)); + // laughs in java 9 + //noinspection ReplaceNullCheck + if (this.partialBurnTemperature == null) buf.writeVarInt(-1); + else buf.writeVarInt(this.partialBurnTemperature); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java index b1bce3c0ecc..b0847f3753e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java @@ -44,7 +44,7 @@ default List getPipeBoxes(PipeTileEntity tileContext) { return pipeBoxes; } - private static AxisAlignedBB getSideBox(EnumFacing side, float thickness) { + static AxisAlignedBB getSideBox(EnumFacing side, float thickness) { float min = (1.0f - thickness) / 2.0f, max = min + thickness; float faceMin = 0f, faceMax = 1f; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java index e7090ef8a03..a602f07b846 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java @@ -3,6 +3,7 @@ import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.unification.material.Material; import gregtech.common.items.MetaItems; import net.minecraft.block.state.IBlockState; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java index bcda0498ee8..3bdb5576c9c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java @@ -1,5 +1,7 @@ package gregtech.api.graphnet.pipenet.physical.block; +import codechicken.lib.raytracer.RayTracer; + import gregtech.api.GTValues; import gregtech.api.block.BuiltInRenderBlock; @@ -253,7 +255,18 @@ public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World wor @Override public RayTraceResult collisionRayTrace(@NotNull IBlockState blockState, @NotNull World worldIn, @NotNull BlockPos pos, @NotNull Vec3d start, @NotNull Vec3d end) { - if (worldIn.isRemote && hasPipeCollisionChangingItem(worldIn, pos, GTUtility.getSP())) { + return collisionRayTrace(worldIn.isRemote ? GTUtility.getSP() : null, blockState, worldIn, pos, start, end); + } + + public RayTraceResult collisionRayTrace(@NotNull EntityPlayer player, @NotNull World world, @NotNull BlockPos pos) { + return collisionRayTrace(player, null, world, pos, RayTracer.getStartVec(player), RayTracer.getEndVec(player)); + } + + @SuppressWarnings("deprecation") + public RayTraceResult collisionRayTrace(@Nullable EntityPlayer player, @Nullable IBlockState blockState, @NotNull World worldIn, @NotNull BlockPos pos, + @NotNull Vec3d start, @NotNull Vec3d end) { + if (blockState == null) blockState = worldIn.getBlockState(pos); + if (hasPipeCollisionChangingItem(worldIn, pos, player)) { return super.collisionRayTrace(blockState, worldIn, pos, start, end); } PipeTileEntity tile = getTileEntity(worldIn, pos); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index d91a50f73a4..aac8672dd6e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -307,6 +307,11 @@ public EnumMap getTargetsWithCapabilities(WorldPipeNetNo return caps; } + /** + * Updates the pipe's active status based on the tile entity connected to the side. + * @param facing the side to check. Can be null, in which case all sides will be checked. + * @param canOpenConnection whether the pipe is allowed to open a new connection if it finds a tile it can connect to. + */ public void updateActiveStatus(@Nullable EnumFacing facing, boolean canOpenConnection) { if (facing == null) { for (EnumFacing side : EnumFacing.VALUES) { @@ -314,7 +319,7 @@ public void updateActiveStatus(@Nullable EnumFacing facing, boolean canOpenConne } return; } - if (!this.isConnected(facing) && !canOpenConnection) { + if (!this.isConnected(facing) && !(canOpenConnection && canConnectTo(facing))) { setAllIdle(facing); return; } diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetData.java b/src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetData.java deleted file mode 100644 index 5141f3a53c7..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetData.java +++ /dev/null @@ -1,15 +0,0 @@ -package gregtech.api.graphnet.pipenetold; - -import gregtech.api.graphnet.logic.NetLogicData; - -import java.util.Collections; -import java.util.List; - -public interface IPipeNetData> extends NetLogicData { - - T getSumData(List datas); - - default T getSumData(Object data) { - return getSumData(Collections.singletonList((T) data)); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetHandler.java b/src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetHandler.java deleted file mode 100644 index 45ef391e87f..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/IPipeNetHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -package gregtech.api.graphnet.pipenetold; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.cover.Cover; -import gregtech.api.cover.CoverHolder; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; - -public interface IPipeNetHandler { - - WorldPipeNetBase getNet(); - - EnumFacing getFacing(); - - default Cover getCoverOnNeighbour(BlockPos pos, EnumFacing facing) { - PipeNetNode node = getNet().getNode(pos); - if (node != null) { - TileEntity tile = node.getConnnected(facing); - if (tile != null) { - CoverHolder coverHolder = tile.getCapability(GregtechTileCapabilities.CAPABILITY_COVER_HOLDER, - facing.getOpposite()); - if (coverHolder == null) return null; - return coverHolder.getCoverAtSide(facing.getOpposite()); - } - } - return null; - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/NetPath.java b/src/main/java/gregtech/api/graphnet/pipenetold/NetPath.java deleted file mode 100644 index 3d4547857f9..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/NetPath.java +++ /dev/null @@ -1,4 +0,0 @@ -package gregtech.api.graphnet.pipenetold; - -public class NetPath { -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/NodeLossResult.java b/src/main/java/gregtech/api/graphnet/pipenetold/NodeLossResult.java deleted file mode 100644 index add527682d6..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/NodeLossResult.java +++ /dev/null @@ -1,20 +0,0 @@ -package gregtech.api.graphnet.pipenetold; - -import net.minecraft.util.Tuple; - -import java.util.function.Consumer; - -public class NodeLossResult extends Tuple>, Double> { - - public NodeLossResult(Consumer> postAction, Double lossFunction) { - super(postAction, lossFunction); - } - - public Consumer> getPostAction() { - return this.getFirst(); - } - - public Double getLossFunction() { - return this.getSecond(); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/PipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenetold/PipeNetNode.java deleted file mode 100644 index 7eb9101e6a0..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/PipeNetNode.java +++ /dev/null @@ -1,269 +0,0 @@ -package gregtech.api.graphnet.pipenetold; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; - -import java.lang.ref.WeakReference; -import java.util.Map; - -public final class PipeNetNode & IPipeType, - NodeDataType extends IPipeNetData, Edge extends NetEdge> - extends NetNode { - - public static final int DEFAULT_MARK = 0; - - /** - * Specifies bitmask of open connections. - * Open connections determine visual connections and graph edges. - * An open connection does not always mean an edge is present. - */ - private int openConnections; - /** - * Specifies bitmask of blocked connections. - * Blocked connections allow flow out, but not flow in. - * Only allowed on directed graphs. - */ - private int blockedConnections; - /** - * Specifies mark of this node - * Nodes can connect only if their marks are equal, or if - * one of marks is default one - */ - public int mark; - - private WeakReference> heldMTE; - - private BlockPos nodePos; - - public PipeNetNode(NodeDataType data, IPipeTile heldMTE, IGraphNet net) { - super(net); - this.setData(data); - this.openConnections = 0; - this.blockedConnections = 0; - this.mark = 0; - this.heldMTE = new WeakReference<>(heldMTE); - this.nodePos = heldMTE.getPipePos(); - } - - /** - * Creates a dummy node for client-side information handling. - * Should never be required to reference its net, data, or position. - */ - @SideOnly(Side.CLIENT) - public PipeNetNode(IPipeTile heldMTE) { - super(null); - this.nodePos = null; - this.setData(null); - this.heldMTE = new WeakReference<>(heldMTE); - this.openConnections = 0; - this.blockedConnections = 0; - } - - /** - * Creates a dummy node for fake flow edges. - * Should never be required to reference its net, mte, or position. - */ - public PipeNetNode(NodeDataType data) { - super(null); - this.nodePos = null; - this.setData(data); - this.heldMTE = null; - this.openConnections = 0; - this.blockedConnections = 0; - } - - /** - * For construction during NBT reading only - */ - @ApiStatus.Internal - public PipeNetNode(IGraphNet net) { - super(net); - this.heldMTE = new WeakReference<>(null); - } - - public boolean hasConnecteds() { - for (EnumFacing facing : EnumFacing.VALUES) { - if (!isConnected(facing)) continue; - if (getHeldMTE().getNonPipeNeighbour(facing) != null) return true; - } - return false; - } - - /** - * Returns null if we cannot get a valid mte for our location; this happens during world load. - */ - public Map getConnecteds() { - try { - getHeldMTE(); - } catch (Exception e) { - return null; - } - Map map = new Object2ObjectOpenHashMap<>(6); - for (EnumFacing facing : EnumFacing.VALUES) { - if (!isConnected(facing)) continue; - if (getHeldMTE().getNonPipeNeighbour(facing) != null) - map.put(facing, getHeldMTE().getNonPipeNeighbour(facing)); - } - return map; - } - - public TileEntity getConnnected(EnumFacing facing) { - return this.getHeldMTE().getNonPipeNeighbour(facing); - } - - public boolean isConnected(EnumFacing facing) { - return (openConnections & 1 << facing.getIndex()) != 0; - } - - /** - * Should only be used with dummy nodes, otherwise go through the net. - */ - public void setOpenConnections(int openConnections) { - this.openConnections = openConnections; - } - - void setConnected(EnumFacing facing, boolean connect) { - if (connect) { - this.openConnections |= 1 << facing.getIndex(); - } else { - this.openConnections &= ~(1 << facing.getIndex()); - } - this.getHeldMTESafe().onConnectionChange(); - } - - public int getOpenConnections() { - return openConnections; - } - - public boolean isBlocked(EnumFacing facing) { - return (blockedConnections & 1 << facing.getIndex()) != 0; - } - - /** - * Should only be used with dummy nodes, otherwise go through the net. - */ - public void setBlockedConnections(int blockedConnections) { - this.blockedConnections = blockedConnections; - } - - void setBlocked(EnumFacing facing, boolean block) { - if (block) { - this.blockedConnections |= 1 << facing.getIndex(); - } else { - this.blockedConnections &= ~(1 << facing.getIndex()); - } - this.getHeldMTESafe().onBlockedChange(); - } - - public int getBlockedConnections() { - return blockedConnections; - } - - public BlockPos getNodePos() { - return nodePos; - } - - public long getLongPos() { - return nodePos.toLong(); - } - - public WorldPipeNetBase getNet() { - return (WorldPipeNetBase) super.getNet(); - } - - public void setHeldMTE(IPipeTile heldMTE) { - if (this.heldMTE.get() != heldMTE) - this.heldMTE = new WeakReference<>(heldMTE); - } - - /** - * Performs no safety checks. - */ - @Nullable - public IPipeTile getHeldMTEUnsafe() { - return heldMTE.get(); - } - - /** - * Ensures that the returned tile is not null. - */ - public IPipeTile getHeldMTE() { - IPipeTile te = getHeldMTEUnsafe(); - if (te == null) { - te = this.getNet().castTE(this.getNet().getWorld().getTileEntity(this.nodePos)); - setHeldMTE(te); - } - return te; - } - - /** - * Ensures that the returned tile is the correct one for this position. - */ - public IPipeTile getHeldMTESafe() { - IPipeTile te = getHeldMTEUnsafe(); - IPipeTile properTE = - this.getNet().castTE(this.getNet().getWorld().getTileEntity(this.nodePos)); - if (te != properTE) { - setHeldMTE(properTE); - } - return properTE; - } - - public void setData(NodeDataType data) { - super.setData(data); - } - - @Override - public void setData(NetLogicData data) { - try { - NodeDataType cast = (NodeDataType) data; - this.setData(cast); - } catch (ClassCastException e) { - throw new IllegalArgumentException("Cannot give a pipenet node an arbitrary data type."); - } - } - - @Override - public NodeDataType getData() { - return (NodeDataType) super.getData(); - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tag = super.serializeNBT(); - tag.setLong("Pos", this.nodePos.toLong()); - tag.setInteger("Mark", this.mark); - tag.setInteger("OpenConnections", this.openConnections); - tag.setInteger("BlockedConnections", this.blockedConnections); - return tag; - } - - @Override - public void deserializeNBT(NBTTagCompound nbt) { - super.deserializeNBT(nbt); - this.nodePos = BlockPos.fromLong(nbt.getLong("Pos")); - this.mark = nbt.getInteger("Mark"); - this.openConnections = nbt.getInteger("OpenConnections"); - this.blockedConnections = nbt.getInteger("BlockedConnections"); - } - - @Override - protected Object getEquivalencyData() { - return this.nodePos; - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/PipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenetold/PipeNetPath.java deleted file mode 100644 index 234f349160f..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/PipeNetPath.java +++ /dev/null @@ -1,117 +0,0 @@ -package gregtech.api.graphnet.pipenetold; - -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.api.util.FacingPos; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; - -import org.jgrapht.GraphPath; - -import java.util.*; -import java.util.stream.Collectors; - -public class PipeNetPath & IPipeType, - NodeDataType extends IPipeNetData, Edge extends NetEdge> - extends NetPath, Edge> { - - private NodeDataType data = null; - - public PipeNetPath(GraphVertex node) { - super(node); - } - - public PipeNetPath(List nodes, List graphEdges, double weight) { - super(nodes, graphEdges, weight); - } - - public PipeNetPath(GraphPath path) { - super(path); - } - - public Iterator getFacingIterator() { - return this.getTargetTEs().keySet().iterator(); - } - - public FacedPipeNetPath firstFacing() { - return this.withFacing(this.getFacingIterator().next()); - } - - public FacedPipeNetPath withFacing(EnumFacing facing) { - return new FacedPipeNetPath<>(this, facing); - } - - public Map getTargetTEs() { - return getTargetNode().getConnecteds(); - } - - public NodeDataType getSumData() { - // generate min data on-demand and cache it, rather than generating for every path always - if (this.data == null) { - this.data = getSourceNode().getData() - .getSumData(this.getNodeList().stream().map(PipeNetNode::getData).collect(Collectors.toList())); - } - return data; - } - - public static class FacedPipeNetPath & IPipeType, NDT extends IPipeNetData, - E extends NetEdge> { - - public PipeNetPath path; - - public EnumFacing facing; - - public FacedPipeNetPath(PipeNetPath path, EnumFacing facing) { - this.path = path; - this.facing = facing; - } - - public TileEntity getTargetTE() { - return path.getTargetTEs().get(facing); - } - - public List> getNodeList() { - return path.getNodeList(); - } - - public List getEdgeList() { - return path.getEdgeList(); - } - - public PipeNetNode getSourceNode() { - return path.getSourceNode(); - } - - public PipeNetNode getTargetNode() { - return path.getTargetNode(); - } - - public Map getTargetTEs() { - return path.getTargetTEs(); - } - - public double getWeight() { - return path.getWeight(); - } - - public NDT getSumData() { - return path.getSumData(); - } - - public boolean checkPredicate(IPredicateTestObject testObject) { - return path.checkPredicate(testObject); - } - - public FacingPos toFacingPos() { - return new FacingPos(path.getTargetNode().getNodePos(), this.facing); - } - - public EnumFacing oppositeFacing() { - return facing.getOpposite(); - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java b/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java deleted file mode 100644 index 1f195bb0764..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetBase.java +++ /dev/null @@ -1,419 +0,0 @@ -package gregtech.api.graphnet.pipenetold; - -import gregtech.api.cover.Cover; -import gregtech.api.graphnet.GraphNetBacker; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetGroup; -import gregtech.api.graphnet.alg.INetAlgorithm; -import gregtech.api.graphnet.alg.iter.ICacheableIterator; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.graph.INetGraph; -import gregtech.api.graphnet.pipenetold.predicate.ShutteredEdgePredicate; -import gregtech.api.graphnet.pipenetold.predicate.IShutteredEdgePredicate; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.common.covers.CoverShutter; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.storage.WorldSavedData; -import net.minecraftforge.common.capabilities.Capability; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.ref.WeakReference; -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; -import java.util.function.Function; - -public abstract class WorldPipeNetBase, - PipeType extends Enum & IPipeType, Edge extends NetEdge> extends WorldSavedData - implements IGraphNet { - - - private final boolean isDirected; - - private WeakReference worldRef = new WeakReference<>(null); - protected final Map> pipeMap = new Object2ObjectOpenHashMap<>(); - - private final GraphNetBacker> backer; - - @SafeVarargs - WorldPipeNetBase(String name, boolean isDirected, INetGraph graph, - Function... algorithmBuilders) { - super(name); - this.backer = new GraphNetBacker(this, graph, algorithmBuilders); - this.isDirected = isDirected; - } - - @Override - public INetGraph getGraph() { - return this.backer.getGraph(); - } - - public final boolean isDirected() { - return isDirected; - } - - protected void markAlgInvalid() { - this.backer.invalidateAlgs(); - } - - public World getWorld() { - return this.worldRef.get(); - } - - protected boolean needsDynamicWeights() { - return false; - } - - protected void setWorldAndInit(World world) { - if (world != this.worldRef.get()) { - this.worldRef = new WeakReference<>(world); - } - } - - public static String getDataID(final String baseID, final World world) { - if (world == null || world.isRemote) - throw new RuntimeException("WorldPipeNetBase should only be created on the server!"); - int dimension = world.provider.getDimension(); - return dimension == 0 ? baseID : baseID + '.' + dimension; - } - - /** - * Preferred override. Only collects a fresh TE from the server if the provided TE is invalid. - * - * @param tile The {@link TileEntityPipeBase} that paths are being requested for - * @return the ordered list of paths associated with the {@link TileEntityPipeBase} - */ - public Iterator> getPaths(TileEntityPipeBase tile) { - return getPaths(this.pipeMap.get(tile.getPipePos()), tile); - } - - /** - * Special-case override. Forces the collection of a fresh TE from the server. - * - * @param pos The {@link BlockPos} that paths are being requested for - * @return the ordered list of paths associated with the {@link BlockPos} - */ - public Iterator> getPaths(BlockPos pos) { - return getPaths(this.pipeMap.get(pos), null); - } - - public Iterator> getPaths(@Nullable PipeNetNode node, - @Nullable TileEntityPipeBase tile) { - if (node == null) return Collections.emptyIterator(); - - node.setHeldMTE(tile); - - Iterator returnable = node.getPathCache(); - if (returnable == null) { - returnable = this.backer.getPaths(node, MAPPER); - if (returnable instanceof ICacheableIterator) { - returnable = node.setPathCache((ICacheableIterator) returnable); - } - } - return (Iterator>) returnable; - } - - @Nullable - protected TileEntityPipeBase castTE(TileEntity te) { - if (te instanceof TileEntityPipeBasepipe) { - if (!getBasePipeClass().isAssignableFrom(pipe.getClass())) { - return null; - } - // noinspection unchecked - return (TileEntityPipeBase) pipe; - } - return null; - } - - public void markNodeAsOldData(PipeNetNode node) { - updateActiveNodeStatus(node); - } - - protected abstract Class> getBasePipeClass(); - - public PipeNetNode getOrCreateNode(@NotNull IPipeTile mte) { - PipeNetNode node = this.pipeMap.get(mte.getPipePos()); - if (node != null) return node; - if (!canAttachNode(mte.getNodeData())) return null; - node = new PipeNetNode<>(mte.getNodeData(), mte, this); - this.addNode(node); - return node; - } - - protected final boolean canNodesConnect(PipeNetNode source, EnumFacing nodeFacing, - PipeNetNode target) { - return areNodeBlockedConnectionsCompatible(source, nodeFacing, target) && - areMarksCompatible(source.mark, target.mark) && - areNodesCustomContactable(source.getData(), target.getData()); - } - - private static boolean areMarksCompatible(int mark1, int mark2) { - return mark1 == mark2 || mark1 == PipeNetNode.DEFAULT_MARK || mark2 == PipeNetNode.DEFAULT_MARK; - } - - private boolean areNodeBlockedConnectionsCompatible(PipeNetNode source, - EnumFacing nodeFacing, - PipeNetNode target) { - return !source.isConnected(nodeFacing) && !target.isConnected(nodeFacing.getOpposite()); - } - - protected boolean areNodesCustomContactable(NodeDataType source, NodeDataType target) { - return true; - } - - protected boolean canAttachNode(NodeDataType nodeData) { - return true; - } - - public void updateActiveConnections(BlockPos nodePos, EnumFacing side, boolean connect) { - PipeNetNode node = pipeMap.get(nodePos); - if (node == null || node.isConnected(side) == connect) return; - - node.setConnected(side, connect); - updateActiveNodeStatus(node); - - PipeNetNode nodeOffset = pipeMap.get(nodePos.offset(side)); - if (nodeOffset == null) return; - - nodeOffset.setConnected(side.getOpposite(), connect); - - if (connect) { - if (!node.isBlocked(side)) { - addEdge(nodeOffset, node, null); - this.predicateEdge(nodeOffset, node, side.getOpposite()); - if (!this.getGraph().isDirected()) return; - } - if (!nodeOffset.isBlocked(side.getOpposite())) { - addEdge(node, nodeOffset, null); - this.predicateEdge(node, nodeOffset, side); - } - } else { - removeUndirectedEdge(node, nodeOffset); - } - } - - public void updateBlockedConnections(BlockPos nodePos, EnumFacing side, boolean blocked) { - if (!isDirected()) return; // no such thing as blocked connections on undirected graphs. - PipeNetNode node = pipeMap.get(nodePos); - if (node == null || node.isBlocked(side) == blocked) return; - - node.setBlocked(side, blocked); - - PipeNetNode nodeOffset = pipeMap.get(nodePos.offset(side)); - if (nodeOffset == null) return; - - if (!blocked) { - addEdge(nodeOffset, node, null); - this.predicateEdge(nodeOffset, node, side); - } else { - removeEdge(nodeOffset, node); - } - } - - public void updateMark(BlockPos nodePos, int newMark) { - PipeNetNode node = pipeMap.get(nodePos); - - int oldMark = node.mark; - node.mark = newMark; - - for (EnumFacing side : EnumFacing.VALUES) { - PipeNetNode nodeOffset = pipeMap.get(nodePos.offset(side)); - if (nodeOffset == null) continue; - if (!areNodeBlockedConnectionsCompatible(node, side, nodeOffset) || - !areNodesCustomContactable(node.getData(), nodeOffset.getData())) - continue; - if (areMarksCompatible(oldMark, nodeOffset.mark) == areMarksCompatible(newMark, nodeOffset.mark)) continue; - - if (areMarksCompatible(newMark, nodeOffset.mark)) { - addEdge(node, nodeOffset, null); - this.predicateEdge(node, nodeOffset, side); - } else { - removeEdge(node, nodeOffset); - } - } - } - - protected abstract Capability[] getConnectionCapabilities(); - - public boolean hasNode(BlockPos pos) { - return pipeMap.containsKey(pos); - } - - public void addNodeSilent(PipeNetNode node) { - backer.addNode(node); - this.pipeMap.put(node.getNodePos(), node); - // we do not need to invalidate the cache, because just adding a node means it's not connected to anything. - } - - public void addNode(PipeNetNode node) { - addNodeSilent(node); - this.markDirty(); - } - - @Nullable - public PipeNetNode getNode(BlockPos pos) { - return this.pipeMap.get(pos); - } - - public void addUndirectedEdge(PipeNetNode source, - PipeNetNode target) { - this.addEdge(source, target, null); - if (this.isDirected()) this.addEdge(target, source, null); - } - - public void addEdge(PipeNetNode source, PipeNetNode target, - @Nullable IEdgePredicateOld predicate) { - addEdge(source, target, source.getData().getWeightFactor() + target.getData().getWeightFactor(), predicate); - } - - public void addUndirectedEdge(PipeNetNode source, - PipeNetNode target, - double weight) { - this.addEdge(source, target, weight, null); - if (this.isDirected()) this.addEdge(target, source, weight, null); - } - - public void addEdge(PipeNetNode source, PipeNetNode target, - double weight, - @Nullable IEdgePredicateOld predicate) { - NetEdge edge = backer.addEdge(source, target, weight); - if (edge != null) { - NetGroup.mergeEdge(source, target); - if (predicate != null) { - edge.setPredicate(predicate); - } - this.markAlgInvalid(); - this.markDirty(); - } - } - - public void predicateUndirectedEdge(BlockPos pos, EnumFacing faceToNeighbour) { - PipeNetNode source = this.pipeMap.get(pos); - PipeNetNode target = this.pipeMap.get(pos.offset(faceToNeighbour)); - if (source != null && target != null) { - this.predicateUndirectedEdge(source, target, faceToNeighbour); - } - } - - public void predicateEdge(BlockPos pos, EnumFacing faceToNeighbour) { - PipeNetNode source = this.pipeMap.get(pos); - PipeNetNode target = this.pipeMap.get(pos.offset(faceToNeighbour)); - if (source != null && target != null) - this.predicateEdge(source, target, faceToNeighbour); - } - - public void predicateUndirectedEdge(PipeNetNode source, - PipeNetNode target, - EnumFacing faceToNeighbour) { - this.predicateEdge(source, target, faceToNeighbour); - if (this.isDirected()) this.predicateEdge(target, source, faceToNeighbour.getOpposite()); - } - - public void predicateEdge(PipeNetNode source, - PipeNetNode target, - EnumFacing faceToNeighbour) { - NetEdge edge = this.backer.getEdge(source, target); - if (edge == null) return; - Cover thisCover = source.getHeldMTESafe().getCoverableImplementation().getCoverAtSide(faceToNeighbour); - Cover neighbourCover = target.getHeldMTESafe().getCoverableImplementation() - .getCoverAtSide(faceToNeighbour.getOpposite()); - IEdgePredicateOld predicate = getPredicate(thisCover, neighbourCover); - predicate.setPosInfo(source.getNodePos(), target.getNodePos()); - edge.setPredicate(predicate); - } - - protected IEdgePredicateOld getPredicate(Cover thisCover, Cover neighbourCover) { - return shutterify(new ShutteredEdgePredicate(), thisCover, neighbourCover); - } - - protected final IEdgePredicateOld shutterify(IEdgePredicateOld predicate, @Nullable Cover thisCover, - @Nullable Cover neighbourCover) { - if (predicate instanceof IShutteredEdgePredicate shutteredEdgePredicate) { - if (thisCover instanceof CoverShutter shutter) { - shutteredEdgePredicate.setShutteredSource(shutter.isWorkingEnabled()); - } - if (neighbourCover instanceof CoverShutter shutter) { - shutteredEdgePredicate.setShutteredTarget(shutter.isWorkingEnabled()); - } - } - return predicate; - } - - public void removeUndirectedEdge(PipeNetNode source, - PipeNetNode target) { - this.removeEdge(source, target); - if (isDirected()) this.removeEdge(target, source); - } - - public void removeEdge(PipeNetNode source, PipeNetNode target) { - if (backer.removeEdge(source, target)) { - this.markAlgInvalid(); - this.markDirty(); - } - } - - public void removeNode(BlockPos pos) { - this.removeNode(this.pipeMap.get(pos)); - } - - public void removeNode(@Nullable PipeNetNode node) { - if (backer.removeNode(node)) { - this.pipeMap.remove(node.getNodePos()); - this.markDirty(); - } - } - - public NetGroup getGroup(BlockPos pos) { - PipeNetNode node = this.getNode(pos); - if (node == null) return null; - if (node.getGroupSafe() != null) return node.getGroupSafe(); - return node.setGroup(new NetGroup(this)); - } - - public boolean updateActiveNodeStatus(PipeNetNode node) { - return markNodeAsActive(node, shouldNodeBeActive(node)); - } - - public boolean shouldNodeBeActive(PipeNetNode node) { - var connecteds = node.getConnecteds(); - if (connecteds != null) return connecteds.entrySet().stream().filter(entry -> { - if (entry.getValue() instanceof IPipeTile) return false; - for (Capability cap : this.getConnectionCapabilities()) { - if (entry.getValue().hasCapability(cap, entry.getKey())) return true; - } - return false; - }).toArray().length > 0; - return false; - } - - public boolean markNodeAsActive(PipeNetNode node, boolean isActive) { - if (node != null && node.isActive() != isActive) { - node.getGroupSafe().clearPathCaches(); - node.setActive(isActive); - this.markDirty(); - return true; - } - return false; - } - - @Override - public void readFromNBT(@NotNull NBTTagCompound nbt) { - backer.readFromNBT(nbt); - } - - @NotNull - @Override - public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { - return backer.writeToNBT(compound); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetComplex.java b/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetComplex.java deleted file mode 100644 index ef8b926906e..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetComplex.java +++ /dev/null @@ -1,52 +0,0 @@ -package gregtech.api.graphnet.pipenetold; - -import gregtech.api.graphnet.alg.INetAlgorithm; -import gregtech.api.graphnet.alg.ShortestPathsAlgorithm; -import gregtech.api.graphnet.alg.SinglePathAlgorithm; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.graph.NetDirectedGraph; -import gregtech.api.graphnet.graph.NetUndirectedGraph; - -import java.util.function.Function; -import java.util.function.Supplier; - -public abstract class WorldPipeNetComplex, - PipeType extends Enum & IPipeType, - Edge extends NetEdge> extends WorldPipeNetBase { - - /** - * Alternate pipenet representation. Allows for using children of the {@link NetEdge} class as edges. - *

- * Note - These child edges cannot be allowed to store information, they must only perform runtime behavior. - * - * @param isDirected Determines whether this net needs directed graph handling. - * Used to respect filter directions in the item net and fluid net, for example. - * If the graph is not directed, pipes should not support blocked connections - * or unidirectional covers. - * @param edgeSupplier The supplier for the custom NetEdge child class. - * @param isSinglePath Determines whether this net allows only one source and one destination per group. - * Allows for optimizations in path lookup. - */ - public WorldPipeNetComplex(String name, boolean isDirected, boolean isSinglePath, Supplier edgeSupplier) { - this(name, isDirected, edgeSupplier, isSinglePath ? SinglePathAlgorithm::new : ShortestPathsAlgorithm::new); - } - - /** - * Alternate pipenet representation. Allows for using children of the {@link NetEdge} class as edges. - *

- * Note - These child edges cannot be allowed to store information, they must only perform runtime behavior. - * - * @param isDirected Determines whether this net needs directed graph handling. - * Used to respect filter directions in the item net and fluid net, for example. - * If the graph is not directed, pipes should not support blocked connections - * or unidirectional covers. - * @param edgeSupplier The supplier for the custom NetEdge child class. - * @param algorithmBuilder custom function to construct a new algorithm when the old one is invalidated. - */ - public WorldPipeNetComplex(String name, boolean isDirected, Supplier edgeSupplier, - Function, INetAlgorithm> algorithmBuilder) { - super(name, isDirected, algorithmBuilder, isDirected ? new NetDirectedGraph<>(null, edgeSupplier) : - new NetUndirectedGraph(null, edgeSupplier)); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetSimple.java b/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetSimple.java deleted file mode 100644 index 203787a1ec0..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/WorldPipeNetSimple.java +++ /dev/null @@ -1,45 +0,0 @@ -package gregtech.api.graphnet.pipenetold; - -import gregtech.api.graphnet.alg.INetAlgorithm; -import gregtech.api.graphnet.alg.ShortestPathsAlgorithm; -import gregtech.api.graphnet.alg.SinglePathAlgorithm; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.graph.NetDirectedGraph; -import gregtech.api.graphnet.graph.NetUndirectedGraph; - -import java.util.function.Function; - -public abstract class WorldPipeNetSimple, - PipeType extends Enum & IPipeType> - extends WorldPipeNetBase { - - /** - * Standard pipenet representation. Provides the base form of the pipenet abstraction. - * - * @param isDirected Determines whether this net needs directed graph handling. - * Used to respect filter directions in the item net and fluid net, for example. - * If the graph is not directed, pipes should not support blocked connections - * or unidirectional covers. - * @param isSinglePath Determines whether this net allows only one source and one destination per group. - * Allows for optimizations in path lookup. - */ - public WorldPipeNetSimple(String name, boolean isDirected, boolean isSinglePath) { - this(name, isDirected, isSinglePath ? SinglePathAlgorithm::new : ShortestPathsAlgorithm::new); - } - - /** - * Standard pipenet representation. Provides the base form of the pipenet abstraction. - * - * @param isDirected Determines whether this net needs directed graph handling. - * Used to respect filter directions in the item net and fluid net, for example. - * If the graph is not directed, pipes should not support blocked connections - * or unidirectional covers. - * @param algorithmBuilder custom function to construct a new algorithm when the old one is invalidated. - */ - public WorldPipeNetSimple(String name, boolean isDirected, - Function, INetAlgorithm> algorithmBuilder) { - super(name, isDirected, algorithmBuilder, isDirected ? new NetDirectedGraph<>(NetEdge.class) : - new NetUndirectedGraph(NetEdge.class)); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/BlockPipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/BlockPipe.java deleted file mode 100644 index d8a4a254f1f..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/block/BlockPipe.java +++ /dev/null @@ -1,680 +0,0 @@ -package gregtech.api.graphnet.pipenetold.block; - -import gregtech.api.block.BuiltInRenderBlock; -import gregtech.api.cover.Cover; -import gregtech.api.cover.CoverHolder; -import gregtech.api.cover.CoverRayTracer; -import gregtech.api.cover.IFacadeCover; -import gregtech.api.graphnet.pipenetold.IBlockAppearance; -import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.items.toolitem.ToolHelper; -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.PipeCoverableImplementation; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.api.util.GTUtility; -import gregtech.common.ConfigHolder; -import gregtech.common.blocks.BlockFrame; -import gregtech.common.blocks.MetaBlocks; -import gregtech.common.items.MetaItems; -import gregtech.integration.ctm.IFacadeWrapper; - -import net.minecraft.block.Block; -import net.minecraft.block.ITileEntityProvider; -import net.minecraft.block.SoundType; -import net.minecraft.block.state.BlockFaceShape; -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.Blocks; -import net.minecraft.item.EnumDyeColor; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.BlockRenderLayer; -import net.minecraft.util.EnumActionResult; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumHand; -import net.minecraft.util.NonNullList; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import codechicken.lib.raytracer.CuboidRayTraceResult; -import codechicken.lib.raytracer.IndexedCuboid6; -import codechicken.lib.raytracer.RayTracer; -import codechicken.lib.vec.Cuboid6; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static gregtech.api.metatileentity.MetaTileEntity.FULL_CUBE_COLLISION; - -@SuppressWarnings("deprecation") -public abstract class BlockPipe & IPipeType, - NodeDataType extends IPipeNetData, Edge extends NetEdge, - WorldPipeNetType extends WorldPipeNetBase> extends BuiltInRenderBlock - implements ITileEntityProvider, IFacadeWrapper, IBlockAppearance { - - protected final ThreadLocal> tileEntities = new ThreadLocal<>(); - - public BlockPipe() { - super(net.minecraft.block.material.Material.IRON); - setTranslationKey("pipe"); - setSoundType(SoundType.METAL); - setHardness(2.0f); - setResistance(3.0f); - setLightOpacity(0); - disableStats(); - } - - public static Cuboid6 getSideBox(EnumFacing side, float thickness) { - float min = (1.0f - thickness) / 2.0f, max = min + thickness; - float faceMin = 0f, faceMax = 1f; - - if (side == null) - return new Cuboid6(min, min, min, max, max, max); - return switch (side) { - case WEST -> new Cuboid6(faceMin, min, min, min, max, max); - case EAST -> new Cuboid6(max, min, min, faceMax, max, max); - case NORTH -> new Cuboid6(min, min, faceMin, max, max, min); - case SOUTH -> new Cuboid6(min, min, max, max, max, faceMax); - case UP -> new Cuboid6(min, max, min, max, faceMax, max); - case DOWN -> new Cuboid6(min, faceMin, min, max, min, max); - }; - } - - /** - * @return the pipe cuboid for that side but with a offset one the facing with the cover to prevent z fighting. - */ - public static Cuboid6 getCoverSideBox(EnumFacing side, float thickness) { - Cuboid6 cuboid = getSideBox(side, thickness); - if (side != null) - cuboid.setSide(side, side.getAxisDirection() == EnumFacing.AxisDirection.NEGATIVE ? 0.001 : 0.999); - return cuboid; - } - - public abstract Class getPipeTypeClass(); - - public abstract WorldPipeNetType getWorldPipeNet(World world); - - public abstract TileEntityPipeBase createNewTileEntity(boolean supportsTicking); - - public abstract NodeDataType createProperties(IPipeTile pipeTile); - - public abstract NodeDataType createItemProperties(ItemStack itemStack); - - public abstract ItemStack getDropItem(IPipeTile pipeTile); - - protected abstract NodeDataType getFallbackType(); - - // TODO this has no reason to need an ItemStack parameter - public abstract PipeType getItemPipeType(ItemStack itemStack); - - public abstract void setTileEntityData(TileEntityPipeBase pipeTile, - ItemStack itemStack); - - @Override - public abstract void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList items); - - @Override - public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); - if (pipeTile != null) { - pipeTile.getCoverableImplementation().dropAllCovers(); - tileEntities.set(pipeTile); - } - super.breakBlock(worldIn, pos, state); - if (!worldIn.isRemote) getWorldPipeNet(worldIn).removeNode(pos); - } - - @Override - public void onBlockAdded(World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { - worldIn.scheduleUpdate(pos, this, 1); - } - - @Override - public void onBlockPlacedBy(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, - @NotNull EntityLivingBase placer, @NotNull ItemStack stack) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); - if (pipeTile != null) { - setTileEntityData((TileEntityPipeBase) pipeTile, stack); - - // Color pipes/cables on place if holding spray can in off-hand - if (placer instanceof EntityPlayer) { - ItemStack offhand = placer.getHeldItemOffhand(); - for (int i = 0; i < EnumDyeColor.values().length; i++) { - if (offhand.isItemEqual(MetaItems.SPRAY_CAN_DYES[i].getStackForm())) { - MetaItems.SPRAY_CAN_DYES[i].getBehaviours().get(0).onItemUse((EntityPlayer) placer, worldIn, - pos, EnumHand.OFF_HAND, EnumFacing.UP, 0, 0, 0); - break; - } - } - } - - } - } - - @Override - public void neighborChanged(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos, - @NotNull Block blockIn, @NotNull BlockPos fromPos) { - if (worldIn.isRemote) return; - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); - if (pipeTile != null) { - pipeTile.getCoverableImplementation().updateInputRedstoneSignals(); - EnumFacing facing = GTUtility.getFacingToNeighbor(pos, fromPos); - if (facing == null) return; - pipeTile.onNeighborChanged(facing); - if (!ConfigHolder.machines.gt6StylePipesCables) { - boolean open = pipeTile.isConnected(facing); - boolean canConnect = pipeTile.getCoverableImplementation().getCoverAtSide(facing) != null || - canConnect(pipeTile, facing); - if (!open && canConnect && state.getBlock() != blockIn) - pipeTile.setConnection(facing, true, false); - if (open && !canConnect) - pipeTile.setConnection(facing, false, false); - } - } - } - - @Override - public void onNeighborChange(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull BlockPos neighbor) { - IPipeTile pipeTile = getPipeTileEntity(world, pos); - if (pipeTile != null) { - EnumFacing facing = GTUtility.getFacingToNeighbor(pos, neighbor); - if (facing != null) { - pipeTile.onNeighborChanged(facing); - } - } - } - - @Override - public boolean canConnectRedstone(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, - @Nullable EnumFacing side) { - IPipeTile pipeTile = getPipeTileEntity(world, pos); - return pipeTile != null && pipeTile.getCoverableImplementation().canConnectRedstone(side); - } - - @Override - public boolean shouldCheckWeakPower(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, - @NotNull EnumFacing side) { - // The check in World::getRedstonePower in the vanilla code base is reversed. Setting this to false will - // actually cause getWeakPower to be called, rather than prevent it. - return false; - } - - @Override - public int getWeakPower(@NotNull IBlockState blockState, @NotNull IBlockAccess blockAccess, @NotNull BlockPos pos, - @NotNull EnumFacing side) { - IPipeTile pipeTile = getPipeTileEntity(blockAccess, pos); - return pipeTile == null ? 0 : pipeTile.getCoverableImplementation().getOutputRedstoneSignal(side.getOpposite()); - } - - @Nullable - @Override - public TileEntity createNewTileEntity(@NotNull World worldIn, int meta) { - return createNewTileEntity(false); - } - - @NotNull - @Override - public ItemStack getPickBlock(@NotNull IBlockState state, @NotNull RayTraceResult target, @NotNull World world, - @NotNull BlockPos pos, @NotNull EntityPlayer player) { - IPipeTile pipeTile = getPipeTileEntity(world, pos); - if (pipeTile == null) { - return ItemStack.EMPTY; - } - if (target instanceof CuboidRayTraceResult result) { - if (result.cuboid6.data instanceof CoverRayTracer.CoverSideData coverSideData) { - EnumFacing coverSide = coverSideData.side; - Cover cover = pipeTile.getCoverableImplementation().getCoverAtSide(coverSide); - return cover == null ? ItemStack.EMPTY : cover.getPickItem(); - } - } - return getDropItem(pipeTile); - } - - @Override - public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, - @NotNull EntityPlayer playerIn, @NotNull EnumHand hand, @NotNull EnumFacing facing, - float hitX, float hitY, float hitZ) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); - CuboidRayTraceResult rayTraceResult = getServerCollisionRayTrace(playerIn, pos, worldIn); - - if (rayTraceResult == null || pipeTile == null) { - return false; - } - return onPipeActivated(worldIn, state, pos, playerIn, hand, facing, rayTraceResult, pipeTile); - } - - public boolean onPipeActivated(World world, IBlockState state, BlockPos pos, EntityPlayer entityPlayer, - EnumHand hand, EnumFacing side, CuboidRayTraceResult hit, - IPipeTile pipeTile) { - ItemStack itemStack = entityPlayer.getHeldItem(hand); - - if (pipeTile.getFrameMaterial() == null && - pipeTile instanceof TileEntityPipeBase && - pipeTile.getPipeType().getThickness() < 1) { - BlockFrame frameBlock = BlockFrame.getFrameBlockFromItem(itemStack); - if (frameBlock != null) { - ((TileEntityPipeBase) pipeTile) - .setFrameMaterial(frameBlock.getGtMaterial(itemStack)); - SoundType type = frameBlock.getSoundType(itemStack); - world.playSound(entityPlayer, pos, type.getPlaceSound(), SoundCategory.BLOCKS, - (type.getVolume() + 1.0F) / 2.0F, type.getPitch() * 0.8F); - if (!entityPlayer.capabilities.isCreativeMode) { - itemStack.shrink(1); - } - return true; - } - } - - if (itemStack.getItem() instanceof ItemBlockPipe) { - IBlockState blockStateAtSide = world.getBlockState(pos.offset(side)); - if (blockStateAtSide.getBlock() instanceof BlockFrame) { - ItemBlockPipe itemBlockPipe = (ItemBlockPipe) itemStack.getItem(); - if (itemBlockPipe.blockPipe.getItemPipeType(itemStack) == getItemPipeType(itemStack)) { - BlockFrame frameBlock = (BlockFrame) blockStateAtSide.getBlock(); - boolean wasPlaced = frameBlock.replaceWithFramedPipe(world, pos.offset(side), blockStateAtSide, - entityPlayer, itemStack, side); - if (wasPlaced) { - pipeTile.setConnection(side, true, false); - } - return wasPlaced; - } - } - } - - EnumFacing coverSide = CoverRayTracer.traceCoverSide(hit); - if (coverSide == null) { - return activateFrame(world, state, pos, entityPlayer, hand, hit, pipeTile); - } - - if (!(hit.cuboid6.data instanceof CoverRayTracer.CoverSideData)) { - switch (onPipeToolUsed(world, pos, itemStack, coverSide, pipeTile, entityPlayer, hand)) { - case SUCCESS -> { - return true; - } - case FAIL -> { - return false; - } - } - } - - Cover cover = pipeTile.getCoverableImplementation().getCoverAtSide(coverSide); - if (cover == null) { - return activateFrame(world, state, pos, entityPlayer, hand, hit, pipeTile); - } - - if (itemStack.getItem().getToolClasses(itemStack).contains(ToolClasses.SOFT_MALLET)) { - if (cover.onSoftMalletClick(entityPlayer, hand, hit) == EnumActionResult.SUCCESS) { - ToolHelper.damageItem(itemStack, entityPlayer); - ToolHelper.playToolSound(itemStack, entityPlayer); - return true; - } - } - - if ((itemStack.isEmpty() && entityPlayer.isSneaking()) || - itemStack.getItem().getToolClasses(itemStack).contains(ToolClasses.SCREWDRIVER)) { - if (cover.onScrewdriverClick(entityPlayer, hand, hit) == EnumActionResult.SUCCESS) { - if (!itemStack.isEmpty()) { - ToolHelper.damageItem(itemStack, entityPlayer); - ToolHelper.playToolSound(itemStack, entityPlayer); - } - return true; - } - } - - if (itemStack.getItem().getToolClasses(itemStack).contains(ToolClasses.CROWBAR)) { - if (!world.isRemote) { - pipeTile.getCoverableImplementation().removeCover(coverSide); - ToolHelper.damageItem(itemStack, entityPlayer); - ToolHelper.playToolSound(itemStack, entityPlayer); - return true; - } - } - - EnumActionResult result = cover.onRightClick(entityPlayer, hand, hit); - if (result == EnumActionResult.PASS) { - if (activateFrame(world, state, pos, entityPlayer, hand, hit, pipeTile)) { - return true; - } - return entityPlayer.isSneaking() && entityPlayer.getHeldItemMainhand().isEmpty() && - cover.onScrewdriverClick(entityPlayer, hand, hit) != EnumActionResult.PASS; - } - return true; - } - - private boolean activateFrame(World world, IBlockState state, BlockPos pos, EntityPlayer entityPlayer, - EnumHand hand, CuboidRayTraceResult hit, - IPipeTile pipeTile) { - if (pipeTile.getFrameMaterial() != null && - !(entityPlayer.getHeldItem(hand).getItem() instanceof ItemBlockPipe)) { - BlockFrame blockFrame = MetaBlocks.FRAMES.get(pipeTile.getFrameMaterial()); - return blockFrame.onBlockActivated(world, pos, state, entityPlayer, hand, hit.sideHit, (float) hit.hitVec.x, - (float) hit.hitVec.y, (float) hit.hitVec.z); - } - return false; - } - - /** - * @return 1 if successfully used tool, 0 if failed to use tool, - * -1 if ItemStack failed the capability check (no action done, continue checks). - */ - public EnumActionResult onPipeToolUsed(World world, BlockPos pos, ItemStack stack, EnumFacing coverSide, - IPipeTile pipeTile, EntityPlayer entityPlayer, - EnumHand hand) { - if (isPipeTool(stack)) { - if (!entityPlayer.world.isRemote) { - if (entityPlayer.isSneaking() && pipeTile.canHaveBlockedFaces()) { - boolean isBlocked = pipeTile.isFaceBlocked(coverSide); - pipeTile.setFaceBlocked(coverSide, !isBlocked); - ToolHelper.playToolSound(stack, entityPlayer); - ToolHelper.damageItem(stack, entityPlayer); - } else { - boolean isOpen = pipeTile.isConnected(coverSide); - pipeTile.setConnection(coverSide, !isOpen, false); - if (isOpen != pipeTile.isConnected(coverSide)) { - ToolHelper.playToolSound(stack, entityPlayer); - ToolHelper.damageItem(stack, entityPlayer); - } - } - return EnumActionResult.SUCCESS; - } - entityPlayer.swingArm(hand); - return EnumActionResult.SUCCESS; - } - return EnumActionResult.PASS; - } - - protected boolean isPipeTool(@NotNull ItemStack stack) { - return ToolHelper.isTool(stack, ToolClasses.WRENCH); - } - - @Override - public void onBlockClicked(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull EntityPlayer playerIn) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); - CuboidRayTraceResult rayTraceResult = (CuboidRayTraceResult) RayTracer.retraceBlock(worldIn, playerIn, pos); - if (pipeTile == null || rayTraceResult == null) { - return; - } - EnumFacing coverSide = CoverRayTracer.traceCoverSide(rayTraceResult); - Cover cover = coverSide == null ? null : pipeTile.getCoverableImplementation().getCoverAtSide(coverSide); - - if (cover != null) { - cover.onLeftClick(playerIn, rayTraceResult); - } - } - - @Override - public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, - @NotNull Entity entityIn) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); - if (pipeTile != null && pipeTile.getFrameMaterial() != null) { - // make pipe with frame climbable - BlockFrame blockFrame = MetaBlocks.FRAMES.get(pipeTile.getFrameMaterial()); - blockFrame.onEntityCollision(worldIn, pos, state, entityIn); - } - } - - @SuppressWarnings("unchecked") - @Override - public void harvestBlock(@NotNull World worldIn, @NotNull EntityPlayer player, @NotNull BlockPos pos, - @NotNull IBlockState state, @Nullable TileEntity te, @NotNull ItemStack stack) { - tileEntities.set(te == null ? tileEntities.get() : (IPipeTile) te); - super.harvestBlock(worldIn, player, pos, state, te, stack); - tileEntities.remove(); - } - - @Override - public void getDrops(@NotNull NonNullList drops, @NotNull IBlockAccess world, @NotNull BlockPos pos, - @NotNull IBlockState state, int fortune) { - IPipeTile pipeTile = tileEntities.get() == null ? getPipeTileEntity(world, pos) : - tileEntities.get(); - if (pipeTile == null) return; - if (pipeTile.getFrameMaterial() != null) { - BlockFrame blockFrame = MetaBlocks.FRAMES.get(pipeTile.getFrameMaterial()); - drops.add(blockFrame.getItem(pipeTile.getFrameMaterial())); - } - drops.add(getDropItem(pipeTile)); - } - - @Override - public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos, - @NotNull AxisAlignedBB entityBox, @NotNull List collidingBoxes, - @Nullable Entity entityIn, boolean isActualState) { - // This iterator causes some heap memory overhead - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); - if (pipeTile != null && pipeTile.getFrameMaterial() != null) { - AxisAlignedBB box = BlockFrame.COLLISION_BOX.offset(pos); - if (box.intersects(entityBox)) { - collidingBoxes.add(box); - } - return; - } - for (Cuboid6 axisAlignedBB : getCollisionBox(worldIn, pos, entityIn)) { - AxisAlignedBB offsetBox = axisAlignedBB.aabb().offset(pos); - if (offsetBox.intersects(entityBox)) collidingBoxes.add(offsetBox); - } - } - - @Nullable - @Override - public RayTraceResult collisionRayTrace(@NotNull IBlockState blockState, World worldIn, @NotNull BlockPos pos, - @NotNull Vec3d start, @NotNull Vec3d end) { - if (worldIn.isRemote) { - return getClientCollisionRayTrace(worldIn, pos, start, end); - } - return RayTracer.rayTraceCuboidsClosest(start, end, pos, getCollisionBox(worldIn, pos, null)); - } - - @SideOnly(Side.CLIENT) - public RayTraceResult getClientCollisionRayTrace(World worldIn, @NotNull BlockPos pos, @NotNull Vec3d start, - @NotNull Vec3d end) { - return RayTracer.rayTraceCuboidsClosest(start, end, pos, - getCollisionBox(worldIn, pos, Minecraft.getMinecraft().player)); - } - - /** - * This method attempts to properly raytrace the pipe to fix the server not getting the correct raytrace result. - */ - @Nullable - public CuboidRayTraceResult getServerCollisionRayTrace(EntityPlayer playerIn, BlockPos pos, World worldIn) { - return RayTracer.rayTraceCuboidsClosest( - RayTracer.getStartVec(playerIn), RayTracer.getEndVec(playerIn), - pos, getCollisionBox(worldIn, pos, playerIn)); - } - - @NotNull - @Override - public BlockFaceShape getBlockFaceShape(@NotNull IBlockAccess worldIn, @NotNull IBlockState state, - @NotNull BlockPos pos, @NotNull EnumFacing face) { - IPipeTile pipeTile = getPipeTileEntity(worldIn, pos); - if (pipeTile != null && pipeTile.getCoverableImplementation().getCoverAtSide(face) != null) { - return BlockFaceShape.SOLID; - } - return BlockFaceShape.UNDEFINED; - } - - @Override - public boolean recolorBlock(World world, @NotNull BlockPos pos, @NotNull EnumFacing side, - @NotNull EnumDyeColor color) { - IPipeTile tileEntityPipe = (IPipeTile) world - .getTileEntity(pos); - if (tileEntityPipe != null && tileEntityPipe.getPipeType() != null && - tileEntityPipe.getPipeType().isPaintable() && - tileEntityPipe.getPaintingColor() != color.colorValue) { - tileEntityPipe.setPaintingColor(color.colorValue); - return true; - } - return false; - } - - protected boolean isThisPipeBlock(Block block) { - return block != null && block.getClass().isAssignableFrom(getClass()); - } - - /** - * Just returns proper pipe tile entity - */ - public IPipeTile getPipeTileEntity(IBlockAccess world, BlockPos selfPos) { - TileEntity tileEntityAtPos = world.getTileEntity(selfPos); - return getPipeTileEntity(tileEntityAtPos); - } - - public IPipeTile getPipeTileEntity(TileEntity tileEntityAtPos) { - if (tileEntityAtPos instanceof IPipeTile && - isThisPipeBlock(((IPipeTile) tileEntityAtPos).getPipeBlock())) { - return (IPipeTile) tileEntityAtPos; - } - return null; - } - - public boolean canConnect(IPipeTile selfTile, EnumFacing facing) { - if (selfTile.getPipeWorld().getBlockState(selfTile.getPipePos().offset(facing)).getBlock() == Blocks.AIR) - return false; - Cover cover = selfTile.getCoverableImplementation().getCoverAtSide(facing); - if (cover != null && !cover.canPipePassThrough()) { - return false; - } - TileEntity other = selfTile.getNeighbor(facing); - if (other instanceof IPipeTile) { - cover = ((IPipeTile) other).getCoverableImplementation().getCoverAtSide(facing.getOpposite()); - if (cover != null && !cover.canPipePassThrough()) - return false; - return canPipesConnect(selfTile, facing, (IPipeTile) other); - } - return canPipeConnectToBlock(selfTile, facing, other); - } - - public abstract boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile); - - public abstract boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, - @Nullable TileEntity tile); - - public boolean canPipeConnectToBlock(World world, BlockPos pos, EnumFacing side, @Nullable TileEntity tile) { - var te = getPipeTileEntity(world, pos); - if (te == null) return false; - return canPipeConnectToBlock(te, side, tile); - } - - private List getCollisionBox(IBlockAccess world, BlockPos pos, @Nullable Entity entityIn) { - IPipeTile pipeTile = getPipeTileEntity(world, pos); - if (pipeTile == null) { - return Collections.emptyList(); - } - if (pipeTile.getFrameMaterial() != null) { - return Collections.singletonList(FULL_CUBE_COLLISION); - } - PipeType pipeType = pipeTile.getPipeType(); - if (pipeType == null) { - return Collections.emptyList(); - } - int actualConnections = pipeTile.getVisualConnections(); - float thickness = pipeType.getThickness(); - List result = new ArrayList<>(); - CoverHolder coverHolder = pipeTile.getCoverableImplementation(); - - // Check if the machine grid is being rendered - boolean usingGrid = hasPipeCollisionChangingItem(world, pos, entityIn); - if (usingGrid) { - result.add(FULL_CUBE_COLLISION); - } - - // Always add normal collision so player doesn't "fall through" the cable/pipe when - // a tool is put in hand, and will still be standing where they were before. - result.add(new IndexedCuboid6(new CoverRayTracer.PrimaryBoxData(usingGrid), getSideBox(null, thickness))); - for (EnumFacing side : EnumFacing.VALUES) { - if ((actualConnections & 1 << side.getIndex()) > 0) { - result.add(new IndexedCuboid6(new PipeConnectionData(side), getSideBox(side, thickness))); - } - } - coverHolder.addCoverCollisionBoundingBox(result); - return result; - } - - public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, Entity entity) { - if (entity instanceof EntityPlayer) { - return hasPipeCollisionChangingItem(world, pos, ((EntityPlayer) entity).getHeldItem(EnumHand.MAIN_HAND)) || - hasPipeCollisionChangingItem(world, pos, ((EntityPlayer) entity).getHeldItem(EnumHand.OFF_HAND)) || - entity.isSneaking() && isHoldingPipe((EntityPlayer) entity); - } - return false; - } - - public abstract boolean isHoldingPipe(EntityPlayer player); - - public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, ItemStack stack) { - if (isPipeTool(stack)) return true; - - IPipeTile pipeTile = getPipeTileEntity(world, pos); - if (pipeTile == null) return false; - - PipeCoverableImplementation coverable = pipeTile.getCoverableImplementation(); - final boolean hasAnyCover = coverable.hasAnyCover(); - - if (hasAnyCover && ToolHelper.isTool(stack, ToolClasses.SCREWDRIVER)) return true; - final boolean acceptsCovers = coverable.acceptsCovers(); - - return GTUtility.isCoverBehaviorItem(stack, () -> hasAnyCover, coverDef -> acceptsCovers); - } - - @Override - public boolean canRenderInLayer(@NotNull IBlockState state, @NotNull BlockRenderLayer layer) { - return true; - } - - @NotNull - @Override - public IBlockState getFacade(@NotNull IBlockAccess world, @NotNull BlockPos pos, @Nullable EnumFacing side, - @NotNull BlockPos otherPos) { - return getFacade(world, pos, side); - } - - @NotNull - @Override - public IBlockState getFacade(@NotNull IBlockAccess world, @NotNull BlockPos pos, EnumFacing side) { - IPipeTile pipeTileEntity = getPipeTileEntity(world, pos); - if (pipeTileEntity != null && side != null) { - Cover cover = pipeTileEntity.getCoverableImplementation().getCoverAtSide(side); - if (cover instanceof IFacadeCover) { - return ((IFacadeCover) cover).getVisualState(); - } - } - return world.getBlockState(pos); - } - - @NotNull - @Override - public IBlockState getVisualState(@NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull EnumFacing side) { - return getFacade(world, pos, side); - } - - @Override - public boolean supportsVisualConnections() { - return true; - } - - public static class PipeConnectionData { - - public final EnumFacing side; - - public PipeConnectionData(EnumFacing side) { - this.side = side; - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/IPipeType.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/IPipeType.java deleted file mode 100644 index 6e94ad7212a..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/block/IPipeType.java +++ /dev/null @@ -1,14 +0,0 @@ -package gregtech.api.graphnet.pipenetold.block; - -import gregtech.api.graphnet.pipenetold.IPipeNetData; - -import net.minecraft.util.IStringSerializable; - -public interface IPipeType> extends IStringSerializable { - - float getThickness(); - - NodeDataType modifyProperties(NodeDataType baseProperties); - - boolean isPaintable(); -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/ItemBlockPipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/ItemBlockPipe.java deleted file mode 100644 index 4e582785284..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/block/ItemBlockPipe.java +++ /dev/null @@ -1,64 +0,0 @@ -package gregtech.api.graphnet.pipenetold.block; - -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.common.ConfigHolder; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemBlock; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import org.jetbrains.annotations.NotNull; - -public class ItemBlockPipe & IPipeType, - NodeDataType extends IPipeNetData> extends ItemBlock { - - protected final BlockPipe blockPipe; - - public ItemBlockPipe(BlockPipe block) { - super(block); - this.blockPipe = block; - setHasSubtypes(true); - } - - @Override - public int getMetadata(int damage) { - return damage; - } - - @Override - @SuppressWarnings({ "rawtypes", "unchecked" }) - public boolean placeBlockAt(@NotNull ItemStack stack, @NotNull EntityPlayer player, @NotNull World world, - @NotNull BlockPos pos, @NotNull EnumFacing side, float hitX, float hitY, float hitZ, - @NotNull IBlockState newState) { - boolean superVal = super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, newState); - if (superVal && !world.isRemote) { - IPipeTile selfTile = (IPipeTile) world.getTileEntity(pos); - if (selfTile == null) return superVal; - if (selfTile.getPipeBlock().canConnect(selfTile, side.getOpposite())) { - selfTile.setConnection(side.getOpposite(), true, false); - } - for (EnumFacing facing : EnumFacing.VALUES) { - TileEntity te = selfTile.getNeighbor(facing); - if (te instanceof IPipeTile otherPipe) { - if (otherPipe.isConnected(facing.getOpposite())) { - if (otherPipe.getPipeBlock().canPipesConnect(otherPipe, facing.getOpposite(), selfTile)) { - selfTile.setConnection(facing, true, true); - } else { - otherPipe.setConnection(facing.getOpposite(), false, true); - } - } - } else if (!ConfigHolder.machines.gt6StylePipesCables && - selfTile.getPipeBlock().canPipeConnectToBlock(selfTile, facing, te)) { - selfTile.setConnection(facing, true, false); - } - } - } - return superVal; - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/BlockMaterialPipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/BlockMaterialPipe.java deleted file mode 100644 index 18e1237e3d6..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/BlockMaterialPipe.java +++ /dev/null @@ -1,116 +0,0 @@ -package gregtech.api.graphnet.pipenetold.block.material; - -import gregtech.api.GTValues; -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.registry.MaterialRegistry; -import gregtech.api.unification.ore.OrePrefix; -import gregtech.client.renderer.pipeold.PipeRenderer; -import gregtech.common.blocks.MetaBlocks; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.renderer.block.model.ModelResourceLocation; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.client.model.ModelLoader; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; - -public abstract class BlockMaterialPipe< - PipeType extends Enum & IPipeType & IMaterialPipeType, - NodeDataType extends IPipeNetData, Edge extends NetEdge, - WorldPipeNetType extends WorldPipeNetBase> - extends BlockPipe { - - protected final PipeType pipeType; - private final MaterialRegistry registry; - - public BlockMaterialPipe(@NotNull PipeType pipeType, @NotNull MaterialRegistry registry) { - this.pipeType = pipeType; - this.registry = registry; - } - - @Override - public NodeDataType createProperties(IPipeTile pipeTile) { - PipeType pipeType = pipeTile.getPipeType(); - Material material = ((IMaterialPipeTile) pipeTile).getPipeMaterial(); - if (pipeType == null || material == null) { - return getFallbackType(); - } - return createProperties(pipeType, material); - } - - @Override - public NodeDataType createItemProperties(ItemStack itemStack) { - Material material = getItemMaterial(itemStack); - if (pipeType == null || material == null) { - return getFallbackType(); - } - return createProperties(pipeType, material); - } - - public ItemStack getItem(Material material) { - if (material == null) return ItemStack.EMPTY; - int materialId = registry.getIDForObject(material); - return new ItemStack(this, 1, materialId); - } - - public Material getItemMaterial(ItemStack itemStack) { - return registry.getObjectById(itemStack.getMetadata()); - } - - @Override - public void setTileEntityData(TileEntityPipeBase pipeTile, ItemStack itemStack) { - ((TileEntityMaterialPipeBase) pipeTile).setPipeData(this, pipeType, - getItemMaterial(itemStack)); - } - - @Override - public ItemStack getDropItem(IPipeTile pipeTile) { - Material material = ((IMaterialPipeTile) pipeTile).getPipeMaterial(); - return getItem(material); - } - - protected abstract NodeDataType createProperties(PipeType pipeType, Material material); - - public OrePrefix getPrefix() { - return pipeType.getOrePrefix(); - } - - public PipeType getItemPipeType(ItemStack is) { - return pipeType; - } - - @NotNull - public MaterialRegistry getMaterialRegistry() { - return registry; - } - - @SideOnly(Side.CLIENT) - @NotNull - public abstract PipeRenderer getPipeRenderer(); - - public void onModelRegister() { - ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(this), stack -> getPipeRenderer().getModelLocation()); - for (IBlockState state : this.getBlockState().getValidStates()) { - ModelResourceLocation resourceLocation = new ModelResourceLocation( - new ResourceLocation(GTValues.MODID, // force pipe models to always be GT's - Objects.requireNonNull(this.getRegistryName()).getPath()), - MetaBlocks.statePropertiesToString(state.getProperties())); - // noinspection ConstantConditions - ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(this), - this.getMetaFromState(state), resourceLocation); - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeTile.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeTile.java deleted file mode 100644 index 37ecb30bb97..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeTile.java +++ /dev/null @@ -1,14 +0,0 @@ -package gregtech.api.graphnet.pipenetold.block.material; - -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.unification.material.Material; - -public interface IMaterialPipeTile & IPipeType, - NodeDataType extends IPipeNetData, Edge extends NetEdge> - extends IPipeTile { - - Material getPipeMaterial(); -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeType.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeType.java deleted file mode 100644 index bb439a42992..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/IMaterialPipeType.java +++ /dev/null @@ -1,16 +0,0 @@ -package gregtech.api.graphnet.pipenetold.block.material; - -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.unification.ore.OrePrefix; - -public interface IMaterialPipeType> extends IPipeType { - - /** - * Determines ore prefix used for this pipe type, which gives pipe ore dictionary key - * when combined with pipe's material - * - * @return ore prefix used for this pipe type - */ - OrePrefix getOrePrefix(); -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/ItemBlockMaterialPipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/ItemBlockMaterialPipe.java deleted file mode 100644 index 2b31a6bf229..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/ItemBlockMaterialPipe.java +++ /dev/null @@ -1,26 +0,0 @@ -package gregtech.api.graphnet.pipenetold.block.material; - -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.block.ItemBlockPipe; -import gregtech.api.unification.material.Material; - -import net.minecraft.item.ItemStack; - -import org.jetbrains.annotations.NotNull; - -public class ItemBlockMaterialPipe & IMaterialPipeType, - NodeDataType extends IPipeNetData> - extends ItemBlockPipe { - - public ItemBlockMaterialPipe(BlockMaterialPipe block) { - super(block); - } - - @NotNull - @Override - public String getItemStackDisplayName(@NotNull ItemStack stack) { - PipeType pipeType = blockPipe.getItemPipeType(stack); - Material material = ((BlockMaterialPipe) blockPipe).getItemMaterial(stack); - return material == null ? " " : pipeType.getOrePrefix().getLocalNameForItem(material); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/TileEntityMaterialPipeBase.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/material/TileEntityMaterialPipeBase.java deleted file mode 100644 index 2076f07300f..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/block/material/TileEntityMaterialPipeBase.java +++ /dev/null @@ -1,109 +0,0 @@ -package gregtech.api.graphnet.pipenetold.block.material; - -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.Materials; -import gregtech.api.unification.material.registry.MaterialRegistry; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.PacketBuffer; - -import org.jetbrains.annotations.NotNull; - -import static gregtech.api.capability.GregtechDataCodes.UPDATE_PIPE_MATERIAL; - -public abstract class TileEntityMaterialPipeBase & IMaterialPipeType, - NodeDataType extends IPipeNetData, Edge extends NetEdge> - extends TileEntityPipeBase - implements IMaterialPipeTile { - - private Material pipeMaterial = Materials.Aluminium; - - @Override - public Material getPipeMaterial() { - return pipeMaterial; - } - - public void setPipeData(BlockPipe pipeBlock, PipeType pipeType, - Material pipeMaterial) { - this.pipeMaterial = pipeMaterial; - super.setPipeData(pipeBlock, pipeType); - if (!getWorld().isRemote) { - writeCustomData(UPDATE_PIPE_MATERIAL, this::writePipeMaterial); - } - } - - @Override - public void setPipeData(BlockPipe pipeBlock, PipeType pipeType) { - throw new UnsupportedOperationException("Unsupported for TileEntityMaterialMaterialPipeBase"); - } - - @Override - public int getDefaultPaintingColor() { - return pipeMaterial == null ? super.getDefaultPaintingColor() : pipeMaterial.getMaterialRGB(); - } - - @Override - public BlockMaterialPipe getPipeBlock() { - return (BlockMaterialPipe) super.getPipeBlock(); - } - - @Override - public void transferDataFrom(IPipeTile tileEntity) { - super.transferDataFrom(tileEntity); - this.pipeMaterial = ((IMaterialPipeTile) tileEntity).getPipeMaterial(); - } - - @NotNull - @Override - public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { - super.writeToNBT(compound); - compound.setString("PipeMaterial", pipeMaterial.toString()); - return compound; - } - - @Override - public void readFromNBT(@NotNull NBTTagCompound compound) { - super.readFromNBT(compound); - MaterialRegistry registry = getPipeBlock().getMaterialRegistry(); - this.pipeMaterial = registry.getObject(compound.getString("PipeMaterial")); - if (this.pipeMaterial == null) { - this.pipeMaterial = registry.getFallbackMaterial(); - } - this.getNode().setData(getPipeBlock().createProperties(this)); - if (!compound.hasKey("PipeNetVersion")) markAsNeedingOldNetSetup(); - } - - private void writePipeMaterial(@NotNull PacketBuffer buf) { - buf.writeVarInt(getPipeBlock().getMaterialRegistry().getIDForObject(pipeMaterial)); - } - - private void readPipeMaterial(@NotNull PacketBuffer buf) { - this.pipeMaterial = getPipeBlock().getMaterialRegistry().getObjectById(buf.readVarInt()); - } - - @Override - public void writeInitialSyncData(PacketBuffer buf) { - buf.writeVarInt(getPipeBlock().getMaterialRegistry().getIDForObject(pipeMaterial)); - super.writeInitialSyncData(buf); - } - - @Override - public void receiveInitialSyncData(PacketBuffer buf) { - this.pipeMaterial = getPipeBlock().getMaterialRegistry().getObjectById(buf.readVarInt()); - super.receiveInitialSyncData(buf); - } - - @Override - public void receiveCustomData(int discriminator, PacketBuffer buf) { - super.receiveCustomData(discriminator, buf); - if (discriminator == UPDATE_PIPE_MATERIAL) { - readPipeMaterial(buf); - scheduleRenderUpdate(); - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/block/simple/BlockSimplePipe.java b/src/main/java/gregtech/api/graphnet/pipenetold/block/simple/BlockSimplePipe.java deleted file mode 100644 index a4eec35eff6..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/block/simple/BlockSimplePipe.java +++ /dev/null @@ -1,44 +0,0 @@ -package gregtech.api.graphnet.pipenetold.block.simple; - -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; - -import net.minecraft.item.ItemStack; - -public abstract class BlockSimplePipe & IPipeType, - NodeDataType extends IPipeNetData, Edge extends NetEdge, - WorldPipeNetType extends WorldPipeNetBase> - extends BlockPipe { - - @Override - public NodeDataType createProperties(IPipeTile pipeTile) { - return createProperties(pipeTile.getPipeType()); - } - - @Override - public NodeDataType createItemProperties(ItemStack itemStack) { - return createProperties(getItemPipeType(itemStack)); - } - - protected abstract NodeDataType createProperties(PipeType pipeType); - - @Override - public ItemStack getDropItem(IPipeTile pipeTile) { - return new ItemStack(this, 1, pipeTile.getPipeType().ordinal()); - } - - @Override - public PipeType getItemPipeType(ItemStack itemStack) { - return getPipeTypeClass().getEnumConstants()[itemStack.getMetadata()]; - } - - @Override - public void setTileEntityData(TileEntityPipeBase pipeTile, ItemStack itemStack) { - pipeTile.setPipeData(this, getItemPipeType(itemStack)); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistanceNetwork.java b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistanceNetwork.java index fe42a1478e0..8ec3219eaa2 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistanceNetwork.java +++ b/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistanceNetwork.java @@ -1,7 +1,5 @@ package gregtech.api.graphnet.pipenetold.longdist; -import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; - import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -331,7 +329,7 @@ public static WorldData get(World world) { if (worldData != null) { return worldData; } - String DATA_ID = WorldPipeNetBase.getDataID("long_dist_pipe", world); + String DATA_ID = getDataID("long_dist_pipe", world); WorldData netWorldData = (WorldData) world.loadData(WorldData.class, DATA_ID); if (netWorldData == null) { netWorldData = new WorldData(DATA_ID); @@ -342,6 +340,13 @@ public static WorldData get(World world) { return netWorldData; } + public static String getDataID(final String baseID, final World world) { + if (world == null || world.isRemote) + throw new RuntimeException("Long Distance Nets should only be created on the server!"); + int dimension = world.provider.getDimension(); + return dimension == 0 ? baseID : baseID + '.' + dimension; + } + private static long getChunkPos(BlockPos pos) { return ChunkPos.asLong(pos.getX() >> 4, pos.getZ() >> 4); } diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/predicate/FilteredEdgePredicate.java b/src/main/java/gregtech/api/graphnet/pipenetold/predicate/FilteredEdgePredicate.java deleted file mode 100644 index 1493a11fdc0..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/predicate/FilteredEdgePredicate.java +++ /dev/null @@ -1,73 +0,0 @@ -package gregtech.api.graphnet.pipenetold.predicate; - -import gregtech.api.util.IDirtyNotifiable; -import gregtech.common.covers.filter.BaseFilterContainer; - -import net.minecraft.nbt.NBTTagCompound; - -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -public abstract class FilteredEdgePredicate> extends IEdgePredicateOld - implements IShutteredEdgePredicate { - - protected static final IDirtyNotifiable DECOY = () -> {}; - - protected boolean shutteredSource; - protected boolean shutteredTarget; - - protected @NotNull BaseFilterContainer sourceFilter; - protected @NotNull BaseFilterContainer targetFilter; - - public FilteredEdgePredicate() { - sourceFilter = this.getDefaultFilterContainer(); - targetFilter = this.getDefaultFilterContainer(); - } - - @Override - public void setShutteredSource(boolean shutteredSource) { - this.shutteredSource = shutteredSource; - } - - @Override - public void setShutteredTarget(boolean shutteredTarget) { - this.shutteredTarget = shutteredTarget; - } - - public void setSourceFilter(@NotNull BaseFilterContainer sourceFilter) { - this.sourceFilter = sourceFilter; - } - - public void setTargetFilter(@NotNull BaseFilterContainer targetFilter) { - this.targetFilter = targetFilter; - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tag = new NBTTagCompound(); - if (shutteredSource) tag.setBoolean("ShutteredSource", true); - if (shutteredTarget) tag.setBoolean("ShutteredTarget", true); - if (this.sourceFilter.getFilter() != null) { - tag.setTag("SourceFilter", this.sourceFilter.serializeNBT()); - } - if (this.targetFilter.getFilter() != null) { - tag.setTag("TargetFilter", this.targetFilter.serializeNBT()); - } - return tag; - } - - @Override - public void deserializeNBT(@NotNull NBTTagCompound nbt) { - shutteredSource = nbt.getBoolean("ShutteredSource"); - shutteredTarget = nbt.getBoolean("ShutteredTarget"); - if (nbt.hasKey("SourceFilter")) { - this.sourceFilter.deserializeNBT(nbt.getCompoundTag("SourceFilter")); - } - if (nbt.hasKey("TargetFilter")) { - this.targetFilter.deserializeNBT(nbt.getCompoundTag("TargetFilter")); - } - } - - @Contract("-> new") - protected abstract @NotNull BaseFilterContainer getDefaultFilterContainer(); -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/predicate/IShutteredEdgePredicate.java b/src/main/java/gregtech/api/graphnet/pipenetold/predicate/IShutteredEdgePredicate.java deleted file mode 100644 index d14316f2861..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/predicate/IShutteredEdgePredicate.java +++ /dev/null @@ -1,8 +0,0 @@ -package gregtech.api.graphnet.pipenetold.predicate; - -public interface IShutteredEdgePredicate { - - void setShutteredSource(boolean shutteredSource); - - void setShutteredTarget(boolean shutteredTarget); -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/predicate/ShutteredEdgePredicate.java b/src/main/java/gregtech/api/graphnet/pipenetold/predicate/ShutteredEdgePredicate.java deleted file mode 100644 index 8987bd7450e..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/predicate/ShutteredEdgePredicate.java +++ /dev/null @@ -1,50 +0,0 @@ -package gregtech.api.graphnet.pipenetold.predicate; - -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import net.minecraft.nbt.NBTTagCompound; - -import org.jetbrains.annotations.NotNull; - -public class ShutteredEdgePredicate extends IEdgePredicateOld - implements IShutteredEdgePredicate { - - public final static String KEY = "Basic"; - - protected boolean shutteredSource; - protected boolean shutteredTarget; - - @Override - public void setShutteredSource(boolean shutteredSource) { - this.shutteredSource = shutteredSource; - } - - @Override - public void setShutteredTarget(boolean shutteredTarget) { - this.shutteredTarget = shutteredTarget; - } - - @Override - public boolean test(IPredicateTestObject o) { - return !(shutteredSource || shutteredTarget); - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tag = new NBTTagCompound(); - if (shutteredSource) tag.setBoolean("ShutteredSource", true); - if (shutteredTarget) tag.setBoolean("ShutteredTarget", true); - return tag; - } - - @Override - public void deserializeNBT(@NotNull NBTTagCompound nbt) { - shutteredSource = nbt.getBoolean("ShutteredSource"); - shutteredTarget = nbt.getBoolean("ShutteredTarget"); - } - - @Override - protected String predicateName() { - return KEY; - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/tile/IPipeTile.java b/src/main/java/gregtech/api/graphnet/pipenetold/tile/IPipeTile.java deleted file mode 100644 index 1613131bfc1..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/tile/IPipeTile.java +++ /dev/null @@ -1,111 +0,0 @@ -package gregtech.api.graphnet.pipenetold.tile; - -import gregtech.api.graphnet.pipenetold.PipeNetNode; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.metatileentity.interfaces.INeighborCache; -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.unification.material.Material; - -import net.minecraft.network.PacketBuffer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; - -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; - -public interface IPipeTile & IPipeType, - NodeDataType extends IPipeNetData, Edge extends NetEdge> extends INeighborCache { - - World getPipeWorld(); - - BlockPos getPipePos(); - - @Override - default World world() { - return getPipeWorld(); - } - - @Override - default BlockPos pos() { - return getPipePos(); - } - - default long getTickTimer() { - return getPipeWorld().getTotalWorldTime(); - } - - BlockPipe getPipeBlock(); - - void transferDataFrom(IPipeTile sourceTile); - - int getPaintingColor(); - - void setPaintingColor(int paintingColor); - - boolean isPainted(); - - int getDefaultPaintingColor(); - - int getConnections(); - - int getNumConnections(); - - boolean isConnected(EnumFacing side); - - void setConnection(EnumFacing side, boolean connected, boolean fromNeighbor); - - void onConnectionChange(); - - // if a face is blocked it will still render as connected, but it won't be able to receive stuff from that direction - default boolean canHaveBlockedFaces() { - return true; - } - - int getBlockedConnections(); - - void onBlockedChange(); - - boolean isFaceBlocked(EnumFacing side); - - void setFaceBlocked(EnumFacing side, boolean blocked); - - int getVisualConnections(); - - PipeType getPipeType(); - - NodeDataType getNodeData(); - - PipeNetNode getNode(); - - @Nullable - TileEntity getNonPipeNeighbour(EnumFacing facing); - - PipeCoverableImplementation getCoverableImplementation(); - - @Nullable - Material getFrameMaterial(); - - boolean supportsTicking(); - - IPipeTile setSupportsTicking(); - - boolean canPlaceCoverOnSide(EnumFacing side); - - T getCapability(Capability capability, EnumFacing side); - - T getCapabilityInternal(Capability capability, EnumFacing side); - - void notifyBlockUpdate(); - - void writeCoverCustomData(int id, Consumer writer); - - void markAsDirty(); - - boolean isValidTile(); -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/tile/PipeCoverableImplementation.java b/src/main/java/gregtech/api/graphnet/pipenetold/tile/PipeCoverableImplementation.java deleted file mode 100644 index 6dfc4a65a8c..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/tile/PipeCoverableImplementation.java +++ /dev/null @@ -1,300 +0,0 @@ -package gregtech.api.graphnet.pipenetold.tile; - -import gregtech.api.cover.Cover; -import gregtech.api.cover.CoverHolder; -import gregtech.api.cover.CoverSaveHandler; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.util.GTUtility; -import gregtech.common.ConfigHolder; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.PacketBuffer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.ITickable; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.EnumMap; -import java.util.function.Consumer; - -import static gregtech.api.capability.GregtechDataCodes.*; - -public class PipeCoverableImplementation implements CoverHolder { - - private IPipeTile holder; - private final EnumMap covers = new EnumMap<>(EnumFacing.class); - private final int[] sidedRedstoneInput = new int[6]; - - public PipeCoverableImplementation(IPipeTile holder) { - this.holder = holder; - } - - public void transferDataTo(PipeCoverableImplementation destImpl) { - for (EnumFacing side : EnumFacing.VALUES) { - Cover cover = covers.get(side); - if (cover == null) continue; - NBTTagCompound tagCompound = new NBTTagCompound(); - cover.writeToNBT(tagCompound); - Cover newCover = cover.getDefinition().createCover(destImpl, side); - newCover.readFromNBT(tagCompound); - destImpl.covers.put(side, newCover); - } - } - - @Override - public final void addCover(@NotNull EnumFacing side, @NotNull Cover cover) { - if (cover instanceof ITickable && !holder.supportsTicking()) { - IPipeTile newHolderTile = holder.setSupportsTicking(); - newHolderTile.getCoverableImplementation().addCover(side, cover); - holder = newHolderTile; - return; - } - // we checked before if the side already has a cover - this.covers.put(side, cover); - if (!getWorld().isRemote) { - // do not sync or handle logic on client side - CoverSaveHandler.writeCoverPlacement(this, COVER_ATTACHED_PIPE, side, cover); - if (cover.shouldAutoConnectToPipes()) { - holder.setConnection(side, true, false); - } - } - - holder.notifyBlockUpdate(); - holder.markAsDirty(); - } - - @Override - public final void removeCover(@NotNull EnumFacing side) { - Cover cover = getCoverAtSide(side); - if (cover == null) return; - - dropCover(side); - covers.remove(side); - writeCustomData(COVER_REMOVED_PIPE, buffer -> buffer.writeByte(side.getIndex())); - if (cover.shouldAutoConnectToPipes()) { - holder.setConnection(side, false, false); - } - holder.notifyBlockUpdate(); - holder.markAsDirty(); - } - - @SuppressWarnings("unchecked") - @Override - public @NotNull ItemStack getStackForm() { - BlockPipe pipeBlock = holder.getPipeBlock(); - return pipeBlock.getDropItem(holder); - } - - public void onLoad() { - for (EnumFacing side : EnumFacing.VALUES) { - this.sidedRedstoneInput[side.getIndex()] = GTUtility.getRedstonePower(getWorld(), getPos(), side); - } - } - - @Override - public final int getInputRedstoneSignal(@NotNull EnumFacing side, boolean ignoreCover) { - if (!ignoreCover && getCoverAtSide(side) != null) { - return 0; // covers block input redstone signal for machine - } - return sidedRedstoneInput[side.getIndex()]; - } - - public void updateInputRedstoneSignals() { - for (EnumFacing side : EnumFacing.VALUES) { - int redstoneValue = GTUtility.getRedstonePower(getWorld(), getPos(), side); - int currentValue = sidedRedstoneInput[side.getIndex()]; - if (redstoneValue != currentValue) { - this.sidedRedstoneInput[side.getIndex()] = redstoneValue; - Cover cover = getCoverAtSide(side); - if (cover != null) { - cover.onRedstoneInputSignalChange(redstoneValue); - } - } - } - } - - @Override - public void notifyBlockUpdate() { - holder.notifyBlockUpdate(); - } - - @Override - public void scheduleRenderUpdate() { - BlockPos pos = getPos(); - getWorld().markBlockRangeForRenderUpdate( - pos.getX() - 1, pos.getY() - 1, pos.getZ() - 1, - pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1); - } - - @Override - public double getCoverPlateThickness() { - float thickness = holder.getPipeType().getThickness(); - // no cover plate for pipes >= 1 block thick - if (thickness >= 1) return 0; - - // If the available space for the cover is less than the regular cover plate thickness, use that - - // need to divide by 2 because thickness is centered on the block, so the space is half on each side of the pipe - return Math.min(1.0 / 16.0, (1.0 - thickness) / 2); - } - - @Override - public boolean shouldRenderCoverBackSides() { - return false; - } - - @Override - public int getPaintingColorForRendering() { - return ConfigHolder.client.defaultPaintingColor; - } - - @Override - public boolean canPlaceCoverOnSide(@NotNull EnumFacing side) { - return holder.canPlaceCoverOnSide(side); - } - - @Override - public final boolean acceptsCovers() { - return covers.size() < EnumFacing.VALUES.length; - } - - public boolean canConnectRedstone(@Nullable EnumFacing side) { - // so far null side means either upwards or downwards redstone wire connection - // so check both top cover and bottom cover - if (side == null) { - return canConnectRedstone(EnumFacing.UP) || - canConnectRedstone(EnumFacing.DOWN); - } - Cover cover = getCoverAtSide(side); - return cover != null && cover.canConnectRedstone(); - } - - public int getOutputRedstoneSignal(@Nullable EnumFacing side) { - if (side == null) { - return getHighestOutputRedstoneSignal(); - } - Cover cover = getCoverAtSide(side); - return cover == null ? 0 : cover.getRedstoneSignalOutput(); - } - - public int getHighestOutputRedstoneSignal() { - int highestSignal = 0; - for (EnumFacing side : EnumFacing.VALUES) { - Cover cover = getCoverAtSide(side); - if (cover == null) continue; - highestSignal = Math.max(highestSignal, cover.getRedstoneSignalOutput()); - } - return highestSignal; - } - - public void update() { - if (!getWorld().isRemote) { - updateCovers(); - } - } - - @Override - public void writeCoverData(@NotNull Cover cover, int discriminator, @NotNull Consumer<@NotNull PacketBuffer> buf) { - writeCustomData(UPDATE_COVER_DATA_PIPE, buffer -> { - buffer.writeByte(cover.getAttachedSide().getIndex()); - buffer.writeVarInt(discriminator); - buf.accept(buffer); - }); - } - - public void writeInitialSyncData(PacketBuffer buf) { - CoverSaveHandler.writeInitialSyncData(buf, this); - } - - public void readInitialSyncData(PacketBuffer buf) { - CoverSaveHandler.receiveInitialSyncData(buf, this); - } - - @Override - public void writeCustomData(int dataId, @NotNull Consumer writer) { - holder.writeCoverCustomData(dataId, writer); - } - - public void readCustomData(int dataId, PacketBuffer buf) { - if (dataId == COVER_ATTACHED_PIPE) { - CoverSaveHandler.readCoverPlacement(buf, this); - } else if (dataId == COVER_REMOVED_PIPE) { - // cover removed event - EnumFacing placementSide = EnumFacing.VALUES[buf.readByte()]; - this.covers.remove(placementSide); - holder.scheduleRenderUpdate(); - } else if (dataId == UPDATE_COVER_DATA_PIPE) { - // cover custom data received - EnumFacing coverSide = EnumFacing.VALUES[buf.readByte()]; - Cover cover = getCoverAtSide(coverSide); - int internalId = buf.readVarInt(); - if (cover != null) { - cover.readCustomData(internalId, buf); - } - } - } - - public void writeToNBT(NBTTagCompound data) { - CoverSaveHandler.writeCoverNBT(data, this); - } - - public void readFromNBT(NBTTagCompound data) { - CoverSaveHandler.readCoverNBT(data, this, covers::put); - } - - @Override - public World getWorld() { - return holder.getPipeWorld(); - } - - @Override - public BlockPos getPos() { - return holder.getPipePos(); - } - - public TileEntity getTileEntityHere() { - return holder instanceof TileEntity te ? te : getWorld().getTileEntity(getPos()); - } - - @Override - public @Nullable TileEntity getNeighbor(@NotNull EnumFacing facing) { - return holder.getNeighbor(facing); - } - - @Override - public long getOffsetTimer() { - return holder.getTickTimer(); - } - - @Nullable - @Override - public Cover getCoverAtSide(@NotNull EnumFacing side) { - return covers.get(side); - } - - @Override - public boolean hasAnyCover() { - return !covers.isEmpty(); - } - - @Override - public void markDirty() { - holder.markAsDirty(); - } - - @Override - public boolean isValid() { - return holder.isValidTile(); - } - - @Override - public T getCapability(Capability capability, EnumFacing side) { - return holder.getCapabilityInternal(capability, side); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java b/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java deleted file mode 100644 index 144847d52ca..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenetold/tile/TileEntityPipeBase.java +++ /dev/null @@ -1,617 +0,0 @@ -package gregtech.api.graphnet.pipenetold.tile; - -import gregtech.api.GregTechAPI; -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.cover.Cover; -import gregtech.api.graphnet.pipenetold.IPipeNetData; -import gregtech.api.graphnet.pipenetold.PipeNetNode; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.metatileentity.NeighborCacheTileEntityBase; -import gregtech.api.metatileentity.SyncedTileEntityBase; -import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; -import gregtech.api.unification.material.Material; - -import net.minecraft.block.Block; -import net.minecraft.block.state.IBlockState; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.PacketBuffer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.ITickable; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.WorldServer; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.Constants.NBT; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Arrays; -import java.util.function.Consumer; - -import static gregtech.api.capability.GregtechDataCodes.*; - -public abstract class TileEntityPipeBase & IPipeType, - NodeDataType extends IPipeNetData, Edge extends NetEdge> extends NeighborCacheTileEntityBase - implements IPipeTile { - - protected final PipeCoverableImplementation coverableImplementation = new PipeCoverableImplementation(this); - /** - * this - no information - * null - neighbor is a pipe - * te - neighbor is the stored value - */ - private final TileEntity[] nonPipeNeighbors = new TileEntity[6]; - private boolean nonPipeNeighborsInvalidated = false; - protected int paintingColor = -1; - /** - * Our node stores connection data and NodeData data - */ - protected @Nullable PipeNetNode pipeNetNode; - private BlockPipe pipeBlock; - private PipeType pipeType = getPipeTypeClass().getEnumConstants()[0]; - @Nullable - private Material frameMaterial; - // set when this pipe is replaced with a ticking variant to redirect sync packets - private TileEntityPipeBase tickingPipe; - - private boolean nbtLoad = false; - private boolean needsOldNetSetup = false; - - public TileEntityPipeBase() { - super(false); - invalidateNeighbors(); - } - - public void setPipeData(BlockPipe pipeBlock, PipeType pipeType) { - this.pipeBlock = pipeBlock; - this.pipeType = pipeType; - this.getNode().setData(getPipeBlock().createProperties(this)); - if (!getWorld().isRemote) { - writeCustomData(UPDATE_PIPE_TYPE, this::writePipeProperties); - } - } - - @Override - public void transferDataFrom(IPipeTile tileEntity) { - this.pipeType = tileEntity.getPipeType(); - this.paintingColor = tileEntity.getPaintingColor(); - this.pipeNetNode = tileEntity.getNode(); - this.pipeNetNode.setData(getPipeBlock().createProperties(this)); - if (tileEntity instanceof SyncedTileEntityBase pipeBase) { - addPacketsFrom(pipeBase); - } - coverableImplementation.transferDataTo(tileEntity.getCoverableImplementation()); - setFrameMaterial(tileEntity.getFrameMaterial()); - } - - @Override - public PipeNetNode getNode() { - if (pipeNetNode == null) { - if (this.getPipeWorld().isRemote) - pipeNetNode = new PipeNetNode<>(this); - else pipeNetNode = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()).getOrCreateNode(this); - } - return pipeNetNode; - } - - @Override - protected void setWorldCreate(@NotNull World worldIn) { - this.setWorld(worldIn); - } - - public abstract Class getPipeTypeClass(); - - @Nullable - @Override - public Material getFrameMaterial() { - return frameMaterial; - } - - public void setFrameMaterial(@Nullable Material frameMaterial) { - this.frameMaterial = frameMaterial; - if (world != null && world.isRemote) { - writeCustomData(UPDATE_FRAME_MATERIAL, buf -> { - buf.writeVarInt(frameMaterial == null ? -1 : frameMaterial.getRegistry().getNetworkId()); - buf.writeVarInt(frameMaterial == null ? -1 : frameMaterial.getId()); - }); - } - } - - @Override - public boolean supportsTicking() { - return this instanceof ITickable; - } - - @Override - public World getPipeWorld() { - return getWorld(); - } - - @Override - public BlockPos getPipePos() { - return getPos(); - } - - @SuppressWarnings("ConstantConditions") // yes this CAN actually be null - @Override - public void markDirty() { - if (getWorld() != null && getPos() != null) { - getWorld().markChunkDirty(getPos(), this); - } - } - - @Override - protected void invalidateNeighbors() { - super.invalidateNeighbors(); - if (!this.nonPipeNeighborsInvalidated) { - Arrays.fill(nonPipeNeighbors, this); - this.nonPipeNeighborsInvalidated = true; - } - } - - public @Nullable TileEntity getNonPipeNeighbour(EnumFacing facing) { - if (world == null || pos == null) return null; - int i = facing.getIndex(); - TileEntity neighbor = this.nonPipeNeighbors[i]; - if (neighbor == null) return null; - if (neighbor == this || (neighbor.isInvalid())) { - neighbor = getNeighbor(facing); - if (neighbor instanceof IPipeTile) neighbor = null; - this.nonPipeNeighbors[i] = neighbor; - this.nonPipeNeighborsInvalidated = false; - } - return neighbor; - } - - @Override - public void onNeighborChanged(@NotNull EnumFacing facing) { - super.onNeighborChanged(facing); - this.nonPipeNeighbors[facing.getIndex()] = this; - if (!this.getPipeWorld().isRemote) this.getNode().net.updateActiveNodeStatus(this.getNode()); - } - - @Override - public PipeCoverableImplementation getCoverableImplementation() { - return coverableImplementation; - } - - @Override - public boolean canPlaceCoverOnSide(EnumFacing side) { - return true; - } - - @Override - public IPipeTile setSupportsTicking() { - if (supportsTicking()) { - return this; - } - if (this.tickingPipe != null) { - // pipe was already set to tick before - // reuse ticking pipe - return this.tickingPipe; - } - // create new tickable tile entity, transfer data, and replace it - TileEntityPipeBase newTile = getPipeBlock().createNewTileEntity(true); - if (!newTile.supportsTicking()) throw new IllegalStateException("Expected pipe to be ticking, but isn't!"); - newTile.transferDataFrom(this); - getWorld().setTileEntity(getPos(), newTile); - this.tickingPipe = newTile; - return newTile; - } - - @Override - public BlockPipe getPipeBlock() { - if (pipeBlock == null) { - Block block = getBlockState().getBlock(); - // noinspection unchecked - this.pipeBlock = block instanceof BlockPipeblockPipe ? - (BlockPipe) blockPipe : null; - } - return pipeBlock; - } - - @Override - public int getConnections() { - return this.getNode().getOpenConnections(); - } - - @Override - public int getNumConnections() { - int count = 0; - int connections = getConnections(); - while (connections > 0) { - count++; - connections = connections & (connections - 1); - } - return count; - } - - @Override - public int getBlockedConnections() { - return this.getNode().getBlockedConnections(); - } - - @Override - public int getPaintingColor() { - return isPainted() ? paintingColor : getDefaultPaintingColor(); - } - - @Override - public void setPaintingColor(int paintingColor) { - this.paintingColor = paintingColor; - if (!getWorld().isRemote) { - getPipeBlock().getWorldPipeNet(getWorld()).updateMark(getPos(), getCableMark()); - writeCustomData(UPDATE_PAINT, buffer -> buffer.writeInt(paintingColor)); - markDirty(); - } - } - - @Override - public boolean isPainted() { - return this.paintingColor != -1; - } - - @Override - public int getDefaultPaintingColor() { - return 0xFFFFFF; - } - - @Override - public boolean isConnected(EnumFacing side) { - return this.getNode().isConnected(side); - } - - public static boolean isConnected(int connections, EnumFacing side) { - return (connections & 1 << side.getIndex()) > 0; - } - - @Override - public void setConnection(EnumFacing side, boolean connected, boolean fromNeighbor) { - if (!getWorld().isRemote) { - if (isConnected(side) == connected) return; - getPipeBlock().getWorldPipeNet(getWorld()).updateActiveConnections(getPos(), side, connected); - } - } - - @Override - public void onConnectionChange() { - if (!getWorld().isRemote) { - this.scheduleRenderUpdate(); - this.markDirty(); - writeCustomData(UPDATE_CONNECTIONS, buffer -> buffer.writeVarInt(this.getConnections())); - } - } - - @Override - public void setFaceBlocked(EnumFacing side, boolean blocked) { - if (!getWorld().isRemote && canHaveBlockedFaces()) { - if (isFaceBlocked(side) == blocked) return; - getPipeBlock().getWorldPipeNet(getWorld()).updateBlockedConnections(getPos(), side, blocked); - } - } - - @Override - public void onBlockedChange() { - if (!getWorld().isRemote) { - this.scheduleRenderUpdate(); - this.markDirty(); - writeCustomData(UPDATE_BLOCKED_CONNECTIONS, buf -> buf.writeVarInt(this.getBlockedConnections())); - } - } - - @Override - public boolean isFaceBlocked(EnumFacing side) { - return this.getNode().isBlocked(side); - } - - public static boolean isFaceBlocked(int blockedConnections, EnumFacing side) { - return (blockedConnections & (1 << side.getIndex())) != 0; - } - - @Override - public PipeType getPipeType() { - return pipeType; - } - - @Override - public NodeDataType getNodeData() { - // the only thing standing between this and a stack overflow error - if (this.pipeNetNode == null) return getPipeBlock().createProperties(this); - - if (this.getNode().getData() == null) { - this.getNode().setData(getPipeBlock().createProperties(this)); - } - return this.getNode().getData(); - } - - private int getCableMark() { - return paintingColor == -1 ? 0 : paintingColor; - } - - /** - * This returns open connections purely for rendering - * - * @return open connections - */ - public int getVisualConnections() { - int connections = getConnections(); - float selfThickness = getPipeType().getThickness(); - for (EnumFacing facing : EnumFacing.values()) { - if (isConnected(facing)) { - if (world.getTileEntity(pos.offset(facing)) instanceof IPipeTilepipeTile && - pipeTile.isConnected(facing.getOpposite()) && - pipeTile.getPipeType().getThickness() < selfThickness) { - connections |= 1 << (facing.getIndex() + 6); - } - if (getCoverableImplementation().getCoverAtSide(facing) != null) { - connections |= 1 << (facing.getIndex() + 12); - } - } - } - return connections; - } - - public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { - if (capability == GregtechTileCapabilities.CAPABILITY_COVER_HOLDER) { - return GregtechTileCapabilities.CAPABILITY_COVER_HOLDER.cast(getCoverableImplementation()); - } - return super.getCapability(capability, facing); - } - - @Nullable - @Override - public final T getCapability(@NotNull Capability capability, @Nullable EnumFacing facing) { - T pipeCapability = getPipeBlock() == null ? null : getCapabilityInternal(capability, facing); - - if (capability == GregtechTileCapabilities.CAPABILITY_COVER_HOLDER) { - return pipeCapability; - } - - Cover cover = facing == null ? null : coverableImplementation.getCoverAtSide(facing); - if (cover == null) { - if (facing == null || isConnected(facing)) { - return pipeCapability; - } - return null; - } - - T coverCapability = cover.getCapability(capability, pipeCapability); - if (coverCapability == pipeCapability) { - if (isConnected(facing)) { - return pipeCapability; - } - return null; - } - return coverCapability; - } - - @Override - public final boolean hasCapability(@NotNull Capability capability, @Nullable EnumFacing facing) { - return getCapability(capability, facing) != null; - } - - @NotNull - @Override - public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { - super.writeToNBT(compound); - BlockPipe pipeBlock = getPipeBlock(); - if (pipeBlock != null) { - // noinspection ConstantConditions - compound.setString("WorldPipeBlock", pipeBlock.getRegistryName().toString()); - } - compound.setInteger("PipeNetVersion", 2); - compound.setInteger("PipeType", pipeType.ordinal()); - compound.setInteger("Connections", getNode().getOpenConnections()); - compound.setInteger("BlockedConnections", getNode().getBlockedConnections()); - if (isPainted()) { - compound.setInteger("InsulationColor", paintingColor); - } - compound.setString("FrameMaterial", frameMaterial == null ? "" : frameMaterial.getRegistryName()); - this.coverableImplementation.writeToNBT(compound); - return compound; - } - - @Override - public void readFromNBT(@NotNull NBTTagCompound compound) { - if (this.tickingPipe != null) { - this.tickingPipe.readFromNBT(compound); - return; - } - super.readFromNBT(compound); - if (compound.hasKey("WorldPipeBlock", NBT.TAG_STRING)) { - Block block = Block.REGISTRY.getObject(new ResourceLocation(compound.getString("WorldPipeBlock"))); - // noinspection unchecked - this.pipeBlock = block instanceof BlockPipeblockPipe ? - (BlockPipe) blockPipe : null; - } - this.pipeType = getPipeTypeClass().getEnumConstants()[compound.getInteger("PipeType")]; - - this.nbtLoad = true; - if (compound.hasKey("Connections")) { - this.getNode().setOpenConnections(compound.getInteger("Connections")); - } else if (compound.hasKey("BlockedConnectionsMap")) { - int connections = 0; - NBTTagCompound blockedConnectionsTag = compound.getCompoundTag("BlockedConnectionsMap"); - for (String attachmentTypeKey : blockedConnectionsTag.getKeySet()) { - int blockedConnections = blockedConnectionsTag.getInteger(attachmentTypeKey); - connections |= blockedConnections; - } - this.getNode().setOpenConnections(connections); - } - this.getNode().setBlockedConnections(compound.getInteger("BlockedConnections")); - - if (compound.hasKey("InsulationColor")) { - this.paintingColor = compound.getInteger("InsulationColor"); - } - String frameMaterialName = compound.getString("FrameMaterial"); - if (!frameMaterialName.isEmpty()) { - this.frameMaterial = GregTechAPI.materialManager.getMaterial(frameMaterialName); - } - - this.coverableImplementation.readFromNBT(compound); - if (this.tickingPipe != null && this.coverableImplementation.hasAnyCover()) { - // one of the covers set the pipe to ticking, and we need to send over the rest of the covers - this.coverableImplementation.transferDataTo(this.tickingPipe.coverableImplementation); - } - this.nbtLoad = false; - - if (!compound.hasKey("PipeNetVersion") && !compound.hasKey("PipeMaterial")) markAsNeedingOldNetSetup(); - } - - protected void markAsNeedingOldNetSetup() { - this.needsOldNetSetup = true; - } - - protected void doOldNetSetup() { - // TODO inexplicable crash during world load when old net setup required - // something to do with removing the tile entities that the chunk is iterating over to load - WorldPipeNetBase net = this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()); - for (EnumFacing facing : EnumFacing.VALUES) { - PipeNetNode nodeOffset = net.getNode(this.getPipePos().offset(facing)); - if (nodeOffset == null) continue; - if (net.isDirected()) { - // offset node might've been read before us, so we have to cover for it. - if (nodeOffset.isConnected(facing.getOpposite())) { - net.addEdge(nodeOffset, this.getNode(), null); - net.predicateEdge(nodeOffset, this.getNode(), facing.getOpposite()); - } - } - if (this.isConnected(facing)) { - net.addEdge(this.getNode(), nodeOffset, null); - net.predicateEdge(this.getNode(), nodeOffset, facing); - } - } - net.markNodeAsOldData(this.getNode()); - } - - @Override - public void onLoad() { - super.onLoad(); - if (this.needsOldNetSetup) doOldNetSetup(); - } - - protected void writePipeProperties(PacketBuffer buf) { - buf.writeVarInt(pipeType.ordinal()); - } - - protected void readPipeProperties(PacketBuffer buf) { - this.pipeType = getPipeTypeClass().getEnumConstants()[buf.readVarInt()]; - } - - @Override - public void writeInitialSyncData(PacketBuffer buf) { - writePipeProperties(buf); - buf.writeVarInt(this.getNode().getOpenConnections()); - buf.writeVarInt(this.getNode().getBlockedConnections()); - buf.writeInt(paintingColor); - buf.writeVarInt(frameMaterial == null ? -1 : frameMaterial.getRegistry().getNetworkId()); - buf.writeVarInt(frameMaterial == null ? -1 : frameMaterial.getId()); - this.coverableImplementation.writeInitialSyncData(buf); - } - - @Override - public void receiveInitialSyncData(PacketBuffer buf) { - if (this.tickingPipe != null) { - this.tickingPipe.receiveInitialSyncData(buf); - return; - } - readPipeProperties(buf); - this.getNode().setOpenConnections(buf.readVarInt()); - this.getNode().setBlockedConnections(buf.readVarInt()); - this.paintingColor = buf.readInt(); - int registryId = buf.readVarInt(); - int frameMaterialId = buf.readVarInt(); - if (registryId >= 0 && frameMaterialId >= 0) { - this.frameMaterial = GregTechAPI.materialManager.getRegistry(registryId).getObjectById(frameMaterialId); - } else { - this.frameMaterial = null; - } - this.coverableImplementation.readInitialSyncData(buf); - if (this.tickingPipe != null && this.coverableImplementation.hasAnyCover()) { - // one of the covers set the pipe to ticking, and we need to send over the rest of the covers - this.coverableImplementation.transferDataTo(this.tickingPipe.coverableImplementation); - } - } - - @Override - public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { - if (this.tickingPipe != null) { - this.tickingPipe.receiveCustomData(discriminator, buf); - return; - } - if (discriminator == UPDATE_PAINT) { - this.paintingColor = buf.readInt(); - } else if (discriminator == UPDATE_CONNECTIONS) { - this.getNode().setOpenConnections(buf.readVarInt()); - } else if (discriminator == SYNC_COVER_IMPLEMENTATION) { - this.coverableImplementation.readCustomData(buf.readVarInt(), buf); - } else if (discriminator == UPDATE_PIPE_TYPE) { - readPipeProperties(buf); - } else if (discriminator == UPDATE_BLOCKED_CONNECTIONS) { - this.getNode().setBlockedConnections(buf.readVarInt()); - } else if (discriminator == UPDATE_FRAME_MATERIAL) { - int registryId = buf.readVarInt(); - int frameMaterialId = buf.readVarInt(); - if (registryId >= 0 && frameMaterialId >= 0) { - this.frameMaterial = GregTechAPI.materialManager.getRegistry(registryId).getObjectById(frameMaterialId); - } else { - this.frameMaterial = null; - } - } else return; - scheduleRenderUpdate(); - } - - @Override - public void writeCoverCustomData(int id, Consumer writer) { - writeCustomData(SYNC_COVER_IMPLEMENTATION, buffer -> { - buffer.writeVarInt(id); - writer.accept(buffer); - }); - } - - @Override - public void notifyBlockUpdate() { - getWorld().notifyNeighborsOfStateChange(getPos(), getBlockType(), true); - } - - @Override - public void markAsDirty() { - markDirty(); - // this most notably gets called when the covers of a pipe get updated, aka the edge predicates need syncing. - if (getWorld().isRemote || this.nbtLoad) return; - for (EnumFacing facing : EnumFacing.VALUES) { - if (!isConnected(facing)) continue; - this.getPipeBlock().getWorldPipeNet(this.getPipeWorld()).predicateUndirectedEdge(this.getPipePos(), facing); - } - } - - @Override - public boolean isValidTile() { - return !isInvalid(); - } - - @Override - public boolean shouldRefresh(@NotNull World world, @NotNull BlockPos pos, @NotNull IBlockState oldState, - @NotNull IBlockState newSate) { - // always return true to ensure that the chunk marks the old MTE as invalid - return true; - } - - @Deprecated - public void doExplosion(float explosionPower) { - getWorld().setBlockToAir(getPos()); - if (!getWorld().isRemote) { - ((WorldServer) getWorld()).spawnParticle(EnumParticleTypes.SMOKE_LARGE, getPos().getX() + 0.5, - getPos().getY() + 0.5, getPos().getZ() + 0.5, - 10, 0.2, 0.2, 0.2, 0.0); - } - getWorld().createExplosion(null, getPos().getX() + 0.5, getPos().getY() + 0.5, getPos().getZ() + 0.5, - explosionPower, false); - } -} diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java index b90673cdfef..09e02782ad7 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockControllerBase.java @@ -5,11 +5,11 @@ import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IMultiblockController; import gregtech.api.capability.IMultipleRecipeMaps; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.pattern.*; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.Material; import gregtech.api.util.BlockInfo; import gregtech.api.util.GTLog; @@ -240,9 +240,7 @@ public static TraceabilityPredicate frames(Material... frameMaterials) { .toArray(IBlockState[]::new)) .or(new TraceabilityPredicate(blockWorldState -> { TileEntity tileEntity = blockWorldState.getTileEntity(); - if (!(tileEntity instanceof IPipeTilepipeTile)) { - return false; - } + if (!(tileEntity instanceof PipeTileEntity pipeTile)) return false; return ArrayUtils.contains(frameMaterials, pipeTile.getFrameMaterial()); })); } diff --git a/src/main/java/gregtech/api/util/GTStringUtils.java b/src/main/java/gregtech/api/util/GTStringUtils.java index 6e7649dca2e..5bb3edaa976 100644 --- a/src/main/java/gregtech/api/util/GTStringUtils.java +++ b/src/main/java/gregtech/api/util/GTStringUtils.java @@ -1,10 +1,10 @@ package gregtech.api.util; import gregtech.api.block.machines.MachineItemBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.items.materialitem.MetaPrefixItem; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; import gregtech.api.recipes.ingredients.IntCircuitIngredient; import gregtech.api.unification.material.Material; import gregtech.api.unification.ore.OrePrefix; @@ -55,8 +55,10 @@ public static String prettyPrintItemStack(@NotNull ItemStack stack) { id = "block" + ((BlockCompressed) block).getGtMaterial(stack).toCamelCaseString(); } else if (block instanceof BlockFrame) { id = "frame" + ((BlockFrame) block).getGtMaterial(stack).toCamelCaseString(); - } else if (block instanceof BlockMaterialPipe blockMaterialPipe) { - id = blockMaterialPipe.getPrefix().name + blockMaterialPipe.getItemMaterial(stack).toCamelCaseString(); + } else if (block instanceof PipeMaterialBlock blockMaterialPipe) { + Material mat = blockMaterialPipe.getMaterialForStack(stack); + if (mat != null) + id = blockMaterialPipe.getStructure().getOrePrefix().name + mat.toCamelCaseString(); } if (id != null) { diff --git a/src/main/java/gregtech/client/renderer/pipeold/CableRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/CableRenderer.java deleted file mode 100644 index 68ad587aa50..00000000000 --- a/src/main/java/gregtech/client/renderer/pipeold/CableRenderer.java +++ /dev/null @@ -1,109 +0,0 @@ -package gregtech.client.renderer.pipeold; - -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.unification.material.Material; -import gregtech.api.util.GTUtility; -import gregtech.common.pipelikeold.cable.Insulation; - -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.util.ResourceLocation; - -import codechicken.lib.render.pipeline.ColourMultiplier; -import codechicken.lib.render.pipeline.IVertexOperation; -import codechicken.lib.texture.TextureUtils; -import codechicken.lib.vec.uv.IconTransformation; -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.Nullable; - -public class CableRenderer extends PipeRenderer { - - public static final CableRenderer INSTANCE = new CableRenderer(); - private final TextureAtlasSprite[] insulationTextures = new TextureAtlasSprite[6]; - private TextureAtlasSprite wireTexture; - - private CableRenderer() { - super("gt_cable", GTUtility.gregtechId("cable")); - } - - @Override - public void registerIcons(TextureMap map) { - ResourceLocation wireLocation = GTUtility.gregtechId("blocks/cable/wire"); - this.wireTexture = map.registerSprite(wireLocation); - for (int i = 0; i < insulationTextures.length; i++) { - ResourceLocation location = GTUtility.gregtechId("blocks/cable/insulation_" + i); - this.insulationTextures[i] = map.registerSprite(location); - } - } - - @Override - public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, - IPipeTile pipeTile, - IPipeType pipeType, @Nullable Material material) { - if (material == null || !(pipeType instanceof Insulation)) { - return; - } - - int insulationLevel = ((Insulation) pipeType).insulationLevel; - IVertexOperation wireRender = new IconTransformation(wireTexture); - ColourMultiplier wireColor = new ColourMultiplier( - GTUtility.convertRGBtoOpaqueRGBA_CL(material.getMaterialRGB())); - ColourMultiplier insulationColor = new ColourMultiplier(GTUtility.convertRGBtoOpaqueRGBA_CL(0x404040)); - if (pipeTile != null) { - if (pipeTile.getPaintingColor() != pipeTile.getDefaultPaintingColor()) { - wireColor.colour = GTUtility.convertRGBtoOpaqueRGBA_CL(pipeTile.getPaintingColor()); - } - insulationColor.colour = GTUtility.convertRGBtoOpaqueRGBA_CL(pipeTile.getPaintingColor()); - } - - if (insulationLevel != -1) { - - if ((renderContext.getConnections() & 63) == 0) { - // render only insulation when cable has no connections - renderContext.addOpenFaceRender(false, new IconTransformation(insulationTextures[5]), insulationColor); - return; - } - - renderContext.addOpenFaceRender(false, wireRender, wireColor) - .addOpenFaceRender(false, new IconTransformation(insulationTextures[insulationLevel]), - insulationColor) - .addSideRender(false, new IconTransformation(insulationTextures[5]), insulationColor); - } else { - renderContext.addOpenFaceRender(false, wireRender, wireColor) - .addSideRender(false, wireRender, wireColor); - } - } - - @Override - public TextureAtlasSprite getParticleTexture(IPipeType pipeType, @Nullable Material material) { - return null; - } - - @Override - public Pair getParticleTexture(IPipeTile pipeTile) { - if (pipeTile == null) { - return Pair.of(TextureUtils.getMissingSprite(), 0xFFFFFF); - } - IPipeType pipeType = pipeTile.getPipeType(); - if (!(pipeType instanceof Insulation)) { - return Pair.of(TextureUtils.getMissingSprite(), 0xFFFFFF); - } - Material material = pipeTile instanceof TileEntityMaterialPipeBase ? - ((TileEntityMaterialPipeBase) pipeTile).getPipeMaterial() : null; - - TextureAtlasSprite atlasSprite; - int particleColor; - int insulationLevel = ((Insulation) pipeType).insulationLevel; - if (insulationLevel == -1) { - atlasSprite = wireTexture; - particleColor = material == null ? 0xFFFFFF : material.getMaterialRGB(); - } else { - atlasSprite = insulationTextures[5]; - particleColor = pipeTile.getPaintingColor(); - } - return Pair.of(atlasSprite, particleColor); - } -} diff --git a/src/main/java/gregtech/client/renderer/pipeold/FluidPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/FluidPipeRenderer.java deleted file mode 100644 index fe9df0bec8a..00000000000 --- a/src/main/java/gregtech/client/renderer/pipeold/FluidPipeRenderer.java +++ /dev/null @@ -1,69 +0,0 @@ -package gregtech.client.renderer.pipeold; - -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.recipes.ModHandler; -import gregtech.api.unification.material.Material; -import gregtech.api.util.GTUtility; -import gregtech.client.renderer.texture.Textures; -import gregtech.common.pipelikeold.fluidpipe.FluidPipeType; - -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureMap; - -import codechicken.lib.vec.uv.IconTransformation; -import org.jetbrains.annotations.Nullable; - -import java.util.EnumMap; - -public class FluidPipeRenderer extends PipeRenderer { - - public static final FluidPipeRenderer INSTANCE = new FluidPipeRenderer(); - private final EnumMap pipeTextures = new EnumMap<>(FluidPipeType.class); - private final EnumMap pipeTexturesWood = new EnumMap<>(FluidPipeType.class); - - private FluidPipeRenderer() { - super("gt_fluid_pipe", GTUtility.gregtechId("fluid_pipe")); - } - - @Override - public void registerIcons(TextureMap map) { - pipeTextures.put(FluidPipeType.TINY, Textures.PIPE_TINY); - pipeTextures.put(FluidPipeType.SMALL, Textures.PIPE_SMALL); - pipeTextures.put(FluidPipeType.NORMAL, Textures.PIPE_NORMAL); - pipeTextures.put(FluidPipeType.LARGE, Textures.PIPE_LARGE); - pipeTextures.put(FluidPipeType.HUGE, Textures.PIPE_HUGE); - pipeTextures.put(FluidPipeType.QUADRUPLE, Textures.PIPE_QUADRUPLE); - pipeTextures.put(FluidPipeType.NONUPLE, Textures.PIPE_NONUPLE); - - pipeTexturesWood.put(FluidPipeType.SMALL, Textures.PIPE_SMALL_WOOD); - pipeTexturesWood.put(FluidPipeType.NORMAL, Textures.PIPE_NORMAL_WOOD); - pipeTexturesWood.put(FluidPipeType.LARGE, Textures.PIPE_LARGE_WOOD); - } - - @Override - public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, - IPipeTile pipeTile, IPipeType pipeType, @Nullable Material material) { - if (material == null || !(pipeType instanceof FluidPipeType)) { - return; - } - if (ModHandler.isMaterialWood(material)) { - TextureAtlasSprite sprite = pipeTexturesWood.get(pipeType); - if (sprite != null) { - renderContext.addOpenFaceRender(new IconTransformation(sprite)); - } else { - renderContext.addOpenFaceRender(new IconTransformation(pipeTextures.get(pipeType))); - } - renderContext.addSideRender(new IconTransformation(Textures.PIPE_SIDE_WOOD)); - } else { - renderContext.addOpenFaceRender(new IconTransformation(pipeTextures.get(pipeType))) - .addSideRender(new IconTransformation(Textures.PIPE_SIDE)); - } - } - - @Override - public TextureAtlasSprite getParticleTexture(IPipeType pipeType, @Nullable Material material) { - return Textures.PIPE_SIDE; - } -} diff --git a/src/main/java/gregtech/client/renderer/pipeold/ItemPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/ItemPipeRenderer.java deleted file mode 100644 index acee00a413f..00000000000 --- a/src/main/java/gregtech/client/renderer/pipeold/ItemPipeRenderer.java +++ /dev/null @@ -1,58 +0,0 @@ -package gregtech.client.renderer.pipeold; - -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.unification.material.Material; -import gregtech.api.util.GTUtility; -import gregtech.client.renderer.texture.Textures; -import gregtech.common.pipelikeold.itempipe.ItemPipeType; - -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureMap; - -import codechicken.lib.vec.uv.IconTransformation; -import org.jetbrains.annotations.Nullable; - -import java.util.EnumMap; - -public class ItemPipeRenderer extends PipeRenderer { - - public static final ItemPipeRenderer INSTANCE = new ItemPipeRenderer(); - private final EnumMap pipeTextures = new EnumMap<>(ItemPipeType.class); - - private ItemPipeRenderer() { - super("gt_item_pipe", GTUtility.gregtechId("item_pipe")); - } - - @Override - public void registerIcons(TextureMap map) { - pipeTextures.put(ItemPipeType.SMALL, Textures.PIPE_SMALL); - pipeTextures.put(ItemPipeType.NORMAL, Textures.PIPE_NORMAL); - pipeTextures.put(ItemPipeType.LARGE, Textures.PIPE_LARGE); - pipeTextures.put(ItemPipeType.HUGE, Textures.PIPE_HUGE); - pipeTextures.put(ItemPipeType.RESTRICTIVE_SMALL, Textures.PIPE_SMALL); - pipeTextures.put(ItemPipeType.RESTRICTIVE_NORMAL, Textures.PIPE_NORMAL); - pipeTextures.put(ItemPipeType.RESTRICTIVE_LARGE, Textures.PIPE_LARGE); - pipeTextures.put(ItemPipeType.RESTRICTIVE_HUGE, Textures.PIPE_HUGE); - } - - @Override - public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, - IPipeTile pipeTile, IPipeType pipeType, @Nullable Material material) { - if (material == null || !(pipeType instanceof ItemPipeType)) { - return; - } - renderContext.addOpenFaceRender(new IconTransformation(pipeTextures.get(pipeType))) - .addSideRender(new IconTransformation(Textures.PIPE_SIDE)); - - if (((ItemPipeType) pipeType).isRestrictive()) { - renderContext.addSideRender(false, new IconTransformation(Textures.RESTRICTIVE_OVERLAY)); - } - } - - @Override - public TextureAtlasSprite getParticleTexture(IPipeType pipeType, @Nullable Material material) { - return Textures.PIPE_SIDE; - } -} diff --git a/src/main/java/gregtech/client/renderer/pipeold/LaserPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/LaserPipeRenderer.java deleted file mode 100644 index 1ce9c0cfde2..00000000000 --- a/src/main/java/gregtech/client/renderer/pipeold/LaserPipeRenderer.java +++ /dev/null @@ -1,103 +0,0 @@ -package gregtech.client.renderer.pipeold; - -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.unification.material.Material; -import gregtech.api.util.GTUtility; -import gregtech.client.renderer.texture.Textures; -import gregtech.client.utils.BloomEffectUtil; -import gregtech.common.ConfigHolder; -import gregtech.common.pipelikeold.laser.LaserPipeType; -import gregtech.common.pipelikeold.laser.tile.TileEntityLaserPipe; - -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.util.BlockRenderLayer; -import net.minecraft.util.EnumFacing; - -import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.pipeline.IVertexOperation; -import codechicken.lib.vec.Cuboid6; -import codechicken.lib.vec.uv.IconTransformation; -import org.apache.commons.lang3.ArrayUtils; -import org.jetbrains.annotations.Nullable; - -import java.util.EnumMap; - -public class LaserPipeRenderer extends PipeRenderer { - - public static final LaserPipeRenderer INSTANCE = new LaserPipeRenderer(); - private final EnumMap pipeTextures = new EnumMap<>(LaserPipeType.class); - private boolean active = false; - - public LaserPipeRenderer() { - super("gt_laser_pipe", GTUtility.gregtechId("laser_pipe")); - } - - @Override - public void registerIcons(TextureMap map) { - pipeTextures.put(LaserPipeType.NORMAL, Textures.LASER_PIPE_IN); - } - - @Override - public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, - @Nullable IPipeTile pipeTile, IPipeType pipeType, - @Nullable Material material) { - if (pipeType instanceof LaserPipeType) { - renderContext.addOpenFaceRender(new IconTransformation(pipeTextures.get(pipeType))) - .addSideRender(false, new IconTransformation(Textures.LASER_PIPE_SIDE)); - if (pipeTile != null && pipeTile.isPainted()) { - renderContext.addSideRender(new IconTransformation(Textures.LASER_PIPE_OVERLAY)); - } - - active = !ConfigHolder.client.preventAnimatedCables && pipeTile instanceof TileEntityLaserPipe laserPipe && - laserPipe.isActive(); - } - } - - @Override - protected void renderOtherLayers(BlockRenderLayer layer, CCRenderState renderState, - PipeRenderContext renderContext) { - if (active && layer == BloomEffectUtil.getEffectiveBloomLayer() && - (renderContext.getConnections() & 0b111111) != 0) { - Cuboid6 innerCuboid = BlockPipe.getSideBox(null, renderContext.getPipeThickness()); - if ((renderContext.getConnections() & 0b111111) != 0) { - for (EnumFacing side : EnumFacing.VALUES) { - if ((renderContext.getConnections() & (1 << side.getIndex())) == 0) { - int oppositeIndex = side.getOpposite().getIndex(); - if ((renderContext.getConnections() & (1 << oppositeIndex)) <= 0 || - (renderContext.getConnections() & 0b111111 & ~(1 << oppositeIndex)) != 0) { - // render pipe side - IVertexOperation[] ops = renderContext.getBaseVertexOperation(); - ops = ArrayUtils.addAll(ops, new IconTransformation(Textures.LASER_PIPE_OVERLAY_EMISSIVE)); - renderFace(renderState, ops, side, innerCuboid); - } - } else { - // render connection cuboid - Cuboid6 sideCuboid = BlockPipe.getSideBox(side, renderContext.getPipeThickness()); - for (EnumFacing connectionSide : EnumFacing.VALUES) { - if (connectionSide.getAxis() != side.getAxis()) { - // render side textures - IVertexOperation[] ops = renderContext.getBaseVertexOperation(); - ops = ArrayUtils.addAll(ops, - new IconTransformation(Textures.LASER_PIPE_OVERLAY_EMISSIVE)); - renderFace(renderState, ops, connectionSide, sideCuboid); - } - } - } - } - } - } - } - - @Override - protected boolean canRenderInLayer(BlockRenderLayer layer) { - return super.canRenderInLayer(layer) || layer == BloomEffectUtil.getEffectiveBloomLayer(); - } - - @Override - public TextureAtlasSprite getParticleTexture(IPipeType pipeType, @Nullable Material material) { - return Textures.LASER_PIPE_SIDE; - } -} diff --git a/src/main/java/gregtech/client/renderer/pipeold/OpticalPipeRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/OpticalPipeRenderer.java deleted file mode 100644 index 3203c9fa989..00000000000 --- a/src/main/java/gregtech/client/renderer/pipeold/OpticalPipeRenderer.java +++ /dev/null @@ -1,57 +0,0 @@ -package gregtech.client.renderer.pipeold; - -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.unification.material.Material; -import gregtech.api.util.GTUtility; -import gregtech.client.renderer.texture.Textures; -import gregtech.common.ConfigHolder; -import gregtech.common.pipelikeold.optical.OpticalPipeType; -import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; - -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureMap; - -import codechicken.lib.vec.uv.IconTransformation; -import org.jetbrains.annotations.Nullable; - -import java.util.EnumMap; - -public final class OpticalPipeRenderer extends PipeRenderer { - - public static final OpticalPipeRenderer INSTANCE = new OpticalPipeRenderer(); - private final EnumMap pipeTextures = new EnumMap<>(OpticalPipeType.class); - - private OpticalPipeRenderer() { - super("gt_optical_pipe", GTUtility.gregtechId("optical_pipe")); - } - - @Override - public void registerIcons(TextureMap map) { - pipeTextures.put(OpticalPipeType.NORMAL, Textures.OPTICAL_PIPE_IN); - } - - @Override - public void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, - @Nullable IPipeTile pipeTile, IPipeType pipeType, - @Nullable Material material) { - if (pipeType instanceof OpticalPipeType) { - renderContext.addOpenFaceRender(new IconTransformation(pipeTextures.get(pipeType))) - .addSideRender(false, new IconTransformation(Textures.OPTICAL_PIPE_SIDE)); - - if (ConfigHolder.client.preventAnimatedCables) { - renderContext.addSideRender(new IconTransformation(Textures.OPTICAL_PIPE_SIDE_OVERLAY)); - } else if (pipeTile instanceof TileEntityOpticalPipe opticalPipe && opticalPipe.isActive()) { - renderContext.addSideRender(new IconTransformation(Textures.OPTICAL_PIPE_SIDE_OVERLAY_ACTIVE)); - } else { - renderContext.addSideRender(new IconTransformation(Textures.OPTICAL_PIPE_SIDE_OVERLAY)); - } - } - } - - @Override - public TextureAtlasSprite getParticleTexture(IPipeType pipeType, @Nullable Material material) { - return Textures.OPTICAL_PIPE_SIDE; - } -} diff --git a/src/main/java/gregtech/client/renderer/pipeold/PipeRenderer.java b/src/main/java/gregtech/client/renderer/pipeold/PipeRenderer.java deleted file mode 100644 index f14dfbbb440..00000000000 --- a/src/main/java/gregtech/client/renderer/pipeold/PipeRenderer.java +++ /dev/null @@ -1,577 +0,0 @@ -package gregtech.client.renderer.pipeold; - -import gregtech.api.cover.CoverHolder; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.IPipeType; -import gregtech.api.graphnet.pipenetold.block.ItemBlockPipe; -import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; -import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.info.MaterialIconType; -import gregtech.api.util.GTUtility; -import gregtech.client.renderer.CubeRendererState; -import gregtech.client.renderer.texture.Textures; -import gregtech.client.utils.ItemRenderCompat; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType; -import net.minecraft.client.renderer.block.model.ModelResourceLocation; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.item.ItemStack; -import net.minecraft.util.BlockRenderLayer; -import net.minecraft.util.EnumBlockRenderType; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.IBlockAccess; -import net.minecraftforge.client.MinecraftForgeClient; -import net.minecraftforge.client.event.ModelBakeEvent; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.model.IModelState; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import codechicken.lib.lighting.LightMatrix; -import codechicken.lib.render.BlockRenderer; -import codechicken.lib.render.CCRenderState; -import codechicken.lib.render.block.BlockRenderingRegistry; -import codechicken.lib.render.block.ICCBlockRenderer; -import codechicken.lib.render.item.IItemRenderer; -import codechicken.lib.render.pipeline.ColourMultiplier; -import codechicken.lib.render.pipeline.IVertexOperation; -import codechicken.lib.texture.TextureUtils; -import codechicken.lib.util.TransformUtils; -import codechicken.lib.vec.Cuboid6; -import codechicken.lib.vec.Matrix4; -import codechicken.lib.vec.Translation; -import codechicken.lib.vec.Vector3; -import codechicken.lib.vec.uv.IconTransformation; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.Nullable; -import org.lwjgl.opengl.GL11; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; - -@SideOnly(Side.CLIENT) -public abstract class PipeRenderer implements ICCBlockRenderer, IItemRenderer { - - public final ModelResourceLocation modelLocation; - private final String name; - private EnumBlockRenderType blockRenderType; - protected static final ThreadLocal blockFaces = ThreadLocal - .withInitial(BlockRenderer.BlockFace::new); - private static final Cuboid6 FRAME_RENDER_CUBOID = new Cuboid6(0.001, 0.001, 0.001, 0.999, 0.999, 0.999); - private static final EnumMap> FACE_BORDER_MAP = new EnumMap<>( - EnumFacing.class); - private static final Int2ObjectMap RESTRICTOR_MAP = new Int2ObjectOpenHashMap<>(); - - @SuppressWarnings("unused") - public static void initializeRestrictor(TextureMap map) { - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_UP, Border.TOP); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_DOWN, Border.BOTTOM); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_UD, Border.TOP, Border.BOTTOM); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_LEFT, Border.LEFT); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_UL, Border.TOP, Border.LEFT); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_DL, Border.BOTTOM, Border.LEFT); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_NR, Border.TOP, Border.BOTTOM, Border.LEFT); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_RIGHT, Border.RIGHT); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_UR, Border.TOP, Border.RIGHT); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_DR, Border.BOTTOM, Border.RIGHT); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_NL, Border.TOP, Border.BOTTOM, Border.RIGHT); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_LR, Border.LEFT, Border.RIGHT); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_ND, Border.TOP, Border.LEFT, Border.RIGHT); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY_NU, Border.BOTTOM, Border.LEFT, Border.RIGHT); - addRestrictor(Textures.PIPE_BLOCKED_OVERLAY, Border.TOP, Border.BOTTOM, Border.LEFT, Border.RIGHT); - } - - static { - FACE_BORDER_MAP.put(EnumFacing.DOWN, - borderMap(EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.WEST, EnumFacing.EAST)); - FACE_BORDER_MAP.put(EnumFacing.UP, - borderMap(EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.WEST, EnumFacing.EAST)); - FACE_BORDER_MAP.put(EnumFacing.NORTH, - borderMap(EnumFacing.UP, EnumFacing.DOWN, EnumFacing.EAST, EnumFacing.WEST)); - FACE_BORDER_MAP.put(EnumFacing.SOUTH, - borderMap(EnumFacing.UP, EnumFacing.DOWN, EnumFacing.WEST, EnumFacing.EAST)); - FACE_BORDER_MAP.put(EnumFacing.WEST, - borderMap(EnumFacing.UP, EnumFacing.DOWN, EnumFacing.NORTH, EnumFacing.SOUTH)); - FACE_BORDER_MAP.put(EnumFacing.EAST, - borderMap(EnumFacing.UP, EnumFacing.DOWN, EnumFacing.SOUTH, EnumFacing.NORTH)); - } - - public PipeRenderer(String name, ModelResourceLocation modelLocation) { - this.name = name; - this.modelLocation = modelLocation; - } - - public PipeRenderer(String name, ResourceLocation modelLocation) { - this(name, new ModelResourceLocation(modelLocation, "normal")); - } - - public void preInit() { - blockRenderType = BlockRenderingRegistry.createRenderType(name); - BlockRenderingRegistry.registerRenderer(blockRenderType, this); - MinecraftForge.EVENT_BUS.register(this); - TextureUtils.addIconRegister(this::registerIcons); - } - - public ModelResourceLocation getModelLocation() { - return modelLocation; - } - - public EnumBlockRenderType getBlockRenderType() { - return blockRenderType; - } - - public abstract void registerIcons(TextureMap map); - - @SubscribeEvent - public void onModelsBake(ModelBakeEvent event) { - event.getModelRegistry().putObject(modelLocation, this); - } - - public abstract void buildRenderer(PipeRenderContext renderContext, BlockPipe blockPipe, - @Nullable IPipeTile pipeTile, IPipeType pipeType, - @Nullable Material material); - - @Override - public void renderItem(ItemStack rawItemStack, TransformType transformType) { - ItemStack stack = ItemRenderCompat.getRepresentedStack(rawItemStack); - if (!(stack.getItem() instanceof ItemBlockPipe)) { - return; - } - CCRenderState renderState = CCRenderState.instance(); - GlStateManager.enableBlend(); - renderState.reset(); - renderState.startDrawing(GL11.GL_QUADS, DefaultVertexFormats.ITEM); - BlockPipe blockFluidPipe = (BlockPipe) ((ItemBlockPipe) stack.getItem()) - .getBlock(); - IPipeType pipeType = blockFluidPipe.getItemPipeType(stack); - Material material = blockFluidPipe instanceof BlockMaterialPipeblockMaterialPipe ? - blockMaterialPipe.getItemMaterial(stack) : null; - if (pipeType != null) { - // 12 == 0b1100 is North and South connection (index 2 & 3) - PipeRenderContext renderContext = new PipeRenderContext(12, 0, pipeType.getThickness()); - renderContext.color = GTUtility.convertRGBtoOpaqueRGBA_CL(getPipeColor(material, -1)); - buildRenderer(renderContext, blockFluidPipe, null, pipeType, material); - renderPipeBlock(renderState, renderContext); - } - renderState.draw(); - GlStateManager.disableBlend(); - } - - @Override - public boolean renderBlock(IBlockAccess world, BlockPos pos, IBlockState state, BufferBuilder buffer) { - CCRenderState renderState = CCRenderState.instance(); - renderState.reset(); - renderState.bind(buffer); - renderState.setBrightness(world, pos); - - BlockPipe blockPipe = (BlockPipe) state.getBlock(); - IPipeTile pipeTile = blockPipe.getPipeTileEntity(world, pos); - - if (pipeTile == null) { - return false; - } - - IPipeType pipeType = pipeTile.getPipeType(); - Material pipeMaterial = pipeTile instanceof TileEntityMaterialPipeBase ? - ((TileEntityMaterialPipeBase) pipeTile).getPipeMaterial() : null; - int paintingColor = pipeTile.getPaintingColor(); - int connectedSidesMap = pipeTile.getVisualConnections(); - int blockedConnections = pipeTile.getBlockedConnections(); - - if (pipeType != null) { - BlockRenderLayer renderLayer = MinecraftForgeClient.getRenderLayer(); - boolean[] sideMask = new boolean[EnumFacing.VALUES.length]; - for (EnumFacing side : EnumFacing.VALUES) { - sideMask[side.getIndex()] = state.shouldSideBeRendered(world, pos, side); - } - Textures.RENDER_STATE.set(new CubeRendererState(renderLayer, sideMask, world)); - if (canRenderInLayer(renderLayer)) { - renderState.lightMatrix.locate(world, pos); - PipeRenderContext renderContext = new PipeRenderContext(pos, renderState.lightMatrix, connectedSidesMap, - blockedConnections, pipeType.getThickness()); - renderContext.color = GTUtility.convertRGBtoOpaqueRGBA_CL(getPipeColor(pipeMaterial, paintingColor)); - buildRenderer(renderContext, blockPipe, pipeTile, pipeType, pipeMaterial); - if (renderLayer == BlockRenderLayer.CUTOUT) { - renderPipeBlock(renderState, renderContext); - renderFrame(pipeTile, pos, renderState, connectedSidesMap); - } else { - renderOtherLayers(renderLayer, renderState, renderContext); - } - } - - CoverHolder coverHolder = pipeTile.getCoverableImplementation(); - coverHolder.renderCovers(renderState, new Matrix4().translate(pos.getX(), pos.getY(), pos.getZ()), - renderLayer); - Textures.RENDER_STATE.remove(); - } - return true; - } - - private static void renderFrame(IPipeTile pipeTile, BlockPos pos, CCRenderState renderState, - int connections) { - Material frameMaterial = pipeTile.getFrameMaterial(); - if (frameMaterial != null) { - ResourceLocation rl = MaterialIconType.frameGt.getBlockTexturePath(frameMaterial.getMaterialIconSet()); - TextureAtlasSprite sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(rl.toString()); - IVertexOperation[] pipeline = { - new Translation(pos), - renderState.lightMatrix, - new IconTransformation(sprite), - new ColourMultiplier(GTUtility.convertRGBtoOpaqueRGBA_CL(frameMaterial.getMaterialRGB())) - }; - - for (EnumFacing side : EnumFacing.VALUES) { - // only render frame if it doesn't have a cover - if ((connections & 1 << (12 + side.getIndex())) == 0) { - BlockRenderer.BlockFace blockFace = blockFaces.get(); - blockFace.loadCuboidFace(FRAME_RENDER_CUBOID, side.getIndex()); - renderState.setPipeline(blockFace, 0, blockFace.verts.length, pipeline); - renderState.render(); - } - } - } - } - - private static int getPipeColor(Material material, int paintingColor) { - if (paintingColor == -1) { - return material == null ? 0xFFFFFF : material.getMaterialRGB(); - } - return paintingColor; - } - - public void renderPipeBlock(CCRenderState renderState, PipeRenderContext renderContext) { - Cuboid6 cuboid6 = BlockPipe.getSideBox(null, renderContext.pipeThickness); - if ((renderContext.connections & 63) == 0) { - // base pipe without connections - for (EnumFacing renderedSide : EnumFacing.VALUES) { - renderOpenFace(renderState, renderContext, renderedSide, cuboid6); - } - } else { - for (EnumFacing renderedSide : EnumFacing.VALUES) { - // if connection is blocked - if ((renderContext.connections & 1 << renderedSide.getIndex()) == 0) { - int oppositeIndex = renderedSide.getOpposite().getIndex(); - if ((renderContext.connections & 1 << oppositeIndex) > 0 && - (renderContext.connections & 63 & ~(1 << oppositeIndex)) == 0) { - // render open texture if opposite is open and no other - renderOpenFace(renderState, renderContext, renderedSide, cuboid6); - } else { - // else render pipe side - renderPipeSide(renderState, renderContext, renderedSide, cuboid6); - } - } else { - // else render connection cuboid - renderPipeCube(renderState, renderContext, renderedSide); - } - } - } - } - - protected void renderPipeCube(CCRenderState renderState, PipeRenderContext renderContext, EnumFacing side) { - Cuboid6 cuboid = BlockPipe.getSideBox(side, renderContext.pipeThickness); - boolean doRenderBlockedOverlay = (renderContext.blockedConnections & (1 << side.getIndex())) > 0; - // render connection cuboid - for (EnumFacing renderedSide : EnumFacing.VALUES) { - if (renderedSide.getAxis() != side.getAxis()) { - // render side textures - renderPipeSide(renderState, renderContext, renderedSide, cuboid); - if (doRenderBlockedOverlay) { - // render blocked connections - renderFace(renderState, renderContext.blockedOverlay, renderedSide, cuboid); - } - } - } - if ((renderContext.connections & 1 << (6 + side.getIndex())) > 0) { - // if neighbour pipe is smaller, render closed texture - renderPipeSide(renderState, renderContext, side, cuboid); - } else { - if ((renderContext.connections & 1 << (12 + side.getIndex())) > 0) { - // if face has a cover offset face by 0.001 to avoid z fighting - cuboid = BlockPipe.getCoverSideBox(side, renderContext.pipeThickness); - } - renderOpenFace(renderState, renderContext, side, cuboid); - } - } - - protected void renderOpenFace(CCRenderState renderState, PipeRenderContext renderContext, EnumFacing side, - Cuboid6 cuboid6) { - for (IVertexOperation[] vertexOperations : renderContext.openFaceRenderer) { - renderFace(renderState, vertexOperations, side, cuboid6); - } - } - - protected void renderPipeSide(CCRenderState renderState, PipeRenderContext renderContext, EnumFacing side, - Cuboid6 cuboid6) { - for (IVertexOperation[] vertexOperations : renderContext.pipeSideRenderer) { - renderFace(renderState, vertexOperations, side, cuboid6); - } - int blockedConnections = renderContext.getBlockedConnections(); - int connections = renderContext.getConnections(); - if (blockedConnections != 0) { - int borderMask = 0; - for (Border border : Border.VALUES) { - EnumFacing borderSide = getSideAtBorder(side, border); - if (TileEntityPipeBase.isFaceBlocked(blockedConnections, borderSide) && - TileEntityPipeBase.isConnected(connections, borderSide)) { - // only render when the side is blocked *and* connected - borderMask |= border.mask; - } - } - if (borderMask != 0) { - IVertexOperation[] pipeline = ArrayUtils.addAll(renderContext.getBaseVertexOperation(), - RESTRICTOR_MAP.get(borderMask)); - renderFace(renderState, pipeline, side, cuboid6); - } - } - } - - protected void renderFace(CCRenderState renderState, IVertexOperation[] pipeline, EnumFacing side, - Cuboid6 cuboid6) { - BlockRenderer.BlockFace blockFace = blockFaces.get(); - blockFace.loadCuboidFace(cuboid6, side.getIndex()); - renderState.setPipeline(blockFace, 0, blockFace.verts.length, pipeline); - renderState.render(); - } - - @Override - public void renderBrightness(IBlockState state, float brightness) {} - - /** - * Override to render in other layers, e.g. emissive stuff - * {@link #canRenderInLayer} also need to be overridden - */ - protected void renderOtherLayers(BlockRenderLayer layer, CCRenderState renderState, - PipeRenderContext renderContext) {} - - /** - * What layers can be rendered in. - * See also {@link #renderOtherLayers} - * - * @param layer the current layer being rendered too - * @return true if this should render in {@code layer} - */ - protected boolean canRenderInLayer(BlockRenderLayer layer) { - return layer == BlockRenderLayer.CUTOUT; - } - - @Override - public void handleRenderBlockDamage(IBlockAccess world, BlockPos pos, IBlockState state, TextureAtlasSprite sprite, - BufferBuilder buffer) { - CCRenderState renderState = CCRenderState.instance(); - renderState.reset(); - renderState.bind(buffer); - renderState.setPipeline(new Vector3(new Vec3d(pos)).translation(), new IconTransformation(sprite)); - BlockPipe blockPipe = (BlockPipe) state.getBlock(); - IPipeTile pipeTile = blockPipe.getPipeTileEntity(world, pos); - if (pipeTile == null) { - return; - } - IPipeType pipeType = pipeTile.getPipeType(); - if (pipeType == null) { - return; - } - float thickness = pipeType.getThickness(); - int connectedSidesMask = pipeTile.getConnections(); - Cuboid6 baseBox = BlockPipe.getSideBox(null, thickness); - BlockRenderer.renderCuboid(renderState, baseBox, 0); - for (EnumFacing renderSide : EnumFacing.VALUES) { - if ((connectedSidesMask & (1 << renderSide.getIndex())) > 0) { - Cuboid6 sideBox = BlockPipe.getSideBox(renderSide, thickness); - BlockRenderer.renderCuboid(renderState, sideBox, 0); - } - } - } - - @Override - public void registerTextures(TextureMap map) {} - - @Override - public IModelState getTransforms() { - return TransformUtils.DEFAULT_BLOCK; - } - - @Override - public TextureAtlasSprite getParticleTexture() { - return TextureUtils.getMissingSprite(); - } - - @Override - public boolean isBuiltInRenderer() { - return true; - } - - @Override - public boolean isAmbientOcclusion() { - return true; - } - - @Override - public boolean isGui3d() { - return true; - } - - public Pair getParticleTexture(IPipeTile pipeTile) { - if (pipeTile == null) { - return Pair.of(TextureUtils.getMissingSprite(), 0xFFFFFF); - } - IPipeType pipeType = pipeTile.getPipeType(); - Material material = pipeTile instanceof TileEntityMaterialPipeBase ? - ((TileEntityMaterialPipeBase) pipeTile).getPipeMaterial() : null; - if (pipeType == null) { - return Pair.of(TextureUtils.getMissingSprite(), 0xFFFFFF); - } - TextureAtlasSprite atlasSprite = getParticleTexture(pipeType, material); - int pipeColor = getPipeColor(material, pipeTile.getPaintingColor()); - return Pair.of(atlasSprite, pipeColor); - } - - public abstract TextureAtlasSprite getParticleTexture(IPipeType pipeType, @Nullable Material material); - - public static class PipeRenderContext { - - private final BlockPos pos; - private final LightMatrix lightMatrix; - protected final List openFaceRenderer = new ArrayList<>(); - protected final List pipeSideRenderer = new ArrayList<>(); - // Blocked overlay is used for the pipe connector cube, not the main cube - private final IVertexOperation[] blockedOverlay; - private final float pipeThickness; - private int color; - private final int connections; - private final int blockedConnections; - - public PipeRenderContext(BlockPos pos, LightMatrix lightMatrix, int connections, int blockedConnections, - float thickness) { - this.pos = pos; - this.lightMatrix = lightMatrix; - this.connections = connections; - this.blockedConnections = blockedConnections; - this.pipeThickness = thickness; - if (pos != null && lightMatrix != null) { - blockedOverlay = new IVertexOperation[] { new Translation(pos), lightMatrix, - new IconTransformation(Textures.PIPE_BLOCKED_OVERLAY) }; - } else { - blockedOverlay = new IVertexOperation[] { new IconTransformation(Textures.PIPE_BLOCKED_OVERLAY) }; - } - } - - public PipeRenderContext(int connections, int blockedConnections, float thickness) { - this(null, null, connections, blockedConnections, thickness); - } - - public PipeRenderContext addOpenFaceRender(IVertexOperation... vertexOperations) { - return addOpenFaceRender(true, vertexOperations); - } - - public PipeRenderContext addOpenFaceRender(boolean applyDefaultColor, IVertexOperation... vertexOperations) { - IVertexOperation[] baseVertexOperation = getBaseVertexOperation(); - baseVertexOperation = ArrayUtils.addAll(baseVertexOperation, vertexOperations); - if (applyDefaultColor) { - baseVertexOperation = ArrayUtils.addAll(baseVertexOperation, getColorOperation()); - } - openFaceRenderer.add(baseVertexOperation); - return this; - } - - public PipeRenderContext addSideRender(IVertexOperation... vertexOperations) { - return addSideRender(true, vertexOperations); - } - - public PipeRenderContext addSideRender(boolean applyDefaultColor, IVertexOperation... vertexOperations) { - IVertexOperation[] baseVertexOperation = getBaseVertexOperation(); - baseVertexOperation = ArrayUtils.addAll(baseVertexOperation, vertexOperations); - if (applyDefaultColor) { - baseVertexOperation = ArrayUtils.addAll(baseVertexOperation, getColorOperation()); - } - pipeSideRenderer.add(baseVertexOperation); - return this; - } - - public ColourMultiplier getColorOperation() { - return new ColourMultiplier(color); - } - - protected IVertexOperation[] getBaseVertexOperation() { - if (pos == null) { - return lightMatrix == null ? new IVertexOperation[0] : new IVertexOperation[] { lightMatrix }; - } - return lightMatrix == null ? new IVertexOperation[] { new Translation(pos) } : - new IVertexOperation[] { new Translation(pos), lightMatrix }; - } - - public int getConnections() { - return connections; - } - - public int getBlockedConnections() { - return blockedConnections; - } - - public List getPipeSideRenderer() { - return pipeSideRenderer; - } - - public List getOpenFaceRenderer() { - return openFaceRenderer; - } - - public float getPipeThickness() { - return pipeThickness; - } - } - - private static EnumMap borderMap(EnumFacing topSide, EnumFacing bottomSide, EnumFacing leftSide, - EnumFacing rightSide) { - EnumMap sideMap = new EnumMap<>(Border.class); - sideMap.put(Border.TOP, topSide); - sideMap.put(Border.BOTTOM, bottomSide); - sideMap.put(Border.LEFT, leftSide); - sideMap.put(Border.RIGHT, rightSide); - return sideMap; - } - - private static void addRestrictor(TextureAtlasSprite sprite, Border... borders) { - int mask = 0; - for (Border border : borders) { - mask |= border.mask; - } - RESTRICTOR_MAP.put(mask, new IVertexOperation[] { new IconTransformation(sprite) }); - } - - protected static EnumFacing getSideAtBorder(EnumFacing side, Border border) { - return FACE_BORDER_MAP.get(side).get(border); - } - - public enum Border { - - TOP, - BOTTOM, - LEFT, - RIGHT; - - public static final Border[] VALUES = values(); - - public final int mask; - - Border() { - mask = 1 << this.ordinal(); - } - } -} diff --git a/src/main/java/gregtech/client/utils/FacadeBlockAccess.java b/src/main/java/gregtech/client/utils/FacadeBlockAccess.java index 879b446bddd..57b8866b4f8 100644 --- a/src/main/java/gregtech/client/utils/FacadeBlockAccess.java +++ b/src/main/java/gregtech/client/utils/FacadeBlockAccess.java @@ -55,8 +55,7 @@ public Result getAction(BlockPos pos) { IBlockState worldState = world.getBlockState(pos); Block worldBlock = worldState.getBlock(); - if (worldBlock instanceof IBlockAppearance) { - IBlockAppearance blockAppearance = (IBlockAppearance) worldBlock; + if (worldBlock instanceof IBlockAppearance blockAppearance) { if (blockAppearance.supportsVisualConnections()) { return Result.COVER; } diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index 0e80780e5cb..a8f47ff0a09 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -29,16 +29,6 @@ import gregtech.common.pipelike.block.laser.LaserPipeBlock; import gregtech.common.pipelike.block.optical.OpticalPipeBlock; import gregtech.common.pipelike.block.pipe.PipeBlock; -import gregtech.common.pipelikeold.cable.BlockCable; -import gregtech.common.pipelikeold.cable.ItemBlockCable; -import gregtech.common.pipelikeold.fluidpipe.BlockFluidPipe; -import gregtech.common.pipelikeold.fluidpipe.ItemBlockFluidPipe; -import gregtech.common.pipelikeold.itempipe.BlockItemPipe; -import gregtech.common.pipelikeold.itempipe.ItemBlockItemPipe; -import gregtech.common.pipelikeold.laser.BlockLaserPipe; -import gregtech.common.pipelikeold.laser.ItemBlockLaserPipe; -import gregtech.common.pipelikeold.optical.BlockOpticalPipe; -import gregtech.common.pipelikeold.optical.ItemBlockOpticalPipe; import gregtech.integration.groovy.GroovyScriptModule; import gregtech.loaders.MaterialInfoLoader; import gregtech.loaders.OreDictionaryLoader; diff --git a/src/main/java/gregtech/common/EventHandlers.java b/src/main/java/gregtech/common/EventHandlers.java index f4869c33c9d..f2c6c6a4424 100644 --- a/src/main/java/gregtech/common/EventHandlers.java +++ b/src/main/java/gregtech/common/EventHandlers.java @@ -2,12 +2,12 @@ import gregtech.api.GTValues; import gregtech.api.block.IWalkingSpeedBonus; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.armor.ArmorMetaItem; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.graphnet.pipenetold.longdist.LongDistanceNetwork; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.unification.material.Materials; import gregtech.api.util.BlockUtility; import gregtech.api.util.CapesRegistry; @@ -101,7 +101,7 @@ public static void onPlayerInteractionRightClickBlock(PlayerInteractEvent.RightC TileEntity tileEntity = event.getWorld().getTileEntity(event.getPos()); if (tileEntity instanceof IGregTechTileEntity) { event.setUseBlock(Event.Result.ALLOW); - } else if (tileEntity instanceof IPipeTile) { + } else if (tileEntity instanceof PipeTileEntity) { event.setUseBlock(Event.Result.ALLOW); } diff --git a/src/main/java/gregtech/common/ToolEventHandlers.java b/src/main/java/gregtech/common/ToolEventHandlers.java index 305bd503437..2f59d66db2f 100644 --- a/src/main/java/gregtech/common/ToolEventHandlers.java +++ b/src/main/java/gregtech/common/ToolEventHandlers.java @@ -7,6 +7,8 @@ import gregtech.api.capability.impl.ElectricItem; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverHolder; +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.toolitem.IGTTool; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; @@ -14,9 +16,6 @@ import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.util.GTUtility; import gregtech.api.util.TaskScheduler; import gregtech.common.items.tool.rotation.CustomBlockRotations; @@ -303,7 +302,7 @@ private static void postRenderDamagedBlocks() { @SideOnly(Side.CLIENT) private static boolean shouldRenderGridOverlays(@NotNull IBlockState state, @Nullable TileEntity tile, ItemStack mainHand, ItemStack offHand, boolean isSneaking) { - if (state.getBlock() instanceof BlockPipepipe) { + if (state.getBlock() instanceof WorldPipeBlock pipe) { if (isSneaking && (mainHand.isEmpty() || mainHand.getItem().getClass() == Item.getItemFromBlock(pipe).getClass())) { return true; @@ -316,15 +315,15 @@ private static boolean shouldRenderGridOverlays(@NotNull IBlockState state, @Nul BooleanSupplier hasCover; Predicate canCover; - if (tile instanceof IPipeTilepipeTile) { - final boolean hasAnyCover = pipeTile.getCoverableImplementation().hasAnyCover(); + if (tile instanceof PipeTileEntity pipeTile) { + final boolean hasAnyCover = pipeTile.getCoverHolder().hasAnyCover(); if (hasAnyCover) { if (mainToolClasses.contains(ToolClasses.SCREWDRIVER)) return true; if (offToolClasses.contains(ToolClasses.SCREWDRIVER)) return true; } hasCover = () -> hasAnyCover; - final boolean acceptsCovers = pipeTile.getCoverableImplementation().acceptsCovers(); + final boolean acceptsCovers = pipeTile.getCoverHolder().acceptsCovers(); canCover = coverDefinition -> acceptsCovers; if (GTUtility.isCoverBehaviorItem(mainHand, hasCover, canCover) || @@ -384,9 +383,9 @@ private static boolean renderGridOverlays(@NotNull EntityPlayer player, BlockPos rColour = gColour = bColour = 0.2F + (float) Math.sin((float) (System.currentTimeMillis() % (Math.PI * 800)) / 800) / 2; - if (tile instanceof TileEntityPipeBasetepb) { - drawGridOverlays(facing, box, face -> tepb.isConnected(face) || - tepb.getCoverableImplementation().getCoverAtSide(face) != null); + if (tile instanceof PipeTileEntity pipe) { + drawGridOverlays(facing, box, face -> pipe.isConnected(face) || + pipe.getCoverHolder().getCoverAtSide(face) != null); } else if (tile instanceof MetaTileEntityHolder) { MetaTileEntity mte = ((MetaTileEntityHolder) tile).getMetaTileEntity(); drawGridOverlays(facing, box, mte::isSideUsed); diff --git a/src/main/java/gregtech/common/blocks/BlockFrame.java b/src/main/java/gregtech/common/blocks/BlockFrame.java index 6fb87bfe308..8a823bbafd7 100644 --- a/src/main/java/gregtech/common/blocks/BlockFrame.java +++ b/src/main/java/gregtech/common/blocks/BlockFrame.java @@ -1,11 +1,10 @@ package gregtech.common.blocks; +import gregtech.api.graphnet.pipenet.physical.block.ItemPipeBlock; +import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.ItemBlockPipe; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.recipes.ModHandler; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.info.MaterialIconType; @@ -123,34 +122,30 @@ public boolean canCreatureSpawn(@NotNull IBlockState state, @NotNull IBlockAcces public boolean replaceWithFramedPipe(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, ItemStack stackInHand, EnumFacing facing) { - BlockPipe blockPipe = (BlockPipe) ((ItemBlockPipe) stackInHand.getItem()) - .getBlock(); - if (blockPipe.getItemPipeType(stackInHand).getThickness() < 1) { + WorldPipeBlock block = WorldPipeBlock.getBlockFromItem(stackInHand); + if (block != null && block.getStructure().getRenderThickness() < 1) { ItemBlock itemBlock = (ItemBlock) stackInHand.getItem(); - IBlockState pipeState = blockPipe.getDefaultState(); + IBlockState pipeState = block.getDefaultState(); // these 0 values are not actually used by forge itemBlock.placeBlockAt(stackInHand, playerIn, worldIn, pos, facing, 0, 0, 0, pipeState); - IPipeTile pipeTile = blockPipe.getPipeTileEntity(worldIn, pos); - if (pipeTile instanceof TileEntityPipeBasetile) { - tile.setFrameMaterial(getGtMaterial(state)); - } else { - GTLog.logger.error("Pipe was not placed!"); - return false; - } - SoundType type = blockPipe.getSoundType(state, worldIn, pos, playerIn); - worldIn.playSound(playerIn, pos, type.getPlaceSound(), SoundCategory.BLOCKS, - (type.getVolume() + 1.0F) / 2.0F, type.getPitch() * 0.8F); - if (!playerIn.capabilities.isCreativeMode) { - stackInHand.shrink(1); + PipeTileEntity pipeTile = block.getTileEntity(worldIn, pos); + if (pipeTile != null) { + pipeTile.setFrameMaterial(getGtMaterial(state)); + SoundType type = block.getSoundType(state, worldIn, pos, playerIn); + worldIn.playSound(playerIn, pos, type.getPlaceSound(), SoundCategory.BLOCKS, + (type.getVolume() + 1.0F) / 2.0F, type.getPitch() * 0.8F); + if (!playerIn.capabilities.isCreativeMode) { + stackInHand.shrink(1); + } + return true; } - return true; } return false; } public boolean removeFrame(World world, BlockPos pos, EntityPlayer player, ItemStack stack) { TileEntity te = world.getTileEntity(pos); - if (te instanceof TileEntityPipeBasepipeTile) { + if (te instanceof PipeTileEntity pipeTile) { Material frameMaterial = pipeTile.getFrameMaterial(); if (frameMaterial != null) { pipeTile.setFrameMaterial(null); @@ -172,7 +167,7 @@ public boolean onBlockActivated(@NotNull World world, @NotNull BlockPos pos, @No return false; } // replace frame with pipe and set the frame material to this frame - if (stack.getItem() instanceof ItemBlockPipe) { + if (stack.getItem() instanceof ItemPipeBlock) { return replaceWithFramedPipe(world, pos, state, player, stack, facing); } @@ -191,8 +186,9 @@ public boolean onBlockActivated(@NotNull World world, @NotNull BlockPos pos, @No continue; } TileEntity te = world.getTileEntity(blockPos); - if (te instanceof IPipeTile && ((IPipeTile) te).getFrameMaterial() != null) { + if (te instanceof PipeTileEntity tile && tile.getFrameMaterial() != null) { blockPos.move(EnumFacing.UP); + te = world.getTileEntity(blockPos); continue; } if (canPlaceBlockAt(world, blockPos)) { @@ -206,11 +202,11 @@ public boolean onBlockActivated(@NotNull World world, @NotNull BlockPos pos, @No } blockPos.release(); return true; - } else if (te instanceof TileEntityPipeBasetile && tile.getFrameMaterial() == null) { + } else if (te instanceof PipeTileEntity tile && tile.getFrameMaterial() == null) { tile.setFrameMaterial(frameBlock.getGtMaterial(stack)); SoundType type = getSoundType(stack); - world.playSound(null, pos, type.getPlaceSound(), SoundCategory.BLOCKS, (type.getVolume() + 1.0F) / 2.0F, - type.getPitch() * 0.8F); + world.playSound(null, pos, type.getPlaceSound(), SoundCategory.BLOCKS, + (type.getVolume() + 1.0F) / 2.0F, type.getPitch() * 0.8F); if (!player.capabilities.isCreativeMode) { stack.shrink(1); } diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 36cdbb84005..fb30de08f06 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -47,10 +47,6 @@ import gregtech.common.pipelike.block.pipe.PipeStructure; import gregtech.common.pipelikeold.fluidpipe.longdistance.LDFluidPipeType; import gregtech.common.pipelikeold.itempipe.longdistance.LDItemPipeType; -import gregtech.common.pipelikeold.laser.BlockLaserPipe; -import gregtech.common.pipelikeold.laser.LaserPipeType; -import gregtech.common.pipelikeold.optical.BlockOpticalPipe; -import gregtech.common.pipelikeold.optical.OpticalPipeType; import net.minecraft.block.Block; import net.minecraft.block.BlockFence; diff --git a/src/main/java/gregtech/common/command/CommandRecipeCheck.java b/src/main/java/gregtech/common/command/CommandRecipeCheck.java index a7bb61663f0..1d9a9d0adc1 100644 --- a/src/main/java/gregtech/common/command/CommandRecipeCheck.java +++ b/src/main/java/gregtech/common/command/CommandRecipeCheck.java @@ -1,11 +1,11 @@ package gregtech.common.command; import gregtech.api.block.machines.MachineItemBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.items.materialitem.MetaPrefixItem; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.metaitem.MetaItem.MetaValueItem; import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.chance.output.impl.ChancedFluidOutput; @@ -15,6 +15,7 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.util.GTLog; +import gregtech.api.util.GTStringUtils; import gregtech.api.util.GTUtility; import gregtech.common.blocks.BlockCompressed; import gregtech.common.blocks.BlockFrame; @@ -298,46 +299,6 @@ public static String prettyPrintRecipeInput(GTRecipeInput recipeInput) { } public static String prettyPrintItemStack(ItemStack stack) { - if (stack.getItem() instanceof MetaItemmetaItem) { - MetaValueItem metaValueItem = metaItem.getItem(stack); - if (metaValueItem == null) { - if (metaItem instanceof MetaPrefixItem metaPrefixItem) { - Material material = metaPrefixItem.getMaterial(stack); - OrePrefix orePrefix = metaPrefixItem.getOrePrefix(); - return "(MetaItem) OrePrefix: " + orePrefix.name + ", Material: " + material + " * " + - stack.getCount(); - } - } else { - if (MetaItems.INTEGRATED_CIRCUIT.isItemEqual(stack)) { - return "Config circuit #" + IntCircuitIngredient.getCircuitConfiguration(stack); - } - return "(MetaItem) " + metaValueItem.unlocalizedName + " * " + stack.getCount(); - } - } else if (stack.getItem() instanceof MachineItemBlock) { - MetaTileEntity mte = GTUtility.getMetaTileEntity(stack); - if (mte != null) { - String id = mte.metaTileEntityId.toString(); - if (mte.metaTileEntityId.getNamespace().equals("gregtech")) - id = mte.metaTileEntityId.getPath(); - return "(MetaTileEntity) " + id + " * " + stack.getCount(); - } - } else { - Block block = Block.getBlockFromItem(stack.getItem()); - String id = null; - if (block instanceof BlockCompressed) { - id = "block" + ((BlockCompressed) block).getGtMaterial(stack).toCamelCaseString(); - } else if (block instanceof BlockFrame) { - id = "frame" + ((BlockFrame) block).getGtMaterial(stack).toCamelCaseString(); - } else if (block instanceof BlockMaterialPipeblockMaterialPipe) { - id = blockMaterialPipe.getPrefix().name + blockMaterialPipe.getItemMaterial(stack).toCamelCaseString(); - } - - if (id != null) { - return "(MetaBlock) " + id + " * " + stack.getCount(); - } - } - // noinspection ConstantConditions - return stack.getItem().getRegistryName().toString() + " * " + stack.getCount() + " (Meta " + - stack.getItemDamage() + ")"; + return GTStringUtils.prettyPrintItemStack(stack); } } diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 20bf62d9cad..98025ecf825 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -15,7 +15,6 @@ import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; import gregtech.common.covers.filter.ItemFilterContainer; -import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipe; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; @@ -100,14 +99,6 @@ public void setTransferRate(int transferRate) { if (getWorld() != null && getWorld().isRemote) { // tile at cover holder pos TileEntity te = getTileEntityHere(); - if (te instanceof TileEntityItemPipe) { - ((TileEntityItemPipe) te).resetTransferred(); - } - // tile neighbour to holder pos at attached side - te = getNeighbor(getAttachedSide()); - if (te instanceof TileEntityItemPipe) { - ((TileEntityItemPipe) te).resetTransferred(); - } } } diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index fa3139006d3..2adcdb29188 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -6,7 +6,6 @@ import gregtech.api.mui.GTGuiTextures; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.SmartItemFilter; -import gregtech.common.pipelikeold.itempipe.net.ItemNetHandler; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -58,14 +57,14 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO @Override protected int doTransferItems(IItemHandler itemHandler, IItemHandler myItemHandler, int maxTransferAmount) { - if (conveyorMode == ConveyorMode.EXPORT && itemHandler instanceof ItemNetHandler && - transferMode == TransferMode.KEEP_EXACT) { - return 0; - } - if (conveyorMode == ConveyorMode.IMPORT && myItemHandler instanceof ItemNetHandler && - transferMode == TransferMode.KEEP_EXACT) { - return 0; - } +// if (conveyorMode == ConveyorMode.EXPORT && itemHandler instanceof ItemNetHandler && +// transferMode == TransferMode.KEEP_EXACT) { +// return 0; +// } +// if (conveyorMode == ConveyorMode.IMPORT && myItemHandler instanceof ItemNetHandler && +// transferMode == TransferMode.KEEP_EXACT) { +// return 0; +// } return switch (transferMode) { case TRANSFER_ANY -> doTransferItemsAny(itemHandler, myItemHandler, maxTransferAmount); case TRANSFER_EXACT -> doTransferExact(itemHandler, myItemHandler, maxTransferAmount); diff --git a/src/main/java/gregtech/common/gui/widget/monitor/WidgetCoverList.java b/src/main/java/gregtech/common/gui/widget/monitor/WidgetCoverList.java index f8bc247c0bd..540cba726e1 100644 --- a/src/main/java/gregtech/common/gui/widget/monitor/WidgetCoverList.java +++ b/src/main/java/gregtech/common/gui/widget/monitor/WidgetCoverList.java @@ -1,12 +1,12 @@ package gregtech.common.gui.widget.monitor; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCoverHolder; import gregtech.api.gui.IRenderContext; import gregtech.api.gui.Widget; import gregtech.api.gui.widgets.LabelWidget; import gregtech.api.gui.widgets.ScrollableListWidget; import gregtech.api.gui.widgets.SlotWidget; import gregtech.api.gui.widgets.WidgetGroup; -import gregtech.api.graphnet.pipenetold.tile.PipeCoverableImplementation; import gregtech.api.util.GTLog; import gregtech.api.util.Position; import gregtech.api.util.Size; @@ -48,7 +48,7 @@ public WidgetCoverList(int xPosition, int yPosition, int width, int slotSize, Li for (CoverDigitalInterface cover : covers) { ItemStack itemStack = cover.getPickItem(); BlockPos pos = cover.getPos(); - if (cover.getCoverableView() instanceof PipeCoverableImplementation) { + if (cover.getCoverableView() instanceof PipeCoverHolder) { itemStack = null; pos = pos.offset(cover.getAttachedSide()); TileEntity tileEntity = cover.getWorld().getTileEntity(pos); diff --git a/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java b/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java index 1949724c0fd..ff476feb713 100644 --- a/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java +++ b/src/main/java/gregtech/common/items/behaviors/ColorSprayBehaviour.java @@ -1,9 +1,9 @@ package gregtech.common.items.behaviors; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.metaitem.stats.IItemDurabilityManager; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.util.GradientUtil; import gregtech.api.util.Mods; import gregtech.core.sound.GTSoundEvents; @@ -135,9 +135,9 @@ private static boolean tryStripBlockColor(EntityPlayer player, World world, Bloc } // TileEntityPipeBase special case - if (te instanceof IPipeTilepipe) { + if (te instanceof PipeTileEntity pipe) { if (pipe.isPainted()) { - pipe.setPaintingColor(-1); + pipe.setPaintingColor(-1, false); return true; } else return false; } diff --git a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java index cb62eda55ea..eb18e0939a3 100644 --- a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java @@ -4,18 +4,17 @@ import gregtech.api.GregTechAPI; import gregtech.api.capability.*; import gregtech.api.capability.impl.FluidTankList; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.metaitem.stats.IItemBehaviour; import gregtech.api.metatileentity.IDataInfoProvider; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.util.GTUtility; import gregtech.api.util.LocalizationUtils; import gregtech.api.util.TextFormattingUtil; import gregtech.api.worldgen.bedrockFluids.BedrockFluidVeinHandler; import gregtech.common.ConfigHolder; -import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; import gregtech.core.sound.GTSoundEvents; import net.minecraft.block.Block; @@ -263,13 +262,12 @@ else if (metaTileEntity instanceof IDataInfoProvider) list.addAll(provider.getDataInfo()); } - } else if (tileEntity instanceof IPipeTilepipeTile) { + } else if (tileEntity instanceof PipeTileEntity pipeTile) { // pipes need special name handling - - if (pipeTile.getPipeBlock().getRegistryName() != null) { + if (pipeTile.getBlockType().getRegistryName() != null) { list.add(new TextComponentTranslation("behavior.tricorder.block_name", new TextComponentTranslation( - LocalizationUtils.format(pipeTile.getPipeBlock().getTranslationKey())) + LocalizationUtils.format(pipeTile.getBlockType().getTranslationKey())) .setStyle(new Style().setColor(TextFormatting.BLUE)), new TextComponentTranslation( TextFormattingUtil.formatNumbers(block.getMetaFromState(world.getBlockState(pos)))) @@ -283,11 +281,6 @@ else if (metaTileEntity instanceof IDataInfoProvider) list.addAll(provider.getDataInfo()); } - - if (tileEntity instanceof TileEntityFluidPipe) { - // getting fluid info always costs 500 - energyCost += 500; - } } else if (tileEntity instanceof IDataInfoProvider) { IDataInfoProvider provider = (IDataInfoProvider) tileEntity; diff --git a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityWorldAccelerator.java b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityWorldAccelerator.java index 723c2d1cc2f..2214469b001 100644 --- a/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityWorldAccelerator.java +++ b/src/main/java/gregtech/common/metatileentities/electric/MetaTileEntityWorldAccelerator.java @@ -4,11 +4,11 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; import gregtech.api.capability.impl.EnergyContainerHandler; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.gui.ModularUI; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.TieredMetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.api.util.GTLog; import gregtech.client.renderer.texture.Textures; import gregtech.common.ConfigHolder; @@ -367,7 +367,7 @@ private static void gatherWorldAcceleratorBlacklist() { private static boolean canTileAccelerate(TileEntity tile) { // Check GT tiles first - if (tile instanceof IGregTechTileEntity || tile instanceof TileEntityPipeBase) return false; + if (tile instanceof IGregTechTileEntity || tile instanceof PipeTileEntity) return false; gatherWorldAcceleratorBlacklist(); diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java index 2df02b2c251..df1bdb76c06 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityMonitorScreen.java @@ -3,6 +3,7 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.Cover; import gregtech.api.cover.CoverHolder; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.*; @@ -15,7 +16,6 @@ import gregtech.api.metatileentity.MetaTileEntityUIFactory; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; import gregtech.api.util.FacingPos; import gregtech.api.util.GTLog; import gregtech.client.utils.RenderUtil; @@ -128,8 +128,8 @@ public CoverDigitalInterface getCoverFromPosSide(FacingPos posFacing) { IGregTechTileEntity holder = getHolderFromPos(posFacing.getPos()); if (holder == null) { TileEntity te = this.getWorld() == null ? null : this.getWorld().getTileEntity(posFacing.getPos()); - if (te instanceof IPipeTilepipeTile) { - coverHolder = pipeTile.getCoverableImplementation(); + if (te instanceof PipeTileEntity pipeTile) { + coverHolder = pipeTile.getCoverHolder(); } } else { coverHolder = holder.getMetaTileEntity(); diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java index 3f9859ce3d6..afaad7dbc8f 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java @@ -15,7 +15,6 @@ import gregtech.api.capability.data.query.IBridgeable; import gregtech.api.capability.data.query.IComputationQuery; import gregtech.client.renderer.texture.Textures; -import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java index 5bea9628ed7..70f12553cc2 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java @@ -13,7 +13,6 @@ import gregtech.api.capability.data.query.DataQueryObject; import gregtech.api.capability.data.query.IBridgeable; import gregtech.client.renderer.texture.Textures; -import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 543b86a447a..f3b1a15a40c 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -18,6 +18,7 @@ import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.TraverseHelpers; import gregtech.api.util.GTLog; + import gregtech.common.pipelikeold.cable.net.EnergyGroupData; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index ff69322b486..d6620d1ffd5 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -9,11 +9,8 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.TraverseHelpers; -import gregtech.common.pipelike.net.energy.EnergyTraverseData; import gregtech.common.pipelike.net.energy.WorldEnergyNet; -import gregtech.common.pipelikeold.cable.net.EnergyGroupData; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; diff --git a/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java b/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java deleted file mode 100644 index 1baec90e87c..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/cable/BlockCable.java +++ /dev/null @@ -1,204 +0,0 @@ -package gregtech.common.pipelikeold.cable; - -import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.damagesources.DamageSources; -import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.items.toolitem.ToolHelper; -import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; -import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.registry.MaterialRegistry; -import gregtech.api.util.GTUtility; -import gregtech.client.renderer.pipeold.CableRenderer; -import gregtech.client.renderer.pipeold.PipeRenderer; -import gregtech.common.creativetab.GTCreativeTabs; -import gregtech.common.pipelikeold.cable.net.WorldEnergyNet; -import gregtech.common.pipelikeold.cable.tile.TileEntityCable; -import gregtech.common.pipelikeold.cable.tile.TileEntityCableTickable; -import gregtech.core.advancement.AdvancementTriggers; - -import net.minecraft.block.ITileEntityProvider; -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumBlockRenderType; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockAccess; -import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import com.google.common.base.Preconditions; -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.TreeMap; - -public class BlockCable extends BlockMaterialPipe - implements ITileEntityProvider { - - private final Map enabledMaterials = new TreeMap<>(); - - public BlockCable(Insulation cableType, MaterialRegistry registry) { - super(cableType, registry); - setCreativeTab(GTCreativeTabs.TAB_GREGTECH_CABLES); - setHarvestLevel(ToolClasses.WIRE_CUTTER, 1); - } - - public void addCableMaterial(Material material, WireProperties wireProperties) { - Preconditions.checkNotNull(material, "material was null"); - Preconditions.checkNotNull(wireProperties, "material %s wireProperties was null", material); - Preconditions.checkArgument(material.getRegistry().getNameForObject(material) != null, - "material %s is not registered", material); - if (!pipeType.orePrefix.isIgnored(material)) { - this.enabledMaterials.put(material, wireProperties); - } - } - - public Collection getEnabledMaterials() { - return Collections.unmodifiableSet(enabledMaterials.keySet()); - } - - @Override - public Class getPipeTypeClass() { - return Insulation.class; - } - - @Override - protected WireProperties createProperties(Insulation insulation, Material material) { - return insulation.modifyProperties(enabledMaterials.getOrDefault(material, getFallbackType())); - } - - @SideOnly(Side.CLIENT) - @NotNull - @Override - public PipeRenderer getPipeRenderer() { - return CableRenderer.INSTANCE; - } - - @Override - protected WireProperties getFallbackType() { - return enabledMaterials.values().iterator().next(); - } - - @Override - public WorldEnergyNet getWorldPipeNet(World world) { - return WorldEnergyNet.getWorldEnergyNet(world); - } - - @Override - public void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList items) { - for (Material material : enabledMaterials.keySet()) { - items.add(getItem(material)); - } - } - - @Override - protected boolean isPipeTool(@NotNull ItemStack stack) { - return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); - } - - @Override - public int getLightValue(@NotNull IBlockState state, IBlockAccess world, @NotNull BlockPos pos) { - TileEntity tile = world.getTileEntity(pos); - if (tile instanceof TileEntityCable) { - TileEntityCable cable = (TileEntityCable) tile; - int temp = cable.getTemperature(); - // max light at 5000 K - // min light at 500 K - if (temp >= 5000) { - return 15; - } - if (temp > 500) { - return (temp - 500) * 15 / (4500); - } - } - return 0; - } - - @Override - public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { - if (worldIn.isRemote) { - TileEntityCable cable = (TileEntityCable) getPipeTileEntity(worldIn, pos); - cable.killParticle(); - } - super.breakBlock(worldIn, pos, state); - } - - @Override - public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile) { - return selfTile instanceof TileEntityCable && sideTile instanceof TileEntityCable; - } - - @Override - public boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, - TileEntity tile) { - return tile != null && - tile.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, side.getOpposite()) != null; - } - - @Override - public boolean isHoldingPipe(EntityPlayer player) { - if (player == null) { - return false; - } - ItemStack stack = player.getHeldItemMainhand(); - return stack != ItemStack.EMPTY && stack.getItem() instanceof ItemBlockCable; - } - - @Override - public void onEntityCollision(World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, - @NotNull Entity entityIn) { - super.onEntityCollision(worldIn, pos, state, entityIn); - if (worldIn.isRemote) return; - Insulation insulation = getPipeTileEntity(worldIn, pos).getPipeType(); - if (insulation.insulationLevel == -1 && entityIn instanceof EntityLivingBase) { - EntityLivingBase entityLiving = (EntityLivingBase) entityIn; - TileEntityCable cable = (TileEntityCable) getPipeTileEntity(worldIn, pos); - if (cable != null && cable.getFrameMaterial() == null && cable.getNodeData().getLoss() > 0) { - long voltage = cable.getCurrentMaxVoltage(); - double amperage = cable.getAverageAmperage(); - if (voltage > 0L && amperage > 0L) { - float damageAmount = (float) ((GTUtility.getTierByVoltage(voltage) + 1) * amperage * 4); - entityLiving.attackEntityFrom(DamageSources.getElectricDamage(), damageAmount); - if (entityLiving instanceof EntityPlayerMP) { - AdvancementTriggers.ELECTROCUTION_DEATH.trigger((EntityPlayerMP) entityLiving); - } - } - } - } - } - - @NotNull - @Override - @SideOnly(Side.CLIENT) - @SuppressWarnings("deprecation") - public EnumBlockRenderType getRenderType(@NotNull IBlockState state) { - return CableRenderer.INSTANCE.getBlockRenderType(); - } - - @Override - public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { - return supportsTicking ? new TileEntityCableTickable() : new TileEntityCable(); - } - - @Override - @SideOnly(Side.CLIENT) - protected Pair getParticleTexture(World world, BlockPos blockPos) { - return CableRenderer.INSTANCE.getParticleTexture((TileEntityCable) world.getTileEntity(blockPos)); - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/cable/Insulation.java b/src/main/java/gregtech/common/pipelikeold/cable/Insulation.java deleted file mode 100644 index b1bc89894ef..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/cable/Insulation.java +++ /dev/null @@ -1,76 +0,0 @@ -package gregtech.common.pipelikeold.cable; - -import gregtech.api.graphnet.pipenetold.block.material.IMaterialPipeType; -import gregtech.api.unification.ore.OrePrefix; - -import org.jetbrains.annotations.NotNull; - -public enum Insulation implements IMaterialPipeType { - - WIRE_SINGLE("wire_single", 0.125f, 1, 2, OrePrefix.wireGtSingle, -1), - WIRE_DOUBLE("wire_double", 0.25f, 2, 2, OrePrefix.wireGtDouble, -1), - WIRE_QUADRUPLE("wire_quadruple", 0.375f, 4, 3, OrePrefix.wireGtQuadruple, -1), - WIRE_OCTAL("wire_octal", 0.5f, 8, 3, OrePrefix.wireGtOctal, -1), - WIRE_HEX("wire_hex", 0.75f, 16, 3, OrePrefix.wireGtHex, -1), - - CABLE_SINGLE("cable_single", 0.25f, 1, 1, OrePrefix.cableGtSingle, 0), - CABLE_DOUBLE("cable_double", 0.375f, 2, 1, OrePrefix.cableGtDouble, 1), - CABLE_QUADRUPLE("cable_quadruple", 0.5f, 4, 1, OrePrefix.cableGtQuadruple, 2), - CABLE_OCTAL("cable_octal", 0.75f, 8, 1, OrePrefix.cableGtOctal, 3), - CABLE_HEX("cable_hex", 1.0f, 16, 1, OrePrefix.cableGtHex, 4); - - public static final Insulation[] VALUES = values(); - - public final String name; - public final float thickness; - public final int amperage; - public final int lossMultiplier; - public final OrePrefix orePrefix; - public final int insulationLevel; - - Insulation(String name, float thickness, int amperage, int lossMultiplier, OrePrefix orePrefix, int insulated) { - this.name = name; - this.thickness = thickness; - this.amperage = amperage; - this.orePrefix = orePrefix; - this.insulationLevel = insulated; - this.lossMultiplier = lossMultiplier; - } - - @NotNull - @Override - public String getName() { - return name; - } - - @Override - public float getThickness() { - return thickness; - } - - @Override - public OrePrefix getOrePrefix() { - return orePrefix; - } - - public boolean isCable() { - return ordinal() > 4; - } - - @Override - public WireProperties modifyProperties(WireProperties baseProperties) { - int lossPerBlock; - if (!baseProperties.isSuperconductor() && baseProperties.getLoss() == 0) - lossPerBlock = (int) (0.75 * lossMultiplier); - else lossPerBlock = baseProperties.getLoss() * lossMultiplier; - - return new WireProperties(baseProperties.getVoltage(), baseProperties.getAmperage() * amperage, lossPerBlock, - baseProperties.getMeltTemperature(), baseProperties.isSuperconductor(), - baseProperties.getSuperconductorCriticalTemperature()); - } - - @Override - public boolean isPaintable() { - return true; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/cable/ItemBlockCable.java b/src/main/java/gregtech/common/pipelikeold/cable/ItemBlockCable.java deleted file mode 100644 index 1ba813b11be..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/cable/ItemBlockCable.java +++ /dev/null @@ -1,55 +0,0 @@ -package gregtech.common.pipelikeold.cable; - -import gregtech.api.GTValues; -import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; -import gregtech.api.graphnet.pipenetold.block.material.ItemBlockMaterialPipe; -import gregtech.api.util.GTUtility; -import gregtech.client.utils.TooltipHelper; -import gregtech.common.ConfigHolder; - -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.item.ItemStack; -import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class ItemBlockCable extends ItemBlockMaterialPipe { - - public ItemBlockCable(BlockCable block) { - super(block); - } - - @Override - @SideOnly(Side.CLIENT) - public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, - @NotNull ITooltipFlag flagIn) { - super.addInformation(stack, worldIn, tooltip, flagIn); - WireProperties wireProperties = blockPipe.createItemProperties(stack); - int tier = GTUtility.getTierByVoltage(wireProperties.getVoltage()); - if (wireProperties.isSuperconductor()) - tooltip.add(I18n.format("gregtech.cable.superconductor", GTValues.VN[tier])); - tooltip.add(I18n.format("gregtech.cable.voltage", wireProperties.getVoltage(), GTValues.VNF[tier])); - tooltip.add(I18n.format("gregtech.cable.amperage", wireProperties.getAmperage())); - tooltip.add(I18n.format("gregtech.cable.loss_per_block", wireProperties.getLoss())); - - if (TooltipHelper.isShiftDown()) { - tooltip.add(I18n.format("gregtech.tool_action.wire_cutter.connect")); - tooltip.add(I18n.format("gregtech.tool_action.screwdriver.access_covers")); - tooltip.add(I18n.format("gregtech.tool_action.crowbar")); - } else { - tooltip.add(I18n.format("gregtech.tool_action.show_tooltips")); - } - - if (ConfigHolder.misc.debug) { - BlockMaterialPipe blockMaterialPipe = (BlockMaterialPipe) blockPipe; - tooltip.add("MetaItem Id: " + blockMaterialPipe.getPrefix().name + - blockMaterialPipe.getItemMaterial(stack).toCamelCaseString()); - } - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java deleted file mode 100644 index 4afd7138770..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyNetHandler.java +++ /dev/null @@ -1,372 +0,0 @@ -package gregtech.common.pipelikeold.cable.net; - -import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.capability.IEnergyContainer; -import gregtech.api.graphnet.AbstractGroupData; -import gregtech.api.graphnet.pipenetold.IPipeNetHandler; -import gregtech.api.graphnet.pipenetold.PipeNetNode; -import gregtech.api.graphnet.pipenetold.PipeNetPath; -import gregtech.api.graphnet.pipenetold.NodeLossResult; -import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.util.FacingPos; -import gregtech.api.util.GTLog; -import gregtech.api.util.GTUtility; -import gregtech.common.pipelikeold.cable.Insulation; -import gregtech.common.pipelikeold.cable.tile.TileEntityCable; - -import net.minecraft.util.EnumFacing; -import net.minecraftforge.fml.common.FMLCommonHandler; - -import it.unimi.dsi.fastutil.doubles.DoubleArrayList; -import it.unimi.dsi.fastutil.doubles.DoubleList; -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Consumer; - -public class EnergyNetHandler implements IEnergyContainer, IPipeNetHandler { - - protected static final PipeNetNode FAKE_SOURCE = new PipeNetNode<>( - new WireProperties(Integer.MAX_VALUE, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, false)); - - private final WorldEnergyNet net; - private boolean transfer; - private final TileEntityCable cable; - private final EnumFacing facing; - private final Map, NodeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); - private Object2LongOpenHashMap destSimulationCache; - private final NetFlowEdge inputEdge; - - public EnergyNetHandler(WorldEnergyNet net, TileEntityCable cable, EnumFacing facing) { - this.net = net; - this.cable = cable; - this.facing = facing; - this.inputEdge = new NetFlowEdge(1) { - - @Override - public PipeNetNode getSource() { - return FAKE_SOURCE; - } - - @Override - public PipeNetNode getTarget() { - return EnergyNetHandler.this.cable.getNode(); - } - }; - } - - @Override - public WorldEnergyNet getNet() { - return net; - } - - @Override - public EnumFacing getFacing() { - return facing; - } - - @Override - public long getInputPerSec() { - AbstractGroupData data = net.getGroup(cable.getPipePos()).getData(); - if (!(data instanceof EnergyGroupData e)) return 0; - return e.getEnergyFluxPerSec(); - } - - @Override - public long getOutputPerSec() { - AbstractGroupData data = net.getGroup(cable.getPipePos()).getData(); - if (!(data instanceof EnergyGroupData e)) return 0; - return e.getEnergyFluxPerSec(); - } - - @Override - public long getEnergyCanBeInserted() { - return getEnergyCapacity(); - } - - @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { - if (transfer) return 0; - if (side == null) { - if (facing == null) return 0; - side = facing; - } - if (amperage <= 0 || voltage <= 0) - return 0; - - long queryTick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - SimulatorKey simulator = simulate ? SimulatorKey.getNewSimulatorInstance() : null; - destSimulationCache = simulate ? new Object2LongOpenHashMap<>() : null; - - this.getNet().getGraph().prepareForAlgorithmRun(null, simulator); - long amperesUsed = distributionRespectCapacity(side, voltage, amperage, queryTick, - this.getNet().getPaths(cable), simulator); - if (amperesUsed < amperage) { - // if we still have undistributed amps, attempt to distribute them while going over edge capacities. - amperesUsed += distributionIgnoreCapacity(side, voltage, amperage - amperesUsed, queryTick, - this.getNet().getPaths(cable), simulator); - } - this.lossResultCache.forEach((k, v) -> v.getPostAction().accept(k)); - this.lossResultCache.clear(); - - this.destSimulationCache = null; - - if (this.cable.getNode().getGroupSafe().getData() instanceof EnergyGroupData data) - data.addEnergyFluxPerSec(amperesUsed * voltage); - return amperesUsed; - } - - private long distributionRespectCapacity(EnumFacing side, long voltage, long amperage, long queryTick, - Iterator> paths, - SimulatorKey simulator) { - long availableAmperage = amperage; - mainloop: - while (paths.hasNext()) { - PipeNetPath path = paths.next(); - // skip paths where loss exceeds available voltage - if (path.getSumData().getLoss() > voltage) continue; - Iterator iterator = path.getFacingIterator(); - boolean pathDestThis = path.getTargetNode().getNodePos().equals(this.cable.getPipePos()); - while (iterator.hasNext()) { - PipeNetPath.FacedPipeNetPath facedPath = path - .withFacing(iterator.next()); - if (pathDestThis && facedPath.facing == side) { - // do not distribute power back into our source - continue; - } - - IEnergyContainer dest = facedPath.getTargetTE() - .getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facedPath.oppositeFacing()); - if (dest == null || dest == this) continue; - if (!dest.inputsEnergy(facedPath.oppositeFacing()) || dest.getEnergyCanBeInserted() <= 0) continue; - - List> nodeList = facedPath.getNodeList(); - DoubleList voltageCaps = new DoubleArrayList(); - long pathAmperage = availableAmperage; - - List edgeList = facedPath.getEdgeList(); - FlowConsumerList flowLimitConsumers = new FlowConsumerList<>(); - for (int j = 0; j < nodeList.size(); j++) { - NetFlowEdge edge = j == 0 ? inputEdge : edgeList.get(j - 1); - PipeNetNode target = nodeList.get(j); - // amperage capping - long max = Math.min(pathAmperage, - edge.getFlowLimit(null, this.net.getGraph(), queryTick, simulator)); - double ratio = (double) max / pathAmperage; - pathAmperage = max; - flowLimitConsumers.modifyRatios(ratio); - - TileEntityCable tile = simulator == null ? (TileEntityCable) target.getHeldMTEUnsafe() : null; - long finalVoltage = voltage; - flowLimitConsumers.add(edge, null, this.net.getGraph(), pathAmperage, queryTick, - simulator, tile != null ? amps -> { - tile.contributeAmperageFlow(amps); - tile.contributeVoltageFlow(finalVoltage); - } : null); - // voltage loss - voltage -= target.getData().getLoss(); - if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) continue mainloop; - } - // skip paths where we can't transfer amperage - if (pathAmperage <= 0) continue; - // complete transfer - this.transfer = true; - // actual voltage that reaches the destination is the geometric mean of the input and all the caps - long finalVoltage = Math.min((long) GTUtility.geometricMean((double) voltage, - voltageCaps.toArray(new double[] {})), voltage); - long accepted = dest.acceptEnergyFromNetwork(facedPath.oppositeFacing(), finalVoltage, pathAmperage, - simulator != null); - this.transfer = false; - if (simulator != null) - accepted = getSimulatedAccepted(destSimulationCache, facedPath.toFacingPos(), accepted); - flowLimitConsumers.doConsumption((double) accepted / pathAmperage); - availableAmperage -= accepted; - - if (availableAmperage <= 0) return amperage; - } - } - return amperage - availableAmperage; - } - - private long distributionIgnoreCapacity(EnumFacing side, long voltage, long amperage, long queryTick, - Iterator> paths, - SimulatorKey simulator) { - Object2LongOpenHashMap localDestSimulationCache = new Object2LongOpenHashMap<>(); - - long availableAmperage = amperage; - mainloop: - while (paths.hasNext()) { - PipeNetPath path = paths.next(); - // skip paths where loss exceeds available voltage - if (path.getSumData().getLoss() > voltage) continue; - Iterator iterator = path.getFacingIterator(); - boolean pathDestThis = path.getTargetNode().getNodePos().equals(this.cable.getPipePos()); - while (iterator.hasNext()) { - PipeNetPath.FacedPipeNetPath facedPath = path - .withFacing(iterator.next()); - if (pathDestThis && facedPath.facing == side) { - // do not distribute power back into our source - continue; - } - - IEnergyContainer dest = facedPath.getTargetTE() - .getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, facedPath.oppositeFacing()); - if (dest == null || dest == this) continue; - if (!dest.inputsEnergy(facedPath.oppositeFacing()) || dest.getEnergyCanBeInserted() <= 0) continue; - - List> nodeList = facedPath.getNodeList(); - DoubleList voltageCaps = new DoubleArrayList(); - long pathAmperage = availableAmperage; - - List edgeList = facedPath.getEdgeList(); - List> flowLimitConsumers = new ObjectArrayList<>(); - List> amperageLossHeat = new ObjectArrayList<>(); - for (int j = 0; j < nodeList.size(); j++) { - NetFlowEdge edge = j == 0 ? inputEdge : edgeList.get(j - 1); - PipeNetNode target = nodeList.get(j); - // amperage capping - long flowLimit = edge.getFlowLimit(null, this.net.getGraph(), queryTick, simulator); - long finalPathAmperage = pathAmperage; - if (simulator == null && finalPathAmperage != 0) { - amperageLossHeat.add((ratio) -> { - long adjustedAmperage = (long) (finalPathAmperage * ratio); - if (adjustedAmperage > flowLimit) { - int heat = calculateHeat(adjustedAmperage - flowLimit, adjustedAmperage, 1); - getOrGenerateLossResult(target, heat, false); - } - }); - } - - TileEntityCable tile = simulator == null ? (TileEntityCable) target.getHeldMTEUnsafe() : null; - long finalVoltage = voltage; - flowLimitConsumers.add((ratio) -> { - long consumption = Math.min((long) (finalPathAmperage * ratio), flowLimit); - if (consumption == 0) return; - edge.consumeFlowLimit(null, getNet().getGraph(), consumption, queryTick, simulator); - if (tile != null) { - tile.contributeAmperageFlow(consumption); - tile.contributeVoltageFlow(finalVoltage); - } - }); - pathAmperage = Math.min(pathAmperage, flowLimit); - // voltage loss - voltage -= target.getData().getLoss(); - if (calculateVoltageLoss(voltage, simulator, voltageCaps, pathAmperage, target)) continue mainloop; - } - - // actual voltage that reaches the destination is the geometric mean of the input and all the caps - this.transfer = true; - long finalVoltage = Math.min((long) GTUtility.geometricMean((double) voltage, - voltageCaps.toArray(new double[] {})), voltage); - long simulatedAccepted = dest.acceptEnergyFromNetwork(facedPath.oppositeFacing(), finalVoltage, - availableAmperage, true); - this.transfer = false; - simulatedAccepted = getSimulatedAccepted(localDestSimulationCache, facedPath.toFacingPos(), - simulatedAccepted); - if (simulator != null) - simulatedAccepted = getSimulatedAccepted(destSimulationCache, facedPath.toFacingPos(), - simulatedAccepted); - double ratio = (double) simulatedAccepted / availableAmperage; - flowLimitConsumers.forEach(consumer -> consumer.accept(ratio)); - amperageLossHeat.forEach(consumer -> consumer.accept(ratio)); - availableAmperage -= simulatedAccepted; - - if (availableAmperage <= 0) return amperage; - } - } - return amperage - availableAmperage; - } - - private long getSimulatedAccepted(Object2LongOpenHashMap destSimulationCache, - FacingPos facingPos, - long accepted) { - AtomicLong atomicAccepted = new AtomicLong(accepted); - destSimulationCache.compute(facingPos, (k, v) -> { - if (v == null) return atomicAccepted.get(); - atomicAccepted.set(Math.max(atomicAccepted.get() - v, 0)); - return v + atomicAccepted.get(); - }); - return atomicAccepted.get(); - } - - private boolean calculateVoltageLoss(long voltage, SimulatorKey simulator, - DoubleList voltageCaps, long pathAmperage, - PipeNetNode target) { - // TODO undo loss & heating on backflow - if (target.getData().getVoltage() < voltage) { - int heat = calculateHeat(pathAmperage, voltage, target.getData().getVoltage()); - NodeLossResult lossResult = getOrGenerateLossResult(target, heat, simulator != null); - - if (lossResult.getLossFunction() == 0) { - // stop this path, a cable burned - return true; - } - voltageCaps.add(target.getData().getVoltage()); - } - return false; - } - - private int calculateHeat(long exceedingAmperage, long voltage, long maxVoltage) { - return (int) (exceedingAmperage * (Math.log1p(Math.log((double) voltage / maxVoltage)) * 45 + 36.5)); - } - - @Override - public long getInputAmperage() { - return cable.getNodeData().getAmperage(); - } - - @Override - public long getInputVoltage() { - return cable.getNodeData().getVoltage(); - } - - @Override - public long getEnergyCapacity() { - return getInputVoltage() * getInputAmperage(); - } - - @Override - public long changeEnergy(long energyToAdd) { - GTLog.logger.fatal("Do not use changeEnergy() for cables! Use acceptEnergyFromNetwork()"); - return acceptEnergyFromNetwork(facing == null ? EnumFacing.UP : facing, - energyToAdd / getInputAmperage(), - energyToAdd / getInputVoltage()) * getInputVoltage(); - } - - @Override - public boolean outputsEnergy(EnumFacing side) { - return true; - } - - @Override - public boolean inputsEnergy(EnumFacing side) { - return true; - } - - @Override - public long getEnergyStored() { - return 0; - } - - @Override - public boolean isOneProbeHidden() { - return true; - } - - protected NodeLossResult getOrGenerateLossResult(PipeNetNode node, - int heat, boolean simulate) { - var cachedResult = this.lossResultCache.get(node); - if (cachedResult == null) { - cachedResult = ((TileEntityCable) node.getHeldMTE()).applyHeat(heat, simulate); - if (cachedResult.getLossFunction() != 0) return cachedResult; - else this.lossResultCache.put(node, cachedResult); - } - return cachedResult; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/cable/net/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelikeold/cable/net/WorldEnergyNet.java deleted file mode 100644 index 3af22fc6583..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/cable/net/WorldEnergyNet.java +++ /dev/null @@ -1,75 +0,0 @@ -package gregtech.common.pipelikeold.cable.net; - -import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.graphnet.AbstractGroupData; -import gregtech.api.graphnet.pipenetold.WorldPipeNetComplex; -import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; -import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.common.pipelikeold.cable.Insulation; -import gregtech.common.pipelikeold.cable.tile.TileEntityCable; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; - -public class WorldEnergyNet extends WorldPipeNetComplex { - - private static final String DATA_ID_BASE = "gregtech.e_net"; - - public static WorldEnergyNet getWorldEnergyNet(World world) { - final String DATA_ID = getDataID(DATA_ID_BASE, world); - WorldEnergyNet eNetWorldData = (WorldEnergyNet) world.loadData(WorldEnergyNet.class, DATA_ID); - if (eNetWorldData == null) { - eNetWorldData = new WorldEnergyNet(DATA_ID); - world.setData(DATA_ID, eNetWorldData); - } - eNetWorldData.setWorldAndInit(world); - return eNetWorldData; - } - - public WorldEnergyNet(String name) { - super(name, true, () -> new NetFlowEdge(1), DynamicWeightsShortestPathsAlgorithm::new); - } - - @Override - protected boolean needsDynamicWeights() { - return true; - } - - @Override - protected Capability[] getConnectionCapabilities() { - return new Capability[] { GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER }; - } - - @Override - protected Class> getBasePipeClass() { - return TileEntityCable.class; - } - - @Override - public AbstractGroupData getBlankGroupData() { - return new EnergyGroupData(); - } - - @Override - public void writeNodeData(WireProperties nodeData, NBTTagCompound tagCompound) { - tagCompound.setInteger("voltage", nodeData.getVoltage()); - tagCompound.setInteger("amperage", nodeData.getAmperage()); - tagCompound.setInteger("loss", nodeData.getLoss()); - tagCompound.setInteger("meltTemperature", nodeData.getMeltTemperature()); - tagCompound.setInteger("critical", nodeData.getSuperconductorCriticalTemperature()); - tagCompound.setBoolean("supercond", nodeData.isSuperconductor()); - } - - @Override - protected WireProperties readNodeData(NBTTagCompound tagCompound) { - int voltage = tagCompound.getInteger("voltage"); - int amperage = tagCompound.getInteger("amperage"); - int lossPerBlock = tagCompound.getInteger("loss"); - int meltTemperature = tagCompound.getInteger("meltTemperature"); - int critical = tagCompound.getInteger("critical"); - boolean supercond = tagCompound.getBoolean("supercond"); - return new WireProperties(voltage, amperage, lossPerBlock, meltTemperature, supercond, critical); - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/cable/tile/AveragingPerTickCounter.java b/src/main/java/gregtech/common/pipelikeold/cable/tile/AveragingPerTickCounter.java deleted file mode 100644 index 0dd33aa769f..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/cable/tile/AveragingPerTickCounter.java +++ /dev/null @@ -1,91 +0,0 @@ -package gregtech.common.pipelikeold.cable.tile; - -import net.minecraft.world.World; - -import java.util.Arrays; - -public class AveragingPerTickCounter { - - private final long defaultValue; - private final long[] values; - private long lastUpdatedWorldTime = 0; - private int currentIndex = 0; - private boolean dirty = true; - private double lastAverage = 0; - - public AveragingPerTickCounter() { - this(0, 20); - } - - /** - * Averages a value over a certain amount of ticks - * - * @param defaultValue self-explanatory - * @param length amount of ticks to average (20 for 1 second) - */ - public AveragingPerTickCounter(long defaultValue, int length) { - this.defaultValue = defaultValue; - this.values = new long[length]; - Arrays.fill(values, defaultValue); - } - - private void checkValueState(World world) { - if (world == null) return; - long currentWorldTime = world.getTotalWorldTime(); - if (currentWorldTime != lastUpdatedWorldTime) { - long dif = currentWorldTime - lastUpdatedWorldTime; - if (dif >= values.length || dif < 0) { - Arrays.fill(values, defaultValue); - currentIndex = 0; - } else { - currentIndex += dif; - if (currentIndex > values.length - 1) - currentIndex -= values.length; - int index; - for (int i = 0, n = values.length; i < dif; i++) { - index = i + currentIndex; - if (index >= n) - index -= n; - values[index] = defaultValue; - } - } - this.lastUpdatedWorldTime = currentWorldTime; - dirty = true; - } - } - - /** - * @return the value from the current tick - */ - public long getLast(World world) { - checkValueState(world); - return values[currentIndex]; - } - - /** - * @return the average of all values - */ - public double getAverage(World world) { - checkValueState(world); - if (!dirty) - return lastAverage; - dirty = false; - return lastAverage = Arrays.stream(values).sum() / (double) (values.length); - } - - /** - * @param value the value to increment the current value by - */ - public void increment(World world, long value) { - checkValueState(world); - values[currentIndex] += value; - } - - /** - * @param value the value to set current value to - */ - public void set(World world, long value) { - checkValueState(world); - values[currentIndex] = value; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/cable/tile/PerTickLongCounter.java b/src/main/java/gregtech/common/pipelikeold/cable/tile/PerTickLongCounter.java deleted file mode 100644 index 11c9a571471..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/cable/tile/PerTickLongCounter.java +++ /dev/null @@ -1,58 +0,0 @@ -package gregtech.common.pipelikeold.cable.tile; - -import net.minecraft.world.World; - -public class PerTickLongCounter { - - private final long defaultValue; - private long lastUpdatedWorldTime; - private long lastValue; - private long currentValue; - - public PerTickLongCounter() { - this(0); - } - - public PerTickLongCounter(long defaultValue) { - this.defaultValue = defaultValue; - this.currentValue = defaultValue; - this.lastValue = defaultValue; - } - - private void checkValueState(World world) { - if (world == null) return; - long currentWorldTime = world.getTotalWorldTime(); - if (currentWorldTime != lastUpdatedWorldTime) { - if (currentWorldTime == lastUpdatedWorldTime + 1) { - // last updated time is 1 tick ago, so we can move current value to last - // before resetting it to default value - this.lastValue = currentValue; - } else { - // otherwise, set last value as default value - this.lastValue = defaultValue; - } - this.lastUpdatedWorldTime = currentWorldTime; - this.currentValue = defaultValue; - } - } - - public long get(World world) { - checkValueState(world); - return currentValue; - } - - public long getLast(World world) { - checkValueState(world); - return lastValue; - } - - public void increment(World world, long value) { - checkValueState(world); - this.currentValue += value; - } - - public void set(World world, long value) { - checkValueState(world); - this.currentValue = value; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCable.java b/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCable.java deleted file mode 100644 index 6974d7191d3..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCable.java +++ /dev/null @@ -1,320 +0,0 @@ -package gregtech.common.pipelikeold.cable.tile; - -import gregtech.api.GTValues; -import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.capability.IEnergyContainer; -import gregtech.api.metatileentity.IDataInfoProvider; -import gregtech.api.graphnet.pipenetold.PipeNetNode; -import gregtech.api.graphnet.pipenetold.NodeLossResult; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; -import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.util.TaskScheduler; -import gregtech.api.util.TextFormattingUtil; -import gregtech.client.particle.GTOverheatParticle; -import gregtech.client.particle.GTParticleManager; -import gregtech.common.blocks.MetaBlocks; -import gregtech.common.pipelikeold.cable.BlockCable; -import gregtech.common.pipelikeold.cable.Insulation; -import gregtech.common.pipelikeold.cable.net.EnergyNetHandler; -import gregtech.common.pipelikeold.cable.net.WorldEnergyNet; - -import net.minecraft.init.Blocks; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.PacketBuffer; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.Style; -import net.minecraft.util.text.TextComponentTranslation; -import net.minecraft.util.text.TextFormatting; -import net.minecraft.world.WorldServer; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import codechicken.lib.vec.Cuboid6; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.function.Consumer; - -import static gregtech.api.capability.GregtechDataCodes.*; - -public class TileEntityCable extends TileEntityMaterialPipeBase - implements IDataInfoProvider { - - private final EnumMap handlers = new EnumMap<>(EnumFacing.class); - private final PerTickLongCounter maxVoltageCounter = new PerTickLongCounter(); - private final AveragingPerTickCounter averageVoltageCounter = new AveragingPerTickCounter(); - private final AveragingPerTickCounter averageAmperageCounter = new AveragingPerTickCounter(); - private EnergyNetHandler defaultHandler; - // the EnergyNetHandler can only be created on the server, so we have an empty placeholder for the client - private final IEnergyContainer clientCapability = IEnergyContainer.DEFAULT; - @SideOnly(Side.CLIENT) - private GTOverheatParticle particle; - private int temperature = getDefaultTemp(); - private boolean isTicking = false; - - public long getWorldTime() { - return hasWorld() ? getWorld().getTotalWorldTime() : 0L; - } - - @Override - public Class getPipeTypeClass() { - return Insulation.class; - } - - @Override - public boolean supportsTicking() { - return false; - } - - @Override - public boolean canHaveBlockedFaces() { - return false; - } - - private void initHandlers() { - WorldEnergyNet net = WorldEnergyNet.getWorldEnergyNet(getPipeWorld()); - for (EnumFacing facing : EnumFacing.VALUES) { - handlers.put(facing, new EnergyNetHandler(net, this, facing)); - } - defaultHandler = new EnergyNetHandler(net, this, null); - } - - @Override - public void onLoad() { - super.onLoad(); - if (!world.isRemote) { - setTemperature(temperature); - if (temperature > getDefaultTemp()) { - TaskScheduler.scheduleTask(world, this::update); - } - } - } - - public NodeLossResult applyHeat(int amount, boolean simulate) { - double loss = 1; - Consumer> destructionResult = null; - - if (temperature + amount >= getMeltTemp()) { - // cable melted - destructionResult = node -> { - isTicking = false; - getWorld().setBlockState(pos, Blocks.FIRE.getDefaultState()); - if (!getWorld().isRemote) { - ((WorldServer) getWorld()).spawnParticle(EnumParticleTypes.SMOKE_LARGE, - pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, - 5 + getWorld().rand.nextInt(3), 0.0, 0.0, 0.0, 0.1); - } - }; - loss = 0; - } - if (!simulate) setTemperature(temperature + amount); - return new NodeLossResult(destructionResult == null ? node -> {} : destructionResult, loss); - } - - private boolean update() { - // thicker cables cool faster - setTemperature((int) (temperature - Math.pow(temperature - getDefaultTemp(), 0.35) * - Math.sqrt(this.getPipeType().getThickness()) * 4)); - - if (getPipeType().insulationLevel >= 0 && temperature >= 1500 && GTValues.RNG.nextFloat() < 0.1) { - // insulation melted - uninsulate(); - isTicking = false; - } - return isTicking; - } - - private void uninsulate() { - int temp = temperature; - setTemperature(getDefaultTemp()); - int index = getPipeType().insulationLevel; - BlockCable newBlock = MetaBlocks.CABLES.get(getPipeBlock().getMaterialRegistry().getModid())[index]; - world.setBlockState(pos, newBlock.getDefaultState()); - TileEntityCable newCable = (TileEntityCable) world.getTileEntity(pos); - if (newCable != null) { // should never be null - newCable.transferDataFrom(this); - newCable.setPipeData(newBlock, newBlock.getItemPipeType(null), getPipeMaterial()); - for (EnumFacing facing : EnumFacing.VALUES) { - if (isConnected(facing)) { - newCable.setConnection(facing, true, true); - } - } - newCable.setTemperature(temp); - if (!newCable.isTicking) { - TaskScheduler.scheduleTask(world, newCable::update); - newCable.isTicking = true; - } - } - } - - public void setTemperature(int temperature) { - this.temperature = temperature; - world.checkLight(pos); - if (!world.isRemote) { - writeCustomData(CABLE_TEMPERATURE, buf -> buf.writeVarInt(temperature)); - if (!isTicking && temperature > getDefaultTemp()) { - isTicking = true; - TaskScheduler.scheduleTask(getWorld(), this::update); - } else if (isTicking && temperature <= getDefaultTemp()) { - isTicking = false; - } - } else { - // TODO fix particle sometimes not rendering after world load - if (temperature <= getDefaultTemp()) { - if (isParticleAlive()) - particle.setExpired(); - } else { - if (!isParticleAlive()) { - createParticle(); - } - particle.setTemperature(temperature); - } - } - } - - @Override - public void transferDataFrom(IPipeTile tileEntity) { - super.transferDataFrom(tileEntity); - } - - public int getDefaultTemp() { - return 293; - } - - public int getTemperature() { - return temperature; - } - - public int getMeltTemp() { - return this.getNodeData().getMeltTemperature(); - } - - @SideOnly(Side.CLIENT) - public void createParticle() { - particle = new GTOverheatParticle(this, getMeltTemp(), getPipeBoxes(), getPipeType().insulationLevel >= 0); - GTParticleManager.INSTANCE.addEffect(particle); - } - - @SideOnly(Side.CLIENT) - public void killParticle() { - if (isParticleAlive()) { - particle.setExpired(); - particle = null; - } - } - - public void contributeAmperageFlow(long amperage) { - averageAmperageCounter.increment(getWorld(), amperage); - } - - public void contributeVoltageFlow(long voltage) { - if (voltage > maxVoltageCounter.get(getWorld())) maxVoltageCounter.set(getWorld(), voltage); - averageVoltageCounter.set(getWorld(), maxVoltageCounter.get(getWorld())); - } - - public double getAverageAmperage() { - return averageAmperageCounter.getAverage(getWorld()); - } - - public long getCurrentMaxVoltage() { - return maxVoltageCounter.get(getWorld()); - } - - public double getAverageVoltage() { - return averageVoltageCounter.getAverage(getWorld()); - } - - public long getMaxAmperage() { - return getNodeData().getAmperage(); - } - - @ApiStatus.ScheduledForRemoval(inVersion = "2.9") - @Deprecated - public long getMaxVoltage() { - return getNodeData().getVoltage(); - } - - @Nullable - @Override - public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { - if (capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER) { - if (world.isRemote) - return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER.cast(clientCapability); - if (handlers.isEmpty()) - initHandlers(); - return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER.cast(handlers.getOrDefault(facing, defaultHandler)); - } - return super.getCapabilityInternal(capability, facing); - } - - @Override - public int getDefaultPaintingColor() { - return 0x404040; - } - - @Override - public void receiveCustomData(int discriminator, PacketBuffer buf) { - if (discriminator == CABLE_TEMPERATURE) { - setTemperature(buf.readVarInt()); - } else { - super.receiveCustomData(discriminator, buf); - if (isParticleAlive() && discriminator == UPDATE_CONNECTIONS) { - particle.updatePipeBoxes(getPipeBoxes()); - } - } - } - - @SideOnly(Side.CLIENT) - public boolean isParticleAlive() { - return particle != null && particle.isAlive(); - } - - protected List getPipeBoxes() { - List pipeBoxes = new ArrayList<>(); - float thickness = getPipeType().getThickness(); - if ((getConnections() & 63) < 63) { - pipeBoxes.add(BlockPipe.getSideBox(null, thickness)); - } - for (EnumFacing facing : EnumFacing.VALUES) { - if (isConnected(facing)) - pipeBoxes.add(BlockPipe.getSideBox(facing, thickness)); - } - return pipeBoxes; - } - - @NotNull - @Override - public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { - super.writeToNBT(compound); - compound.setInteger("Temp", temperature); - return compound; - } - - @Override - public void readFromNBT(@NotNull NBTTagCompound compound) { - super.readFromNBT(compound); - temperature = compound.getInteger("Temp"); - } - - @NotNull - @Override - public List getDataInfo() { - List list = new ArrayList<>(); - list.add(new TextComponentTranslation("behavior.tricorder.eut_per_sec", - new TextComponentTranslation(TextFormattingUtil.formatNumbers(this.getAverageVoltage())) - .setStyle(new Style().setColor(TextFormatting.RED)))); - list.add(new TextComponentTranslation("behavior.tricorder.amp_per_sec", - new TextComponentTranslation(TextFormattingUtil.formatNumbers(this.getAverageAmperage())) - .setStyle(new Style().setColor(TextFormatting.RED)))); - return list; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCableTickable.java b/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCableTickable.java deleted file mode 100644 index b07b3ca4117..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/cable/tile/TileEntityCableTickable.java +++ /dev/null @@ -1,18 +0,0 @@ -package gregtech.common.pipelikeold.cable.tile; - -import net.minecraft.util.ITickable; - -public class TileEntityCableTickable extends TileEntityCable implements ITickable { - - public TileEntityCableTickable() {} - - @Override - public void update() { - getCoverableImplementation().update(); - } - - @Override - public boolean supportsTicking() { - return true; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java deleted file mode 100644 index 5474f265946..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/BlockFluidPipe.java +++ /dev/null @@ -1,184 +0,0 @@ -package gregtech.common.pipelikeold.fluidpipe; - -import gregtech.api.fluids.FluidConstants; -import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.graphnet.pipenetold.PipeNetNode; -import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; -import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.registry.MaterialRegistry; -import gregtech.api.util.EntityDamageUtil; -import gregtech.client.renderer.pipeold.FluidPipeRenderer; -import gregtech.client.renderer.pipeold.PipeRenderer; -import gregtech.common.creativetab.GTCreativeTabs; -import gregtech.common.pipelikeold.fluidpipe.net.WorldFluidPipeNet; -import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; -import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipeTickable; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumBlockRenderType; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fml.common.FMLCommonHandler; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import com.google.common.base.Preconditions; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Collections; -import java.util.Set; -import java.util.SortedMap; -import java.util.TreeMap; - -public class BlockFluidPipe extends - BlockMaterialPipe { - - private final SortedMap enabledMaterials = new TreeMap<>(); - - public BlockFluidPipe(FluidPipeType pipeType, MaterialRegistry registry) { - super(pipeType, registry); - setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); - setHarvestLevel(ToolClasses.WRENCH, 1); - } - - public void addPipeMaterial(Material material, FluidPipeProperties fluidPipeProperties) { - Preconditions.checkNotNull(material, "material"); - Preconditions.checkNotNull(fluidPipeProperties, "material %s fluidPipeProperties was null", material); - Preconditions.checkArgument(material.getRegistry().getNameForObject(material) != null, - "material %s is not registered", material); - this.enabledMaterials.put(material, fluidPipeProperties); - } - - public Collection getEnabledMaterials() { - return Collections.unmodifiableSet(enabledMaterials.keySet()); - } - - @Override - public Class getPipeTypeClass() { - return FluidPipeType.class; - } - - @Override - public WorldFluidPipeNet getWorldPipeNet(World world) { - return WorldFluidPipeNet.getWorldPipeNet(world); - } - - @Override - protected FluidPipeProperties createProperties(FluidPipeType fluidPipeType, Material material) { - return fluidPipeType.modifyProperties(enabledMaterials.getOrDefault(material, getFallbackType())); - } - - @SideOnly(Side.CLIENT) - @NotNull - @Override - public PipeRenderer getPipeRenderer() { - return FluidPipeRenderer.INSTANCE; - } - - @Override - protected FluidPipeProperties getFallbackType() { - return enabledMaterials.values().iterator().next(); - } - - @Override - public void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList items) { - for (Material material : enabledMaterials.keySet()) { - items.add(getItem(material)); - } - } - - @Override - public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { - super.breakBlock(worldIn, pos, state); - // TODO insert to neighbours - } - - @Override - public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile) { - return selfTile instanceof TileEntityFluidPipe && sideTile instanceof TileEntityFluidPipe; - } - - @Override - public boolean canPipeConnectToBlock(IPipeTile selfTile, - EnumFacing side, - TileEntity tile) { - return tile != null && - tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side.getOpposite()) != null; - } - - @Override - public boolean isHoldingPipe(EntityPlayer player) { - if (player == null) { - return false; - } - ItemStack stack = player.getHeldItemMainhand(); - return stack != ItemStack.EMPTY && stack.getItem() instanceof ItemBlockFluidPipe; - } - - @Override - public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, - @NotNull Entity entityIn) { - super.onEntityCollision(worldIn, pos, state, entityIn); - if (worldIn.isRemote) return; - TileEntityFluidPipe pipe = (TileEntityFluidPipe) getPipeTileEntity(worldIn, pos); - if (pipe.getFrameMaterial() == null && pipe.getOffsetTimer() % 10 == 0) { - if (entityIn instanceof EntityLivingBase living) { - PipeNetNode node = pipe.getNode(); - var net = node.getNet(); - Set fluids = new ObjectOpenHashSet<>(); - for (NetFlowEdge edge : net.getGraph().edgesOf(node)) { - for (Object obj : edge.getActiveChannels(null, - FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter())) { - if (obj instanceof FluidTestObject tester) fluids.add(tester); - } - } - int maxTemp = FluidConstants.ROOM_TEMPERATURE; - int minTemp = FluidConstants.ROOM_TEMPERATURE; - for (FluidTestObject fluid : fluids) { - int temp = fluid.fluid.getTemperature(fluid.recombine()); - maxTemp = Math.max(temp, maxTemp); - minTemp = Math.min(temp, minTemp); - } - EntityDamageUtil.applyTemperatureDamage(living, maxTemp, 1.0F, 5); - EntityDamageUtil.applyTemperatureDamage(living, minTemp, 1.0F, 5); - } - } - } - - @Override - public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { - return supportsTicking ? new TileEntityFluidPipeTickable() : new TileEntityFluidPipe(); - } - - @Override - @NotNull - @SideOnly(Side.CLIENT) - @SuppressWarnings("deprecation") - public EnumBlockRenderType getRenderType(@NotNull IBlockState state) { - return FluidPipeRenderer.INSTANCE.getBlockRenderType(); - } - - @Override - @SideOnly(Side.CLIENT) - protected Pair getParticleTexture(World world, BlockPos blockPos) { - return FluidPipeRenderer.INSTANCE.getParticleTexture((IPipeTile) world.getTileEntity(blockPos)); - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/FluidPipeType.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/FluidPipeType.java deleted file mode 100644 index a0dda3ff22d..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/FluidPipeType.java +++ /dev/null @@ -1,74 +0,0 @@ -package gregtech.common.pipelikeold.fluidpipe; - -import gregtech.api.graphnet.pipenetold.block.material.IMaterialPipeType; -import gregtech.api.unification.ore.OrePrefix; - -import org.jetbrains.annotations.NotNull; - -public enum FluidPipeType implements IMaterialPipeType { - - TINY("tiny", 0.25f, 1, OrePrefix.pipeTinyFluid, true), - SMALL("small", 0.375f, 2, OrePrefix.pipeSmallFluid, true), - NORMAL("normal", 0.5f, 6, OrePrefix.pipeNormalFluid, true), - LARGE("large", 0.75f, 12, OrePrefix.pipeLargeFluid, true), - HUGE("huge", 0.875f, 24, OrePrefix.pipeHugeFluid, true), - - QUADRUPLE("quadruple", 0.95f, 2, OrePrefix.pipeQuadrupleFluid, true, 4), - NONUPLE("nonuple", 0.95f, 2, OrePrefix.pipeNonupleFluid, true, 9); - - public static final FluidPipeType[] VALUES = values(); - - public final String name; - public final float thickness; - public final int capacityMultiplier; - public final OrePrefix orePrefix; - public final boolean opaque; - public final int channels; - - FluidPipeType(String name, float thickness, int capacityMultiplier, OrePrefix orePrefix, boolean opaque) { - this(name, thickness, capacityMultiplier, orePrefix, opaque, 1); - } - - FluidPipeType(String name, float thickness, int capacityMultiplier, OrePrefix orePrefix, boolean opaque, - int channels) { - this.name = name; - this.thickness = thickness; - this.capacityMultiplier = capacityMultiplier; - this.orePrefix = orePrefix; - this.opaque = opaque; - this.channels = channels; - } - - @NotNull - @Override - public String getName() { - return name; - } - - @Override - public float getThickness() { - return thickness; - } - - @Override - public OrePrefix getOrePrefix() { - return orePrefix; - } - - @Override - public FluidPipeProperties modifyProperties(FluidPipeProperties baseProperties) { - return new FluidPipeProperties( - baseProperties.getMaxFluidTemperature(), - baseProperties.getThroughput() * capacityMultiplier, - baseProperties.isGasProof(), - baseProperties.isAcidProof(), - baseProperties.isCryoProof(), - baseProperties.isPlasmaProof(), - channels); - } - - @Override - public boolean isPaintable() { - return true; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/ItemBlockFluidPipe.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/ItemBlockFluidPipe.java deleted file mode 100644 index 115476c21f1..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/ItemBlockFluidPipe.java +++ /dev/null @@ -1,53 +0,0 @@ -package gregtech.common.pipelikeold.fluidpipe; - -import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; -import gregtech.api.graphnet.pipenetold.block.material.ItemBlockMaterialPipe; -import gregtech.client.utils.TooltipHelper; -import gregtech.common.ConfigHolder; - -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.item.ItemStack; -import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class ItemBlockFluidPipe extends ItemBlockMaterialPipe { - - public ItemBlockFluidPipe(BlockFluidPipe block) { - super(block); - } - - @Override - @SideOnly(Side.CLIENT) - public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, - @NotNull ITooltipFlag flagIn) { - super.addInformation(stack, worldIn, tooltip, flagIn); - FluidPipeProperties pipeProperties = blockPipe.createItemProperties(stack); - tooltip.add(I18n.format("gregtech.universal.tooltip.fluid_transfer_rate", pipeProperties.getThroughput())); - tooltip.add(I18n.format("gregtech.fluid_pipe.capacity", pipeProperties.getThroughput() * 20)); - tooltip.add(I18n.format("gregtech.fluid_pipe.max_temperature", pipeProperties.getMaxFluidTemperature())); - if (pipeProperties.getTanks() > 1) - tooltip.add(I18n.format("gregtech.fluid_pipe.channels", pipeProperties.getTanks())); - - pipeProperties.appendTooltips(tooltip, false, false); - - if (TooltipHelper.isShiftDown()) { - tooltip.add(I18n.format("gregtech.tool_action.wrench.connect_and_block")); - tooltip.add(I18n.format("gregtech.tool_action.screwdriver.access_covers")); - tooltip.add(I18n.format("gregtech.tool_action.crowbar")); - } - - BlockMaterialPipe blockMaterialPipe = (BlockMaterialPipe) blockPipe; - - if (ConfigHolder.misc.debug) { - tooltip.add("MetaItem Id: " + blockMaterialPipe.getPrefix().name + - blockMaterialPipe.getItemMaterial(stack).toCamelCaseString()); - } - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidEdgePredicate.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidEdgePredicate.java deleted file mode 100644 index d5fbc9e3e02..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidEdgePredicate.java +++ /dev/null @@ -1,38 +0,0 @@ -package gregtech.common.pipelikeold.fluidpipe.net; - -import gregtech.api.graphnet.pipenetold.predicate.FilteredEdgePredicate; -import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.common.covers.filter.BaseFilterContainer; -import gregtech.common.covers.filter.FluidFilterContainer; - -import net.minecraftforge.fluids.FluidStack; - -import org.jetbrains.annotations.NotNull; - -public class FluidEdgePredicate extends FilteredEdgePredicate { - - private final static String KEY = "Fluid"; - - static { - REGISTRY.put(KEY, FluidEdgePredicate::new); - } - - @Override - public boolean test(IPredicateTestObject o) { - if (shutteredSource || shutteredTarget) return false; - if (!(o instanceof FluidTestObject tester)) return false; - FluidStack stack = tester.recombine(); - return sourceFilter.test(stack) && targetFilter.test(stack); - } - - @Override - protected String predicateName() { - return KEY; - } - - @Override - protected @NotNull BaseFilterContainer getDefaultFilterContainer() { - return new FluidFilterContainer(DECOY); - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java deleted file mode 100644 index c4608916cd7..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/FluidNetHandler.java +++ /dev/null @@ -1,287 +0,0 @@ -package gregtech.common.pipelikeold.fluidpipe.net; - -import gregtech.api.cover.Cover; -import gregtech.api.graphnet.pipenetold.IPipeNetHandler; -import gregtech.api.graphnet.pipenetold.PipeNetNode; -import gregtech.api.graphnet.pipenetold.PipeNetPath; -import gregtech.api.graphnet.pipenetold.NodeLossResult; -import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.common.covers.CoverFluidRegulator; -import gregtech.common.covers.CoverPump; -import gregtech.common.pipelikeold.fluidpipe.FluidPipeType; -import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; - -import net.minecraft.util.EnumFacing; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidTankProperties; -import net.minecraftforge.fml.common.FMLCommonHandler; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -public class FluidNetHandler implements IFluidHandler, IPipeNetHandler { - - protected static final PipeNetNode FAKE_SOURCE = new PipeNetNode<>( - new FluidPipeProperties(Integer.MAX_VALUE, Integer.MAX_VALUE, true, true, true, true, Integer.MAX_VALUE)); - - private static final IFluidTankProperties[] EMPTY = new IFluidTankProperties[0]; - - private final WorldFluidPipeNet net; - private TileEntityFluidPipe pipe; - private final EnumFacing facing; - - private final IFluidHandler testHandler = new FluidTank(Integer.MAX_VALUE); - - private SimulatorKey simulatorKey; - private FluidStack lastFillResource; - private final Map, NodeLossResult> lossResultCache = new Object2ObjectOpenHashMap<>(); - - private final NetFlowEdge inputEdge; - - public FluidNetHandler(WorldFluidPipeNet net, TileEntityFluidPipe pipe, EnumFacing facing) { - this.net = net; - this.pipe = pipe; - this.facing = facing; - this.inputEdge = new NetFlowEdge(1) { - - @Override - public PipeNetNode getSource() { - return FAKE_SOURCE; - } - - @Override - public PipeNetNode getTarget() { - return FluidNetHandler.this.pipe.getNode(); - } - }; - } - - public void updatePipe(TileEntityFluidPipe pipe) { - this.pipe = pipe; - } - - @Override - public WorldFluidPipeNet getNet() { - return net; - } - - @Override - public EnumFacing getFacing() { - return facing; - } - - @Override - public IFluidTankProperties[] getTankProperties() { - // TODO instead collect a list of all connected tanks? - return EMPTY; - } - - @Override - public int fill(FluidStack resource, boolean doFill) { - if (net == null || pipe == null || pipe.isInvalid() || pipe.isFaceBlocked(facing)) return 0; - - if (!resource.isFluidStackIdentical(this.lastFillResource)) { - // cache needs to persist through the entire 'try with doFill false then try with doFill true' process, - // but should not persist into a new fill attempt. - this.lossResultCache.clear(); - this.lastFillResource = resource.copy(); - } - - FluidTestObject testObject = new FluidTestObject(resource); - long queryTick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - FluidStack helper = resource.copy(); - if (!doFill) this.simulatorKey = SimulatorKey.getNewSimulatorInstance(); - else this.simulatorKey = null; - this.getNet().getGraph().prepareForAlgorithmRun(testObject, simulatorKey); - mainloop: - for (Iterator> iter = this.getNet() - .getPaths(pipe); iter.hasNext();) { - PipeNetPath path = iter.next(); - for (Iterator it = path.getFacingIterator(); it.hasNext();) { - EnumFacing facing = it.next(); - PipeNetPath.FacedPipeNetPath routePath = path - .withFacing(facing); - helper.amount -= this.fill(routePath, testObject, queryTick, helper, doFill); - if (helper.amount <= 0) break mainloop; - } - } - if (!doFill) this.simulatorKey = null; - if (doFill && !this.lossResultCache.isEmpty()) { - this.lossResultCache.forEach((k, v) -> v.getPostAction().accept(k)); - this.lossResultCache.clear(); - } - return resource.amount - helper.amount; - } - - public int fill(PipeNetPath.FacedPipeNetPath routePath, - FluidTestObject testObject, long tick, FluidStack resource, boolean doFill) { - if (routePath.getTargetNode().getNodePos().equals(this.pipe.getPos()) && routePath.facing == this.facing) { - return 0; - } - int allowed = resource.amount; - Cover pipeCover = routePath.getTargetNode().getHeldMTE().getCoverableImplementation() - .getCoverAtSide(routePath.facing); - Cover tileCover = getCoverOnNeighbour(routePath.getTargetNode().getNodePos(), - routePath.oppositeFacing()); - - if (pipeCover != null) { - FluidStack helper; - testHandler.fill(resource, true); - IFluidHandler fluidHandler = pipeCover.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - testHandler); - if (fluidHandler == null || (fluidHandler != testHandler && - ((helper = fluidHandler.drain(resource, false)) == null || - (allowed = helper.amount) <= 0))) { - testHandler.drain(Integer.MAX_VALUE, true); - return 0; - } - testHandler.drain(Integer.MAX_VALUE, true); - } - IFluidHandler neighbourHandler = routePath.getTargetTE() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, routePath.oppositeFacing()); - if (neighbourHandler == null) return 0; - - if (pipeCover instanceof CoverFluidRegulator && - ((CoverFluidRegulator) pipeCover).getPumpMode() == CoverPump.PumpMode.EXPORT) { - return fillOverRegulator(routePath, neighbourHandler, testObject, tick, (CoverFluidRegulator) pipeCover, - resource, allowed, doFill); - } else if (tileCover instanceof CoverFluidRegulator && - ((CoverFluidRegulator) tileCover).getPumpMode() == CoverPump.PumpMode.IMPORT) { - return fillOverRegulator(routePath, neighbourHandler, testObject, tick, - (CoverFluidRegulator) tileCover, - resource, allowed, doFill); - } else { - return fill(routePath, neighbourHandler, testObject, tick, resource, allowed, doFill); - } - } - - public int fillOverRegulator(PipeNetPath.FacedPipeNetPath routePath, - IFluidHandler handler, FluidTestObject testObject, long tick, - CoverFluidRegulator regulator, FluidStack resource, int allowed, boolean doFill) { - var matched = regulator.getFluidFilterContainer().match(resource); - boolean isStackSpecific = false; - int rate, count; - - if (matched.isMatched()) { - int index = matched.getFilterIndex(); - rate = regulator.getFluidFilterContainer().getTransferLimit(index); - isStackSpecific = true; - } else { - rate = regulator.getFluidFilterContainer().getTransferSize(); - } - - switch (regulator.getTransferMode()) { - case TRANSFER_ANY -> { - return fill(routePath, handler, testObject, tick, resource, allowed, doFill); - } - case KEEP_EXACT -> { - count = rate - countStack(handler, resource, regulator, isStackSpecific); - if (count <= 0) return 0; - count = Math.min(allowed, Math.min(resource.amount, count)); - return fill(routePath, handler, testObject, tick, resource, count, doFill); - } - case TRANSFER_EXACT -> { - // TODO can regulators have the equivalent of robot arm buffering? - count = Math.min(allowed, Math.min(rate, resource.amount)); - if (count < rate) { - return 0; - } - if (fill(routePath, handler, testObject, tick, resource, count, false) != count) { - return 0; - } - return fill(routePath, handler, testObject, tick, resource, count, true); - } - } - return 0; - } - - private int fill(PipeNetPath.FacedPipeNetPath routePath, - IFluidHandler handler, - FluidTestObject testObject, long tick, FluidStack resource, int allowed, boolean doFill) { - FluidStack helper = new FluidStack(resource, allowed); - allowed = handler.fill(helper, false); - if (allowed == 0) return 0; - - // iterate through path - List> nodeList = routePath.getNodeList(); - List edgeList = routePath.getEdgeList(); - FlowConsumerList flowLimitConsumers = new FlowConsumerList<>(); - - int inputAmount = resource.amount; - int outputAmount = resource.amount; - - for (int i = 0; i < nodeList.size(); i++) { - NetFlowEdge edge = i == 0 ? inputEdge : edgeList.get(i - 1); - if (!edge.getPredicate().test(testObject)) return 0; - long flow = Math.min(edge.getFlowLimit(testObject, getNet().getGraph(), tick, simulatorKey), outputAmount); - double ratio = (double) flow / outputAmount; - inputAmount *= ratio; - flowLimitConsumers.modifyRatios(ratio); - flowLimitConsumers.add(edge, testObject, getNet().getGraph(), flow, tick, simulatorKey); - // TODO undo loss when backflowing - NodeLossResult targetResult = getOrGenerateLossResult(nodeList.get(i), resource); - outputAmount = (int) (flow * targetResult.getLossFunction()); - if (outputAmount == 0) break; - } - // outputAmount is currently the maximum flow to the endpoint, and inputAmount is the requisite flow into the - // net - allowed = Math.min(allowed, outputAmount); - - helper.amount = allowed; - double ratio; - if (outputAmount == 0) { - ratio = 1; - } else { - allowed = handler.fill(helper, doFill); - ratio = (double) allowed / outputAmount; - } - flowLimitConsumers.doConsumption(ratio); - - return (int) (inputAmount * ratio); - } - - public static int countStack(IFluidHandler handler, FluidStack stack, CoverFluidRegulator regulator, - boolean isStackSpecific) { - if (regulator == null) return 0; - int count = 0; - for (int i = 0; i < handler.getTankProperties().length; i++) { - FluidStack slot = handler.getTankProperties()[i].getContents(); - if (slot == null) continue; - if (isStackSpecific ? slot.isFluidEqual(stack) : - regulator.getFluidFilterContainer().test(slot)) { - count += slot.amount; - } - } - return count; - } - - @Override - public FluidStack drain(FluidStack resource, boolean doDrain) { - // TODO support pulling from net? - return null; - } - - @Override - public FluidStack drain(int maxDrain, boolean doDrain) { - // TODO support pulling from net? - return null; - } - - protected NodeLossResult getOrGenerateLossResult(PipeNetNode node, - FluidStack resource) { - var cachedResult = this.lossResultCache.get(node); - if (cachedResult == null) { - cachedResult = node.getData().determineFluidPassthroughResult(resource, net.getWorld(), node.getNodePos()); - this.lossResultCache.put(node, cachedResult); - } - return cachedResult; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/WorldFluidPipeNet.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/WorldFluidPipeNet.java deleted file mode 100644 index 2398a89787c..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/net/WorldFluidPipeNet.java +++ /dev/null @@ -1,91 +0,0 @@ -package gregtech.common.pipelikeold.fluidpipe.net; - -import gregtech.api.cover.Cover; -import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.pipenetold.WorldPipeNetComplex; -import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; -import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.common.covers.CoverFluidFilter; -import gregtech.common.covers.CoverPump; -import gregtech.common.covers.FluidFilterMode; -import gregtech.common.covers.ManualImportExportMode; -import gregtech.common.pipelikeold.fluidpipe.FluidPipeType; -import gregtech.common.pipelikeold.fluidpipe.tile.TileEntityFluidPipe; - -import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; - -import org.jetbrains.annotations.NotNull; - -public class WorldFluidPipeNet extends WorldPipeNetComplex { - - // TODO handle fluids in old fluid pipes - - private static final String DATA_ID_BASE = "gregtech.fluid_pipe_net"; - - public static WorldFluidPipeNet getWorldPipeNet(World world) { - String DATA_ID = getDataID(DATA_ID_BASE, world); - WorldFluidPipeNet netWorldData = (WorldFluidPipeNet) world.loadData(WorldFluidPipeNet.class, DATA_ID); - if (netWorldData == null) { - netWorldData = new WorldFluidPipeNet(DATA_ID); - world.setData(DATA_ID, netWorldData); - } - netWorldData.setWorldAndInit(world); - return netWorldData; - } - - public WorldFluidPipeNet(String name) { - super(name, true, () -> new NetFlowEdge(20), DynamicWeightsShortestPathsAlgorithm::new); - } - - @Override - protected boolean needsDynamicWeights() { - return true; - } - - @Override - protected Capability[] getConnectionCapabilities() { - return new Capability[] { CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY }; - } - - @Override - protected Class> getBasePipeClass() { - return TileEntityFluidPipe.class; - } - - @Override - protected IEdgePredicateOld getPredicate(Cover thisCover, Cover neighbourCover) { - FluidEdgePredicate predicate = new FluidEdgePredicate(); - if (thisCover instanceof CoverFluidFilter filter && - filter.getFilterMode() != FluidFilterMode.FILTER_FILL) { - predicate.setSourceFilter(filter.getFilterContainer()); - } - if (neighbourCover instanceof CoverFluidFilter filter && - filter.getFilterMode() != FluidFilterMode.FILTER_DRAIN) { - predicate.setTargetFilter(filter.getFilterContainer()); - } - if (thisCover instanceof CoverPump pump) { - if (pump.getManualImportExportMode() == ManualImportExportMode.DISABLED) { - predicate.setShutteredSource(true); - } else if (pump.getManualImportExportMode() == ManualImportExportMode.FILTERED) { - predicate.setSourceFilter(pump.getFluidFilterContainer()); - } - } - if (neighbourCover instanceof CoverPump pump) { - if (pump.getManualImportExportMode() == ManualImportExportMode.DISABLED) { - predicate.setShutteredTarget(true); - } else if (pump.getManualImportExportMode() == ManualImportExportMode.FILTERED) { - predicate.setTargetFilter(pump.getFluidFilterContainer()); - } - } - // TODO should fluid regulators apply rate limits to edge predicates? - return shutterify(predicate, thisCover, neighbourCover); - } - - @Override - public @NotNull NetLogicData getDefaultNodeData() { - return new FluidPipeProperties(); - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipe.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipe.java deleted file mode 100644 index 346c1a84da0..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipe.java +++ /dev/null @@ -1,205 +0,0 @@ -package gregtech.common.pipelikeold.fluidpipe.tile; - -import gregtech.api.GTValues; -import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; -import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.util.TaskScheduler; -import gregtech.common.pipelikeold.fluidpipe.FluidPipeType; -import gregtech.common.pipelikeold.fluidpipe.net.FluidNetHandler; -import gregtech.common.pipelikeold.fluidpipe.net.WorldFluidPipeNet; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.init.Blocks; -import net.minecraft.init.SoundEvents; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.WorldServer; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fml.common.FMLCommonHandler; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.EnumMap; -import java.util.List; -import java.util.function.Consumer; - -public class TileEntityFluidPipe extends TileEntityMaterialPipeBase { - - private FluidTank[] fluidTanks = null; - - private final EnumMap handlers = new EnumMap<>(EnumFacing.class); - private FluidNetHandler defaultHandler; - // the FluidNetHandler can only be created on the server so we have a empty placeholder for the client - private final IFluidHandler clientCapability = new FluidTank(0); - private final int offset = GTValues.RNG.nextInt(20); - private long nextSoundTime = 0; - private long nextDamageTime = 0; - - public long getOffsetTimer() { - return FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter() + offset; - } - - @Nullable - @Override - public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { - if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { - if (world.isRemote) - return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(clientCapability); - - if (handlers.size() == 0) - initHandlers(); - return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(handlers.getOrDefault(facing, defaultHandler)); - } - return super.getCapabilityInternal(capability, facing); - } - - private void initHandlers() { - WorldFluidPipeNet net = WorldFluidPipeNet.getWorldPipeNet(getPipeWorld()); - for (EnumFacing facing : EnumFacing.values()) { - handlers.put(facing, new FluidNetHandler(net, this, facing)); - } - defaultHandler = new FluidNetHandler(net, this, null); - } - - @Override - public void transferDataFrom(IPipeTile tileEntity) { - super.transferDataFrom(tileEntity); - TileEntityFluidPipe fluidPipe = (TileEntityFluidPipe) tileEntity; - // take handlers from old pipe - if (!fluidPipe.handlers.isEmpty()) { - this.handlers.clear(); - for (FluidNetHandler handler : fluidPipe.handlers.values()) { - handler.updatePipe(this); - this.handlers.put(handler.getFacing(), handler); - } - } - if (fluidPipe.defaultHandler != null) { - fluidPipe.defaultHandler.updatePipe(this); - this.defaultHandler = fluidPipe.defaultHandler; - } - } - - public void playLossSound() { - long timer = getOffsetTimer(); - if (timer >= this.nextSoundTime) { - getPipeWorld().playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); - this.nextSoundTime = timer + 20; - } - } - - public void dealAreaDamage(int size, Consumer damageFunction) { - long timer = getOffsetTimer(); - if (timer >= this.nextDamageTime) { - List entities = getPipeWorld().getEntitiesWithinAABB(EntityLivingBase.class, - new AxisAlignedBB(getPipePos()).grow(size)); - entities.forEach(damageFunction); - this.nextDamageTime = timer + 20; - } - } - - @Override - public Class getPipeTypeClass() { - return FluidPipeType.class; - } - - @Override - public boolean supportsTicking() { - return false; - } - - public int getCapacityPerTank() { - return getNodeData().getThroughput() * 20; - } - - public static void setNeighboursToFire(World world, BlockPos selfPos) { - for (EnumFacing side : EnumFacing.VALUES) { - if (!GTValues.RNG.nextBoolean()) continue; - BlockPos blockPos = selfPos.offset(side); - IBlockState blockState = world.getBlockState(blockPos); - if (blockState.getBlock().isAir(blockState, world, blockPos) || - blockState.getBlock().isFlammable(world, blockPos, side.getOpposite())) { - world.setBlockState(blockPos, Blocks.FIRE.getDefaultState()); - } - } - } - - public static void spawnParticles(World worldIn, BlockPos pos, EnumFacing direction, EnumParticleTypes particleType, - int particleCount) { - if (worldIn instanceof WorldServer) { - ((WorldServer) worldIn).spawnParticle(particleType, - pos.getX() + 0.5, - pos.getY() + 0.5, - pos.getZ() + 0.5, - particleCount, - direction.getXOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, - direction.getYOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, - direction.getZOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, - 0.1); - } - } - - @NotNull - @Override - public NBTTagCompound writeToNBT(@NotNull NBTTagCompound nbt) { - super.writeToNBT(nbt); - if (fluidTanks == null) return nbt; - NBTTagList list = new NBTTagList(); - for (FluidTank fluidTank : fluidTanks) { - FluidStack stack1 = fluidTank.getFluid(); - NBTTagCompound fluidTag = new NBTTagCompound(); - if (stack1 == null || stack1.amount <= 0) - fluidTag.setBoolean("isNull", true); - else - stack1.writeToNBT(fluidTag); - list.appendTag(fluidTag); - } - nbt.setTag("Fluids", list); - return nbt; - } - - @Override - public void readFromNBT(@NotNull NBTTagCompound nbt) { - super.readFromNBT(nbt); - if (!nbt.hasKey("Fluids")) return; - fluidTanks = new FluidTank[getNodeData().getTanks()]; - for (int i = 0; i < getNodeData().getTanks(); i++) { - fluidTanks[i] = new FluidTank(getCapacityPerTank()); - } - NBTTagList list = (NBTTagList) nbt.getTag("Fluids"); - for (int i = 0; i < list.tagCount(); i++) { - NBTTagCompound tag = list.getCompoundTagAt(i); - if (!tag.getBoolean("isNull")) { - FluidStack stack = FluidStack.loadFluidStackFromNBT(tag); - if (stack == null) continue; - fluidTanks[i].setFluid(stack); - } - } - TaskScheduler.scheduleTask(world, this::pushFluids); - } - - private boolean pushFluids() { - boolean remaining = false; - for (FluidTank tank : fluidTanks) { - if (tank == null || tank.getFluidAmount() == 0) continue; - assert tank.getFluid() != null; - int fill = defaultHandler.fill(tank.getFluid(), true); - if (fill <= tank.getFluidAmount()) remaining = true; - tank.getFluid().amount -= fill; - } - if (!remaining) fluidTanks = null; - return remaining; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipeTickable.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipeTickable.java deleted file mode 100644 index dbf86ed6867..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/tile/TileEntityFluidPipeTickable.java +++ /dev/null @@ -1,16 +0,0 @@ -package gregtech.common.pipelikeold.fluidpipe.tile; - -import net.minecraft.util.ITickable; - -public class TileEntityFluidPipeTickable extends TileEntityFluidPipe implements ITickable { - - @Override - public void update() { - getCoverableImplementation().update(); - } - - @Override - public boolean supportsTicking() { - return true; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java b/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java deleted file mode 100644 index 56547560762..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/BlockItemPipe.java +++ /dev/null @@ -1,136 +0,0 @@ -package gregtech.common.pipelikeold.itempipe; - -import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.registry.MaterialRegistry; -import gregtech.client.renderer.pipeold.ItemPipeRenderer; -import gregtech.client.renderer.pipeold.PipeRenderer; -import gregtech.common.creativetab.GTCreativeTabs; -import gregtech.common.pipelikeold.itempipe.net.WorldItemPipeNet; -import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipe; -import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipeTickable; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumBlockRenderType; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; -import net.minecraftforge.items.CapabilityItemHandler; - -import com.google.common.base.Preconditions; -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public class BlockItemPipe extends BlockMaterialPipe { - - private final Map enabledMaterials = new HashMap<>(); - - public BlockItemPipe(ItemPipeType itemPipeType, MaterialRegistry registry) { - super(itemPipeType, registry); - setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); - setHarvestLevel(ToolClasses.WRENCH, 1); - } - - public void addPipeMaterial(Material material, ItemPipeProperties properties) { - Preconditions.checkNotNull(material, "material"); - Preconditions.checkNotNull(properties, "material %s itemPipeProperties was null", material); - Preconditions.checkArgument(material.getRegistry().getNameForObject(material) != null, - "material %s is not registered", material); - this.enabledMaterials.put(material, properties); - } - - @Override - public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { - return supportsTicking ? new TileEntityItemPipeTickable() : new TileEntityItemPipe(); - } - - @Override - public Class getPipeTypeClass() { - return ItemPipeType.class; - } - - @Override - protected ItemPipeProperties getFallbackType() { - return enabledMaterials.values().iterator().next(); - } - - @Override - public WorldItemPipeNet getWorldPipeNet(World world) { - return WorldItemPipeNet.getWorldPipeNet(world); - } - - @Override - protected Pair getParticleTexture(World world, BlockPos blockPos) { - return ItemPipeRenderer.INSTANCE.getParticleTexture((TileEntityItemPipe) world.getTileEntity(blockPos)); - } - - @Override - protected ItemPipeProperties createProperties(ItemPipeType itemPipeType, Material material) { - return itemPipeType.modifyProperties(enabledMaterials.getOrDefault(material, getFallbackType())); - } - - @SideOnly(Side.CLIENT) - @NotNull - @Override - public PipeRenderer getPipeRenderer() { - return ItemPipeRenderer.INSTANCE; - } - - public Collection getEnabledMaterials() { - return Collections.unmodifiableSet(enabledMaterials.keySet()); - } - - @Override - public void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList items) { - for (Material material : enabledMaterials.keySet()) { - items.add(getItem(material)); - } - } - - @Override - public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile) { - return selfTile instanceof TileEntityItemPipe && sideTile instanceof TileEntityItemPipe; - } - - @Override - public boolean canPipeConnectToBlock(IPipeTile selfTile, EnumFacing side, - TileEntity tile) { - return tile != null && - tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side.getOpposite()) != null; - } - - @Override - public boolean isHoldingPipe(EntityPlayer player) { - if (player == null) { - return false; - } - ItemStack stack = player.getHeldItemMainhand(); - return stack != ItemStack.EMPTY && stack.getItem() instanceof ItemBlockItemPipe; - } - - @Override - @NotNull - @SideOnly(Side.CLIENT) - @SuppressWarnings("deprecation") - public EnumBlockRenderType getRenderType(@NotNull IBlockState state) { - return ItemPipeRenderer.INSTANCE.getBlockRenderType(); - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/ItemBlockItemPipe.java b/src/main/java/gregtech/common/pipelikeold/itempipe/ItemBlockItemPipe.java deleted file mode 100644 index 6c530bdb54f..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/ItemBlockItemPipe.java +++ /dev/null @@ -1,55 +0,0 @@ -package gregtech.common.pipelikeold.itempipe; - -import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; -import gregtech.api.graphnet.pipenetold.block.material.ItemBlockMaterialPipe; -import gregtech.client.utils.TooltipHelper; -import gregtech.common.ConfigHolder; - -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.item.ItemStack; -import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class ItemBlockItemPipe extends ItemBlockMaterialPipe { - - public ItemBlockItemPipe(BlockItemPipe block) { - super(block); - } - - @Override - @SideOnly(Side.CLIENT) - public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, - @NotNull ITooltipFlag flagIn) { - super.addInformation(stack, worldIn, tooltip, flagIn); - ItemPipeProperties pipeProperties = blockPipe.createItemProperties(stack); - if (pipeProperties.getTransferRate() % 1 != 0) { - tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate", - (int) ((pipeProperties.getTransferRate() * 64) + 0.5))); - } else { - tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate_stacks", - (int) pipeProperties.getTransferRate())); - } - tooltip.add(I18n.format("gregtech.item_pipe.priority", pipeProperties.getPriority())); - - if (TooltipHelper.isShiftDown()) { - tooltip.add(I18n.format("gregtech.tool_action.wrench.connect")); - tooltip.add(I18n.format("gregtech.tool_action.screwdriver.access_covers")); - tooltip.add(I18n.format("gregtech.tool_action.crowbar")); - } else { - tooltip.add(I18n.format("gregtech.tool_action.show_tooltips")); - } - - if (ConfigHolder.misc.debug) { - BlockMaterialPipe blockMaterialPipe = (BlockMaterialPipe) blockPipe; - tooltip.add("MetaItem Id: " + blockMaterialPipe.getPrefix().name + - blockMaterialPipe.getItemMaterial(stack).toCamelCaseString()); - } - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/ItemPipeType.java b/src/main/java/gregtech/common/pipelikeold/itempipe/ItemPipeType.java deleted file mode 100644 index a62043bd54f..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/ItemPipeType.java +++ /dev/null @@ -1,78 +0,0 @@ -package gregtech.common.pipelikeold.itempipe; - -import gregtech.api.graphnet.pipenetold.block.material.IMaterialPipeType; -import gregtech.api.unification.ore.OrePrefix; - -import org.jetbrains.annotations.NotNull; - -public enum ItemPipeType implements IMaterialPipeType { - - // TINY_OPAQUE("tiny", 0.25f, OrePrefix.pipeTinyItem, 0.25f, 2f), - SMALL("small", 0.375f, OrePrefix.pipeSmallItem, 0.5f, 1.5f), - NORMAL("normal", 0.5f, OrePrefix.pipeNormalItem, 1f, 1f), - LARGE("large", 0.75f, OrePrefix.pipeLargeItem, 2f, 0.75f), - HUGE("huge", 0.875f, OrePrefix.pipeHugeItem, 4f, 0.5f), - - RESTRICTIVE_SMALL("small_restrictive", 0.375f, OrePrefix.pipeSmallRestrictive, 0.5f, 150f), - RESTRICTIVE_NORMAL("normal_restrictive", 0.5f, OrePrefix.pipeNormalRestrictive, 1f, 100f), - RESTRICTIVE_LARGE("large_restrictive", 0.75f, OrePrefix.pipeLargeRestrictive, 2f, 75f), - RESTRICTIVE_HUGE("huge_restrictive", 0.875f, OrePrefix.pipeHugeRestrictive, 4f, 50f); - - public static final ItemPipeType[] VALUES = values(); - - public final String name; - private final float thickness; - private final float rateMultiplier; - private final float resistanceMultiplier; - private final OrePrefix orePrefix; - - ItemPipeType(String name, float thickness, OrePrefix orePrefix, float rateMultiplier, float resistanceMultiplier) { - this.name = name; - this.thickness = thickness; - this.orePrefix = orePrefix; - this.rateMultiplier = rateMultiplier; - this.resistanceMultiplier = resistanceMultiplier; - } - - public boolean isRestrictive() { - return ordinal() > 3; - } - - public String getSizeForTexture() { - if (!isRestrictive()) - return name; - else - return name.substring(0, name.length() - 12); - } - - @Override - public float getThickness() { - return thickness; - } - - @Override - public ItemPipeProperties modifyProperties(ItemPipeProperties baseProperties) { - return new ItemPipeProperties((int) ((baseProperties.getPriority() * resistanceMultiplier) + 0.5), - baseProperties.getTransferRate() * rateMultiplier); - } - - public float getRateMultiplier() { - return rateMultiplier; - } - - @Override - public boolean isPaintable() { - return true; - } - - @NotNull - @Override - public String getName() { - return name; - } - - @Override - public OrePrefix getOrePrefix() { - return orePrefix; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemEdgePredicate.java b/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemEdgePredicate.java deleted file mode 100644 index fa5cec2d130..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemEdgePredicate.java +++ /dev/null @@ -1,38 +0,0 @@ -package gregtech.common.pipelikeold.itempipe.net; - -import gregtech.api.graphnet.pipenetold.predicate.FilteredEdgePredicate; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.common.covers.filter.BaseFilterContainer; -import gregtech.common.covers.filter.ItemFilterContainer; - -import net.minecraft.item.ItemStack; - -import org.jetbrains.annotations.NotNull; - -public class ItemEdgePredicate extends FilteredEdgePredicate { - - private final static String KEY = "Item"; - - static { - REGISTRY.put(KEY, ItemEdgePredicate::new); - } - - @Override - public boolean test(IPredicateTestObject o) { - if (shutteredSource || shutteredTarget) return false; - if (!(o instanceof ItemTestObject tester)) return false; - ItemStack stack = tester.recombine(); - return sourceFilter.test(stack) && targetFilter.test(stack); - } - - @Override - protected String predicateName() { - return KEY; - } - - @Override - protected @NotNull BaseFilterContainer getDefaultFilterContainer() { - return new ItemFilterContainer(DECOY); - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemNetHandler.java b/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemNetHandler.java deleted file mode 100644 index 928aacebff7..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/net/ItemNetHandler.java +++ /dev/null @@ -1,518 +0,0 @@ -package gregtech.common.pipelikeold.itempipe.net; - -import gregtech.api.cover.Cover; -import gregtech.api.graphnet.pipenetold.IPipeNetHandler; -import gregtech.api.graphnet.pipenetold.PipeNetPath; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.util.FacingPos; -import gregtech.api.util.GTTransferUtils; -import gregtech.api.util.ItemStackHashStrategy; -import gregtech.common.covers.CoverConveyor; -import gregtech.common.covers.CoverItemFilter; -import gregtech.common.covers.CoverRoboticArm; -import gregtech.common.covers.DistributionMode; -import gregtech.common.covers.ItemFilterMode; -import gregtech.common.pipelikeold.itempipe.ItemPipeType; -import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipe; - -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumFacing; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemStackHandler; - -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; - -// TODO exploit flow edges for itemnet -public class ItemNetHandler implements IItemHandler, IPipeNetHandler { - - private final WorldItemPipeNet net; - private TileEntityItemPipe pipe; - private final EnumFacing facing; - private final Object2IntMap simulatedTransfersGlobalRoundRobin = new Object2IntOpenHashMap<>(); - private int simulatedTransfers = 0; - private final ItemStackHandler testHandler = new ItemStackHandler(1); - - public ItemNetHandler(WorldItemPipeNet net, TileEntityItemPipe pipe, EnumFacing facing) { - this.net = net; - this.pipe = pipe; - this.facing = facing; - } - - public void updatePipe(TileEntityItemPipe pipe) { - this.pipe = pipe; - } - - @Override - public WorldItemPipeNet getNet() { - return net; - } - - @Override - public EnumFacing getFacing() { - return facing; - } - - private void copyTransferred() { - simulatedTransfers = pipe.getTransferredItems(); - simulatedTransfersGlobalRoundRobin.clear(); - simulatedTransfersGlobalRoundRobin.putAll(pipe.getTransferred()); - } - - @NotNull - @Override - public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { - if (stack.isEmpty()) return stack; - - if (net == null || pipe == null || pipe.isInvalid() || pipe.isFaceBlocked(facing)) { - return stack; - } - - copyTransferred(); - Cover pipeCover = this.pipe.getCoverableImplementation().getCoverAtSide(facing); - Cover tileCover = getCoverOnNeighbour(this.pipe.getPipePos(), facing); - - boolean pipeConveyor = pipeCover instanceof CoverConveyor, tileConveyor = tileCover instanceof CoverConveyor; - // abort if there are two conveyors - if (pipeConveyor && tileConveyor) return stack; - - if (tileCover != null && !checkImportCover(tileCover, false, stack)) - return stack; - - if (!pipeConveyor && !tileConveyor) - return insertFirst(stack, simulate); - - CoverConveyor conveyor = (CoverConveyor) (pipeConveyor ? pipeCover : tileCover); - if (conveyor.getConveyorMode() == - (pipeConveyor ? CoverConveyor.ConveyorMode.IMPORT : CoverConveyor.ConveyorMode.EXPORT)) { - boolean roundRobinGlobal = conveyor.getDistributionMode() == DistributionMode.ROUND_ROBIN_GLOBAL; - if (roundRobinGlobal || conveyor.getDistributionMode() == DistributionMode.ROUND_ROBIN_PRIO) - return insertRoundRobin(stack, simulate, roundRobinGlobal); - } - - return insertFirst(stack, simulate); - } - - public static boolean checkImportCover(Cover cover, boolean onPipe, ItemStack stack) { - if (cover == null) return true; - if (cover instanceof CoverItemFilter filter) { - return (filter.getFilterMode() != ItemFilterMode.FILTER_BOTH && - (filter.getFilterMode() != ItemFilterMode.FILTER_INSERT || !onPipe) && - (filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT || onPipe)) || filter.testItemStack(stack); - } - return true; - } - - public ItemStack insertFirst(ItemStack stack, boolean simulate) { - for (Iterator> it = net.getPaths(pipe); it.hasNext();) { - PipeNetPath inv = it.next(); - stack = insert(inv.firstFacing(), stack, simulate); - if (stack.isEmpty()) - return ItemStack.EMPTY; - } - return stack; - } - - public ItemStack insertRoundRobin(ItemStack stack, boolean simulate, boolean global) { - Iterator> routePaths = net.getPaths(pipe); - if (!routePaths.hasNext()) return stack; - List> routePathsCopy = new ObjectArrayList<>(); - routePaths.forEachRemaining(routePathsCopy::add); - - if (global) { - stack = insertToHandlersEnhanced(routePathsCopy, stack, simulate); - } else { - stack = insertToHandlers(routePathsCopy, stack, simulate); - if (!stack.isEmpty() && !routePathsCopy.isEmpty()) - stack = insertToHandlers(routePathsCopy, stack, simulate); - } - - return stack; - } - - /** - * Inserts items equally to all handlers - * if it couldn't insert all items, the handler will be removed - * - * @param copy to insert to - * @param stack to insert - * @param simulate simulate - * @return remainder - */ - private ItemStack insertToHandlers(List> copy, ItemStack stack, - boolean simulate) { - Iterator> routePathIterator = copy.listIterator(); - int inserted = 0; - int count = stack.getCount(); - int c = count / copy.size(); - int m = c == 0 ? count % copy.size() : 0; - mainloop: - while (routePathIterator.hasNext()) { - PipeNetPath routePath = routePathIterator.next(); - Iterator iterator = routePath.getFacingIterator(); - while (iterator.hasNext()) { - PipeNetPath.FacedPipeNetPath facedPipeNetPath = routePath - .withFacing(iterator.next()); - int amount = c; - if (m > 0) { - amount++; - m--; - } - amount = Math.min(amount, stack.getCount() - inserted); - if (amount == 0) break mainloop; - ItemStack toInsert = stack.copy(); - toInsert.setCount(amount); - int r = insert(facedPipeNetPath, toInsert, simulate).getCount(); - if (r < amount) { - inserted += (amount - r); - } - if (r == 1 && c == 0 && amount == 1) { - m++; - } - - if (r > 0) - routePathIterator.remove(); - } - } - - ItemStack remainder = stack.copy(); - remainder.setCount(count - inserted); - return remainder; - } - - private ItemStack insertToHandlersEnhanced(List> copy, - ItemStack stack, boolean simulate) { - List transferred = new ArrayList<>(); - IntList steps = new IntArrayList(); - int min = Integer.MAX_VALUE; - ItemStack simStack; - - // find inventories that are not full and get the amount that was inserted in total - for (PipeNetPath inv : copy) { - Iterator iterator = inv.getFacingIterator(); - while (iterator.hasNext()) { - PipeNetPath.FacedPipeNetPath faceInv = inv - .withFacing(iterator.next()); - simStack = stack.copy(); - int ins = stack.getCount() - insert(faceInv, simStack, true, true).getCount(); - if (ins <= 0) - continue; - int didTransfer = didTransferTo(faceInv, simulate); - EnhancedRoundRobinData data = new EnhancedRoundRobinData(faceInv, ins, didTransfer); - transferred.add(data); - - min = Math.min(min, didTransfer); - - if (!steps.contains(didTransfer)) { - steps.add(didTransfer); - } - } - } - - if (transferred.isEmpty() || steps.isEmpty()) - return stack; - - if (!simulate && min < Integer.MAX_VALUE) { - decrementBy(min); - } - - transferred.sort(Comparator.comparingInt(data -> data.transferred)); - steps.sort(Integer::compare); - - if (transferred.get(0).transferred != steps.get(0)) { - return stack; - } - - int amount = stack.getCount(); - int c = amount / transferred.size(); - int m = amount % transferred.size(); - List transferredCopy = new ArrayList<>(transferred); - int nextStep = steps.removeInt(0); - - // equally distribute items over all inventories - // it takes into account how much was inserted in total - // f.e. if inv1 has 2 inserted and inv2 has 6 inserted, it will first try to insert 4 into inv1 so that both - // have 6 and then it will distribute the rest equally - outer: - while (amount > 0 && !transferredCopy.isEmpty()) { - Iterator iterator = transferredCopy.iterator(); - int i = 0; - while (iterator.hasNext()) { - EnhancedRoundRobinData data = iterator.next(); - if (nextStep >= 0 && data.transferred >= nextStep) - break; - - int toInsert; - if (nextStep <= 0) { - if (amount <= m) { - // break outer; - toInsert = 1; - } else { - toInsert = Math.min(c, amount); - } - } else { - toInsert = Math.min(amount, nextStep - data.transferred); - } - if (data.toTransfer + toInsert >= data.maxInsertable) { - data.toTransfer = data.maxInsertable; - iterator.remove(); - } else { - data.toTransfer += toInsert; - } - - data.transferred += toInsert; - - if ((amount -= toInsert) == 0) { - break outer; - } - i++; - } - - for (EnhancedRoundRobinData data : transferredCopy) { - if (data.transferred < nextStep) - continue outer; - } - if (steps.isEmpty()) { - if (nextStep >= 0) { - c = amount / transferredCopy.size(); - m = amount % transferredCopy.size(); - nextStep = -1; - } - } else { - nextStep = steps.removeInt(0); - } - } - - int inserted = 0; - - // finally actually insert the item - for (EnhancedRoundRobinData data : transferred) { - ItemStack toInsert = stack.copy(); - toInsert.setCount(data.toTransfer); - int ins = data.toTransfer - insert(data.routePath, toInsert, simulate).getCount(); - inserted += ins; - transferTo(data.routePath, simulate, ins); - } - - ItemStack remainder = stack.copy(); - remainder.shrink(inserted); - return remainder; - } - - public ItemStack insert(PipeNetPath.FacedPipeNetPath routePath, ItemStack stack, - boolean simulate) { - return insert(routePath, stack, simulate, false); - } - - public ItemStack insert(PipeNetPath.FacedPipeNetPath routePath, ItemStack stack, - boolean simulate, boolean ignoreLimit) { - if (routePath.getTargetNode().getNodePos() == this.pipe.getPos() && routePath.facing == this.facing) { - return stack; - } - int allowed = ignoreLimit ? stack.getCount() : - checkTransferable(routePath.getSumData().getTransferRate(), stack.getCount(), simulate); - if (allowed == 0 || !routePath.checkPredicate(new ItemTestObject(stack))) { - return stack; - } - Cover pipeCover = routePath.getTargetNode().getHeldMTE().getCoverableImplementation() - .getCoverAtSide(routePath.facing); - Cover tileCover = getCoverOnNeighbour(routePath.getTargetNode().getNodePos(), routePath.oppositeFacing()); - - if (pipeCover != null) { - testHandler.setStackInSlot(0, stack.copy()); - IItemHandler itemHandler = pipeCover.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, - testHandler); - if (itemHandler == null || (itemHandler != testHandler && - (allowed = itemHandler.extractItem(0, allowed, true).getCount()) <= 0)) { - testHandler.setStackInSlot(0, ItemStack.EMPTY); - return stack; - } - testHandler.setStackInSlot(0, ItemStack.EMPTY); - } - IItemHandler neighbourHandler = routePath.getTargetTE() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, routePath.oppositeFacing()); - if (pipeCover instanceof CoverRoboticArm && - ((CoverRoboticArm) pipeCover).getConveyorMode() == CoverConveyor.ConveyorMode.EXPORT) { - return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) pipeCover, stack, simulate, allowed, - ignoreLimit); - } - if (tileCover instanceof CoverRoboticArm && - ((CoverRoboticArm) tileCover).getConveyorMode() == CoverConveyor.ConveyorMode.IMPORT) { - return insertOverRobotArm(neighbourHandler, (CoverRoboticArm) tileCover, stack, simulate, allowed, - ignoreLimit); - } - - return insert(neighbourHandler, stack, simulate, allowed, ignoreLimit); - } - - private ItemStack insert(IItemHandler handler, ItemStack stack, boolean simulate, int allowed, - boolean ignoreLimit) { - if (stack.getCount() == allowed) { - ItemStack re = GTTransferUtils.insertItem(handler, stack, simulate); - if (!ignoreLimit) - transfer(simulate, stack.getCount() - re.getCount()); - return re; - } - ItemStack toInsert = stack.copy(); - toInsert.setCount(Math.min(allowed, stack.getCount())); - int r = GTTransferUtils.insertItem(handler, toInsert, simulate).getCount(); - if (!ignoreLimit) - transfer(simulate, toInsert.getCount() - r); - ItemStack remainder = stack.copy(); - remainder.setCount(r + (stack.getCount() - toInsert.getCount())); - return remainder; - } - - public ItemStack insertOverRobotArm(IItemHandler handler, CoverRoboticArm arm, ItemStack stack, boolean simulate, - int allowed, boolean ignoreLimit) { - var matched = arm.getItemFilterContainer().match(stack); - boolean isStackSpecific = false; - int rate, count; - - if (matched.isMatched()) { - int index = matched.getFilterIndex(); - rate = arm.getItemFilterContainer().getTransferLimit(index); - isStackSpecific = true; - } else { - rate = arm.getItemFilterContainer().getTransferSize(); - } - - switch (arm.getTransferMode()) { - case TRANSFER_ANY -> { - return insert(handler, stack, simulate, allowed, ignoreLimit); - } - case KEEP_EXACT -> { - count = rate - countStack(handler, stack, arm, isStackSpecific); - if (count <= 0) return stack; - count = Math.min(allowed, Math.min(stack.getCount(), count)); - return insert(handler, stack, simulate, count, ignoreLimit); - } - case TRANSFER_EXACT -> { - int max = allowed + arm.getBuffer(); - count = Math.min(max, Math.min(rate, stack.getCount())); - if (count < rate) { - arm.buffer(allowed); - return stack; - } else { - arm.clearBuffer(); - } - if (insert(handler, stack, true, count, ignoreLimit).getCount() != stack.getCount() - count) { - return stack; - } - return insert(handler, stack, simulate, count, ignoreLimit); - } - } - return stack; - } - - public static int countStack(IItemHandler handler, ItemStack stack, CoverRoboticArm arm, boolean isStackSpecific) { - if (arm == null) return 0; - int count = 0; - for (int i = 0; i < handler.getSlots(); i++) { - ItemStack slot = handler.getStackInSlot(i); - if (slot.isEmpty()) continue; - if (isStackSpecific ? ItemStackHashStrategy.comparingAllButCount().equals(stack, slot) : - arm.getItemFilterContainer().test(slot)) { - count += slot.getCount(); - } - } - return count; - } - - private int checkTransferable(float rate, int amount, boolean simulate) { - int max = (int) ((rate * 64) + 0.5); - if (simulate) - return Math.max(0, Math.min(max - simulatedTransfers, amount)); - else - return Math.max(0, Math.min(max - pipe.getTransferredItems(), amount)); - } - - private void transfer(boolean simulate, int amount) { - if (simulate) - simulatedTransfers += amount; - else - pipe.addTransferredItems(amount); - } - - @Override - public int getSlots() { - return 1; - } - - @NotNull - @Override - public ItemStack getStackInSlot(int i) { - return ItemStack.EMPTY; - } - - @NotNull - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) { - return ItemStack.EMPTY; - } - - @Override - public int getSlotLimit(int i) { - return 64; - } - - private void transferTo(PipeNetPath.FacedPipeNetPath routePath, boolean simulate, - int amount) { - if (simulate) - simulatedTransfersGlobalRoundRobin.merge(routePath.toFacingPos(), amount, Integer::sum); - else - pipe.getTransferred().merge(routePath.toFacingPos(), amount, Integer::sum); - } - - private boolean contains(PipeNetPath.FacedPipeNetPath routePath, - boolean simulate) { - return simulate ? simulatedTransfersGlobalRoundRobin.containsKey(routePath.toFacingPos()) : - pipe.getTransferred().containsKey(routePath.toFacingPos()); - } - - private int didTransferTo(PipeNetPath.FacedPipeNetPath routePath, - boolean simulate) { - if (simulate) - return simulatedTransfersGlobalRoundRobin.getInt(routePath.toFacingPos()); - return pipe.getTransferred().getInt(routePath.toFacingPos()); - } - - private void resetTransferred(boolean simulated) { - if (simulated) - simulatedTransfersGlobalRoundRobin.clear(); - else - pipe.resetTransferred(); - } - - private void decrementBy(int amount) { - for (Object2IntMap.Entry entry : pipe.getTransferred().object2IntEntrySet()) { - entry.setValue(entry.getIntValue() - amount); - } - } - - private static class EnhancedRoundRobinData { - - private final PipeNetPath.FacedPipeNetPath routePath; - private final int maxInsertable; - private int transferred; - private int toTransfer = 0; - - private EnhancedRoundRobinData(PipeNetPath.FacedPipeNetPath routePath, - int maxInsertable, int transferred) { - this.maxInsertable = maxInsertable; - this.transferred = transferred; - this.routePath = routePath; - } - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/net/WorldItemPipeNet.java b/src/main/java/gregtech/common/pipelikeold/itempipe/net/WorldItemPipeNet.java deleted file mode 100644 index 1afc02c3073..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/net/WorldItemPipeNet.java +++ /dev/null @@ -1,86 +0,0 @@ -package gregtech.common.pipelikeold.itempipe.net; - -import gregtech.api.cover.Cover; -import gregtech.api.graphnet.pipenetold.WorldPipeNetSimple; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.common.covers.CoverConveyor; -import gregtech.common.covers.CoverItemFilter; -import gregtech.common.covers.ItemFilterMode; -import gregtech.common.covers.ManualImportExportMode; -import gregtech.common.pipelikeold.itempipe.ItemPipeType; -import gregtech.common.pipelikeold.itempipe.tile.TileEntityItemPipe; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.items.CapabilityItemHandler; - -public class WorldItemPipeNet extends WorldPipeNetSimple { - - private static final String DATA_ID = "gregtech.item_pipe_net"; - - public static WorldItemPipeNet getWorldPipeNet(World world) { - WorldItemPipeNet netWorldData = (WorldItemPipeNet) world.loadData(WorldItemPipeNet.class, DATA_ID); - if (netWorldData == null) { - netWorldData = new WorldItemPipeNet(DATA_ID); - world.setData(DATA_ID, netWorldData); - } - netWorldData.setWorldAndInit(world); - return netWorldData; - } - - public WorldItemPipeNet(String name) { - super(name, true, false); - } - - @Override - protected Capability[] getConnectionCapabilities() { - return new Capability[] { CapabilityItemHandler.ITEM_HANDLER_CAPABILITY }; - } - - @Override - protected Class> getBasePipeClass() { - return TileEntityItemPipe.class; - } - - @Override - protected IEdgePredicateOld getPredicate(Cover thisCover, Cover neighbourCover) { - ItemEdgePredicate predicate = new ItemEdgePredicate(); - if (thisCover instanceof CoverItemFilter filter && - filter.getFilterMode() != ItemFilterMode.FILTER_INSERT) { - predicate.setSourceFilter(filter.getFilterContainer()); - } - if (neighbourCover instanceof CoverItemFilter filter && - filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT) { - predicate.setTargetFilter(filter.getFilterContainer()); - } - if (thisCover instanceof CoverConveyor conveyor) { - if (conveyor.getManualImportExportMode() == ManualImportExportMode.DISABLED) { - predicate.setShutteredSource(true); - } else if (conveyor.getManualImportExportMode() == ManualImportExportMode.FILTERED) { - predicate.setSourceFilter(conveyor.getItemFilterContainer()); - } - } - if (neighbourCover instanceof CoverConveyor conveyor) { - if (conveyor.getManualImportExportMode() == ManualImportExportMode.DISABLED) { - predicate.setShutteredTarget(true); - } else if (conveyor.getManualImportExportMode() == ManualImportExportMode.FILTERED) { - predicate.setTargetFilter(conveyor.getItemFilterContainer()); - } - } - // TODO should robot arms apply rate limits to edge predicates? - return shutterify(predicate, thisCover, neighbourCover); - } - - @Override - protected void writeNodeData(ItemPipeProperties nodeData, NBTTagCompound tagCompound) { - tagCompound.setInteger("Priority", nodeData.getPriority()); - tagCompound.setFloat("Rate", nodeData.getTransferRate()); - } - - @Override - protected ItemPipeProperties readNodeData(NBTTagCompound tagCompound) { - return new ItemPipeProperties(tagCompound.getInteger("Priority"), tagCompound.getFloat("Rate")); - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipe.java b/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipe.java deleted file mode 100644 index e855ea6d275..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipe.java +++ /dev/null @@ -1,121 +0,0 @@ -package gregtech.common.pipelikeold.itempipe.tile; - -import gregtech.api.graphnet.pipenetold.block.material.TileEntityMaterialPipeBase; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.util.FacingPos; -import gregtech.common.pipelikeold.itempipe.ItemPipeType; -import gregtech.common.pipelikeold.itempipe.net.ItemNetHandler; -import gregtech.common.pipelikeold.itempipe.net.WorldItemPipeNet; - -import net.minecraft.util.EnumFacing; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemStackHandler; - -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import org.jetbrains.annotations.Nullable; - -import java.util.EnumMap; - -public class TileEntityItemPipe extends TileEntityMaterialPipeBase { - - private final EnumMap handlers = new EnumMap<>(EnumFacing.class); - private final Object2IntMap transferred = new Object2IntOpenHashMap<>(); - private ItemNetHandler defaultHandler; - // the ItemNetHandler can only be created on the server so we have a empty placeholder for the client - private final IItemHandler clientCapability = new ItemStackHandler(0); - - private int transferredItems = 0; - private long timer = 0; - - public long getWorldTime() { - return hasWorld() ? getWorld().getTotalWorldTime() : 0L; - } - - @Override - public Class getPipeTypeClass() { - return ItemPipeType.class; - } - - @Override - public boolean supportsTicking() { - return false; - } - - private void initHandlers() { - WorldItemPipeNet net = WorldItemPipeNet.getWorldPipeNet(getPipeWorld()); - for (EnumFacing facing : EnumFacing.values()) { - handlers.put(facing, new ItemNetHandler(net, this, facing)); - } - defaultHandler = new ItemNetHandler(net, this, null); - } - - @Nullable - @Override - public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { - if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { - if (world.isRemote) - return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(clientCapability); - - if (handlers.size() == 0) - initHandlers(); - return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(handlers.getOrDefault(facing, defaultHandler)); - } - return super.getCapabilityInternal(capability, facing); - } - - public void resetTransferred() { - transferred.clear(); - } - - public Object2IntMap getTransferred() { - return transferred; - } - - @Override - public void transferDataFrom(IPipeTile tileEntity) { - super.transferDataFrom(tileEntity); - TileEntityItemPipe itemPipe = (TileEntityItemPipe) tileEntity; - // take handlers from old pipe - if (!itemPipe.handlers.isEmpty()) { - this.handlers.clear(); - for (ItemNetHandler handler : itemPipe.handlers.values()) { - handler.updatePipe(this); - this.handlers.put(handler.getFacing(), handler); - } - } - if (itemPipe.defaultHandler != null) { - itemPipe.defaultHandler.updatePipe(this); - this.defaultHandler = itemPipe.defaultHandler; - } - } - - // every time the transferred variable is accessed this method should be called - // if 20 ticks passed since the last access it will reset it - // this method is equal to - // if (++time % 20 == 0) { - // this.transferredItems = 0; - // } - // if it was in a ticking TileEntity - private void updateTransferredState() { - long currentTime = getWorldTime(); - long dif = currentTime - this.timer; - if (dif >= 20 || dif < 0) { - this.transferredItems = 0; - this.timer = currentTime; - } - } - - public void addTransferredItems(int amount) { - updateTransferredState(); - this.transferredItems += amount; - } - - public int getTransferredItems() { - updateTransferredState(); - return this.transferredItems; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipeTickable.java b/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipeTickable.java deleted file mode 100644 index 8771867385f..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/tile/TileEntityItemPipeTickable.java +++ /dev/null @@ -1,16 +0,0 @@ -package gregtech.common.pipelikeold.itempipe.tile; - -import net.minecraft.util.ITickable; - -public class TileEntityItemPipeTickable extends TileEntityItemPipe implements ITickable { - - @Override - public void update() { - getCoverableImplementation().update(); - } - - @Override - public boolean supportsTicking() { - return true; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/laser/BlockLaserPipe.java b/src/main/java/gregtech/common/pipelikeold/laser/BlockLaserPipe.java deleted file mode 100644 index b2fc95f24d4..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/laser/BlockLaserPipe.java +++ /dev/null @@ -1,151 +0,0 @@ -package gregtech.common.pipelikeold.laser; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.items.toolitem.ToolHelper; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.client.renderer.pipeold.LaserPipeRenderer; -import gregtech.client.utils.BloomEffectUtil; -import gregtech.common.creativetab.GTCreativeTabs; -import gregtech.common.pipelikeold.laser.net.WorldLaserPipeNet; -import gregtech.common.pipelikeold.laser.tile.TileEntityLaserPipe; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.BlockRenderLayer; -import net.minecraft.util.EnumBlockRenderType; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class BlockLaserPipe extends BlockPipe { - - private final LaserPipeType pipeType; - private final LaserPipeProperties properties; - - public BlockLaserPipe(@NotNull LaserPipeType pipeType) { - this.pipeType = pipeType; - this.properties = LaserPipeProperties.INSTANCE; - setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); - setHarvestLevel(ToolClasses.WIRE_CUTTER, 1); - } - - @Override - protected Pair getParticleTexture(World world, BlockPos blockPos) { - return LaserPipeRenderer.INSTANCE.getParticleTexture((TileEntityLaserPipe) world.getTileEntity(blockPos)); - } - - @Override - public Class getPipeTypeClass() { - return LaserPipeType.class; - } - - @Override - public WorldLaserPipeNet getWorldPipeNet(World world) { - return WorldLaserPipeNet.getWorldPipeNet(world); - } - - @Override - public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { - return new TileEntityLaserPipe(); - } - - @Override - public LaserPipeProperties createProperties(IPipeTile pipeTile) { - LaserPipeType pipeType = pipeTile.getPipeType(); - if (pipeType == null) return getFallbackType(); - return this.pipeType.modifyProperties(properties); - } - - @Override - public LaserPipeProperties createItemProperties(ItemStack itemStack) { - if (itemStack.getItem() instanceof ItemBlockLaserPipe pipe) { - return ((BlockLaserPipe) pipe.getBlock()).properties; - } - return null; - } - - @Override - public ItemStack getDropItem(IPipeTile pipeTile) { - return new ItemStack(this, 1, pipeType.ordinal()); - } - - @Override - protected LaserPipeProperties getFallbackType() { - return LaserPipeProperties.INSTANCE; - } - - @Override - public LaserPipeType getItemPipeType(ItemStack itemStack) { - if (itemStack.getItem() instanceof ItemBlockLaserPipe pipe) { - return ((BlockLaserPipe) pipe.getBlock()).pipeType; - } - return null; - } - - @Override - public void setTileEntityData(TileEntityPipeBase pipeTile, - ItemStack itemStack) { - pipeTile.setPipeData(this, pipeType); - } - - @Override - public void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList items) { - items.add(new ItemStack(this, 1, this.pipeType.ordinal())); - } - - @Override - protected boolean isPipeTool(@NotNull ItemStack stack) { - return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); - } - - @Override - public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile) { - return selfTile instanceof TileEntityLaserPipe && sideTile instanceof TileEntityLaserPipe; - } - - @Override - public boolean canPipeConnectToBlock(IPipeTile selfTile, - EnumFacing side, @Nullable TileEntity tile) { - return tile != null && - tile.getCapability(GregtechTileCapabilities.CAPABILITY_LASER, side.getOpposite()) != null; - } - - @Override - public boolean isHoldingPipe(EntityPlayer player) { - if (player == null) { - return false; - } - ItemStack stack = player.getHeldItemMainhand(); - return stack != ItemStack.EMPTY && stack.getItem() instanceof ItemBlockLaserPipe; - } - - @Override - @NotNull - @SideOnly(Side.CLIENT) - @SuppressWarnings("deprecation") - public EnumBlockRenderType getRenderType(@NotNull IBlockState state) { - return LaserPipeRenderer.INSTANCE.getBlockRenderType(); - } - - @Override - public boolean canRenderInLayer(@NotNull IBlockState state, @NotNull BlockRenderLayer layer) { - if (layer == BlockRenderLayer.SOLID || layer == BlockRenderLayer.CUTOUT) return true; - return layer == BloomEffectUtil.getEffectiveBloomLayer(); - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/laser/ItemBlockLaserPipe.java b/src/main/java/gregtech/common/pipelikeold/laser/ItemBlockLaserPipe.java deleted file mode 100644 index d265c7b7bf3..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/laser/ItemBlockLaserPipe.java +++ /dev/null @@ -1,36 +0,0 @@ -package gregtech.common.pipelikeold.laser; - -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.block.ItemBlockPipe; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.client.utils.TooltipHelper; - -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.item.ItemStack; -import net.minecraft.world.World; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class ItemBlockLaserPipe extends ItemBlockPipe { - - public ItemBlockLaserPipe(BlockPipe block) { - super(block); - } - - @Override - public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, - @NotNull ITooltipFlag flagIn) { - super.addInformation(stack, worldIn, tooltip, flagIn); - tooltip.add(I18n.format("tile.laser_pipe_normal.tooltip1")); - - if (TooltipHelper.isShiftDown()) { - tooltip.add(I18n.format("gregtech.tool_action.wire_cutter.connect")); - } else { - tooltip.add(I18n.format("gregtech.tool_action.show_tooltips")); - } - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/laser/LaserPipeProperties.java b/src/main/java/gregtech/common/pipelikeold/laser/LaserPipeProperties.java deleted file mode 100644 index 9aa983f2787..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/laser/LaserPipeProperties.java +++ /dev/null @@ -1,15 +0,0 @@ -package gregtech.common.pipelikeold.laser; - -import gregtech.api.graphnet.pipenetold.IPipeNetData; - -import java.util.List; - -public class LaserPipeProperties implements IPipeNetData { - - public static final LaserPipeProperties INSTANCE = new LaserPipeProperties(); - - @Override - public LaserPipeProperties getSumData(List datas) { - return this; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/laser/LaserPipeType.java b/src/main/java/gregtech/common/pipelikeold/laser/LaserPipeType.java deleted file mode 100644 index fba892a5ea8..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/laser/LaserPipeType.java +++ /dev/null @@ -1,30 +0,0 @@ -package gregtech.common.pipelikeold.laser; - -import gregtech.api.graphnet.pipenetold.block.IPipeType; - -import org.jetbrains.annotations.NotNull; - -public enum LaserPipeType implements IPipeType { - - NORMAL; - - @Override - public @NotNull String getName() { - return "normal"; - } - - @Override - public float getThickness() { - return 0.375f; - } - - @Override - public LaserPipeProperties modifyProperties(LaserPipeProperties baseProperties) { - return baseProperties; - } - - @Override - public boolean isPaintable() { - return true; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/laser/net/LaserNetHandler.java b/src/main/java/gregtech/common/pipelikeold/laser/net/LaserNetHandler.java deleted file mode 100644 index 20a4ad6daab..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/laser/net/LaserNetHandler.java +++ /dev/null @@ -1,131 +0,0 @@ -package gregtech.common.pipelikeold.laser.net; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.ILaserRelay; -import gregtech.api.graphnet.pipenetold.IPipeNetHandler; -import gregtech.api.graphnet.NetGroup; -import gregtech.api.graphnet.pipenetold.PipeNetNode; -import gregtech.api.graphnet.pipenetold.PipeNetPath; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.common.pipelikeold.laser.LaserPipeProperties; -import gregtech.common.pipelikeold.laser.LaserPipeType; -import gregtech.common.pipelikeold.laser.tile.TileEntityLaserPipe; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Iterator; -import java.util.Map; - -public class LaserNetHandler implements ILaserRelay, IPipeNetHandler { - - private final WorldLaserPipeNet net; - private final TileEntityLaserPipe pipe; - private final EnumFacing facing; - - public LaserNetHandler(WorldLaserPipeNet net, @NotNull TileEntityLaserPipe pipe, @Nullable EnumFacing facing) { - this.net = net; - this.pipe = pipe; - this.facing = facing; - } - - @Override - public WorldLaserPipeNet getNet() { - return net; - } - - @Override - public EnumFacing getFacing() { - return facing; - } - - private void setPipesActive() { - NetGroup group = getNet().getNode(this.pipe.getPipePos()) - .getGroupSafe(); - if (group != null) { - for (PipeNetNode node : group.getNodes()) { - if (node.getHeldMTE() instanceof TileEntityLaserPipe laserPipe) { - laserPipe.setActive(true, 100); - } - } - } - } - - @Nullable - private ILaserRelay getInnerContainer() { - if (net == null || pipe.isInvalid() || facing == null) { - return null; - } - - Iterator> data = net.getPaths(this.pipe); - if (data == null || !data.hasNext()) return null; - Map connecteds = data.next().getTargetTEs(); - if (data.hasNext()) return null; - if (connecteds.size() != 1) return null; - EnumFacing facing = connecteds.keySet().iterator().next(); - - return connecteds.get(facing).getCapability(GregtechTileCapabilities.CAPABILITY_LASER, facing.getOpposite()); - } - - @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { - ILaserRelay handler = getInnerContainer(); - if (handler == null) return 0; - setPipesActive(); - return handler.acceptEnergyFromNetwork(side, voltage, amperage, simulate); - } - - @Override - public boolean inputsEnergy(EnumFacing side) { - ILaserRelay handler = getInnerContainer(); - if (handler == null) return false; - return handler.inputsEnergy(side); - } - - @Override - public boolean outputsEnergy(EnumFacing side) { - ILaserRelay handler = getInnerContainer(); - if (handler == null) return false; - return handler.outputsEnergy(side); - } - - @Override - public long changeEnergy(long amount) { - ILaserRelay handler = getInnerContainer(); - if (handler == null) return 0; - setPipesActive(); - return handler.changeEnergy(amount); - } - - @Override - public long getEnergyStored() { - ILaserRelay handler = getInnerContainer(); - if (handler == null) return 0; - return handler.getEnergyStored(); - } - - @Override - public long getEnergyCapacity() { - ILaserRelay handler = getInnerContainer(); - if (handler == null) return 0; - return handler.getEnergyCapacity(); - } - - @Override - public long getInputAmperage() { - return 0; - } - - @Override - public long getInputVoltage() { - return 0; - } - - @Override - public boolean isOneProbeHidden() { - return true; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/laser/net/WorldLaserPipeNet.java b/src/main/java/gregtech/common/pipelikeold/laser/net/WorldLaserPipeNet.java deleted file mode 100644 index bdf8c87832f..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/laser/net/WorldLaserPipeNet.java +++ /dev/null @@ -1,53 +0,0 @@ -package gregtech.common.pipelikeold.laser.net; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.graphnet.pipenetold.WorldPipeNetSimple; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.common.pipelikeold.laser.LaserPipeProperties; -import gregtech.common.pipelikeold.laser.LaserPipeType; -import gregtech.common.pipelikeold.laser.tile.TileEntityLaserPipe; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; - -import org.jetbrains.annotations.NotNull; - -public class WorldLaserPipeNet extends WorldPipeNetSimple { - - private static final String DATA_ID = "gregtech.laser_pipe_net"; - - public WorldLaserPipeNet(String name) { - super(name, false, true); - } - - @Override - protected Capability[] getConnectionCapabilities() { - return new Capability[] { GregtechTileCapabilities.CAPABILITY_LASER }; - } - - @Override - protected Class> getBasePipeClass() { - return TileEntityLaserPipe.class; - } - - @Override - protected void writeNodeData(LaserPipeProperties nodeData, NBTTagCompound tagCompound) {} - - @Override - protected LaserPipeProperties readNodeData(NBTTagCompound tagCompound) { - return new LaserPipeProperties(); - } - - @NotNull - public static WorldLaserPipeNet getWorldPipeNet(@NotNull World world) { - WorldLaserPipeNet netWorldData = (WorldLaserPipeNet) world.loadData(WorldLaserPipeNet.class, DATA_ID); - if (netWorldData == null) { - netWorldData = new WorldLaserPipeNet(DATA_ID); - world.setData(DATA_ID, netWorldData); - } - netWorldData.setWorldAndInit(world); - return netWorldData; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/laser/tile/TileEntityLaserPipe.java b/src/main/java/gregtech/common/pipelikeold/laser/tile/TileEntityLaserPipe.java deleted file mode 100644 index 0f5750628ae..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/laser/tile/TileEntityLaserPipe.java +++ /dev/null @@ -1,232 +0,0 @@ -package gregtech.common.pipelikeold.laser.tile; - -import gregtech.api.capability.GregtechDataCodes; -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.ILaserRelay; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.api.util.TaskScheduler; -import gregtech.common.pipelikeold.laser.LaserPipeProperties; -import gregtech.common.pipelikeold.laser.LaserPipeType; -import gregtech.common.pipelikeold.laser.net.LaserNetHandler; -import gregtech.common.pipelikeold.laser.net.WorldLaserPipeNet; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.PacketBuffer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.Constants; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.EnumMap; - -public class TileEntityLaserPipe extends TileEntityPipeBase { - - private final EnumMap handlers = new EnumMap<>(EnumFacing.class); - // the LaserNetHandler can only be created on the server, so we have an empty placeholder for the client - private final ILaserRelay clientCapability = new DefaultLaserContainer(); - private LaserNetHandler defaultHandler; - - private int ticksActive = 0; - private int activeDuration = 0; - private boolean isActive = false; - - @Override - public Class getPipeTypeClass() { - return LaserPipeType.class; - } - - @Override - public boolean supportsTicking() { - return false; - } - - @Override - public boolean canHaveBlockedFaces() { - return false; - } - - private void initHandlers() { - WorldLaserPipeNet net = WorldLaserPipeNet.getWorldPipeNet(getPipeWorld()); - for (EnumFacing facing : EnumFacing.VALUES) { - handlers.put(facing, new LaserNetHandler(net, this, facing)); - } - defaultHandler = new LaserNetHandler(net, this, null); - } - - @Override - public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { - if (capability == GregtechTileCapabilities.CAPABILITY_LASER) { - if (world.isRemote) { - return GregtechTileCapabilities.CAPABILITY_LASER.cast(clientCapability); - } - - if (handlers.isEmpty()) { - initHandlers(); - } - - return GregtechTileCapabilities.CAPABILITY_LASER.cast(handlers.getOrDefault(facing, defaultHandler)); - } - return super.getCapabilityInternal(capability, facing); - } - - @Override - public void transferDataFrom(IPipeTile tileEntity) { - super.transferDataFrom(tileEntity); - if (getPipeBlock().getWorldPipeNet(getPipeWorld()) == null) { - return; - } - - TileEntityLaserPipe pipe = (TileEntityLaserPipe) tileEntity; - if (!pipe.handlers.isEmpty() && pipe.defaultHandler != null) { - // take handlers from old pipe - handlers.clear(); - handlers.putAll(pipe.handlers); - defaultHandler = pipe.defaultHandler; - } else { - // create new handlers - initHandlers(); - } - } - - @Override - public void setConnection(EnumFacing side, boolean connected, boolean fromNeighbor) { - if (!getWorld().isRemote && connected && !fromNeighbor) { - int connections = getConnections(); - // block connection if any side other than the requested side and its opposite side are already connected. - connections &= ~(1 << side.getIndex()); - connections &= ~(1 << side.getOpposite().getIndex()); - if (connections != 0) return; - - // check the same for the targeted pipe - TileEntity tile = getWorld().getTileEntity(getPos().offset(side)); - if (tile instanceof IPipeTilepipeTile && - pipeTile.getPipeType().getClass() == this.getPipeType().getClass()) { - connections = pipeTile.getConnections(); - connections &= ~(1 << side.getIndex()); - connections &= ~(1 << side.getOpposite().getIndex()); - if (connections != 0) return; - } - } - super.setConnection(side, connected, fromNeighbor); - } - - public boolean isActive() { - return this.isActive; - } - - /** - * @param active if the pipe should become active - * @param duration how long the pipe should be active for - */ - public void setActive(boolean active, int duration) { - if (this.isActive != active) { - this.isActive = active; - notifyBlockUpdate(); - markDirty(); - writeCustomData(GregtechDataCodes.PIPE_LASER_ACTIVE, buf -> buf.writeBoolean(this.isActive)); - if (active && duration != this.activeDuration) { - TaskScheduler.scheduleTask(getWorld(), this::queueDisconnect); - } - } - - this.activeDuration = duration; - if (duration > 0 && active) { - this.ticksActive = 0; - } - } - - public boolean queueDisconnect() { - if (++this.ticksActive % activeDuration == 0) { - this.ticksActive = 0; - setActive(false, -1); - return false; - } - return true; - } - - @Override - public void receiveCustomData(int discriminator, PacketBuffer buf) { - super.receiveCustomData(discriminator, buf); - if (discriminator == GregtechDataCodes.PIPE_LASER_ACTIVE) { - this.isActive = buf.readBoolean(); - scheduleRenderUpdate(); - } - } - - @Override - public void writeInitialSyncData(PacketBuffer buf) { - super.writeInitialSyncData(buf); - buf.writeBoolean(this.isActive); - - // schedule a disconnect on world load, gotta set the duration to something - if (isActive) { - activeDuration = 100; - TaskScheduler.scheduleTask(getWorld(), this::queueDisconnect); - } - } - - @Override - public void receiveInitialSyncData(PacketBuffer buf) { - super.receiveInitialSyncData(buf); - this.isActive = buf.readBoolean(); - scheduleRenderUpdate(); - } - - @NotNull - @Override - public NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { - compound.setBoolean("Active", isActive); - return super.writeToNBT(compound); - } - - @Override - public void readFromNBT(@NotNull NBTTagCompound compound) { - super.readFromNBT(compound); - if (compound.hasKey("Active", Constants.NBT.TAG_BYTE)) { - isActive = compound.getBoolean("Active"); - } - } - - private static class DefaultLaserContainer implements ILaserRelay { - - @Override - public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { - return 0; - } - - @Override - public boolean inputsEnergy(EnumFacing side) { - return false; - } - - @Override - public long changeEnergy(long differenceAmount) { - return 0; - } - - @Override - public long getEnergyStored() { - return 0; - } - - @Override - public long getEnergyCapacity() { - return 0; - } - - @Override - public long getInputAmperage() { - return 0; - } - - @Override - public long getInputVoltage() { - return 0; - } - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/optical/BlockOpticalPipe.java b/src/main/java/gregtech/common/pipelikeold/optical/BlockOpticalPipe.java deleted file mode 100644 index 11480e42a8c..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/optical/BlockOpticalPipe.java +++ /dev/null @@ -1,144 +0,0 @@ -package gregtech.common.pipelikeold.optical; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.items.toolitem.ToolHelper; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.client.renderer.pipeold.OpticalPipeRenderer; -import gregtech.common.creativetab.GTCreativeTabs; -import gregtech.common.pipelikeold.optical.net.WorldOpticalPipeNet; -import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumBlockRenderType; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class BlockOpticalPipe extends BlockPipe { - - private final OpticalPipeType pipeType; - private final OpticalPipeProperties properties; - - public BlockOpticalPipe(@NotNull OpticalPipeType pipeType) { - this.pipeType = pipeType; - this.properties = OpticalPipeProperties.INSTANCE; - setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); - setHarvestLevel(ToolClasses.WIRE_CUTTER, 1); - } - - @Override - protected Pair getParticleTexture(@NotNull World world, BlockPos blockPos) { - return OpticalPipeRenderer.INSTANCE.getParticleTexture((TileEntityOpticalPipe) world.getTileEntity(blockPos)); - } - - @Override - public Class getPipeTypeClass() { - return OpticalPipeType.class; - } - - @Override - public WorldOpticalPipeNet getWorldPipeNet(World world) { - return WorldOpticalPipeNet.getWorldPipeNet(world); - } - - @Override - public TileEntityPipeBase createNewTileEntity(boolean supportsTicking) { - return new TileEntityOpticalPipe(); - } - - @Override - public OpticalPipeProperties createProperties(@NotNull IPipeTile pipeTile) { - OpticalPipeType pipeType = pipeTile.getPipeType(); - if (pipeType == null) return getFallbackType(); - return this.pipeType.modifyProperties(properties); - } - - @Override - public OpticalPipeProperties createItemProperties(@NotNull ItemStack itemStack) { - if (itemStack.getItem() instanceof ItemBlockOpticalPipe pipe) { - return ((BlockOpticalPipe) pipe.getBlock()).properties; - } - return null; - } - - @Override - public ItemStack getDropItem(IPipeTile pipeTile) { - return new ItemStack(this, 1, pipeType.ordinal()); - } - - @Override - protected OpticalPipeProperties getFallbackType() { - return OpticalPipeProperties.INSTANCE; - } - - @Override - public OpticalPipeType getItemPipeType(@NotNull ItemStack itemStack) { - if (itemStack.getItem() instanceof ItemBlockOpticalPipe pipe) { - return ((BlockOpticalPipe) pipe.getBlock()).pipeType; - } - return null; - } - - @Override - public void setTileEntityData(@NotNull TileEntityPipeBase pipeTile, - ItemStack itemStack) { - pipeTile.setPipeData(this, pipeType); - } - - @Override - public void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList items) { - items.add(new ItemStack(this, 1, this.pipeType.ordinal())); - } - - @Override - protected boolean isPipeTool(@NotNull ItemStack stack) { - return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); - } - - @Override - public boolean canPipesConnect(IPipeTile selfTile, EnumFacing side, - IPipeTile sideTile) { - return selfTile instanceof TileEntityOpticalPipe && sideTile instanceof TileEntityOpticalPipe; - } - - @Override - public boolean canPipeConnectToBlock(IPipeTile selfTile, - EnumFacing side, @Nullable TileEntity tile) { - if (tile == null) return false; - if (tile.hasCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, side.getOpposite())) return true; - return tile.hasCapability(GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER, side.getOpposite()); - } - - @Override - public boolean isHoldingPipe(EntityPlayer player) { - if (player == null) { - return false; - } - ItemStack stack = player.getHeldItemMainhand(); - return stack != ItemStack.EMPTY && stack.getItem() instanceof ItemBlockOpticalPipe; - } - - @Override - @NotNull - @SideOnly(Side.CLIENT) - @SuppressWarnings("deprecation") - public EnumBlockRenderType getRenderType(@NotNull IBlockState state) { - return OpticalPipeRenderer.INSTANCE.getBlockRenderType(); - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/optical/ItemBlockOpticalPipe.java b/src/main/java/gregtech/common/pipelikeold/optical/ItemBlockOpticalPipe.java deleted file mode 100644 index ca3be9c45ac..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/optical/ItemBlockOpticalPipe.java +++ /dev/null @@ -1,34 +0,0 @@ -package gregtech.common.pipelikeold.optical; - -import gregtech.api.graphnet.pipenetold.block.ItemBlockPipe; -import gregtech.client.utils.TooltipHelper; - -import net.minecraft.client.resources.I18n; -import net.minecraft.client.util.ITooltipFlag; -import net.minecraft.item.ItemStack; -import net.minecraft.world.World; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class ItemBlockOpticalPipe extends ItemBlockPipe { - - public ItemBlockOpticalPipe(BlockOpticalPipe block) { - super(block); - } - - @Override - public void addInformation(@NotNull ItemStack stack, @Nullable World worldIn, @NotNull List tooltip, - @NotNull ITooltipFlag flagIn) { - super.addInformation(stack, worldIn, tooltip, flagIn); - tooltip.add(I18n.format("tile.optical_pipe_normal.tooltip1")); - - if (TooltipHelper.isShiftDown()) { - tooltip.add(I18n.format("gregtech.tool_action.wire_cutter.connect")); - } else { - tooltip.add(I18n.format("gregtech.tool_action.show_tooltips")); - } - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeProperties.java b/src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeProperties.java deleted file mode 100644 index 9f61ce9247c..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeProperties.java +++ /dev/null @@ -1,15 +0,0 @@ -package gregtech.common.pipelikeold.optical; - -import gregtech.api.graphnet.pipenetold.IPipeNetData; - -import java.util.List; - -public class OpticalPipeProperties implements IPipeNetData { - - public static final OpticalPipeProperties INSTANCE = new OpticalPipeProperties(); - - @Override - public OpticalPipeProperties getSumData(List datas) { - return this; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeType.java b/src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeType.java deleted file mode 100644 index cf0c9958221..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/optical/OpticalPipeType.java +++ /dev/null @@ -1,31 +0,0 @@ -package gregtech.common.pipelikeold.optical; - -import gregtech.api.graphnet.pipenetold.block.IPipeType; - -import org.jetbrains.annotations.NotNull; - -public enum OpticalPipeType implements IPipeType { - - NORMAL; - - @Override - public float getThickness() { - return 0.375F; - } - - @Override - public OpticalPipeProperties modifyProperties(OpticalPipeProperties baseProperties) { - return baseProperties; - } - - @Override - public boolean isPaintable() { - return true; - } - - @NotNull - @Override - public String getName() { - return "normal"; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/optical/net/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelikeold/optical/net/OpticalNetHandler.java deleted file mode 100644 index 3a573419825..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/optical/net/OpticalNetHandler.java +++ /dev/null @@ -1,149 +0,0 @@ -package gregtech.common.pipelikeold.optical.net; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.data.IDataAccess; -import gregtech.api.capability.data.IHatchDataAccess; -import gregtech.api.graphnet.pipenetold.IPipeNetHandler; -import gregtech.api.graphnet.NetGroup; -import gregtech.api.graphnet.pipenetold.PipeNetNode; -import gregtech.api.graphnet.pipenetold.PipeNetPath; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.recipes.Recipe; -import gregtech.common.pipelikeold.optical.OpticalPipeProperties; -import gregtech.common.pipelikeold.optical.OpticalPipeType; -import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.Iterator; -import java.util.Map; - -public class OpticalNetHandler implements IDataAccess, IOpticalComputationProvider, IPipeNetHandler { - - private final TileEntityOpticalPipe pipe; - private final EnumFacing facing; - - private final WorldOpticalPipeNet net; - - public OpticalNetHandler(WorldOpticalPipeNet net, @NotNull TileEntityOpticalPipe pipe, - @Nullable EnumFacing facing) { - this.net = net; - this.pipe = pipe; - this.facing = facing; - } - - @Override - public WorldOpticalPipeNet getNet() { - return net; - } - - @Override - public EnumFacing getFacing() { - return facing; - } - - @Override - public boolean isRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { - boolean isAvailable = traverseRecipeAvailable(recipe, seen); - if (isAvailable) setPipesActive(); - return isAvailable; - } - - @Override - public boolean isCreative() { - return false; - } - - @Override - public int requestCWUt(int cwut, boolean simulate, @NotNull Collection seen) { - int provided = traverseRequestCWUt(cwut, simulate, seen); - if (provided > 0) setPipesActive(); - return provided; - } - - @Override - public int getMaxCWUt(@NotNull Collection seen) { - return traverseMaxCWUt(seen); - } - - @Override - public boolean canBridge(@NotNull Collection seen) { - return traverseCanBridge(seen); - } - - private void setPipesActive() { - NetGroup group = getNet().getNode(this.pipe.getPipePos()) - .getGroupSafe(); - if (group != null) { - for (PipeNetNode node : group.getNodes()) { - if (node.getHeldMTE() instanceof TileEntityOpticalPipe opticalPipe) { - opticalPipe.setActive(true, 100); - } - } - } - } - - private boolean isNetInvalidForTraversal() { - return net == null || pipe.isInvalid() || facing == null; - } - - private boolean traverseRecipeAvailable(@NotNull Recipe recipe, @NotNull Collection seen) { - if (isNetInvalidForTraversal()) return false; - - Iterator> inv = net.getPaths(this.pipe); - if (inv == null || !inv.hasNext()) return false; - Map connecteds = inv.next().getTargetTEs(); - if (inv.hasNext()) return false; - if (connecteds.size() != 1) return false; - EnumFacing facing = connecteds.keySet().iterator().next(); - - IDataAccess access = connecteds.get(facing).getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, - facing.getOpposite()); - if (!(access instanceof IHatchDataAccess hatch) || seen.contains(hatch)) return false; - - if (hatch.isTransmitter()) { - return hatch.isRecipeAvailable(recipe, seen); - } - return false; - } - - private int traverseRequestCWUt(int cwut, boolean simulate, @NotNull Collection seen) { - IOpticalComputationProvider provider = getComputationProvider(seen); - if (provider == null) return 0; - return provider.requestCWUt(cwut, simulate, seen); - } - - private int traverseMaxCWUt(@NotNull Collection seen) { - IOpticalComputationProvider provider = getComputationProvider(seen); - if (provider == null) return 0; - return provider.getMaxCWUt(seen); - } - - private boolean traverseCanBridge(@NotNull Collection seen) { - IOpticalComputationProvider provider = getComputationProvider(seen); - if (provider == null) return true; // nothing found, so don't report a problem, just pass quietly - return provider.canBridge(seen); - } - - @Nullable - private IOpticalComputationProvider getComputationProvider(@NotNull Collection seen) { - if (isNetInvalidForTraversal()) return null; - - Iterator> inv = net.getPaths(this.pipe); - if (inv == null || !inv.hasNext()) return null; - Map connecteds = inv.next().getTargetTEs(); - if (inv.hasNext()) return null; - if (connecteds.size() != 1) return null; - EnumFacing facing = connecteds.keySet().iterator().next(); - - IOpticalComputationProvider hatch = connecteds.get(facing) - .getCapability(GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER, facing.getOpposite());; - if (hatch == null || seen.contains(hatch)) return null; - return hatch; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/optical/net/WorldOpticalPipeNet.java b/src/main/java/gregtech/common/pipelikeold/optical/net/WorldOpticalPipeNet.java deleted file mode 100644 index d3026f83050..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/optical/net/WorldOpticalPipeNet.java +++ /dev/null @@ -1,54 +0,0 @@ -package gregtech.common.pipelikeold.optical.net; - -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.graphnet.pipenetold.WorldPipeNetSimple; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.common.pipelikeold.optical.OpticalPipeProperties; -import gregtech.common.pipelikeold.optical.OpticalPipeType; -import gregtech.common.pipelikeold.optical.tile.TileEntityOpticalPipe; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; - -import org.jetbrains.annotations.NotNull; - -public class WorldOpticalPipeNet extends WorldPipeNetSimple { - - private static final String DATA_ID = "gregtech.optical_pipe_net"; - - public WorldOpticalPipeNet(String name) { - super(name, false, true); - } - - @Override - protected Capability[] getConnectionCapabilities() { - return new Capability[] { GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, - GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER }; - } - - @Override - protected Class> getBasePipeClass() { - return TileEntityOpticalPipe.class; - } - - @Override - protected void writeNodeData(OpticalPipeProperties nodeData, NBTTagCompound tagCompound) {} - - @Override - protected OpticalPipeProperties readNodeData(NBTTagCompound tagCompound) { - return new OpticalPipeProperties(); - } - - @NotNull - public static WorldOpticalPipeNet getWorldPipeNet(@NotNull World world) { - WorldOpticalPipeNet netWorldData = (WorldOpticalPipeNet) world.loadData(WorldOpticalPipeNet.class, DATA_ID); - if (netWorldData == null) { - netWorldData = new WorldOpticalPipeNet(DATA_ID); - world.setData(DATA_ID, netWorldData); - } - netWorldData.setWorldAndInit(world); - return netWorldData; - } -} diff --git a/src/main/java/gregtech/common/pipelikeold/optical/tile/TileEntityOpticalPipe.java b/src/main/java/gregtech/common/pipelikeold/optical/tile/TileEntityOpticalPipe.java deleted file mode 100644 index 164b1bf3a1b..00000000000 --- a/src/main/java/gregtech/common/pipelikeold/optical/tile/TileEntityOpticalPipe.java +++ /dev/null @@ -1,187 +0,0 @@ -package gregtech.common.pipelikeold.optical.tile; - -import gregtech.api.capability.GregtechDataCodes; -import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.data.IDataAccess; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; -import gregtech.api.util.TaskScheduler; -import gregtech.api.capability.data.query.DataQueryObject; -import gregtech.common.pipelikeold.optical.OpticalPipeProperties; -import gregtech.common.pipelikeold.optical.OpticalPipeType; -import gregtech.common.pipelikeold.optical.net.OpticalNetHandler; -import gregtech.common.pipelikeold.optical.net.WorldOpticalPipeNet; - -import net.minecraft.network.PacketBuffer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraftforge.common.capabilities.Capability; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.EnumMap; - -public class TileEntityOpticalPipe extends TileEntityPipeBase { - - private final EnumMap handlers = new EnumMap<>(EnumFacing.class); - // the OpticalNetHandler can only be created on the server, so we have an empty placeholder for the client - private final IDataAccess clientDataHandler = new DefaultDataHandler(); - private final IOpticalComputationProvider clientComputationHandler = new DefaultComputationHandler(); - private OpticalNetHandler defaultHandler; - - private int ticksActive = 0; - private boolean isActive; - - @Override - public Class getPipeTypeClass() { - return OpticalPipeType.class; - } - - @Override - public boolean supportsTicking() { - return false; - } - - @Override - public boolean canHaveBlockedFaces() { - return false; - } - - private void initHandlers() { - WorldOpticalPipeNet net = WorldOpticalPipeNet.getWorldPipeNet(getPipeWorld()); - for (EnumFacing facing : EnumFacing.VALUES) { - handlers.put(facing, new OpticalNetHandler(net, this, facing)); - } - defaultHandler = new OpticalNetHandler(net, this, null); - } - - @Nullable - @Override - public T getCapabilityInternal(Capability capability, @Nullable EnumFacing facing) { - if (capability == GregtechTileCapabilities.CAPABILITY_DATA_ACCESS) { - if (world.isRemote) { - return GregtechTileCapabilities.CAPABILITY_DATA_ACCESS.cast(clientDataHandler); - } - - if (handlers.isEmpty()) initHandlers(); - - return GregtechTileCapabilities.CAPABILITY_DATA_ACCESS.cast(handlers.getOrDefault(facing, defaultHandler)); - } - - if (capability == GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER) { - if (world.isRemote) { - return GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER.cast(clientComputationHandler); - } - - if (handlers.isEmpty()) initHandlers(); - - return GregtechTileCapabilities.CAPABILITY_COMPUTATION_PROVIDER - .cast(handlers.getOrDefault(facing, defaultHandler)); - } - return super.getCapabilityInternal(capability, facing); - } - - @Override - public void transferDataFrom(IPipeTile tileEntity) { - super.transferDataFrom(tileEntity); - TileEntityOpticalPipe pipe = (TileEntityOpticalPipe) tileEntity; - if (!pipe.handlers.isEmpty() && pipe.defaultHandler != null) { - // take handlers from old pipe - handlers.clear(); - handlers.putAll(pipe.handlers); - defaultHandler = pipe.defaultHandler; - } else { - // create new handlers - initHandlers(); - } - } - - @Override - public void setConnection(EnumFacing side, boolean connected, boolean fromNeighbor) { - if (!getWorld().isRemote && connected && !fromNeighbor) { - // never allow more than two connections total - if (getNumConnections() >= 2) return; - - // also check the other pipe - TileEntity tile = getWorld().getTileEntity(getPos().offset(side)); - if (tile instanceof IPipeTilepipeTile && - pipeTile.getPipeType().getClass() == this.getPipeType().getClass()) { - if (pipeTile.getNumConnections() >= 2) return; - } - } - super.setConnection(side, connected, fromNeighbor); - } - - public boolean isActive() { - return this.isActive; - } - - /** - * @param active if the pipe should become active - * @param duration how long the pipe should be active for - */ - public void setActive(boolean active, int duration) { - boolean stateChanged = false; - if (this.isActive && !active) { - this.isActive = false; - stateChanged = true; - } else if (!this.isActive && active) { - this.isActive = true; - stateChanged = true; - TaskScheduler.scheduleTask(getWorld(), () -> { - if (++this.ticksActive % duration == 0) { - this.ticksActive = 0; - setActive(false, -1); - return false; - } - return true; - }); - } - - if (stateChanged) { - writeCustomData(GregtechDataCodes.PIPE_ACTIVE, buf -> { - buf.writeBoolean(this.isActive); - }); - notifyBlockUpdate(); - markDirty(); - } - } - - @Override - public void receiveCustomData(int discriminator, PacketBuffer buf) { - super.receiveCustomData(discriminator, buf); - if (discriminator == GregtechDataCodes.PIPE_ACTIVE) { - this.isActive = buf.readBoolean(); - scheduleRenderUpdate(); - } - } - - private static class DefaultDataHandler implements IDataAccess { - - @Override - public boolean accessData(@NotNull DataQueryObject queryObject) { - return false; - } - } - - private static class DefaultComputationHandler implements IOpticalComputationProvider { - - @Override - public int requestCWUt(int cwut, boolean simulate, @NotNull Collection seen) { - return 0; - } - - @Override - public int getMaxCWUt(@NotNull Collection seen) { - return 0; - } - - @Override - public boolean canBridge(@NotNull Collection seen) { - return false; - } - } -} diff --git a/src/main/java/gregtech/integration/RecipeCompatUtil.java b/src/main/java/gregtech/integration/RecipeCompatUtil.java index a20e9965e2f..f3fab3148e0 100644 --- a/src/main/java/gregtech/integration/RecipeCompatUtil.java +++ b/src/main/java/gregtech/integration/RecipeCompatUtil.java @@ -3,11 +3,13 @@ import gregtech.api.GTValues; import gregtech.api.GregTechAPI; import gregtech.api.block.machines.MachineItemBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.graphnet.pipenetold.block.material.BlockMaterialPipe; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; +import gregtech.api.unification.material.Material; +import gregtech.api.util.GTStringUtils; import gregtech.api.util.GTUtility; import gregtech.common.blocks.BlockCompressed; import gregtech.common.blocks.BlockFrame; @@ -68,8 +70,9 @@ public static String getMetaItemId(ItemStack item) { if (block instanceof BlockFrame) { return "frame" + ((BlockFrame) block).getGtMaterial(item).toCamelCaseString(); } - if (block instanceof BlockMaterialPipe blockMaterialPipe) { - return blockMaterialPipe.getPrefix().name + blockMaterialPipe.getItemMaterial(item).toCamelCaseString(); + if (block instanceof PipeMaterialBlock blockMaterialPipe) { + Material mat = blockMaterialPipe.getMaterialForStack(item); + if (mat != null) return blockMaterialPipe.getStructure().getOrePrefix().name + mat.toCamelCaseString(); } } return null; diff --git a/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java b/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java index 282fd1a6229..bc47b1a6f0f 100644 --- a/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java +++ b/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java @@ -15,9 +15,6 @@ import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; -import gregtech.common.pipelikeold.cable.BlockCable; -import gregtech.common.pipelikeold.fluidpipe.BlockFluidPipe; -import gregtech.common.pipelikeold.itempipe.BlockItemPipe; import gregtech.integration.groovy.GroovyScriptModule; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java index b392b6dd796..55ad596f058 100644 --- a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java +++ b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java @@ -27,9 +27,6 @@ import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; -import gregtech.common.pipelikeold.cable.BlockCable; -import gregtech.common.pipelikeold.fluidpipe.BlockFluidPipe; -import gregtech.common.pipelikeold.itempipe.BlockItemPipe; import gregtech.integration.IntegrationSubmodule; import gregtech.modules.GregTechModules; diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java index a5d07770e3c..d7491a25a06 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java @@ -1,13 +1,8 @@ package gregtech.integration.theoneprobe.provider.debug; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.pipenetold.PipeNetNode; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.graphnet.pipenetold.WorldPipeNetBase; -import gregtech.api.graphnet.pipenetold.block.BlockPipe; -import gregtech.api.graphnet.pipenetold.tile.IPipeTile; -import gregtech.api.graphnet.pipenetold.tile.TileEntityPipeBase; import gregtech.common.ConfigHolder; import net.minecraft.block.state.IBlockState; From 7a32d3ebc8bee0f8c3014713980143b7cad9bf79 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 27 Jul 2024 20:34:36 -0600 Subject: [PATCH 082/157] Spotless edition --- .../api/block/machines/MachineItemBlock.java | 3 - .../gregtech/api/capability/ILaserRelay.java | 3 +- .../api/capability/IPropertyFluidFilter.java | 3 - .../capability/data/IComputationConsumer.java | 3 +- .../capability/data/IComputationProvider.java | 4 +- .../api/capability/data/IDataAccess.java | 6 +- .../api/capability/data/IHatchDataAccess.java | 2 - .../data/query/DataAccessFormat.java | 1 - .../data/query/IComputationQuery.java | 2 +- .../impl/ComputationRecipeLogic.java | 3 +- .../impl/LaserContainerHandler.java | 1 - .../gregtech/api/graphnet/GraphNetBacker.java | 40 +++--- .../java/gregtech/api/graphnet/IGraphNet.java | 32 +++-- .../api/graphnet/MultiNodeHelper.java | 7 +- .../java/gregtech/api/graphnet/NetGroup.java | 3 +- .../java/gregtech/api/graphnet/NetNode.java | 4 +- .../DynamicWeightsShortestPathsAlgorithm.java | 6 +- .../api/graphnet/alg/INetAlgorithm.java | 3 +- .../api/graphnet/alg/NetAlgorithmWrapper.java | 9 +- .../api/graphnet/alg/NetPathMapper.java | 2 +- .../graphnet/alg/ShortestPathsAlgorithm.java | 7 +- .../api/graphnet/alg/SinglePathAlgorithm.java | 4 +- .../graphnet/edge/AbstractNetFlowEdge.java | 12 +- .../api/graphnet/edge/NetFlowEdge.java | 8 +- .../api/graphnet/edge/NetFlowSharedEdge.java | 1 - .../graphnet/gather/GTGraphGatherables.java | 10 +- .../graphnet/gather/GatherLogicsEvent.java | 4 +- .../gather/GatherPredicatesEvent.java | 4 +- .../gather/GatherStructuresEvent.java | 6 +- .../api/graphnet/graph/NetDirectedGraph.java | 3 +- .../graphnet/graph/NetUndirectedGraph.java | 3 +- .../logic/AbstractDoubleLogicData.java | 3 +- .../graphnet/logic/AbstractLongLogicData.java | 4 +- .../api/graphnet/logic/INetLogicEntry.java | 13 +- .../api/graphnet/logic/NetLogicData.java | 23 ++-- .../api/graphnet/logic/WeightFactorLogic.java | 1 - .../api/graphnet/path/AbstractNetPath.java | 1 - .../graphnet/path/GenericGraphNetPath.java | 12 +- .../pipenet/BasicWorldPipeNetPath.java | 9 +- .../pipenet/FlowWorldPipeNetPath.java | 9 +- .../graphnet/pipenet/IPipeNetNodeHandler.java | 3 +- .../api/graphnet/pipenet/NodeLossCache.java | 8 +- .../api/graphnet/pipenet/NodeLossResult.java | 3 +- .../api/graphnet/pipenet/WorldPipeNet.java | 17 ++- .../graphnet/pipenet/WorldPipeNetNode.java | 4 +- .../logic/EdgeCoverReferenceLogic.java | 11 +- .../pipenet/logic/EnumLossFunction.java | 22 +++- .../pipenet/logic/TemperatureLogic.java | 29 ++--- .../logic/TemperatureLossFunction.java | 4 +- .../graphnet/pipenet/physical/IBurnable.java | 1 - .../pipenet/physical/IInsulatable.java | 1 + .../physical/IPipeCapabilityObject.java | 2 + .../pipenet/physical/IPipeStructure.java | 2 +- .../pipenet/physical/block/ItemPipeBlock.java | 7 +- .../physical/block/PipeMaterialBlock.java | 26 +--- .../physical/block/WorldPipeBlock.java | 34 +++--- .../tile/PipeActivableTileEntity.java | 1 - .../physical/tile/PipeCapabilityWrapper.java | 2 - .../physical/tile/PipeCoverHolder.java | 4 +- .../physical/tile/PipeMaterialTileEntity.java | 5 - .../pipenet/physical/tile/PipeTileEntity.java | 40 +++--- .../pipenet/predicate/ShutterPredicate.java | 3 +- .../predicate/EdgePredicateHandler.java | 6 +- .../graphnet/predicate/IEdgePredicate.java | 12 +- .../predicate/test/IPredicateTestObject.java | 1 + .../predicate/test/ItemTestObject.java | 2 - .../api/graphnet/servernet/ServerNet.java | 4 +- .../api/graphnet/servernet/ServerNetNode.java | 1 - .../traverse/AbstractTraverseData.java | 3 +- .../graphnet/traverse/DistributorHelper.java | 6 - .../traverse/IRoundRobinTraverseData.java | 1 + .../api/graphnet/traverse/ITraverseData.java | 17 +-- .../graphnet/traverse/TraverseHelpers.java | 115 ++++++++++-------- .../traverse/util/CompleteLossOperator.java | 1 + .../traverse/util/FlowConsumptionStack.java | 1 + .../traverse/util/MultLossOperator.java | 2 +- .../api/graphnet/worldnet/WorldNet.java | 14 +-- .../api/graphnet/worldnet/WorldNetNode.java | 3 - .../items/metaitem/FilteredFluidStats.java | 3 +- .../interfaces/INeighborCache.java | 1 - .../multiblock/MultiblockAbility.java | 3 +- .../api/unification/material/Material.java | 32 +++-- .../properties/PipeNetProperties.java | 9 +- .../material/properties/PropertyKey.java | 3 +- .../api/unification/ore/OrePrefix.java | 3 +- .../java/gregtech/api/util/GTUtility.java | 5 +- .../client/particle/GTOverheatParticle.java | 1 - .../renderer/pipe/AbstractPipeModel.java | 15 +-- .../renderer/pipe/ActivablePipeModel.java | 22 ++-- .../client/renderer/pipe/CableModel.java | 10 +- .../client/renderer/pipe/PipeItemModel.java | 8 -- .../client/renderer/pipe/PipeModel.java | 3 +- .../renderer/pipe/cache/ActivableSQC.java | 4 +- .../renderer/pipe/cache/BlockableSQC.java | 4 +- .../renderer/pipe/cache/ColorQuadCache.java | 7 +- .../renderer/pipe/cache/ExtraCappedSQC.java | 4 +- .../renderer/pipe/cache/RestrictiveSQC.java | 7 +- .../pipe/cache/StructureQuadCache.java | 14 +-- .../renderer/pipe/quad/PipeQuadHelper.java | 31 +++-- .../pipe/quad/RecolorableBakedQuad.java | 91 ++++++-------- .../client/renderer/pipe/quad/UVCorner.java | 1 + .../client/renderer/pipe/quad/UVMapper.java | 4 +- .../client/renderer/pipe/util/CacheKey.java | 2 - .../pipe/util/PipeSpriteWoodClarifier.java | 3 - .../renderer/pipe/util/SpriteInformation.java | 4 +- .../pipe/util/SpriteInformationWrapper.java | 4 +- .../renderer/pipe/util/WoodCacheKey.java | 2 - .../client/renderer/texture/Textures.java | 99 +++++++-------- .../client/utils/RenderBufferHelper.java | 1 + .../java/gregtech/common/EventHandlers.java | 2 +- .../gregtech/common/blocks/BlockFrame.java | 1 - .../gregtech/common/blocks/MetaBlocks.java | 5 +- .../blocks/properties/PropertyByte.java | 34 ++---- .../blocks/properties/PropertyShort.java | 33 ++--- .../common/command/CommandRecipeCheck.java | 14 --- .../common/covers/CoverRoboticArm.java | 16 +-- .../java/gregtech/common/items/MetaItem1.java | 15 ++- .../metatileentities/MetaTileEntities.java | 2 +- .../MetaTileEntityActiveTransformer.java | 3 - .../electric/MetaTileEntityAssemblyLine.java | 2 +- .../multi/electric/MetaTileEntityHPCA.java | 2 +- .../electric/MetaTileEntityNetworkSwitch.java | 2 +- .../MetaTileEntityResearchStation.java | 4 +- .../MetaTileEntityComputationHatch.java | 18 +-- .../MetaTileEntityDataAccessHatch.java | 8 +- .../MetaTileEntityLaserHatch.java | 2 - .../MetaTileEntityOpticalDataHatch.java | 11 +- .../storage/MetaTileEntityDrum.java | 1 - .../MetaTileEntityLongDistanceEndpoint.java | 4 +- .../pipelike/block/cable/CableBlock.java | 9 +- .../pipelike/block/cable/CableStructure.java | 50 ++++---- .../pipelike/block/laser/LaserPipeBlock.java | 3 - .../pipelike/block/laser/LaserStructure.java | 5 +- .../block/optical/OpticalPipeBlock.java | 2 - .../block/optical/OpticalStructure.java | 8 +- .../common/pipelike/block/pipe/PipeBlock.java | 17 --- .../pipelike/block/pipe/PipeStructure.java | 71 +++++------ .../pipelike/handlers/LaserNetHandler.java | 2 - .../pipelike/handlers/OpticalNetHandler.java | 1 - .../properties/MaterialEnergyProperties.java | 51 ++++---- .../properties/MaterialFluidProperties.java | 19 +-- .../properties/MaterialItemProperties.java | 9 +- .../common/pipelike/net/SlowActiveWalker.java | 10 +- .../net/energy/EnergyCapabilityObject.java | 21 ++-- .../net/energy/EnergyTraverseData.java | 17 ++- .../pipelike/net/energy/WorldEnergyNet.java | 9 +- .../net/fluid/ContainmentFailure.java | 16 ++- .../net/fluid/FluidCapabilityObject.java | 6 +- .../net/fluid/FluidContainmentLogic.java | 12 +- .../pipelike/net/fluid/FluidTraverseData.java | 31 +++-- .../pipelike/net/fluid/WorldFluidNet.java | 8 +- .../net/item/ItemCapabilityObject.java | 8 +- .../pipelike/net/item/ItemTraverseData.java | 9 +- .../pipelike/net/item/WorldItemNet.java | 8 +- .../net/laser/LaserCapabilityObject.java | 5 +- .../net/optical/DataCapabilityObject.java | 12 +- .../pipelike/net/optical/WorldOpticalNet.java | 5 +- .../cable/net/EnergyGroupData.java | 3 - .../MetaTileEntityLDFluidEndpoint.java | 2 +- .../MetaTileEntityLDItemEndpoint.java | 2 +- .../integration/RecipeCompatUtil.java | 1 - .../material/CTMaterialBuilder.java | 6 +- .../material/MaterialPropertyExpansion.java | 13 +- .../recipe/MetaItemBracketHandler.java | 13 +- .../groovy/GroovyScriptModule.java | 13 +- .../groovy/MaterialPropertyExpansion.java | 13 +- .../theoneprobe/provider/LDPipeProvider.java | 4 +- .../recipe/handlers/PartsRecipeHandler.java | 1 - .../recipe/handlers/PipeRecipeHandler.java | 10 +- .../recipe/handlers/WireCombiningHandler.java | 18 +-- .../recipe/handlers/WireRecipeHandler.java | 24 ++-- 171 files changed, 836 insertions(+), 982 deletions(-) diff --git a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java index 09337217886..6570ba4d012 100644 --- a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java +++ b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java @@ -2,7 +2,6 @@ import gregtech.api.GTValues; import gregtech.api.GregTechAPI; -import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.metatileentity.ITieredMetaTileEntity; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.util.GTUtility; @@ -11,7 +10,6 @@ import gregtech.common.ConfigHolder; import gregtech.common.creativetab.GTCreativeTabs; -import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.resources.I18n; import net.minecraft.client.util.ITooltipFlag; @@ -20,7 +18,6 @@ import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; diff --git a/src/main/java/gregtech/api/capability/ILaserRelay.java b/src/main/java/gregtech/api/capability/ILaserRelay.java index c31cdc1caed..77e432fc4a6 100644 --- a/src/main/java/gregtech/api/capability/ILaserRelay.java +++ b/src/main/java/gregtech/api/capability/ILaserRelay.java @@ -4,7 +4,8 @@ public interface ILaserRelay { /** * Receive a laser pulse. - * @param laserVoltage the voltage of the laser. + * + * @param laserVoltage the voltage of the laser. * @param laserAmperage the amperage of the laser. * @return how much amperage was received. */ diff --git a/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java b/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java index 1b74b239e02..2f1ad999eaf 100644 --- a/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java +++ b/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java @@ -1,6 +1,5 @@ package gregtech.api.capability; -import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.AttributedFluid; import gregtech.api.fluids.attribute.FluidAttribute; @@ -16,8 +15,6 @@ import java.util.Collection; import java.util.List; -import static gregtech.api.fluids.FluidConstants.CRYOGENIC_FLUID_THRESHOLD; - /** * Fluid filter based on fluid properties; i.e. temperature, fluid state, and various material flags such as acid * and plasma. diff --git a/src/main/java/gregtech/api/capability/data/IComputationConsumer.java b/src/main/java/gregtech/api/capability/data/IComputationConsumer.java index 19f73509290..c524b23436d 100644 --- a/src/main/java/gregtech/api/capability/data/IComputationConsumer.java +++ b/src/main/java/gregtech/api/capability/data/IComputationConsumer.java @@ -7,8 +7,9 @@ public interface IComputationConsumer { /** * Called to supply CWU. + * * @param requested the requested CWU - * @param simulate whether to simulate the request + * @param simulate whether to simulate the request * @return the amount of CWU supplied. */ long supplyCWU(long requested, boolean simulate); diff --git a/src/main/java/gregtech/api/capability/data/IComputationProvider.java b/src/main/java/gregtech/api/capability/data/IComputationProvider.java index 2a47ce7a7ed..a5525fc108e 100644 --- a/src/main/java/gregtech/api/capability/data/IComputationProvider.java +++ b/src/main/java/gregtech/api/capability/data/IComputationProvider.java @@ -5,14 +5,16 @@ public interface IComputationProvider { /** * Returns whether this provider supports bridging. If false, CWU will not be requested through * network switches with multiple inputs. + * * @return whether bridging is supported. */ boolean supportsBridging(); /** * Called to supply CWU to a requester. + * * @param requested the requested CWU - * @param simulate whether to simulate the request + * @param simulate whether to simulate the request * @return the amount of CWU supplied. */ long supplyCWU(long requested, boolean simulate); diff --git a/src/main/java/gregtech/api/capability/data/IDataAccess.java b/src/main/java/gregtech/api/capability/data/IDataAccess.java index d236a5e8312..e9cf3e0e48a 100644 --- a/src/main/java/gregtech/api/capability/data/IDataAccess.java +++ b/src/main/java/gregtech/api/capability/data/IDataAccess.java @@ -9,8 +9,9 @@ public interface IDataAccess { /** * Queries this {@link IDataAccess} with the specified query. + * * @param queryObject the object representing the query. Can be cached in a weak set created by - * {@link gregtech.api.util.GTUtility#createWeakHashSet()} in order to prevent endless recursion. + * {@link gregtech.api.util.GTUtility#createWeakHashSet()} in order to prevent endless recursion. * @return if the query has been cancelled */ boolean accessData(@NotNull DataQueryObject queryObject); @@ -30,8 +31,9 @@ default boolean supportsQuery(@NotNull DataQueryObject queryObject) { /** * Provides standardized logic for querying a collection of {@link IDataAccess}es. + * * @param accesses the {@link IDataAccess}es to query. - * @param query the object representing the query. + * @param query the object representing the query. * @return if the query has been cancelled */ static boolean accessDatas(@NotNull Iterable accesses, diff --git a/src/main/java/gregtech/api/capability/data/IHatchDataAccess.java b/src/main/java/gregtech/api/capability/data/IHatchDataAccess.java index 5c0332a9c45..f0f8b8f4de5 100644 --- a/src/main/java/gregtech/api/capability/data/IHatchDataAccess.java +++ b/src/main/java/gregtech/api/capability/data/IHatchDataAccess.java @@ -1,7 +1,5 @@ package gregtech.api.capability.data; -import gregtech.api.capability.data.IDataAccess; - public interface IHatchDataAccess extends IDataAccess { /** diff --git a/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java b/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java index 61f0a0736c9..0d550c9fd03 100644 --- a/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java +++ b/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java @@ -38,5 +38,4 @@ public boolean supportsFormat(DataQueryFormat format) { if (supportedFormats == null) return true; else return supportedFormats.contains(format); } - } diff --git a/src/main/java/gregtech/api/capability/data/query/IComputationQuery.java b/src/main/java/gregtech/api/capability/data/query/IComputationQuery.java index ec80e2db9dd..492cfc3218a 100644 --- a/src/main/java/gregtech/api/capability/data/query/IComputationQuery.java +++ b/src/main/java/gregtech/api/capability/data/query/IComputationQuery.java @@ -2,7 +2,7 @@ import gregtech.api.capability.data.IComputationProvider; -public interface IComputationQuery extends IBridgeable{ +public interface IComputationQuery extends IBridgeable { void registerProvider(IComputationProvider provider); } diff --git a/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java index ea84f98c663..8c878b4eea8 100644 --- a/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java @@ -29,7 +29,8 @@ public class ComputationRecipeLogic extends MultiblockRecipeLogic { private boolean hasNotEnoughComputation; private int currentDrawnCWUt; - public ComputationRecipeLogic(T metaTileEntity, ComputationType type) { + public ComputationRecipeLogic(T metaTileEntity, + ComputationType type) { super(metaTileEntity); this.type = type; } diff --git a/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java b/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java index 6142d18ad82..8604f6a0902 100644 --- a/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java +++ b/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java @@ -1,7 +1,6 @@ package gregtech.api.capability.impl; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.capability.IEnergyContainer; import gregtech.api.capability.ILaserContainer; import gregtech.api.capability.ILaserRelay; import gregtech.api.metatileentity.MetaTileEntity; diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index f5c168de6d2..430726823f3 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -7,21 +7,16 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.INetGraph; - import gregtech.api.graphnet.graph.GraphVertex; - +import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.path.INetPath; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import net.minecraft.nbt.NBTTagCompound; + import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; - import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import net.minecraft.nbt.NBTTagCompound; - import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -121,14 +116,18 @@ public void removeEdge(GraphEdge edge) { * most likely a bad remapper was passed in.
* This method should never be exposed outside the net this backer is backing due to this fragility. */ - public > Iterator getPaths(@Nullable NetNode node, int algorithmID, @NotNull NetPathMapper remapper, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + public > Iterator getPaths(@Nullable NetNode node, int algorithmID, + @NotNull NetPathMapper remapper, + IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, long queryTick) { if (node == null) return Collections.emptyIterator(); Iterator> cache = node.getPathCache(); if (cache != null) return (Iterator) cache; this.getGraph().setupInternal(this, backedNet.usesDynamicWeights(algorithmID)); - Iterator iter = this.netAlgorithms[algorithmID].getPathsIterator(node.wrapper, remapper, testObject, simulator, queryTick); + Iterator iter = this.netAlgorithms[algorithmID].getPathsIterator(node.wrapper, remapper, testObject, + simulator, queryTick); if (iter instanceof ICacheableIterator) { return (Iterator) node.setPathCache((ICacheableIterator) iter); } else return iter; @@ -150,20 +149,26 @@ public INetGraph getGraph() { // PROPOSAL FOR ALTERNATIVE STORAGE MECHANISM TO REDUCE MEMORY COSTS // > Always loaded & nbt stored data: - // map & weak map of group ids to groups. No references to group objects exist outside of this, only references to grou ids. + // map & weak map of group ids to groups. No references to group objects exist outside of this, only references to + // grou ids. // (for pipenet) pipes store a reference to their group id // > Disk-stored data: // contents of groups, specifically their nodes and edges. // > Impl (for pipenet) - // When a pipe is loaded, it goes fetch its group and tells it the pipe's chunk. This chunk is added to a *set* of chunks that are 'loading' this group. + // When a pipe is loaded, it goes fetch its group and tells it the pipe's chunk. This chunk is added to a *set* of + // chunks that are 'loading' this group. // When a chunk is unloaded, it is removed from the set of 'loading' chunks for all groups. - // When the set of 'loading' chunks for a group is empty, the group writes its data to disk and removes itself from the map and the graph but not the weak map. - // (proposal - create a graph impl that allows for weak references to vertices and edges, in order to remove need for explicit removal of group from graph?) + // When the set of 'loading' chunks for a group is empty, the group writes its data to disk and removes itself from + // the map and the graph but not the weak map. + // (proposal - create a graph impl that allows for weak references to vertices and edges, in order to remove need + // for explicit removal of group from graph?) // When a pipe fetches its group, if the group is not found in the map, it then checks the weak map. - // If found in the weak map, the pipe's chunk is added to the 'loading' chunks and a reference to the group is added to the map and the contents are added to the graph. + // If found in the weak map, the pipe's chunk is added to the 'loading' chunks and a reference to the group is added + // to the map and the contents are added to the graph. // If not found in the weak map, the group is instead read from disk and initialized. // > Benefits of this Impl - // By only loading the (potentially) large number of edges and nodes into the graph that a group contains when that group is needed, + // By only loading the (potentially) large number of edges and nodes into the graph that a group contains when that + // group is needed, // the number of unnecessary references in the graphnet on, say, a large server is drastically reduced. // however, since there are necessarily more read/write actions to disk, the cpu load would increase in turn. @@ -197,7 +202,8 @@ public void readFromNBT(NBTTagCompound nbt) { int edgeCount = edges.getInteger("Count"); for (int i = 0; i < edgeCount; i++) { NBTTagCompound tag = edges.getCompoundTag(String.valueOf(i)); - GraphEdge graphEdge = this.getGraph().addEdge(vertexMap.get(tag.getInteger("SourceID")), vertexMap.get(tag.getInteger("TargetID"))); + GraphEdge graphEdge = this.getGraph().addEdge(vertexMap.get(tag.getInteger("SourceID")), + vertexMap.get(tag.getInteger("TargetID"))); this.getGraph().setEdgeWeight(graphEdge, tag.getDouble("Weight")); graphEdge.wrapped.deserializeNBT(tag); } diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index 19369050244..11de718d620 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -2,12 +2,9 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.INetGraph; - import gregtech.api.graphnet.graph.GraphVertex; - +import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.logic.NetLogicData; - import gregtech.api.graphnet.logic.WeightFactorLogic; import org.jetbrains.annotations.ApiStatus; @@ -17,7 +14,6 @@ import org.jgrapht.traverse.BreadthFirstIterator; import java.util.Iterator; -import java.util.Set; public interface IGraphNet { @@ -31,12 +27,14 @@ default boolean usesDynamicWeights(int algorithmID) { /** * Adds a node to the graphnet. + * * @param node The node to add. */ void addNode(@NotNull NetNode node); /** * Gets the net node with the given equivalency data, if one exists. + * * @param equivalencyData the equivalency data to match. * @return the matching net node, if one exists. */ @@ -45,14 +43,16 @@ default boolean usesDynamicWeights(int algorithmID) { /** * Removes a node from the graphnet. + * * @param node The node to remove. */ void removeNode(@NotNull NetNode node); /** * Links two nodes by an edge. - * @param source Source node. - * @param target Target node. + * + * @param source Source node. + * @param target Target node. * @param bothWays If the graph is directional, passing in true will create both the forwards and backwards edge. * @return the created edge, if it was created. Returns null if bothWays is set to true. */ @@ -62,6 +62,7 @@ default boolean usesDynamicWeights(int algorithmID) { /** * Returns the edge linking two nodes together, if one exists. + * * @param source Source node. * @param target Target node. * @return the linking edge, if one exists. @@ -71,14 +72,16 @@ default boolean usesDynamicWeights(int algorithmID) { /** * Removes the edge linking two nodes together, if one exists. - * @param source Source node. - * @param target Target node. + * + * @param source Source node. + * @param target Target node. * @param bothWays If the graph is directional, passing in true will remove both the forwards and backwards edge. */ void removeEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays); /** * Gets the net graph backing this graphnet. This should NEVER be modified directly, but can be queried. + * * @return the backing net graph */ @ApiStatus.Internal @@ -88,6 +91,7 @@ default INetGraph getGraph() { /** * Gets the GraphNetBacker backing this graphnet. This should NEVER be used except inside the graphnet impl. + * * @return the backing graphnet backer */ @ApiStatus.Internal @@ -106,6 +110,7 @@ default AbstractGroupData getBlankGroupData() { /** * Get a default node data for this graph. Generally used for immediate nbt deserialization. + * * @return A default node data object. */ @NotNull @@ -115,6 +120,7 @@ default NetLogicData getDefaultNodeData() { /** * Returns whether a node exists in this graph. + * * @param node the node in question. * @return whether the node exists. */ @@ -124,6 +130,7 @@ default boolean containsNode(NetNode node) { /** * Returns a breadth-first iterator through this graph, starting from the passed in node. + * * @param node the node to start from. * @return a breadth-first iterator through this graph. */ @@ -131,7 +138,8 @@ default boolean containsNode(NetNode node) { default Iterator breadthIterator(NetNode node) { return new Iterator<>() { - private final BreadthFirstIterator iterator = new BreadthFirstIterator<>(getGraph(), node.wrapper); + private final BreadthFirstIterator iterator = new BreadthFirstIterator<>(getGraph(), + node.wrapper); @Override public boolean hasNext() { @@ -148,6 +156,7 @@ public NetNode next() { /** * Used in {@link MultiNodeHelper} to determine if a node can be traversed, based on the nets that have been * recently traversed in the {@link MultiNodeHelper}. + * * @param net a recently traversed net * @return if node traversal should be blocked. */ @@ -163,7 +172,8 @@ default boolean clashesWith(IGraphNet net) { /** * While this is crude, it does allow for avoiding generics literally everywhere. * The systems that make up a graphnet intertwine such that generics would be needed in basically every class. - * Basically, instead of a bunch of generics everywhere, we just instate an honor system that crashes the game if you violate it. + * Basically, instead of a bunch of generics everywhere, we just instate an honor system that crashes the game if + * you violate it. */ default void nodeClassCheck(NetNode node) { if (!(getNodeClass().isInstance(node))) diff --git a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java index 74c7783b7d8..5ca7558bec1 100644 --- a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java +++ b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java @@ -12,8 +12,11 @@ /** * MultiNodeHelpers are utility objects used to preserve sync between multiple nodes owned by different graphs. They do - * this by
A) keeping a record of traversals to allow for blocking traversal when another net has been traversed - * recently and
B) make sure that logic entries requiring it are the same object across all synced nodes.

+ * this by
+ * A) keeping a record of traversals to allow for blocking traversal when another net has been traversed + * recently and
+ * B) make sure that logic entries requiring it are the same object across all synced nodes.
+ *
* MultiNodeHelpers have no standard implementation and must be handled by a net and its nodes; see * {@link gregtech.api.graphnet.pipenet.WorldPipeNet} and {@link gregtech.api.graphnet.pipenet.WorldPipeNetNode} * for an example of this in action. diff --git a/src/main/java/gregtech/api/graphnet/NetGroup.java b/src/main/java/gregtech/api/graphnet/NetGroup.java index 33069397dda..19268f21b1a 100644 --- a/src/main/java/gregtech/api/graphnet/NetGroup.java +++ b/src/main/java/gregtech/api/graphnet/NetGroup.java @@ -103,7 +103,8 @@ public void splitNode(NetNode source) { this.clearPathCaches(); List targets = this.net.getGraph().outgoingEdgesOf(source.wrapper).stream().map(a -> { // handling so undirected graphs don't throw an error - if (net.getGraph().isDirected() || Objects.equals(getTarget(a).wrapped, source)) return getTarget(a).wrapped; + if (net.getGraph().isDirected() || Objects.equals(getTarget(a).wrapped, source)) + return getTarget(a).wrapped; return getSource(a).wrapped; }).collect(Collectors.toList()); this.net.getBacker().removeVertex(source.wrapper); diff --git a/src/main/java/gregtech/api/graphnet/NetNode.java b/src/main/java/gregtech/api/graphnet/NetNode.java index 0eb9f71011d..60f1dd115f9 100644 --- a/src/main/java/gregtech/api/graphnet/NetNode.java +++ b/src/main/java/gregtech/api/graphnet/NetNode.java @@ -1,11 +1,8 @@ package gregtech.api.graphnet; import gregtech.api.graphnet.alg.iter.ICacheableIterator; - import gregtech.api.graphnet.graph.GraphVertex; - import gregtech.api.graphnet.logic.NetLogicData; - import gregtech.api.graphnet.path.INetPath; import net.minecraft.nbt.NBTTagCompound; @@ -134,6 +131,7 @@ public void deserializeNBT(NBTTagCompound nbt) { /** * Used to determine if two nodes are equal, for graph purposes. * Should not change over the lifetime of a node, except when {@link #deserializeNBT(NBTTagCompound)} is called. + * * @return equivalency data. Needs to work with {@link Objects#equals(Object, Object)} */ public abstract Object getEquivalencyData(); diff --git a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java index 71469004238..a054c9fc336 100644 --- a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java @@ -1,11 +1,11 @@ package gregtech.api.graphnet.alg; import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.path.INetPath; import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.alg.iter.ICacheableIterator; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.alg.iter.ICacheableIterator; +import gregtech.api.graphnet.path.INetPath; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.alg.shortestpath.DefaultManyToManyShortestPaths; @@ -19,7 +19,7 @@ import java.util.stream.Collectors; public class DynamicWeightsShortestPathsAlgorithm extends DefaultManyToManyShortestPaths - implements INetAlgorithm { + implements INetAlgorithm { public DynamicWeightsShortestPathsAlgorithm(IGraphNet net) { super(net.getGraph()); diff --git a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java index 252c1ffabc3..14219738f00 100644 --- a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java @@ -1,12 +1,11 @@ package gregtech.api.graphnet.alg; -import gregtech.api.graphnet.path.INetPath; import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.path.INetPath; import java.util.Iterator; public interface INetAlgorithm { > Iterator getPathsIterator(GraphVertex source, NetPathMapper remapper); - } diff --git a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java index fd7a7c08420..710ad6576d2 100644 --- a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java +++ b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java @@ -2,9 +2,8 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.path.INetPath; import gregtech.api.graphnet.graph.GraphVertex; - +import gregtech.api.graphnet.path.INetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import org.jetbrains.annotations.NotNull; @@ -34,7 +33,11 @@ public void invalidate() { this.alg = null; } - public > Iterator getPathsIterator(GraphVertex source, NetPathMapper remapper, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + public > Iterator getPathsIterator(GraphVertex source, + NetPathMapper remapper, + IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, + long queryTick) { net.getGraph().prepareForAlgorithmRun(testObject, simulator, queryTick); if (alg == null) alg = builder.apply(net); return alg.getPathsIterator(source, remapper); diff --git a/src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java b/src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java index 4ba08a12257..816a40232ad 100644 --- a/src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java +++ b/src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java @@ -1,8 +1,8 @@ package gregtech.api.graphnet.alg; -import gregtech.api.graphnet.path.INetPath; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.path.INetPath; import gregtech.api.util.function.TriFunction; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java index 094df3d08c3..42e285fdf37 100644 --- a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java @@ -1,11 +1,11 @@ package gregtech.api.graphnet.alg; import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.path.INetPath; import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.alg.iter.SimpleCacheableIterator; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.alg.iter.SimpleCacheableIterator; +import gregtech.api.graphnet.path.INetPath; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; @@ -16,7 +16,8 @@ import java.util.Set; import java.util.stream.Collectors; -public final class ShortestPathsAlgorithm extends CHManyToManyShortestPaths implements INetAlgorithm { +public final class ShortestPathsAlgorithm extends CHManyToManyShortestPaths + implements INetAlgorithm { public ShortestPathsAlgorithm(IGraphNet net) { super(net.getGraph()); diff --git a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java index c8c4c50af11..2513229e4bc 100644 --- a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java @@ -1,10 +1,10 @@ package gregtech.api.graphnet.alg; import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.alg.iter.SimpleCacheableIterator; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.alg.iter.SimpleCacheableIterator; +import gregtech.api.graphnet.path.INetPath; import com.google.common.collect.ImmutableList; import it.unimi.dsi.fastutil.objects.ObjectArrayList; diff --git a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java index 233786c5f6b..188f346efb4 100644 --- a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java @@ -22,7 +22,8 @@ public AbstractNetFlowEdge() { } @Override - public double getDynamicWeight(IPredicateTestObject channel, IGraphNet net, @Nullable SimulatorKey simulator, long queryTick, + public double getDynamicWeight(IPredicateTestObject channel, IGraphNet net, @Nullable SimulatorKey simulator, + long queryTick, double defaultWeight) { long flow = getFlowLimit(channel, net, queryTick, simulator); if (flow <= 0) { @@ -30,7 +31,8 @@ public double getDynamicWeight(IPredicateTestObject channel, IGraphNet net, @Nul } else return defaultWeight * getThroughput() / flow; } - public boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick, @Nullable SimulatorKey simulator) { + public boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick, + @Nullable SimulatorKey simulator) { if (!this.test(channel)) return false; else return getChannels(simulator).cannotSupportChannel(channel, queryTick); } @@ -55,7 +57,8 @@ protected long getThroughput() { return getData().getLogicEntryDefaultable(ThroughputLogic.INSTANCE).getValue(); } - public long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick, @Nullable SimulatorKey simulator) { + public long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick, + @Nullable SimulatorKey simulator) { if (!this.test(channel)) return 0; else return getChannels(simulator).getFlowLimit(channel, graph, queryTick); } @@ -65,7 +68,8 @@ protected long getConsumedLimit(IPredicateTestObject channel, long queryTick, @N else return getChannels(simulator).getConsumedLimit(channel, queryTick); } - public void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick, @Nullable SimulatorKey simulator) { + public void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick, + @Nullable SimulatorKey simulator) { if (this.test(channel)) { getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); } diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java index 84bd84b4e42..e8068f3b22b 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java @@ -1,7 +1,6 @@ package gregtech.api.graphnet.edge; import gregtech.api.graphnet.IGraphNet; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; @@ -31,9 +30,10 @@ public NetFlowEdge(int flowBufferTicks) { /** * NetEdge that provides standard flow behavior handling * - * @param flowBufferMult Determines maximum mult of 'buffer' flow capacity that can be built up along edges. Allows - * for once-an-interval push/pull operations instead of needing them every unit of time - * for maximum throughput. + * @param flowBufferMult Determines maximum mult of 'buffer' flow capacity that can be built up along edges. + * Allows + * for once-an-interval push/pull operations instead of needing them every unit of time + * for maximum throughput. * @param regenerationTime Ticks required for flow to regenerate once. Allows slowing down the rate of regeneration. */ public NetFlowEdge(int flowBufferMult, int regenerationTime) { diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java index 26fea9c1ea0..0d05db60155 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java @@ -1,7 +1,6 @@ package gregtech.api.graphnet.edge; import gregtech.api.graphnet.IGraphNet; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.util.math.MathHelper; diff --git a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java index 7d4b5d7a8dd..61e724c7fa7 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java +++ b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java @@ -3,19 +3,17 @@ import gregtech.api.GTValues; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.MultiNetCountLogic; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.predicate.ShutterPredicate; +import gregtech.api.graphnet.predicate.IEdgePredicate; import gregtech.common.pipelike.block.cable.CableStructure; import gregtech.common.pipelike.block.laser.LaserStructure; import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.block.pipe.PipeStructure; import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; -import gregtech.api.graphnet.logic.MultiNetCountLogic; -import gregtech.api.graphnet.logic.ThroughputLogic; -import gregtech.api.graphnet.logic.WeightFactorLogic; - -import gregtech.api.graphnet.predicate.IEdgePredicate; - import gregtech.common.pipelike.net.energy.SuperconductorLogic; import gregtech.common.pipelike.net.energy.VoltageLimitLogic; diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java index d54042b0327..dbabb7ae179 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java +++ b/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java @@ -2,10 +2,10 @@ import gregtech.api.graphnet.logic.INetLogicEntry; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraftforge.fml.common.eventhandler.Event; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import java.util.Map; import java.util.function.Supplier; diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java index 94dddb838b6..867da71bac5 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java +++ b/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java @@ -2,10 +2,10 @@ import gregtech.api.graphnet.predicate.IEdgePredicate; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraftforge.fml.common.eventhandler.Event; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import java.util.Map; import java.util.function.Supplier; diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java index b6b1b9eca8a..ba3e1eb5297 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java +++ b/src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java @@ -1,13 +1,11 @@ package gregtech.api.graphnet.gather; -import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; - import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraftforge.fml.common.eventhandler.Event; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + import java.util.Set; public class GatherStructuresEvent extends Event { diff --git a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java index 61636af23ec..626494eb0b3 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java @@ -49,7 +49,8 @@ public double getEdgeWeight(GraphEdge graphEdge) { if (graphEdge.wrapped.test(testObject)) { if (dynamicWeights) { - return graphEdge.wrapped.getDynamicWeight(testObject, net, simulator, queryTick, super.getEdgeWeight(graphEdge)); + return graphEdge.wrapped.getDynamicWeight(testObject, net, simulator, queryTick, + super.getEdgeWeight(graphEdge)); } else return super.getEdgeWeight(graphEdge); } else return Double.POSITIVE_INFINITY; } diff --git a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java index ad7a3daacea..41754af6b3b 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java @@ -49,7 +49,8 @@ public double getEdgeWeight(GraphEdge graphEdge) { if (graphEdge.wrapped.test(testObject)) { if (dynamicWeights) { - return graphEdge.wrapped.getDynamicWeight(testObject, net, simulator, queryTick, super.getEdgeWeight(graphEdge)); + return graphEdge.wrapped.getDynamicWeight(testObject, net, simulator, queryTick, + super.getEdgeWeight(graphEdge)); } else return super.getEdgeWeight(graphEdge); } else return Double.POSITIVE_INFINITY; } diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java index d285ac1d39a..a0965ab4523 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java @@ -3,7 +3,8 @@ import net.minecraft.nbt.NBTTagDouble; import net.minecraft.network.PacketBuffer; -public abstract class AbstractDoubleLogicData> implements INetLogicEntry { +public abstract class AbstractDoubleLogicData> + implements INetLogicEntry { private double value; diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java index bd4cc825d29..108862b603b 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java @@ -1,12 +1,12 @@ package gregtech.api.graphnet.logic; import net.minecraft.nbt.NBTTagLong; - import net.minecraft.network.PacketBuffer; import org.jetbrains.annotations.Contract; -public abstract class AbstractLongLogicData> implements INetLogicEntry { +public abstract class AbstractLongLogicData> + implements INetLogicEntry { private long value; diff --git a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java index d3d99e7a26f..f95edba34c7 100644 --- a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java +++ b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java @@ -3,7 +3,6 @@ import gregtech.api.graphnet.MultiNodeHelper; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; - import gregtech.api.network.IPacket; import net.minecraft.nbt.NBTBase; @@ -14,11 +13,12 @@ import org.jetbrains.annotations.Nullable; /** - * Note - all implementers of this interface are suggested to be final, in order to avoid unexpected {@link #union(INetLogicEntry)} behavior. + * Note - all implementers of this interface are suggested to be final, in order to avoid unexpected + * {@link #union(INetLogicEntry)} behavior. */ public interface INetLogicEntry, N extends NBTBase> extends INBTSerializable, - IStringSerializable, - IPacket { + IStringSerializable, + IPacket { default void deserializeNBTNaive(NBTBase nbt) { deserializeNBT((N) nbt); @@ -39,6 +39,7 @@ default T union(INetLogicEntry other) { * all nodes registered to it contain the same object that their entries have been merged to, and when a node * leaves the multi node helper {@link #unmerge(NetNode)} will be called for it. Server-Client sync is handled * by the MultiNodeHelper, do not sync through NetLogicData. See {@link #registerToMultiNodeHelper(MultiNodeHelper)} + * * @return whether logic entry should be merged to a MultiNodeHelper. */ default boolean mergedToMultiNodeHelper() { @@ -53,8 +54,9 @@ default void registerToMultiNodeHelper(MultiNodeHelper helper) {} /** * Should be used exclusively for {@link gregtech.api.graphnet.MultiNodeHelper} logic. + * * @param otherOwner the net node being merged in - * @param other the logic being merged in + * @param other the logic being merged in */ default void merge(NetNode otherOwner, INetLogicEntry other) {} @@ -64,6 +66,7 @@ default void merge(NetNode otherOwner, INetLogicEntry other) {} * if your logic needs to keep track then populate a map during {@link #merge(NetNode, INetLogicEntry)}. * Keep in mind that this can be called for the data's original owner, despite * {@link #merge(NetNode, INetLogicEntry)} not being called for the original owner. + * * @param entryOwner the node being unmerged. */ default void unmerge(NetNode entryOwner) {} diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index 318857dafae..d5ca8c4c2c3 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -1,30 +1,26 @@ package gregtech.api.graphnet.logic; import gregtech.api.graphnet.gather.GTGraphGatherables; - import gregtech.api.graphnet.gather.GatherLogicsEvent; -import gregtech.api.graphnet.gather.GatherPredicatesEvent; import gregtech.api.network.IPacket; import gregtech.api.util.function.TriConsumer; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import it.unimi.dsi.fastutil.objects.ObjectCollection; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.network.PacketBuffer; import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectCollection; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.IOException; import java.util.Set; import java.util.function.Supplier; + /** * Note - since the internal map representation encodes keys using {@link IStringSerializable#getName()} on logics, * making a logics class return two different names is a valid way to register multiple instances.
@@ -37,7 +33,7 @@ public final class NetLogicData implements INBTSerializable, IPacket private final Object2ObjectOpenHashMap> logicEntrySet; private final Set listeners = new ObjectOpenHashSet<>(); - + public NetLogicData() { logicEntrySet = new Object2ObjectOpenHashMap<>(4); } @@ -120,8 +116,8 @@ public void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChan @Contract("_, _ -> new") public static @NotNull NetLogicData union(@NotNull NetLogicData sourceData, @Nullable NetLogicData targetData) { - Object2ObjectOpenHashMap> newLogic = - new Object2ObjectOpenHashMap<>(sourceData.logicEntrySet); + Object2ObjectOpenHashMap> newLogic = new Object2ObjectOpenHashMap<>( + sourceData.logicEntrySet); if (targetData != null) { for (String key : newLogic.keySet()) { newLogic.computeIfPresent(key, (k, v) -> v.union(targetData.logicEntrySet.get(k))); @@ -133,8 +129,8 @@ public void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChan @Contract("_, _ -> new") public static @NotNull NetLogicData union(@NotNull NetLogicData first, @NotNull NetLogicData... others) { - Object2ObjectOpenHashMap> newLogic = - new Object2ObjectOpenHashMap<>(first.logicEntrySet); + Object2ObjectOpenHashMap> newLogic = new Object2ObjectOpenHashMap<>( + first.logicEntrySet); for (NetLogicData other : others) { for (String key : newLogic.keySet()) { newLogic.computeIfPresent(key, (k, v) -> v.union(other.logicEntrySet.get(k))); @@ -204,6 +200,7 @@ public void decode(PacketBuffer buf) { } public final class LogicDataListener { + private final TriConsumer, Boolean, Boolean> listener; public LogicDataListener(TriConsumer, Boolean, Boolean> listener) { diff --git a/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java index 29992672985..abe13884fd4 100644 --- a/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java @@ -23,6 +23,5 @@ public WeightFactorLogic union(INetLogicEntry other) { if (other instanceof WeightFactorLogic l) { return getWith(this.getValue() + l.getValue()); } else return this; - } } diff --git a/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java b/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java index 94057a7d8db..c2fd92c10a5 100644 --- a/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java @@ -6,7 +6,6 @@ import org.jetbrains.annotations.Nullable; -import java.util.Iterator; import java.util.List; public abstract class AbstractNetPath implements INetPath { diff --git a/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java b/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java index 247937ab70c..86ffe4000ea 100644 --- a/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java @@ -6,9 +6,7 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; - import gregtech.api.graphnet.logic.WeightFactorLogic; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import org.jetbrains.annotations.Nullable; @@ -21,8 +19,8 @@ public class GenericGraphNetPath extends AbstractNetPath { - public static final NetPathMapper MAPPER = - new NetPathMapper<>(GenericGraphNetPath::new, GenericGraphNetPath::new, GenericGraphNetPath::new); + public static final NetPathMapper MAPPER = new NetPathMapper<>(GenericGraphNetPath::new, + GenericGraphNetPath::new, GenericGraphNetPath::new); public GenericGraphNetPath(GraphVertex vertex) { this(Collections.singletonList(vertex), Collections.emptyList(), @@ -38,7 +36,9 @@ public GenericGraphNetPath(GraphPath path) { this(path.getVertexList(), path.getEdgeList(), path.getWeight()); } - public interface Provider { - Iterator getPaths(NetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick); + public interface Provider { + + Iterator getPaths(NetNode node, IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, long queryTick); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java index aa6dbd42e15..833f0e65a7b 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java @@ -7,7 +7,6 @@ import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.path.AbstractNetPath; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import org.jetbrains.annotations.Nullable; @@ -20,8 +19,8 @@ public class BasicWorldPipeNetPath extends AbstractNetPath { - public static final NetPathMapper MAPPER = - new NetPathMapper<>(BasicWorldPipeNetPath::new, BasicWorldPipeNetPath::new, BasicWorldPipeNetPath::new); + public static final NetPathMapper MAPPER = new NetPathMapper<>(BasicWorldPipeNetPath::new, + BasicWorldPipeNetPath::new, BasicWorldPipeNetPath::new); public BasicWorldPipeNetPath(GraphVertex vertex) { this(Collections.singletonList(vertex), Collections.emptyList(), @@ -38,6 +37,8 @@ public BasicWorldPipeNetPath(GraphPath path) { } public interface Provider { - Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick); + + Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, long queryTick); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java index 629d9ef5b2f..c583e24be02 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java @@ -7,7 +7,6 @@ import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.path.AbstractNetPath; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import org.jetbrains.annotations.Nullable; @@ -20,8 +19,8 @@ public class FlowWorldPipeNetPath extends AbstractNetPath { - public static final NetPathMapper MAPPER = - new NetPathMapper<>(FlowWorldPipeNetPath::new, FlowWorldPipeNetPath::new, FlowWorldPipeNetPath::new); + public static final NetPathMapper MAPPER = new NetPathMapper<>(FlowWorldPipeNetPath::new, + FlowWorldPipeNetPath::new, FlowWorldPipeNetPath::new); public FlowWorldPipeNetPath(GraphVertex vertex) { this(Collections.singletonList(vertex), Collections.emptyList(), @@ -38,6 +37,8 @@ public FlowWorldPipeNetPath(GraphPath path) { } public interface Provider { - Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick); + + Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, long queryTick); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java index c4aa9f505d5..de46f72e5d8 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java @@ -1,15 +1,14 @@ package gregtech.api.graphnet.pipenet; -import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import java.util.Collection; -import java.util.Map; public interface IPipeNetNodeHandler { + void addToNets(World world, BlockPos pos, IPipeStructure structure); Collection getFromNets(World world, BlockPos pos, IPipeStructure structure); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java index 200e9f623c0..7d5dd25b583 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java @@ -1,17 +1,15 @@ package gregtech.api.graphnet.pipenet; -import com.github.bsideup.jabel.Desugar; - import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.ITraverseData; import gregtech.api.util.TaskScheduler; import gregtech.api.util.function.Task; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.world.World; +import com.github.bsideup.jabel.Desugar; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.Nullable; import java.util.Map; @@ -41,7 +39,6 @@ public static void registerLossResult(Key key, NodeLossResult result) { private final Map cache = new Object2ObjectOpenHashMap<>(); - private NodeLossCache(World world) { TaskScheduler.scheduleTask(world, TaskScheduler.weakTask(this)); } @@ -54,7 +51,6 @@ public void registerResult(Key key, NodeLossResult result) { return cache.get(key); } - @Override public boolean run() { if (cache.isEmpty()) return true; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java index 6f1849ace68..e5a6b18099b 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java @@ -16,7 +16,8 @@ public final class NodeLossResult { private final @Nullable Consumer postAction; private final @NotNull ReversibleLossOperator lossFunction; - public NodeLossResult(@Nullable Consumer postAction, @NotNull ReversibleLossOperator lossFunction) { + public NodeLossResult(@Nullable Consumer postAction, + @NotNull ReversibleLossOperator lossFunction) { this.postAction = postAction; this.lossFunction = lossFunction; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 436e858b8e8..a32605e5905 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -11,22 +11,17 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.pipenet.predicate.ShutterPredicate; import gregtech.api.graphnet.worldnet.WorldNet; - import gregtech.api.util.IDirtyNotifiable; import gregtech.common.covers.CoverShutter; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; - import net.minecraft.world.World; - import net.minecraftforge.common.capabilities.Capability; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -66,6 +61,7 @@ public WorldPipeNet(String name, boolean directed, Functionnot be called twice, so special handling for directedness is needed. - * @param source the source of the edge. + * + * @param source the source of the edge. * @param coverSource the cover on the source facing the target. - * @param target the target of the edge. + * @param target the target of the edge. * @param coverTarget the cover on the target facing the source. */ public void predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode source, @Nullable Cover coverSource, diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java index bca18bf5ce9..9588e4ad39e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java @@ -6,7 +6,6 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; - import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; @@ -71,8 +70,7 @@ public WorldPipeNetNode setPos(BlockPos pos) { public boolean traverse(long queryTick, boolean simulate) { if (overlapHelper != null) { return overlapHelper.traverse(this.getNet(), queryTick, simulate); - } - else return true; + } else return true; } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java index 69a0e85039b..1652dbbe765 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java @@ -2,17 +2,14 @@ import gregtech.api.cover.Cover; import gregtech.api.graphnet.logic.INetLogicEntry; - import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.util.DimensionFacingPos; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; - import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; - import net.minecraft.world.World; import net.minecraftforge.common.DimensionManager; @@ -23,6 +20,7 @@ import java.lang.ref.WeakReference; public class EdgeCoverReferenceLogic implements INetLogicEntry { + public static final EdgeCoverReferenceLogic INSTANCE = new EdgeCoverReferenceLogic(); @Nullable @@ -60,7 +58,8 @@ public EdgeCoverReferenceLogic coverTarget(@NotNull DimensionFacingPos pos, @Not this.coverSource = new WeakReference<>(cover); return cover; } else { - // the cover doesn't exist, which makes no sense since we have a reference to its location but whatever + // the cover doesn't exist, which makes no sense since we have a reference to its location but + // whatever this.coverSource = null; return null; } @@ -88,7 +87,8 @@ public EdgeCoverReferenceLogic coverTarget(@NotNull DimensionFacingPos pos, @Not this.coverTarget = new WeakReference<>(cover); return cover; } else { - // the cover doesn't exist, which makes no sense since we have a reference to its location but whatever + // the cover doesn't exist, which makes no sense since we have a reference to its location but + // whatever this.coverTarget = null; return null; } @@ -142,6 +142,7 @@ public void encode(PacketBuffer buf, boolean fullChange) {} public void decode(PacketBuffer buf, boolean fullChange) {} public interface IThroughputLimiterCover extends Cover { + long getLimit(); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java index af2bb13a83f..bd0fac3e198 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java @@ -5,12 +5,15 @@ * Demonstration Graph */ public enum EnumLossFunction { + // DO NOT REORDER FUNCTIONS, THE ORDER IS USED FOR NBT SERIALIZATION /** * x value is lost every tick. - *
A constant rate. + *
+ * A constant rate. */ ARITHMETIC { + @Override public float applyLoss(float value, float factorX, float factorY, int timePassed) { float initialThermalEnergy = value; @@ -21,9 +24,11 @@ public float applyLoss(float value, float factorX, float factorY, int timePassed }, /** * x% of value is lost every tick. - *
Faster than {@link EnumLossFunction#ARITHMETIC} at large values, but slower at small values. + *
+ * Faster than {@link EnumLossFunction#ARITHMETIC} at large values, but slower at small values. */ GEOMETRIC { + @Override public float applyLoss(float value, float factorX, float factorY, int timePassed) { value *= Math.pow(1 - (factorX / 100), timePassed); @@ -32,9 +37,11 @@ public float applyLoss(float value, float factorX, float factorY, int timePassed }, /** * value is raised to the power of 1 - x every tick. - *
Faster than {@link EnumLossFunction#GEOMETRIC} at large values, but incredibly slow at small values. + *
+ * Faster than {@link EnumLossFunction#GEOMETRIC} at large values, but incredibly slow at small values. */ POWER { + @Override public float applyLoss(float value, float factorX, float factorY, int timePassed) { value = (float) (Math.signum(value) * @@ -44,10 +51,12 @@ public float applyLoss(float value, float factorX, float factorY, int timePassed }, /** * x% of value is lost, then y more, every tick. - *
Slightly faster than {@link EnumLossFunction#GEOMETRIC} at large values, + *
+ * Slightly faster than {@link EnumLossFunction#GEOMETRIC} at large values, * slightly faster than {@link EnumLossFunction#ARITHMETIC} at small values. */ GEOMETRIC_ARITHMETIC { + @Override public float applyLoss(float value, float factorX, float factorY, int timePassed) { float initialThermalEnergy = value; @@ -63,10 +72,12 @@ public float applyLoss(float value, float factorX, float factorY, int timePassed }, /** * value is raised to the power of 1 - x, then y% more is lost, every tick. - *
Slightly faster than {@link EnumLossFunction#POWER} at large values, + *
+ * Slightly faster than {@link EnumLossFunction#POWER} at large values, * slightly faster than {@link EnumLossFunction#GEOMETRIC} at small values. */ POWER_GEOMETRIC { + @Override public float applyLoss(float value, float factorX, float factorY, int timePassed) { float c = 1 - factorX; @@ -79,6 +90,7 @@ public float applyLoss(float value, float factorX, float factorY, int timePassed * The evaluation of value = value - x * (value ^ y) is recursively found for every tick passed. */ WEAK_SCALING { + @Override public float applyLoss(float value, float factorX, float factorY, int timePassed) { for (int i = 0; i < timePassed; i++) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index faacf631b3f..adc11af9d07 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -6,30 +6,23 @@ import gregtech.api.graphnet.logic.INetLogicEntryListener; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.pipenet.NodeLossResult; - import gregtech.api.graphnet.pipenet.physical.IBurnable; - import gregtech.api.graphnet.pipenet.physical.IFreezable; import gregtech.api.graphnet.traverse.util.CompleteLossOperator; - import gregtech.api.graphnet.traverse.util.MultLossOperator; import net.minecraft.block.state.IBlockState; import net.minecraft.nbt.NBTTagCompound; - import net.minecraft.network.PacketBuffer; - import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; - import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; -import java.util.Objects; public final class TemperatureLogic implements INetLogicEntry { @@ -52,23 +45,31 @@ public final class TemperatureLogic implements INetLogicEntry, IPacket { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java index 51cf8739ddd..bf1b2df06c1 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IBurnable.java @@ -3,7 +3,6 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; public interface IBurnable { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IInsulatable.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IInsulatable.java index b0d0bd72954..21e2d660d37 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IInsulatable.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IInsulatable.java @@ -1,5 +1,6 @@ package gregtech.api.graphnet.pipenet.physical; public interface IInsulatable { + boolean isInsulated(); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java index 51f688ccf71..5cfa305a3da 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java @@ -1,12 +1,14 @@ package gregtech.api.graphnet.pipenet.physical; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; + import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import org.jetbrains.annotations.Nullable; public interface IPipeCapabilityObject { + void setTile(PipeTileEntity tile); Capability[] getCapabilities(); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java index b0847f3753e..f47fe5dfd11 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java @@ -1,7 +1,6 @@ package gregtech.api.graphnet.pipenet.physical; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; - import gregtech.client.renderer.pipe.AbstractPipeModel; import net.minecraft.util.EnumFacing; @@ -15,6 +14,7 @@ public interface IPipeStructure extends IStringSerializable { /** * Used as reference for misc things, e.g. rendering the backing of a cover. + * * @return render thickness */ float getRenderThickness(); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java index a602f07b846..095f8dae786 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java @@ -1,16 +1,12 @@ package gregtech.api.graphnet.pipenet.physical.block; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; - -import gregtech.api.unification.material.Material; import gregtech.common.items.MetaItems; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumDyeColor; import net.minecraft.item.ItemBlock; - import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; @@ -31,7 +27,8 @@ public ItemPipeBlock(WorldPipeBlock block) { } @Override - public boolean placeBlockAt(@NotNull ItemStack stack, @NotNull EntityPlayer player, @NotNull World world, @NotNull BlockPos pos, @NotNull EnumFacing side, + public boolean placeBlockAt(@NotNull ItemStack stack, @NotNull EntityPlayer player, @NotNull World world, + @NotNull BlockPos pos, @NotNull EnumFacing side, float hitX, float hitY, float hitZ, @NotNull IBlockState newState) { if (super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, newState)) { ItemStack offhand = player.getHeldItemOffhand(); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index 52190ce8753..445b22376fc 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -1,6 +1,5 @@ package gregtech.api.graphnet.pipenet.physical.block; -import gregtech.api.GTValues; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; @@ -9,41 +8,22 @@ import gregtech.api.unification.material.Materials; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.registry.MaterialRegistry; -import gregtech.api.unification.ore.OrePrefix; import gregtech.api.util.GTUtility; -import gregtech.common.blocks.MetaBlocks; -import gregtech.common.blocks.properties.PropertyMaterial; -import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.block.model.ModelBakery; -import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; - import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.NonNullList; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -import net.minecraftforge.client.model.ModelLoader; - -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; -import java.util.Objects; public abstract class PipeMaterialBlock extends WorldPipeBlock { @@ -98,8 +78,7 @@ public ItemStack getDrop(IBlockAccess world, BlockPos pos, IBlockState state) { lastTilePos = pos; lastTile = new WeakReference<>(pipe); return pipe; - } - else return null; + } else return null; } @Override @@ -111,7 +90,8 @@ public ItemStack getDrop(IBlockAccess world, BlockPos pos, IBlockState state) { protected Pair getParticleTexture(World world, BlockPos blockPos) { PipeMaterialTileEntity tile = getTileEntity(world, blockPos); if (tile != null) { - return ImmutablePair.of(getStructure().getModel().getParticleTexture(tile.getMaterial()), tile.getPaintingColor()); + return ImmutablePair.of(getStructure().getModel().getParticleTexture(tile.getMaterial()), + tile.getPaintingColor()); } return null; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java index 3bdb5576c9c..0a84f5f2122 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java @@ -1,10 +1,6 @@ package gregtech.api.graphnet.pipenet.physical.block; -import codechicken.lib.raytracer.RayTracer; - -import gregtech.api.GTValues; import gregtech.api.block.BuiltInRenderBlock; - import gregtech.api.cover.Cover; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.WorldPipeNet; @@ -18,13 +14,9 @@ import gregtech.api.util.EntityDamageUtil; import gregtech.api.util.GTUtility; import gregtech.common.ConfigHolder; - import gregtech.common.blocks.BlockFrame; - import gregtech.common.creativetab.GTCreativeTabs; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.block.Block; import net.minecraft.block.SoundType; import net.minecraft.block.state.IBlockState; @@ -38,7 +30,6 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.NonNullList; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -46,11 +37,11 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; - -import net.minecraft.world.WorldServer; import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fml.common.FMLCommonHandler; +import codechicken.lib.raytracer.RayTracer; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; @@ -253,7 +244,8 @@ public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World wor @SuppressWarnings("deprecation") @Nullable @Override - public RayTraceResult collisionRayTrace(@NotNull IBlockState blockState, @NotNull World worldIn, @NotNull BlockPos pos, + public RayTraceResult collisionRayTrace(@NotNull IBlockState blockState, @NotNull World worldIn, + @NotNull BlockPos pos, @NotNull Vec3d start, @NotNull Vec3d end) { return collisionRayTrace(worldIn.isRemote ? GTUtility.getSP() : null, blockState, worldIn, pos, start, end); } @@ -263,7 +255,8 @@ public RayTraceResult collisionRayTrace(@NotNull EntityPlayer player, @NotNull W } @SuppressWarnings("deprecation") - public RayTraceResult collisionRayTrace(@Nullable EntityPlayer player, @Nullable IBlockState blockState, @NotNull World worldIn, @NotNull BlockPos pos, + public RayTraceResult collisionRayTrace(@Nullable EntityPlayer player, @Nullable IBlockState blockState, + @NotNull World worldIn, @NotNull BlockPos pos, @NotNull Vec3d start, @NotNull Vec3d end) { if (blockState == null) blockState = worldIn.getBlockState(pos); if (hasPipeCollisionChangingItem(worldIn, pos, player)) { @@ -355,8 +348,7 @@ public PipeTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockP lastTilePos = pos; lastTile = new WeakReference<>(pipe); return pipe; - } - else return null; + } else return null; } @Override @@ -378,13 +370,15 @@ public void onNeighborChange(@NotNull IBlockAccess world, @NotNull BlockPos pos, @SuppressWarnings("deprecation") @Override - public void neighborChanged(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos, @NotNull Block blockIn, @NotNull BlockPos fromPos) { + public void neighborChanged(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos, + @NotNull Block blockIn, @NotNull BlockPos fromPos) { PipeTileEntity tile = getTileEntity(worldIn, pos); if (tile != null) tile.getCoverHolder().updateInputRedstoneSignals(); } @Override - public boolean shouldCheckWeakPower(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull EnumFacing side) { + public boolean shouldCheckWeakPower(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, + @NotNull EnumFacing side) { // The check in World::getRedstonePower in the vanilla code base is reversed. Setting this to false will // actually cause getWeakPower to be called, rather than prevent it. return false; @@ -392,13 +386,15 @@ public boolean shouldCheckWeakPower(@NotNull IBlockState state, @NotNull IBlockA @SuppressWarnings("deprecation") @Override - public int getWeakPower(@NotNull IBlockState blockState, @NotNull IBlockAccess blockAccess, @NotNull BlockPos pos, @NotNull EnumFacing side) { + public int getWeakPower(@NotNull IBlockState blockState, @NotNull IBlockAccess blockAccess, @NotNull BlockPos pos, + @NotNull EnumFacing side) { PipeTileEntity tile = getTileEntity(blockAccess, pos); return tile != null ? tile.getCoverHolder().getOutputRedstoneSignal(side) : 0; } @Override - public boolean canConnectRedstone(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, EnumFacing side) { + public boolean canConnectRedstone(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos, + EnumFacing side) { PipeTileEntity tile = getTileEntity(world, pos); return tile != null && tile.getCoverHolder().canConnectRedstone(side); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java index bd204ad187a..9305e345479 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java @@ -2,7 +2,6 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; - import gregtech.client.renderer.pipe.ActivablePipeModel; import net.minecraft.network.PacketBuffer; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java index 31b03be71fb..2d6e0cb03b0 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java @@ -3,8 +3,6 @@ import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; -import java.util.EnumSet; - public class PipeCapabilityWrapper { private byte activeMask; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java index 7a5dea00174..5704cc71bcb 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java @@ -15,7 +15,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; - import net.minecraftforge.common.util.INBTSerializable; import org.jetbrains.annotations.NotNull; @@ -79,7 +78,8 @@ public final void removeCover(@NotNull EnumFacing side) { writeCustomData(COVER_REMOVED_PIPE, buffer -> buffer.writeByte(side.getIndex())); if (cover.shouldAutoConnectToPipes()) { PipeTileEntity other; - if (holder.isConnected(side) && (other = holder.getPipeNeighbor(side, true)) != null && !other.isConnected(side.getOpposite())) + if (holder.isConnected(side) && (other = holder.getPipeNeighbor(side, true)) != null && + !other.isConnected(side.getOpposite())) holder.setDisconnected(side); } holder.notifyBlockUpdate(); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java index a33e5bf1d12..ca1c0d74db3 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java @@ -1,18 +1,13 @@ package gregtech.api.graphnet.pipenet.physical.tile; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; - -import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.util.GTUtility; - import gregtech.client.renderer.pipe.PipeModel; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; - import net.minecraftforge.common.property.IExtendedBlockState; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index aac8672dd6e..3720bccd04f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -14,11 +14,8 @@ import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.metatileentity.NeighborCacheTileEntityBase; - import gregtech.api.unification.material.Material; - import gregtech.client.particle.GTOverheatParticle; - import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.common.blocks.MetaBlocks; @@ -39,19 +36,16 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.world.WorldServer; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fml.common.FMLCommonHandler; - import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -80,7 +74,6 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick private byte blockedMask; private int paintingColor; - private @Nullable Material frameMaterial; private final Set tickers = new ObjectOpenHashSet<>(); @@ -126,7 +119,7 @@ public long getOffsetTimer() { } public void placedBy(ItemStack stack, EntityPlayer player) {} - + public IPipeStructure getStructure() { return getBlockType().getStructure(); } @@ -140,7 +133,7 @@ public boolean canConnectTo(EnumFacing facing) { public void setConnected(EnumFacing facing, boolean renderClosed) { this.connectionMask |= 1 << facing.ordinal(); updateActiveStatus(facing, false); - if (renderClosed) { + if (renderClosed) { this.renderMask |= 1 << facing.ordinal(); } else { this.renderMask &= ~(1 << facing.ordinal()); @@ -246,7 +239,7 @@ private void syncFrameMaterial() { public void addTicker(ITickable ticker) { this.tickers.add(ticker); - //noinspection ConstantValue + // noinspection ConstantValue if (getWorld() != null) getWorld().tickableTileEntities.add(this); } @@ -258,14 +251,16 @@ public void update() { @Override public void onLoad() { super.onLoad(); - // since we're an instance of ITickable, we're automatically added to the tickable list just before this exact moment. - // it would theoretically be a micro optimization to just pop the last tile from the tickable list, but that's not guaranteed. + // since we're an instance of ITickable, we're automatically added to the tickable list just before this exact + // moment. + // it would theoretically be a micro optimization to just pop the last tile from the tickable list, but that's + // not guaranteed. if (!this.isTicking()) this.getWorld().tickableTileEntities.remove(this); } public void removeTicker(ITickable ticker) { this.tickers.remove(ticker); - //noinspection ConstantValue + // noinspection ConstantValue if (!this.isTicking() && getWorld() != null) getWorld().tickableTileEntities.remove(this); } @@ -289,6 +284,7 @@ public void onNeighborChanged(@NotNull EnumFacing facing) { /** * Returns a map of facings to tile entities that should have at least one of the required capabilities. + * * @param node the node for this tile entity. Used to identify the capabilities to match. * @return a map of facings to tile entities. */ @@ -309,8 +305,10 @@ public EnumMap getTargetsWithCapabilities(WorldPipeNetNo /** * Updates the pipe's active status based on the tile entity connected to the side. - * @param facing the side to check. Can be null, in which case all sides will be checked. - * @param canOpenConnection whether the pipe is allowed to open a new connection if it finds a tile it can connect to. + * + * @param facing the side to check. Can be null, in which case all sides will be checked. + * @param canOpenConnection whether the pipe is allowed to open a new connection if it finds a tile it can connect + * to. */ public void updateActiveStatus(@Nullable EnumFacing facing, boolean canOpenConnection) { if (facing == null) { @@ -425,8 +423,8 @@ protected void initialize(World worldIn) { this.netCapabilities.put(node, new PipeCapabilityWrapper(node.getNet().getTargetCapabilities())); String netName = node.getNet().mapName; netLogicDatas.put(netName, node.getData()); - var listener = node.getData().new LogicDataListener((e, r, f) -> - writeCustomData(UPDATE_PIPE_LOGIC, buf -> { + var listener = node.getData().new LogicDataListener( + (e, r, f) -> writeCustomData(UPDATE_PIPE_LOGIC, buf -> { buf.writeString(netName); buf.writeString(e.getName()); buf.writeBoolean(r); @@ -467,7 +465,8 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { connectionMask = compound.getByte("ConnectionMask"); blockedMask = compound.getByte("BlockedMask"); paintingColor = compound.getInteger("Paint"); - if (compound.hasKey("Frame")) this.frameMaterial = GregTechAPI.materialManager.getMaterial(compound.getString("Frame")); + if (compound.hasKey("Frame")) + this.frameMaterial = GregTechAPI.materialManager.getMaterial(compound.getString("Frame")); else this.frameMaterial = null; this.getCoverHolder().deserializeNBT(compound.getCompoundTag("Covers")); } @@ -614,7 +613,6 @@ public void notifyBlockUpdate() { getWorld().notifyNeighborsOfStateChange(getPos(), getBlockType(), true); } - @SuppressWarnings("ConstantConditions") // yes this CAN actually be null @Override public void markDirty() { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/predicate/ShutterPredicate.java b/src/main/java/gregtech/api/graphnet/pipenet/predicate/ShutterPredicate.java index ba9ee9d08f3..3a4edda56b3 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/predicate/ShutterPredicate.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/predicate/ShutterPredicate.java @@ -1,8 +1,7 @@ package gregtech.api.graphnet.pipenet.predicate; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - import gregtech.api.graphnet.predicate.IEdgePredicate; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTTagString; diff --git a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java index 205317e6e38..39fe69850f3 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java +++ b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java @@ -1,18 +1,16 @@ package gregtech.api.graphnet.predicate; import gregtech.api.graphnet.gather.GTGraphGatherables; - import gregtech.api.graphnet.gather.GatherPredicatesEvent; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import java.util.Map; import java.util.function.Predicate; import java.util.function.Supplier; diff --git a/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java b/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java index eb86764f042..db611221f29 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java +++ b/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java @@ -9,18 +9,22 @@ import org.jetbrains.annotations.Nullable; /** - * Note - all implementers of this interface are suggested to be final, in order to avoid unexpected {@link #union(IEdgePredicate)} behavior. + * Note - all implementers of this interface are suggested to be final, in order to avoid unexpected + * {@link #union(IEdgePredicate)} behavior. */ -public interface IEdgePredicate, N extends NBTBase> extends INBTSerializable, IStringSerializable { +public interface IEdgePredicate, N extends NBTBase> + extends INBTSerializable, IStringSerializable { default void deserializeNBTNaive(NBTBase nbt) { deserializeNBT((N) nbt); } /** - * Whether this predicate should behave in "and" fashion with other predicates.

+ * Whether this predicate should behave in "and" fashion with other predicates.
+ *
* For example, if a predicate handler has 2 and-y predicates and 3 or-y predicates, - * the effective result of evaluation will be:
(andy1) && (andy2) && (ory1 || ory2 || ory3) + * the effective result of evaluation will be:
+ * (andy1) && (andy2) && (ory1 || ory2 || ory3) */ boolean andy(); diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java index 41767edd54f..f08ee1b4018 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java @@ -1,5 +1,6 @@ package gregtech.api.graphnet.predicate.test; public interface IPredicateTestObject { + IPredicateTestObject INSTANCE = new IPredicateTestObject() {}; } diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java index f56e2883af1..9f0bed3a897 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java @@ -4,8 +4,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import org.jetbrains.annotations.Range; - import java.util.Objects; public class ItemTestObject implements IPredicateTestObject { diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java index 1e2746b44e3..7880c75e928 100644 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java @@ -10,7 +10,6 @@ import gregtech.api.graphnet.graph.NetUndirectedGraph; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; - import gregtech.api.util.DimensionPos; import net.minecraft.nbt.NBTTagCompound; @@ -38,7 +37,8 @@ public ServerNet(String name, Function graphBuilder, @SafeVarargs public ServerNet(String name, boolean directed, Function... algorithmBuilders) { - this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), algorithmBuilders); + this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), + algorithmBuilders); } @Override diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java index 79af7d4b2f1..432556aa478 100644 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java @@ -2,7 +2,6 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; - import gregtech.api.util.DimensionPos; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java index 7d5fd615b55..0b947be53ed 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java @@ -15,7 +15,8 @@ public abstract class AbstractTraverseData> { IPredicateTestObject getTestObject(); - @Nullable SimulatorKey getSimulatorKey(); + @Nullable + SimulatorKey getSimulatorKey(); long getQueryTick(); @@ -33,7 +33,7 @@ public interface ITraverseData> { /** * Reports that the traverse is traversing to a node, for additional logic to be run. * - * @param node the node being traversed + * @param node the node being traversed * @param flowReachingNode the flow that has reached this node. * @return the loss operator for the node. */ @@ -42,7 +42,7 @@ public interface ITraverseData> { /** * Reports that the traverse has finished a path walk, for finalization. * - * @param destination the active node the path terminated at. + * @param destination the active node the path terminated at. * @param flowReachingDestination the flow that reached the destination * @return the amount of flow that should be consumed, before walking the next path. */ @@ -51,6 +51,7 @@ public interface ITraverseData> { /** * Allows for reporting a smaller capacity along an edge than it actually has. Do not report a larger capacity * than the actual edge or things will break. + * * @param edge the edge to get capacity for. * @return a non-negative capacity that is less than or equal to the true capacity of the edge. */ @@ -61,11 +62,13 @@ default long getFlowLimit(AbstractNetFlowEdge edge) { /** * Allows for consuming more than just the edge flow limits on a consumption event. Must always consume the correct * amount of edge flow or things will break. - * @param edge the edge to consume along. - * @param targetNode the target node of the edge. + * + * @param edge the edge to consume along. + * @param targetNode the target node of the edge. * @param consumption the amount to consume from the edge's flow limit. */ default void consumeFlowLimit(AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { - edge.consumeFlowLimit(this.getTestObject(), this.getGraphNet(), consumption, this.getQueryTick(), this.getSimulatorKey()); + edge.consumeFlowLimit(this.getTestObject(), this.getGraphNet(), consumption, this.getQueryTick(), + this.getSimulatorKey()); } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index d0af0461db8..54466af03ba 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -4,14 +4,12 @@ import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.path.INetPath; - import gregtech.api.graphnet.traverse.util.FlowConsumptionStack; import gregtech.api.util.GTUtility; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.alg.util.Pair; @@ -33,15 +31,16 @@ private TraverseHelpers() {} * specifically, find the lowest weight path, fill it to capacity, find the next lowest weight path, etc. * Requires dynamic weights to function properly. * - * @param data the traversal data. - * @param paths the paths to traverse. + * @param data the traversal data. + * @param paths the paths to traverse. * @param flowIn the flow to traverse with. * @return the consumed flow. */ - public static , D extends ITraverseData> long traverseFlood( - @NotNull D data, - @NotNull Iterator

paths, - long flowIn) { + public static , + D extends ITraverseData> long traverseFlood( + @NotNull D data, + @NotNull Iterator

paths, + long flowIn) { boolean simulate = data.getSimulatorKey() != null; long availableFlow = flowIn; pathloop: @@ -69,7 +68,8 @@ public static data.consumeFlowLimit(edge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); + stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), + data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); if (pathFlow <= 0) continue pathloop; @@ -90,18 +90,19 @@ public static , D extends ITraverseData> long traverseDumb( - @NotNull D data, - @NotNull Iterator

paths, - @Nullable BiConsumer overflowListener, - long flowIn) { + public static , + D extends ITraverseData> long traverseDumb( + @NotNull D data, + @NotNull Iterator

paths, + @Nullable BiConsumer overflowListener, + long flowIn) { boolean simulate = data.getSimulatorKey() != null; boolean isFlow = overflowListener != null; long availableFlow = isFlow ? flowIn : 0; @@ -118,7 +119,8 @@ public static , D List> overflowReporters = isFlow ? new ObjectArrayList<>() : null; assert nodes.size() == edges.size() + 1; - FlowConsumptionStack stack = isFlow ? new FlowConsumptionStack(data.traverseToNode(nodes.get(0), pathFlow)) : null; + FlowConsumptionStack stack = isFlow ? + new FlowConsumptionStack(data.traverseToNode(nodes.get(0), pathFlow)) : null; if (isFlow) pathFlow = stack.applyLatestLossFunction(pathFlow); for (int i = 0; i < edges.size(); i++) { @@ -142,7 +144,8 @@ public static , D if (finalOverflow > 0) overflowListener.accept(targetNode, finalOverflow); }); } - stack.add(flow -> data.consumeFlowLimit(flowEdge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); + stack.add(flow -> data.consumeFlowLimit(flowEdge, targetNode, flow), + data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); } @@ -164,29 +167,33 @@ public static , D /** * Provides logic for traversing a flow net in an equal distribution manner. Operates in the following stages: - *

+ *
+ *
* Stage One (collection) -- collect paths into a list while iterating, gathering a map of edges to flow info. * Get numbers for what is needed to provide 1 flow per node destination per path, ignoring potential loss. * If a path cannot be traversed, it is either trimmed or we abort based on {@code strict}. - *

+ *
+ *
* Stage Two (scaling) -- scale up the mult with a binary search until we get the largest mult where no edge * capacities are exceeded. If this mult is 0, abort and return 0. - *

+ *
+ *
* Stage Three (traversal) -- traverse the collected paths and perform consumption and flow, using the multiplier * from stage two. * - * @param data the traversal data. - * @param paths the paths to traverse. + * @param data the traversal data. + * @param paths the paths to traverse. * @param flowIn the flow to traverse with. * @param strict whether to abort if one of the destination paths cannot be traversed due to node restrictions, * not edge restrictions. * @return the consumed flow. */ - public static , D extends ITraverseData & IEqualizableTraverseData> long traverseEqualDistribution( - @NotNull D data, - @NotNull Iterator

paths, - long flowIn, - boolean strict) { + public static , + D extends ITraverseData & IEqualizableTraverseData> long traverseEqualDistribution( + @NotNull D data, + @NotNull Iterator

paths, + long flowIn, + boolean strict) { // collection Map, DistributorHelper> distributorHelperMap = new Object2ObjectOpenHashMap<>(); Object2IntOpenHashMap

desiredMap = new Object2IntOpenHashMap<>(); @@ -265,7 +272,8 @@ public static data.consumeFlowLimit(edge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); + stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), + data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); if (pathFlow <= 0) continue pathloop; @@ -288,18 +296,20 @@ public static , D extends ITraverseData & IEqualizableTraverseData> long traverseEqualDistribution( - @NotNull D data, - @NotNull Supplier> pathsSupplier, - long flowIn, - boolean strict) { + public static , + D extends ITraverseData & IEqualizableTraverseData> long traverseEqualDistribution( + @NotNull D data, + @NotNull Supplier> pathsSupplier, + long flowIn, + boolean strict) { long availableFlow = flowIn; byte iterationCount = 0; while (iterationCount <= 100) { @@ -318,18 +328,19 @@ public static , D extends ITraverseData & IRoundRobinTraverseData> long traverseRoundRobin( - @NotNull D data, - @NotNull Iterator

paths, - long flowIn, - boolean strict) { + public static , + D extends ITraverseData & IRoundRobinTraverseData> long traverseRoundRobin( + @NotNull D data, + @NotNull Iterator

paths, + long flowIn, + boolean strict) { long availableFlow = flowIn; ArrayDeque cache = data.getTraversalCache(); @@ -373,12 +384,12 @@ public static , D extends ITraverseData & IRoundRobinTraverseData> long rrTraverse( - @NotNull D data, - @NotNull P path, - long flowIn, - boolean strict) { - + private static , + D extends ITraverseData & IRoundRobinTraverseData> long rrTraverse( + @NotNull D data, + @NotNull P path, + long flowIn, + boolean strict) { boolean simulate = data.getSimulatorKey() != null; List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); long pathFlow = flowIn; diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/CompleteLossOperator.java b/src/main/java/gregtech/api/graphnet/traverse/util/CompleteLossOperator.java index 5f9ca222104..64eeef293fb 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/CompleteLossOperator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/util/CompleteLossOperator.java @@ -1,6 +1,7 @@ package gregtech.api.graphnet.traverse.util; public class CompleteLossOperator implements ReversibleLossOperator { + public static final CompleteLossOperator INSTANCE = new CompleteLossOperator(); private CompleteLossOperator() {} diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java b/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java index 49bfb6dad72..673c66c5f5a 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java +++ b/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java @@ -33,6 +33,7 @@ public void add(LongConsumer flowConsumer, ReversibleLossOperator postLoss) { /** * Walks backwards along the loss operators and applies consumption to flow consumers. + * * @param endValue the target end value * @return the value that needs to be pushed into the start of the stack to achieve the end value. */ diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java b/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java index 1bfc018e6bb..8addf391e0b 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java @@ -29,6 +29,6 @@ public double applyLoss(double value) { @Override public double undoLoss(double value) { - return value / mult; + return value / mult; } } diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java index a5421758e65..dbb6e957921 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -1,21 +1,17 @@ package gregtech.api.graphnet.worldnet; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.path.GenericGraphNetPath; import gregtech.api.graphnet.GraphNetBacker; import gregtech.api.graphnet.IGraphNet; - import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.alg.INetAlgorithm; - import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.INetGraph; - import gregtech.api.graphnet.graph.NetDirectedGraph; import gregtech.api.graphnet.graph.NetUndirectedGraph; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; - +import gregtech.api.graphnet.path.GenericGraphNetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTTagCompound; @@ -43,7 +39,8 @@ public WorldNet(String name, Function graphBuilder, @SafeVarargs public WorldNet(String name, boolean directed, Function... algorithmBuilders) { - this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), algorithmBuilders); + this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), + algorithmBuilders); } public void setWorld(World world) { @@ -55,7 +52,8 @@ public World getWorld() { } @Override - public Iterator getPaths(NetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + public Iterator getPaths(NetNode node, IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, long queryTick) { nodeClassCheck(node); return backer.getPaths(node, 0, GenericGraphNetPath.MAPPER, testObject, simulator, queryTick); } diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java index e539e80b0d6..449211fc581 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java @@ -1,10 +1,7 @@ package gregtech.api.graphnet.worldnet; -import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.pipenet.WorldPipeNet; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/gregtech/api/items/metaitem/FilteredFluidStats.java b/src/main/java/gregtech/api/items/metaitem/FilteredFluidStats.java index d06ac6846ac..5a170e21ee1 100644 --- a/src/main/java/gregtech/api/items/metaitem/FilteredFluidStats.java +++ b/src/main/java/gregtech/api/items/metaitem/FilteredFluidStats.java @@ -26,7 +26,8 @@ public FilteredFluidStats(int capacity, boolean allowPartialFill, @Nullable IFil this.filter = filter; } - public FilteredFluidStats(int capacity, int maxFluidTemperature, int minFluidTemperature, boolean gasProof, boolean acidProof, + public FilteredFluidStats(int capacity, int maxFluidTemperature, int minFluidTemperature, boolean gasProof, + boolean acidProof, boolean plasmaProof, boolean allowPartialFill) { this(capacity, allowPartialFill, new PropertyFluidFilter(maxFluidTemperature, minFluidTemperature, gasProof, acidProof, plasmaProof)); diff --git a/src/main/java/gregtech/api/metatileentity/interfaces/INeighborCache.java b/src/main/java/gregtech/api/metatileentity/interfaces/INeighborCache.java index d40ba85510b..a1920e91f7e 100644 --- a/src/main/java/gregtech/api/metatileentity/interfaces/INeighborCache.java +++ b/src/main/java/gregtech/api/metatileentity/interfaces/INeighborCache.java @@ -2,7 +2,6 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; - import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockAbility.java b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockAbility.java index 88167fc910e..44d3d049453 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockAbility.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockAbility.java @@ -68,7 +68,8 @@ public class MultiblockAbility { public static final MultiblockAbility OPTICAL_DATA_TRANSMISSION = new MultiblockAbility<>( "optical_data_transmission"); public static final MultiblockAbility LASER_RECEPTION = new MultiblockAbility<>("laser_reception"); - public static final MultiblockAbility LASER_TRANSMISSION = new MultiblockAbility<>("laser_transmission"); + public static final MultiblockAbility LASER_TRANSMISSION = new MultiblockAbility<>( + "laser_transmission"); public static final MultiblockAbility COMPUTATION_DATA_RECEPTION = new MultiblockAbility<>( "computation_data_reception"); diff --git a/src/main/java/gregtech/api/unification/material/Material.java b/src/main/java/gregtech/api/unification/material/Material.java index d8dada085fb..91c394eb068 100644 --- a/src/main/java/gregtech/api/unification/material/Material.java +++ b/src/main/java/gregtech/api/unification/material/Material.java @@ -18,11 +18,8 @@ import gregtech.api.util.GTUtility; import gregtech.api.util.LocalizationUtils; import gregtech.api.util.SmallDigits; - import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; - import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; - import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; import net.minecraft.enchantment.Enchantment; @@ -1055,38 +1052,46 @@ public Builder cableProperties(long voltage, long amperage, long loss) { } public Builder cablePropertiesT(long voltage, long amperage, long loss, int meltTemperature) { - getOrCreatePipeNetProperties().setProperty(MaterialEnergyProperties.createT(voltage, amperage, loss, meltTemperature)); + getOrCreatePipeNetProperties() + .setProperty(MaterialEnergyProperties.createT(voltage, amperage, loss, meltTemperature)); return this; } public Builder cablePropertiesS(long voltage, long amperage, long loss, int superconductorTemperature) { - getOrCreatePipeNetProperties().setProperty(MaterialEnergyProperties.createS(voltage, amperage, loss, superconductorTemperature)); + getOrCreatePipeNetProperties() + .setProperty(MaterialEnergyProperties.createS(voltage, amperage, loss, superconductorTemperature)); return this; } - public Builder cableProperties(long voltage, long amperage, long loss, int meltTemperature, int superconductorTemperature) { - getOrCreatePipeNetProperties().setProperty(new MaterialEnergyProperties(voltage, amperage, loss, meltTemperature, superconductorTemperature)); + public Builder cableProperties(long voltage, long amperage, long loss, int meltTemperature, + int superconductorTemperature) { + getOrCreatePipeNetProperties().setProperty( + new MaterialEnergyProperties(voltage, amperage, loss, meltTemperature, superconductorTemperature)); return this; } public Builder fluidPipeProperties(int maxTemp, long throughput, boolean gasProof) { - getOrCreatePipeNetProperties().setProperty(MaterialFluidProperties.createMax(throughput, maxTemp).setContain(FluidState.GAS, gasProof)); + getOrCreatePipeNetProperties().setProperty( + MaterialFluidProperties.createMax(throughput, maxTemp).setContain(FluidState.GAS, gasProof)); return this; } public Builder fluidPipeProperties(int maxTemp, long throughput, boolean gasProof, float priority) { - getOrCreatePipeNetProperties().setProperty(MaterialFluidProperties.createMax(throughput, maxTemp, priority).setContain(FluidState.GAS, gasProof)); + getOrCreatePipeNetProperties().setProperty(MaterialFluidProperties.createMax(throughput, maxTemp, priority) + .setContain(FluidState.GAS, gasProof)); return this; } public Builder fluidPipeProperties(int maxTemp, int throughput, boolean gasProof, boolean acidProof, boolean plasmaProof) { - getOrCreatePipeNetProperties().setProperty(MaterialFluidProperties.createMax(throughput, maxTemp).setContain(FluidState.GAS, gasProof) - .setContain(FluidAttributes.ACID, acidProof).setContain(FluidState.PLASMA, plasmaProof)); + getOrCreatePipeNetProperties().setProperty( + MaterialFluidProperties.createMax(throughput, maxTemp).setContain(FluidState.GAS, gasProof) + .setContain(FluidAttributes.ACID, acidProof).setContain(FluidState.PLASMA, plasmaProof)); return this; } - public Builder fluidPipeProperties(int maxTemp, int minTemp, int throughput, boolean gasProof, boolean acidProof, + public Builder fluidPipeProperties(int maxTemp, int minTemp, int throughput, boolean gasProof, + boolean acidProof, boolean plasmaProof) { getOrCreatePipeNetProperties().setProperty(new MaterialFluidProperties(throughput, maxTemp, minTemp) .setContain(FluidState.GAS, gasProof).setContain(FluidAttributes.ACID, acidProof) @@ -1095,7 +1100,8 @@ public Builder fluidPipeProperties(int maxTemp, int minTemp, int throughput, boo } public Builder itemPipeProperties(int priority, float stacksPerSec) { - getOrCreatePipeNetProperties().setProperty(new MaterialItemProperties((long) (stacksPerSec * 16), priority)); + getOrCreatePipeNetProperties() + .setProperty(new MaterialItemProperties((long) (stacksPerSec * 16), priority)); return this; } diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index aa1799d42fc..ccc3e634e79 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -2,18 +2,14 @@ import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; - import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -104,5 +100,4 @@ T cast(IPipeNetMaterialProperty property) { } } } - } diff --git a/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java b/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java index 8577c41f89f..e1c7445b212 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java +++ b/src/main/java/gregtech/api/unification/material/properties/PropertyKey.java @@ -4,7 +4,8 @@ public class PropertyKey { public static final PropertyKey BLAST = new PropertyKey<>("blast", BlastProperty.class); public static final PropertyKey DUST = new PropertyKey<>("dust", DustProperty.class); - public static final PropertyKey PIPENET_PROPERTIES = new PropertyKey<>("net_pipe", PipeNetProperties.class); + public static final PropertyKey PIPENET_PROPERTIES = new PropertyKey<>("net_pipe", + PipeNetProperties.class); public static final PropertyKey FLUID = new PropertyKey<>("fluid", FluidProperty.class); public static final PropertyKey GEM = new PropertyKey<>("gem", GemProperty.class); public static final PropertyKey INGOT = new PropertyKey<>("ingot", IngotProperty.class); diff --git a/src/main/java/gregtech/api/unification/ore/OrePrefix.java b/src/main/java/gregtech/api/unification/ore/OrePrefix.java index de664c8f877..f617103465c 100644 --- a/src/main/java/gregtech/api/unification/ore/OrePrefix.java +++ b/src/main/java/gregtech/api/unification/ore/OrePrefix.java @@ -280,7 +280,8 @@ public class OrePrefix { ENABLE_UNIFICATION, null); public static final OrePrefix pipeHugeRestrictive = new OrePrefix("pipeHugeRestrictive", M * 12, null, null, ENABLE_UNIFICATION, null); - public static final OrePrefix pipeQuadrupleRestrictive = new OrePrefix("pipeQuadrupleRestrictive", M * 4, null, null, + public static final OrePrefix pipeQuadrupleRestrictive = new OrePrefix("pipeQuadrupleRestrictive", M * 4, null, + null, ENABLE_UNIFICATION, null); public static final OrePrefix pipeNonupleRestrictive = new OrePrefix("pipeNonupleRestrictive", M * 9, null, null, ENABLE_UNIFICATION, null); diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index de2e1ad55a5..b5501a2c9f2 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -19,9 +19,6 @@ import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.ore.OrePrefix; -import it.unimi.dsi.fastutil.bytes.ByteArrayList; -import it.unimi.dsi.fastutil.bytes.ByteList; - import net.minecraft.block.BlockRedstoneWire; import net.minecraft.block.BlockSnow; import net.minecraft.block.material.MapColor; @@ -931,7 +928,7 @@ public static int[] convertARGBtoArray(int argb) { int r = argb >> 16 & 255; int g = argb >> 8 & 255; int b = argb & 255; - return new int[] {a, r, g, b}; + return new int[] { a, r, g, b }; } @Contract(pure = true) diff --git a/src/main/java/gregtech/client/particle/GTOverheatParticle.java b/src/main/java/gregtech/client/particle/GTOverheatParticle.java index e6df6596ba6..09d82a051eb 100644 --- a/src/main/java/gregtech/client/particle/GTOverheatParticle.java +++ b/src/main/java/gregtech/client/particle/GTOverheatParticle.java @@ -23,7 +23,6 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import codechicken.lib.vec.Cuboid6; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; diff --git a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java index fe58561fee6..ff0c90df0f5 100644 --- a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java @@ -10,13 +10,8 @@ import gregtech.client.renderer.pipe.cache.ColorQuadCache; import gregtech.client.renderer.pipe.cache.StructureQuadCache; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; - import gregtech.client.renderer.pipe.util.CacheKey; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.BakedQuad; @@ -28,15 +23,15 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; - import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.common.property.IExtendedBlockState; - import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -157,12 +152,14 @@ protected static BlockRenderLayer getCurrentRenderLayer() { } protected static class FakeItemOverrideList extends ItemOverrideList { + public static final FakeItemOverrideList INSTANCE = new FakeItemOverrideList(); @Override - public @NotNull IBakedModel handleItemState(@NotNull IBakedModel originalModel, @NotNull ItemStack stack, World world, + public @NotNull IBakedModel handleItemState(@NotNull IBakedModel originalModel, @NotNull ItemStack stack, + World world, EntityLivingBase entity) { - if (originalModel instanceof AbstractPipeModel model) { + if (originalModel instanceof AbstractPipeModelmodel) { PipeItemModel item = model.getItemModel(stack, world, entity); if (item != null) return item; } diff --git a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java index c1fefff4e73..5f6aaebd3e2 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java @@ -1,7 +1,6 @@ package gregtech.client.renderer.pipe; import gregtech.api.block.UnlistedBooleanProperty; -import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.unification.material.Material; @@ -10,20 +9,11 @@ import gregtech.client.renderer.pipe.cache.StructureQuadCache; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.util.ActivableCacheKey; -import gregtech.client.renderer.pipe.util.CacheKey; - import gregtech.client.renderer.pipe.util.SpriteInformation; - import gregtech.client.renderer.texture.Textures; - import gregtech.client.utils.BloomEffectUtil; - import gregtech.common.ConfigHolder; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.IBakedModel; import net.minecraft.client.renderer.block.model.ModelResourceLocation; @@ -36,6 +26,7 @@ import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -107,12 +98,14 @@ public ActivablePipeModel(@NotNull Supplier inTex, @NotNull S @Override protected StructureQuadCache constructForKey(ActivableCacheKey key) { - return ActivableSQC.create(PipeQuadHelper.create(key.getThickness()), inTex.get(), sideTex.get(), overlayTex.get(), overlayActiveTex.get()); + return ActivableSQC.create(PipeQuadHelper.create(key.getThickness()), inTex.get(), sideTex.get(), + overlayTex.get(), overlayActiveTex.get()); } @Override public boolean canRenderInLayer(BlockRenderLayer layer) { - return layer == BlockRenderLayer.CUTOUT_MIPPED || (allowActive() && emissiveActive && layer == BloomEffectUtil.getEffectiveBloomLayer()); + return layer == BlockRenderLayer.CUTOUT_MIPPED || + (allowActive() && emissiveActive && layer == BloomEffectUtil.getEffectiveBloomLayer()); } public boolean allowActive() { @@ -121,10 +114,11 @@ public boolean allowActive() { @Override protected @Nullable PipeItemModel getItemModel(@NotNull ItemStack stack, World world, - EntityLivingBase entity) { + EntityLivingBase entity) { WorldPipeBlock block = WorldPipeBlock.getBlockFromItem(stack); if (block == null) return null; - return new PipeItemModel<>(this, new ActivableCacheKey(block.getStructure().getRenderThickness(), false), PipeTileEntity.DEFAULT_COLOR); + return new PipeItemModel<>(this, new ActivableCacheKey(block.getStructure().getRenderThickness(), false), + PipeTileEntity.DEFAULT_COLOR); } public static void registerModels(IRegistry registry) { diff --git a/src/main/java/gregtech/client/renderer/pipe/CableModel.java b/src/main/java/gregtech/client/renderer/pipe/CableModel.java index 7afb06f71c7..e674b3fce31 100644 --- a/src/main/java/gregtech/client/renderer/pipe/CableModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/CableModel.java @@ -4,15 +4,12 @@ import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.cache.ExtraCappedSQC; import gregtech.client.renderer.pipe.cache.StructureQuadCache; - import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.util.CacheKey; import gregtech.client.renderer.pipe.util.SpriteInformation; -import gregtech.client.renderer.pipe.util.WoodCacheKey; import gregtech.client.renderer.texture.Textures; import net.minecraft.client.renderer.block.model.IBakedModel; @@ -24,7 +21,6 @@ import net.minecraft.util.registry.IRegistry; import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; - import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -84,7 +80,8 @@ protected StructureQuadCache constructForKey(CacheKey key) { if (insulationTex == null) { return StructureQuadCache.create(PipeQuadHelper.create(key.getThickness()), wireTex.get(), sideTex); } else { - return ExtraCappedSQC.create(PipeQuadHelper.create(key.getThickness()), wireTex.get(), sideTex, insulationTex.get()); + return ExtraCappedSQC.create(PipeQuadHelper.create(key.getThickness()), wireTex.get(), sideTex, + insulationTex.get()); } } @@ -94,7 +91,8 @@ protected StructureQuadCache constructForKey(CacheKey key) { WorldPipeBlock block = WorldPipeBlock.getBlockFromItem(stack); if (block == null) return null; Material mater = block instanceof PipeMaterialBlock mat ? mat.getMaterialForStack(stack) : null; - return new PipeItemModel<>(this, new CacheKey(block.getStructure().getRenderThickness()), mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : PipeTileEntity.DEFAULT_COLOR); + return new PipeItemModel<>(this, new CacheKey(block.getStructure().getRenderThickness()), + mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : PipeTileEntity.DEFAULT_COLOR); } public static void registerModels(IRegistry registry) { diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java index 6d9f1b8cb59..f16be3ede76 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java @@ -1,25 +1,17 @@ package gregtech.client.renderer.pipe; -import com.github.bsideup.jabel.Desugar; - -import gregtech.client.renderer.pipe.AbstractPipeModel; - import gregtech.client.renderer.pipe.util.CacheKey; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.IBakedModel; import net.minecraft.client.renderer.block.model.ItemOverrideList; -import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.EnumFacing; -import net.minecraft.util.IStringSerializable; - import org.jetbrains.annotations.NotNull; import java.util.List; -import java.util.Objects; public class PipeItemModel implements IBakedModel { diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java index 07855a74462..a42fc31e69d 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java @@ -115,7 +115,8 @@ protected PipeItemModel getItemModel(@NotNull ItemStack stack, Wor Material mater = null; boolean wood = block instanceof PipeMaterialBlock mat && (mater = mat.getMaterialForStack(stack)) != null && mater.hasProperty(PropertyKey.WOOD); - return new PipeItemModel<>(this, new WoodCacheKey(block.getStructure().getRenderThickness(), wood), mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : PipeTileEntity.DEFAULT_COLOR); + return new PipeItemModel<>(this, new WoodCacheKey(block.getStructure().getRenderThickness(), wood), + mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : PipeTileEntity.DEFAULT_COLOR); } public static void registerModels(IRegistry registry) { diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java index ef25c17a481..64243ed1742 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java @@ -28,7 +28,9 @@ protected ActivableSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteIn this.overlayActiveTex = overlayActiveTex; } - public static @NotNull ActivableSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation overlayTex, SpriteInformation overlayActiveTex) { + public static @NotNull ActivableSQC create(PipeQuadHelper helper, SpriteInformation endTex, + SpriteInformation sideTex, SpriteInformation overlayTex, + SpriteInformation overlayActiveTex) { ActivableSQC cache = new ActivableSQC(helper, endTex, sideTex, overlayTex, overlayActiveTex); cache.buildPrototype(); return cache; diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java index d34a9976198..ca214627eaf 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java @@ -7,7 +7,6 @@ import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.util.EnumFacing; - import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -29,7 +28,8 @@ protected BlockableSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteIn this.blockedTex = blockedTex; } - public static @NotNull BlockableSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation blockedTex) { + public static @NotNull BlockableSQC create(PipeQuadHelper helper, SpriteInformation endTex, + SpriteInformation sideTex, SpriteInformation blockedTex) { BlockableSQC cache = new BlockableSQC(helper, endTex, sideTex, blockedTex); cache.buildPrototype(); return cache; diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java index d6b06a5e223..c0c7f4cb9de 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java @@ -2,14 +2,13 @@ import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; -import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import java.util.List; @SideOnly(Side.CLIENT) diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java index 657b8c42e43..a5a424c818c 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java @@ -7,7 +7,6 @@ import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.util.EnumFacing; - import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -29,7 +28,8 @@ protected ExtraCappedSQC(PipeQuadHelper helper, SpriteInformation endTex, Sprite this.extraEndTex = extraEndTex; } - public static @NotNull ExtraCappedSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation extraEndTex) { + public static @NotNull ExtraCappedSQC create(PipeQuadHelper helper, SpriteInformation endTex, + SpriteInformation sideTex, SpriteInformation extraEndTex) { ExtraCappedSQC cache = new ExtraCappedSQC(helper, endTex, sideTex, extraEndTex); cache.buildPrototype(); return cache; diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java index 611b5cb5ee1..fe09d954bc1 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java @@ -2,15 +2,11 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; - import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; - import gregtech.client.renderer.pipe.util.SpriteInformation; import net.minecraft.client.renderer.block.model.BakedQuad; - import net.minecraft.util.EnumFacing; - import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -32,7 +28,8 @@ protected RestrictiveSQC(PipeQuadHelper helper, SpriteInformation endTex, Sprite this.restrictiveTex = restrictiveTex; } - public static @NotNull RestrictiveSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, + public static @NotNull RestrictiveSQC create(PipeQuadHelper helper, SpriteInformation endTex, + SpriteInformation sideTex, SpriteInformation blockedTex, SpriteInformation restrictiveTex) { RestrictiveSQC sqc = new RestrictiveSQC(helper, endTex, sideTex, blockedTex, restrictiveTex); sqc.buildPrototype(); diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java index 35853be2491..d2a33670557 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java @@ -1,23 +1,17 @@ package gregtech.client.renderer.pipe.cache; -import com.github.bsideup.jabel.Desugar; - import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; - import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; - import gregtech.client.renderer.pipe.util.SpriteInformation; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.client.renderer.block.model.BakedQuad; - import net.minecraft.util.EnumFacing; - import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.github.bsideup.jabel.Desugar; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import java.util.EnumMap; @@ -45,7 +39,8 @@ protected StructureQuadCache(PipeQuadHelper helper, SpriteInformation endTex, Sp this.sideTex = sideTex; } - public static @NotNull StructureQuadCache create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex) { + public static @NotNull StructureQuadCache create(PipeQuadHelper helper, SpriteInformation endTex, + SpriteInformation sideTex) { StructureQuadCache cache = new StructureQuadCache(helper, endTex, sideTex); cache.buildPrototype(); return cache; @@ -123,5 +118,4 @@ protected record SubListAddress(int startInclusive, int endExclusive) { return list.subList(startInclusive, endExclusive); } } - } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java index 304c460d305..538cc60db20 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -2,8 +2,6 @@ import gregtech.client.renderer.pipe.util.SpriteInformation; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.VertexFormat; @@ -11,6 +9,8 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import java.util.List; @SideOnly(Side.CLIENT) @@ -70,9 +70,13 @@ public void setTargetSprite(SpriteInformation sprite) { public RecolorableBakedQuad visitCore(EnumFacing facing) { return switch (facing.getAxis()) { - case X -> visitQuad(facing, 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, y + small, y + large, z + small, z + large, squareMapper); - case Y -> visitQuad(facing, x + small, x + large, 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, z + small, z + large, squareMapper); - case Z -> visitQuad(facing, x + small, x + large, y + small, y + large, 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, squareMapper); + case X -> visitQuad(facing, 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, y + small, + y + large, z + small, z + large, squareMapper); + case Y -> visitQuad(facing, x + small, x + large, + 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, z + small, z + large, + squareMapper); + case Z -> visitQuad(facing, x + small, x + large, y + small, y + large, + 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, squareMapper); }; } @@ -130,13 +134,17 @@ public List visitTube(EnumFacing facing) { public RecolorableBakedQuad visitCapper(EnumFacing facing) { return switch (facing.getAxis()) { - case X -> visitQuad(facing, 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, y + small, y + large, z + small, z + large, squareMapper); - case Y -> visitQuad(facing, x + small, x + large, 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, z + small, z + large, squareMapper); - case Z -> visitQuad(facing, x + small, x + large, y + small, y + large, 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, squareMapper); + case X -> visitQuad(facing, 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, y + small, y + large, + z + small, z + large, squareMapper); + case Y -> visitQuad(facing, x + small, x + large, 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, + z + small, z + large, squareMapper); + case Z -> visitQuad(facing, x + small, x + large, y + small, y + large, + 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, squareMapper); }; } - public RecolorableBakedQuad visitQuad(EnumFacing normal, float x1, float x2, float y1, float y2, float z1, float z2, UVMapper mapper) { + public RecolorableBakedQuad visitQuad(EnumFacing normal, float x1, float x2, float y1, float y2, float z1, float z2, + UVMapper mapper) { building = new RecolorableBakedQuad.Builder(FORMAT); switch (normal.getAxis()) { case X -> { @@ -198,7 +206,7 @@ private static void putVertex(RecolorableBakedQuad.Builder consumer, VertexForma case COLOR: float a = ((argb >> 24) & 0xFF) / 255f; // alpha float r = ((argb >> 16) & 0xFF) / 255f; // red - float g = ((argb >> 8) & 0xFF) / 255f; // green + float g = ((argb >> 8) & 0xFF) / 255f; // green float b = ((argb) & 0xFF) / 255f; // blue consumer.put(e, r, g, b, a); break; @@ -209,8 +217,7 @@ private static void putVertex(RecolorableBakedQuad.Builder consumer, VertexForma consumer.put(e, offX, offY, offZ, 0f); break; case UV: - if (format.getElement(e).getIndex() == 0) - { + if (format.getElement(e).getIndex() == 0) { consumer.put(e, u, v, 0f, 1f); break; } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java index 72b0df0902b..6e3e2d0c6df 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java @@ -6,7 +6,6 @@ import net.minecraft.client.renderer.vertex.VertexFormatElement; import net.minecraft.util.EnumFacing; import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; - import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -30,9 +29,9 @@ public RecolorableBakedQuad withColor(int argb) { float a = ((argb >> 24) & 0xFF) / 255f; // alpha float r = ((argb >> 16) & 0xFF) / 255f; // red - float g = ((argb >> 8) & 0xFF) / 255f; // green + float g = ((argb >> 8) & 0xFF) / 255f; // green float b = ((argb) & 0xFF) / 255f; // blue - float[] array = new float[] {r, g, b, a}; + float[] array = new float[] { r, g, b, a }; for (int v = 0; v < 4; v++) { for (int e = 0; e < format.getElementCount(); e++) { if (format.getElement(e).getUsage() == VertexFormatElement.EnumUsage.COLOR) { @@ -42,10 +41,12 @@ public RecolorableBakedQuad withColor(int argb) { } } } - return new RecolorableBakedQuad(newData, this.tintIndex, this.face, this.spriteInformation, this.applyDiffuseLighting, this.format); + return new RecolorableBakedQuad(newData, this.tintIndex, this.face, this.spriteInformation, + this.applyDiffuseLighting, this.format); } public static class Builder { + private final VertexFormat format; private final float[][][] unpackedData; private int tint = -1; @@ -58,122 +59,98 @@ public static class Builder { private boolean full = false; private boolean contractUVs = false; - public Builder(VertexFormat format) - { + public Builder(VertexFormat format) { this.format = format; unpackedData = new float[4][format.getElementCount()][4]; } - public @NotNull VertexFormat getVertexFormat() - { + public @NotNull VertexFormat getVertexFormat() { return format; } - public void setContractUVs(boolean value) - { + public void setContractUVs(boolean value) { this.contractUVs = value; } - public void setQuadTint(int tint) - { + + public void setQuadTint(int tint) { this.tint = tint; } - public void setQuadOrientation(@NotNull EnumFacing orientation) - { + public void setQuadOrientation(@NotNull EnumFacing orientation) { this.orientation = orientation; } - public void setTexture(@NotNull SpriteInformation texture) - { + public void setTexture(@NotNull SpriteInformation texture) { this.texture = texture; } - public void setApplyDiffuseLighting(boolean diffuse) - { + public void setApplyDiffuseLighting(boolean diffuse) { this.applyDiffuseLighting = diffuse; } - public void put(int element, float @NotNull ... data) - { - for(int i = 0; i < 4; i++) - { - if(i < data.length) - { + public void put(int element, float @NotNull... data) { + for (int i = 0; i < 4; i++) { + if (i < data.length) { unpackedData[vertices][element][i] = data[i]; - } - else - { + } else { unpackedData[vertices][element][i] = 0; } } elements++; - if(elements == format.getElementCount()) - { + if (elements == format.getElementCount()) { vertices++; elements = 0; } - if(vertices == 4) - { + if (vertices == 4) { full = true; } } public RecolorableBakedQuad build() { - if(!full) - { + if (!full) { throw new IllegalStateException("not enough data"); } - if(texture == null) - { + if (texture == null) { throw new IllegalStateException("texture not set"); } - if(contractUVs) - { + if (contractUVs) { float tX = texture.sprite().getIconWidth() / (texture.sprite().getMaxU() - texture.sprite().getMinU()); float tY = texture.sprite().getIconHeight() / (texture.sprite().getMaxV() - texture.sprite().getMinV()); float tS = Math.max(tX, tY); float ep = 1f / (tS * 0x100); int uve = 0; - while(uve < format.getElementCount()) - { + while (uve < format.getElementCount()) { VertexFormatElement e = format.getElement(uve); - if(e.getUsage() == VertexFormatElement.EnumUsage.UV && e.getIndex() == 0) - { + if (e.getUsage() == VertexFormatElement.EnumUsage.UV && e.getIndex() == 0) { break; } uve++; } - if(uve == format.getElementCount()) - { + if (uve == format.getElementCount()) { throw new IllegalStateException("Can't contract UVs: format doesn't contain UVs"); } float[] uvc = new float[4]; - for(int v = 0; v < 4; v++) - { - for(int i = 0; i < 4; i++) - { + for (int v = 0; v < 4; v++) { + for (int i = 0; i < 4; i++) { uvc[i] += unpackedData[v][uve][i] / 4; } } - for(int v = 0; v < 4; v++) - { - for (int i = 0; i < 4; i++) - { + for (int v = 0; v < 4; v++) { + for (int i = 0; i < 4; i++) { float uo = unpackedData[v][uve][i]; float eps = 1f / 0x100; float un = uo * (1 - eps) + uvc[i] * eps; float ud = uo - un; float aud = ud; - if(aud < 0) aud = -aud; - if(aud < ep) // not moving a fraction of a pixel + if (aud < 0) aud = -aud; + if (aud < ep) // not moving a fraction of a pixel { float udc = uo - uvc[i]; - if(udc < 0) udc = -udc; - if(udc < 2 * ep) // center is closer than 2 fractions of a pixel, don't move too close + if (udc < 0) udc = -udc; + if (udc < 2 * ep) // center is closer than 2 fractions of a pixel, don't move too close { un = (uo + uvc[i]) / 2; - } - else // move at least by a fraction + } else // move at least by a fraction { un = uo + (ud < 0 ? ep : -ep); } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java b/src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java index fcc4bf696a4..2c4849333be 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java @@ -5,6 +5,7 @@ @SideOnly(Side.CLIENT) public enum UVCorner { + UL, UR, DR, diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java index 9a11d40cfa3..9d3ef087010 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java @@ -1,11 +1,11 @@ package gregtech.client.renderer.pipe.quad; -import com.github.bsideup.jabel.Desugar; - import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.github.bsideup.jabel.Desugar; + @SideOnly(Side.CLIENT) @FunctionalInterface interface UVMapper { diff --git a/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java index ebf5303afb2..4da26329bb4 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java @@ -1,7 +1,5 @@ package gregtech.client.renderer.pipe.util; -import gregtech.client.renderer.pipe.AbstractPipeModel; - import net.minecraft.util.IStringSerializable; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java b/src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java index eb251655170..8335d4286f4 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java @@ -1,8 +1,5 @@ package gregtech.client.renderer.pipe.util; -import gregtech.client.renderer.pipe.util.SpriteInformation; - -import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; diff --git a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java index 1e0324da16f..284f34d77df 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java @@ -1,11 +1,11 @@ package gregtech.client.renderer.pipe.util; -import com.github.bsideup.jabel.Desugar; - import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.github.bsideup.jabel.Desugar; + @SideOnly(Side.CLIENT) @Desugar public record SpriteInformation(TextureAtlasSprite sprite, boolean colorable) {} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java index 1ae793f767d..e964e19c7a0 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java @@ -6,7 +6,9 @@ import java.util.function.Consumer; import java.util.function.Supplier; -public class SpriteInformationWrapper implements Supplier, Consumer, BiConsumer { +public class SpriteInformationWrapper implements Supplier, Consumer, + BiConsumer { + private SpriteInformation sprite; @Override diff --git a/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java index 8ebff9fd169..2fd2cd1d78c 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java @@ -1,7 +1,5 @@ package gregtech.client.renderer.pipe.util; -import gregtech.client.renderer.pipe.PipeModel; - import org.jetbrains.annotations.NotNull; import java.util.Objects; diff --git a/src/main/java/gregtech/client/renderer/texture/Textures.java b/src/main/java/gregtech/client/renderer/texture/Textures.java index 5bc9b44a507..18063be72f6 100644 --- a/src/main/java/gregtech/client/renderer/texture/Textures.java +++ b/src/main/java/gregtech/client/renderer/texture/Textures.java @@ -7,7 +7,6 @@ import gregtech.client.renderer.CubeRendererState; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.cclop.UVMirror; -import gregtech.client.renderer.pipe.util.SpriteInformation; import gregtech.client.renderer.pipe.util.SpriteInformationWrapper; import gregtech.client.renderer.texture.cube.AlignedOrientedOverlayRenderer; import gregtech.client.renderer.texture.cube.LDPipeOverlayRenderer; @@ -46,7 +45,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.function.Function; import static gregtech.api.util.GTUtility.gregtechId; @@ -583,36 +581,36 @@ public class Textures { @SideOnly(Side.CLIENT) public static final SpriteInformationWrapper LASER_PIPE_OVERLAY_EMISSIVE = new SpriteInformationWrapper(); -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY; @SideOnly(Side.CLIENT) public static final SpriteInformationWrapper PIPE_BLOCKED_OVERLAY_UP = new SpriteInformationWrapper(); -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DOWN; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_LEFT; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_RIGHT; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NU; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_ND; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NL; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NR; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UD; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UL; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UR; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DL; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DR; -// @SideOnly(Side.CLIENT) -// public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_LR; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DOWN; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_LEFT; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_RIGHT; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NU; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_ND; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NL; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NR; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UD; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UL; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UR; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DL; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DR; + // @SideOnly(Side.CLIENT) + // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_LR; @SideOnly(Side.CLIENT) public static ThreadLocal RENDER_STATE; @@ -655,21 +653,22 @@ public static void register(TextureMap textureMap) { PIPE_SIDE_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_side_wood")), true); // Fluid Pipe Blocked overlay textures -// PIPE_BLOCKED_OVERLAY = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked")); - PIPE_BLOCKED_OVERLAY_UP.accept(textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_up")), false); -// PIPE_BLOCKED_OVERLAY_DOWN = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_down")); -// PIPE_BLOCKED_OVERLAY_LEFT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_left")); -// PIPE_BLOCKED_OVERLAY_RIGHT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_right")); -// PIPE_BLOCKED_OVERLAY_NU = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nu")); -// PIPE_BLOCKED_OVERLAY_ND = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nd")); -// PIPE_BLOCKED_OVERLAY_NL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nl")); -// PIPE_BLOCKED_OVERLAY_NR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nr")); -// PIPE_BLOCKED_OVERLAY_UD = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ud")); -// PIPE_BLOCKED_OVERLAY_UL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ul")); -// PIPE_BLOCKED_OVERLAY_UR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ur")); -// PIPE_BLOCKED_OVERLAY_DL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_dl")); -// PIPE_BLOCKED_OVERLAY_DR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_dr")); -// PIPE_BLOCKED_OVERLAY_LR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_lr")); + // PIPE_BLOCKED_OVERLAY = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked")); + PIPE_BLOCKED_OVERLAY_UP.accept(textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_up")), + false); + // PIPE_BLOCKED_OVERLAY_DOWN = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_down")); + // PIPE_BLOCKED_OVERLAY_LEFT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_left")); + // PIPE_BLOCKED_OVERLAY_RIGHT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_right")); + // PIPE_BLOCKED_OVERLAY_NU = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nu")); + // PIPE_BLOCKED_OVERLAY_ND = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nd")); + // PIPE_BLOCKED_OVERLAY_NL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nl")); + // PIPE_BLOCKED_OVERLAY_NR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nr")); + // PIPE_BLOCKED_OVERLAY_UD = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ud")); + // PIPE_BLOCKED_OVERLAY_UL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ul")); + // PIPE_BLOCKED_OVERLAY_UR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ur")); + // PIPE_BLOCKED_OVERLAY_DL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_dl")); + // PIPE_BLOCKED_OVERLAY_DR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_dr")); + // PIPE_BLOCKED_OVERLAY_LR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_lr")); OPTICAL_PIPE_IN.accept(textureMap .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_in")), false); @@ -678,16 +677,18 @@ public static void register(TextureMap textureMap) { OPTICAL_PIPE_SIDE_OVERLAY.accept(textureMap .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side_overlay")), true); OPTICAL_PIPE_SIDE_OVERLAY_ACTIVE.accept(textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side_overlay_active")), true); + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side_overlay_active")), + true); - LASER_PIPE_IN.accept(textureMap. - registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_in")), false); + LASER_PIPE_IN.accept( + textureMap.registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_in")), false); LASER_PIPE_SIDE.accept(textureMap .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side")), false); LASER_PIPE_OVERLAY.accept(textureMap .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side_overlay")), true); LASER_PIPE_OVERLAY_EMISSIVE.accept(textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side_overlay_emissive")), true); + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side_overlay_emissive")), + true); for (MaterialIconSet iconSet : MaterialIconSet.ICON_SETS.values()) { textureMap.registerSprite(MaterialIconType.frameGt.getBlockTexturePath(iconSet)); diff --git a/src/main/java/gregtech/client/utils/RenderBufferHelper.java b/src/main/java/gregtech/client/utils/RenderBufferHelper.java index cd4e8902163..e64aa933ae9 100644 --- a/src/main/java/gregtech/client/utils/RenderBufferHelper.java +++ b/src/main/java/gregtech/client/utils/RenderBufferHelper.java @@ -56,6 +56,7 @@ public static void renderCubeFace(BufferBuilder buffer, Cuboid6 cuboid, float r, renderCubeFace(buffer, cuboid.min.x, cuboid.min.y, cuboid.min.z, cuboid.max.x, cuboid.max.y, cuboid.max.z, r, g, b, a, shade); } + public static void renderCubeFace(BufferBuilder buffer, AxisAlignedBB cuboid, float r, float g, float b, float a, boolean shade) { renderCubeFace(buffer, cuboid.minX, cuboid.minY, cuboid.minZ, cuboid.maxX, cuboid.maxY, cuboid.maxZ, r, g, diff --git a/src/main/java/gregtech/common/EventHandlers.java b/src/main/java/gregtech/common/EventHandlers.java index f2c6c6a4424..4a9b3d3d92a 100644 --- a/src/main/java/gregtech/common/EventHandlers.java +++ b/src/main/java/gregtech/common/EventHandlers.java @@ -3,11 +3,11 @@ import gregtech.api.GTValues; import gregtech.api.block.IWalkingSpeedBonus; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.graphnet.pipenetold.longdist.LongDistanceNetwork; import gregtech.api.items.armor.ArmorMetaItem; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.graphnet.pipenetold.longdist.LongDistanceNetwork; import gregtech.api.unification.material.Materials; import gregtech.api.util.BlockUtility; import gregtech.api.util.CapesRegistry; diff --git a/src/main/java/gregtech/common/blocks/BlockFrame.java b/src/main/java/gregtech/common/blocks/BlockFrame.java index 8a823bbafd7..799d15a7cd3 100644 --- a/src/main/java/gregtech/common/blocks/BlockFrame.java +++ b/src/main/java/gregtech/common/blocks/BlockFrame.java @@ -8,7 +8,6 @@ import gregtech.api.recipes.ModHandler; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.info.MaterialIconType; -import gregtech.api.util.GTLog; import gregtech.client.model.MaterialStateMapper; import gregtech.client.model.modelfactories.MaterialBlockModelLoader; import gregtech.common.ConfigHolder; diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index fb30de08f06..cd8b67874e0 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -5,8 +5,8 @@ import gregtech.api.block.machines.BlockMachine; import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.graphnet.pipenetold.longdist.BlockLongDistancePipe; +import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; @@ -537,7 +537,8 @@ public static void registerStateMappers() { for (MaterialRegistry registry : GregTechAPI.materialManager.getRegistries()) { for (CableBlock cable : CABLES.get(registry.getModid())) { - ModelLoader.setCustomStateMapper(cable, new SimpleStateMapper(cable.getStructure().getModel().getLoc())); + ModelLoader.setCustomStateMapper(cable, + new SimpleStateMapper(cable.getStructure().getModel().getLoc())); } for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) { ModelLoader.setCustomStateMapper(pipe, new SimpleStateMapper(pipe.getStructure().getModel().getLoc())); diff --git a/src/main/java/gregtech/common/blocks/properties/PropertyByte.java b/src/main/java/gregtech/common/blocks/properties/PropertyByte.java index 3042eaca500..3a270a0c5f4 100644 --- a/src/main/java/gregtech/common/blocks/properties/PropertyByte.java +++ b/src/main/java/gregtech/common/blocks/properties/PropertyByte.java @@ -1,13 +1,10 @@ package gregtech.common.blocks.properties; +import net.minecraft.block.properties.PropertyHelper; import com.google.common.base.Optional; import com.google.common.collect.ImmutableSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - -import net.minecraft.block.properties.PropertyHelper; -import net.minecraft.block.properties.PropertyInteger; - import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -15,6 +12,7 @@ import java.util.Set; public class PropertyByte extends PropertyHelper { + private final ImmutableSet allowedValues; protected PropertyByte(String name, byte min, byte max) { @@ -22,15 +20,12 @@ protected PropertyByte(String name, byte min, byte max) { if (min < 0) { throw new IllegalArgumentException("Min value of " + name + " must be 0 or greater"); - } - else if (max <= min) { + } else if (max <= min) { throw new IllegalArgumentException("Max value of " + name + " must be greater than min (" + min + ")"); - } - else { + } else { Set set = new ObjectOpenHashSet<>(); - for (byte i = min; i <= max; ++i) - { + for (byte i = min; i <= max; ++i) { set.add(i); } @@ -39,8 +34,7 @@ else if (max <= min) { } @Override - public @NotNull Collection getAllowedValues() - { + public @NotNull Collection getAllowedValues() { return this.allowedValues; } @@ -48,25 +42,20 @@ else if (max <= min) { public boolean equals(Object other) { if (this == other) { return true; - } - else if (other instanceof PropertyByte propertyByte && super.equals(other)) { + } else if (other instanceof PropertyByte propertyByte && super.equals(other)) { return this.allowedValues.equals(propertyByte.allowedValues); - } - else - { + } else { return false; } } @Override - public int hashCode() - { + public int hashCode() { return 31 * super.hashCode() + this.allowedValues.hashCode(); } @Contract("_, _, _ -> new") - public static @NotNull PropertyByte create(String name, byte min, byte max) - { + public static @NotNull PropertyByte create(String name, byte min, byte max) { return new PropertyByte(name, min, max); } @@ -85,8 +74,7 @@ public int hashCode() * Get the name for the given value. */ @Override - public @NotNull String getName(Byte value) - { + public @NotNull String getName(Byte value) { return value.toString(); } } diff --git a/src/main/java/gregtech/common/blocks/properties/PropertyShort.java b/src/main/java/gregtech/common/blocks/properties/PropertyShort.java index 87fc052920c..7f8c0f0cf51 100644 --- a/src/main/java/gregtech/common/blocks/properties/PropertyShort.java +++ b/src/main/java/gregtech/common/blocks/properties/PropertyShort.java @@ -1,12 +1,10 @@ package gregtech.common.blocks.properties; +import net.minecraft.block.properties.PropertyHelper; import com.google.common.base.Optional; import com.google.common.collect.ImmutableSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - -import net.minecraft.block.properties.PropertyHelper; - import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -14,6 +12,7 @@ import java.util.Set; public class PropertyShort extends PropertyHelper { + private final ImmutableSet allowedValues; protected PropertyShort(String name, short min, short max) { @@ -21,15 +20,12 @@ protected PropertyShort(String name, short min, short max) { if (min < 0) { throw new IllegalArgumentException("Min value of " + name + " must be 0 or greater"); - } - else if (max <= min) { + } else if (max <= min) { throw new IllegalArgumentException("Max value of " + name + " must be greater than min (" + min + ")"); - } - else { + } else { Set set = new ObjectOpenHashSet<>(); - for (short i = min; i <= max; ++i) - { + for (short i = min; i <= max; ++i) { set.add(i); } @@ -38,8 +34,7 @@ else if (max <= min) { } @Override - public @NotNull Collection getAllowedValues() - { + public @NotNull Collection getAllowedValues() { return this.allowedValues; } @@ -47,25 +42,20 @@ else if (max <= min) { public boolean equals(Object other) { if (this == other) { return true; - } - else if (other instanceof PropertyShort propertyByte && super.equals(other)) { + } else if (other instanceof PropertyShort propertyByte && super.equals(other)) { return this.allowedValues.equals(propertyByte.allowedValues); - } - else - { + } else { return false; } } @Override - public int hashCode() - { + public int hashCode() { return 31 * super.hashCode() + this.allowedValues.hashCode(); } @Contract("_, _, _ -> new") - public static @NotNull PropertyShort create(String name, short min, short max) - { + public static @NotNull PropertyShort create(String name, short min, short max) { return new PropertyShort(name, min, max); } @@ -84,8 +74,7 @@ public int hashCode() * Get the name for the given value. */ @Override - public @NotNull String getName(Short value) - { + public @NotNull String getName(Short value) { return value.toString(); } } diff --git a/src/main/java/gregtech/common/command/CommandRecipeCheck.java b/src/main/java/gregtech/common/command/CommandRecipeCheck.java index 1d9a9d0adc1..3158ffb2835 100644 --- a/src/main/java/gregtech/common/command/CommandRecipeCheck.java +++ b/src/main/java/gregtech/common/command/CommandRecipeCheck.java @@ -1,27 +1,13 @@ package gregtech.common.command; -import gregtech.api.block.machines.MachineItemBlock; -import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; -import gregtech.api.items.materialitem.MetaPrefixItem; -import gregtech.api.items.metaitem.MetaItem; -import gregtech.api.items.metaitem.MetaItem.MetaValueItem; -import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.chance.output.impl.ChancedFluidOutput; import gregtech.api.recipes.chance.output.impl.ChancedItemOutput; import gregtech.api.recipes.ingredients.GTRecipeInput; -import gregtech.api.recipes.ingredients.IntCircuitIngredient; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.ore.OrePrefix; import gregtech.api.util.GTLog; import gregtech.api.util.GTStringUtils; -import gregtech.api.util.GTUtility; -import gregtech.common.blocks.BlockCompressed; -import gregtech.common.blocks.BlockFrame; -import gregtech.common.items.MetaItems; -import net.minecraft.block.Block; import net.minecraft.command.CommandBase; import net.minecraft.command.ICommandSender; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 2adcdb29188..a999c19f8d2 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -57,14 +57,14 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO @Override protected int doTransferItems(IItemHandler itemHandler, IItemHandler myItemHandler, int maxTransferAmount) { -// if (conveyorMode == ConveyorMode.EXPORT && itemHandler instanceof ItemNetHandler && -// transferMode == TransferMode.KEEP_EXACT) { -// return 0; -// } -// if (conveyorMode == ConveyorMode.IMPORT && myItemHandler instanceof ItemNetHandler && -// transferMode == TransferMode.KEEP_EXACT) { -// return 0; -// } + // if (conveyorMode == ConveyorMode.EXPORT && itemHandler instanceof ItemNetHandler && + // transferMode == TransferMode.KEEP_EXACT) { + // return 0; + // } + // if (conveyorMode == ConveyorMode.IMPORT && myItemHandler instanceof ItemNetHandler && + // transferMode == TransferMode.KEEP_EXACT) { + // return 0; + // } return switch (transferMode) { case TRANSFER_ANY -> doTransferItemsAny(itemHandler, myItemHandler, maxTransferAmount); case TRANSFER_EXACT -> doTransferExact(itemHandler, myItemHandler, maxTransferAmount); diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index 1a29afdeb9b..1d774736d84 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -202,7 +202,8 @@ public void registerSubItems() { new ItemFluidContainer()) .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); - MaterialFluidProperties properties = Materials.Steel.getProperty(PropertyKey.PIPENET_PROPERTIES).getProperty(MaterialFluidProperties.KEY); + MaterialFluidProperties properties = Materials.Steel.getProperty(PropertyKey.PIPENET_PROPERTIES) + .getProperty(MaterialFluidProperties.KEY); FLUID_CELL_LARGE_STEEL = addItem(80, "large_fluid_cell.steel") .addComponents(new FilteredFluidStats(8000, properties.getMaxFluidTemperature(), @@ -211,7 +212,8 @@ public void registerSubItems() { .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Steel, M * 4))) // ingot * 4 .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); - properties = Materials.Aluminium.getProperty(PropertyKey.PIPENET_PROPERTIES).getProperty(MaterialFluidProperties.KEY); + properties = Materials.Aluminium.getProperty(PropertyKey.PIPENET_PROPERTIES) + .getProperty(MaterialFluidProperties.KEY); FLUID_CELL_LARGE_ALUMINIUM = addItem(81, "large_fluid_cell.aluminium") .addComponents(new FilteredFluidStats(32000, @@ -220,7 +222,8 @@ public void registerSubItems() { .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Aluminium, M * 4))) // ingot * 4 .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); - properties = Materials.StainlessSteel.getProperty(PropertyKey.PIPENET_PROPERTIES).getProperty(MaterialFluidProperties.KEY); + properties = Materials.StainlessSteel.getProperty(PropertyKey.PIPENET_PROPERTIES) + .getProperty(MaterialFluidProperties.KEY); FLUID_CELL_LARGE_STAINLESS_STEEL = addItem(82, "large_fluid_cell.stainless_steel") .addComponents(new FilteredFluidStats(64000, @@ -229,7 +232,8 @@ public void registerSubItems() { .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.StainlessSteel, M * 6))) // ingot * 6 .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); - properties = Materials.Titanium.getProperty(PropertyKey.PIPENET_PROPERTIES).getProperty(MaterialFluidProperties.KEY); + properties = Materials.Titanium.getProperty(PropertyKey.PIPENET_PROPERTIES) + .getProperty(MaterialFluidProperties.KEY); FLUID_CELL_LARGE_TITANIUM = addItem(83, "large_fluid_cell.titanium") .addComponents(new FilteredFluidStats(128000, @@ -238,7 +242,8 @@ public void registerSubItems() { .setMaterialInfo(new ItemMaterialInfo(new MaterialStack(Materials.Titanium, M * 6))) // ingot * 6 .setCreativeTabs(GTCreativeTabs.TAB_GREGTECH_TOOLS); - properties = Materials.TungstenSteel.getProperty(PropertyKey.PIPENET_PROPERTIES).getProperty(MaterialFluidProperties.KEY); + properties = Materials.TungstenSteel.getProperty(PropertyKey.PIPENET_PROPERTIES) + .getProperty(MaterialFluidProperties.KEY); FLUID_CELL_LARGE_TUNGSTEN_STEEL = addItem(84, "large_fluid_cell.tungstensteel") .addComponents(new FilteredFluidStats(512000, diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java index 0ed7b91661c..a0881c35bbd 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java @@ -1254,7 +1254,7 @@ public static void registerMetaTileEntities( } public static T registerMetaTileEntity(int id, T sampleMetaTileEntity) { - if (sampleMetaTileEntity instanceof IMultiblockAbilityPart abilityPart) { + if (sampleMetaTileEntity instanceof IMultiblockAbilityPartabilityPart) { MultiblockAbility.registerMultiblockAbility(abilityPart.getAbility(), sampleMetaTileEntity); } if (sampleMetaTileEntity instanceof MultiblockControllerBase && Mods.JustEnoughItems.isModLoaded()) { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java index d66cbb56001..2fed122b289 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java @@ -4,8 +4,6 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; import gregtech.api.capability.IEnergyContainer; -import gregtech.api.capability.ILaserRelay; -import gregtech.api.capability.ILaserContainer; import gregtech.api.capability.impl.EnergyContainerList; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; @@ -43,7 +41,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.math.BigInteger; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java index 027acd17680..959c9b69fc8 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java @@ -3,6 +3,7 @@ import gregtech.api.GTValues; import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.data.IDataAccess; +import gregtech.api.capability.data.query.RecipeDataQuery; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; @@ -17,7 +18,6 @@ import gregtech.api.recipes.recipeproperties.ResearchProperty; import gregtech.api.util.GTUtility; import gregtech.api.util.RelativeDirection; -import gregtech.api.capability.data.query.RecipeDataQuery; import gregtech.client.particle.GTLaserBeamParticle; import gregtech.client.particle.GTParticleManager; import gregtech.client.renderer.ICubeRenderer; diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java index 7e61044b8ff..a5fe6ccf84e 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java @@ -66,7 +66,7 @@ import java.util.function.Supplier; public class MetaTileEntityHPCA extends MultiblockWithDisplayBase - implements IComputationProvider, IControllable, IProgressBarMultiblock { + implements IComputationProvider, IControllable, IProgressBarMultiblock { private static final double IDLE_TEMPERATURE = 200; private static final double DAMAGE_TEMPERATURE = 1000; diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java index 7b89e941084..fa99b9a3db6 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java @@ -2,6 +2,7 @@ import gregtech.api.GTValues; import gregtech.api.capability.data.IDataAccess; +import gregtech.api.capability.data.query.ComputationQuery; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; @@ -12,7 +13,6 @@ import gregtech.api.pattern.PatternMatchContext; import gregtech.api.util.TextComponentUtil; import gregtech.api.util.TextFormattingUtil; -import gregtech.api.capability.data.query.ComputationQuery; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.common.blocks.BlockComputerCasing; diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java index 2cb741a778c..71e8d5f017a 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java @@ -1,9 +1,10 @@ package gregtech.common.metatileentities.multi.electric; import gregtech.api.GTValues; +import gregtech.api.capability.IObjectHolder; import gregtech.api.capability.data.IComputationConsumer; import gregtech.api.capability.data.IDataAccess; -import gregtech.api.capability.IObjectHolder; +import gregtech.api.capability.data.query.ComputationQuery; import gregtech.api.capability.impl.ComputationRecipeLogic; import gregtech.api.capability.impl.ItemHandlerList; import gregtech.api.metatileentity.MetaTileEntity; @@ -19,7 +20,6 @@ import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMaps; import gregtech.api.util.GTUtility; -import gregtech.api.capability.data.query.ComputationQuery; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.common.ConfigHolder; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java index afaad7dbc8f..532708723da 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java @@ -5,15 +5,15 @@ import gregtech.api.capability.data.IComputationDataAccess; import gregtech.api.capability.data.IComputationProvider; import gregtech.api.capability.data.IDataAccess; +import gregtech.api.capability.data.query.DataQueryObject; +import gregtech.api.capability.data.query.IBridgeable; +import gregtech.api.capability.data.query.IComputationQuery; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; import gregtech.api.util.GTUtility; -import gregtech.api.capability.data.query.DataQueryObject; -import gregtech.api.capability.data.query.IBridgeable; -import gregtech.api.capability.data.query.IComputationQuery; import gregtech.client.renderer.texture.Textures; import net.minecraft.client.resources.I18n; @@ -33,8 +33,9 @@ import java.util.List; import java.util.Set; -public class MetaTileEntityComputationHatch extends MetaTileEntityMultiblockPart implements IMultiblockAbilityPart, - IComputationDataAccess { +public class MetaTileEntityComputationHatch extends MetaTileEntityMultiblockPart + implements IMultiblockAbilityPart, + IComputationDataAccess { private final boolean isTransmitter; @@ -63,10 +64,12 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { MultiblockControllerBase controller = getController(); if (!controller.isActive()) return false; - if (controller instanceof IComputationProvider provider && queryObject instanceof IComputationQuery cq) { + if (controller instanceof IComputationProvider provider && + queryObject instanceof IComputationQuery cq) { cq.registerProvider(provider); } - List reception = controller.getAbilities(MultiblockAbility.COMPUTATION_DATA_RECEPTION); + List reception = controller + .getAbilities(MultiblockAbility.COMPUTATION_DATA_RECEPTION); if (queryObject instanceof IBridgeable bridgeable && reception.size() > 1) { bridgeable.setBridged(); } @@ -83,7 +86,6 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { return false; } - @Override protected boolean openGUIOnRightClick() { return false; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java index 2778e521187..87dafb5989b 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java @@ -2,6 +2,9 @@ import gregtech.api.GTValues; import gregtech.api.capability.data.IDataAccess; +import gregtech.api.capability.data.query.DataAccessFormat; +import gregtech.api.capability.data.query.DataQueryObject; +import gregtech.api.capability.data.query.RecipeDataQuery; import gregtech.api.capability.impl.NotifiableItemStackHandler; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; @@ -18,9 +21,6 @@ import gregtech.api.util.AssemblyLineManager; import gregtech.api.util.ItemStackHashStrategy; import gregtech.api.util.LocalizationUtils; -import gregtech.api.capability.data.query.DataAccessFormat; -import gregtech.api.capability.data.query.DataQueryObject; -import gregtech.api.capability.data.query.RecipeDataQuery; import gregtech.client.renderer.texture.Textures; import gregtech.client.utils.TooltipHelper; import gregtech.common.ConfigHolder; @@ -50,7 +50,7 @@ public class MetaTileEntityDataAccessHatch extends MetaTileEntityMultiblockNotifiablePart implements IMultiblockAbilityPart, IDataAccess, - IDataInfoProvider { + IDataInfoProvider { private final Set recipes; private final boolean isCreative; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityLaserHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityLaserHatch.java index 6934ab46916..fa5466c1e79 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityLaserHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityLaserHatch.java @@ -4,7 +4,6 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserContainer; import gregtech.api.capability.impl.LaserContainerHandler; -import gregtech.api.gui.ModularUI; import gregtech.api.metatileentity.IDataInfoProvider; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; @@ -13,7 +12,6 @@ import gregtech.client.renderer.texture.Textures; import net.minecraft.client.resources.I18n; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java index 70f12553cc2..abb51b7f299 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java @@ -4,14 +4,14 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.data.IDataAccess; import gregtech.api.capability.data.IStandardDataAccess; +import gregtech.api.capability.data.query.DataQueryObject; +import gregtech.api.capability.data.query.IBridgeable; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; import gregtech.api.util.GTUtility; -import gregtech.api.capability.data.query.DataQueryObject; -import gregtech.api.capability.data.query.IBridgeable; import gregtech.client.renderer.texture.Textures; import net.minecraft.client.resources.I18n; @@ -32,8 +32,8 @@ import java.util.Set; public class MetaTileEntityOpticalDataHatch extends MetaTileEntityMultiblockNotifiablePart implements - IMultiblockAbilityPart, - IStandardDataAccess { + IMultiblockAbilityPart, + IStandardDataAccess { private final Set recentQueries = GTUtility.createWeakHashSet(); @@ -70,7 +70,8 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { MultiblockControllerBase controller = getController(); if (!controller.isActive()) return false; - if (IDataAccess.accessDatas(controller.getAbilities(MultiblockAbility.DATA_ACCESS_HATCH), queryObject)) return true; + if (IDataAccess.accessDatas(controller.getAbilities(MultiblockAbility.DATA_ACCESS_HATCH), queryObject)) + return true; List reception = controller.getAbilities(MultiblockAbility.OPTICAL_DATA_RECEPTION); if (queryObject instanceof IBridgeable bridgeable && reception.size() > 1) { diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java index a3795288cc8..d4aed6a1893 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java @@ -13,7 +13,6 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; import gregtech.client.utils.TooltipHelper; - import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; import net.minecraft.client.renderer.texture.TextureAtlasSprite; diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java index 31886adb0f6..b4455d1d4bd 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java @@ -1,10 +1,10 @@ package gregtech.common.metatileentities.storage; -import gregtech.api.metatileentity.IDataInfoProvider; -import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; import gregtech.api.graphnet.pipenetold.longdist.LongDistanceNetwork; import gregtech.api.graphnet.pipenetold.longdist.LongDistancePipeType; +import gregtech.api.metatileentity.IDataInfoProvider; +import gregtech.api.metatileentity.MetaTileEntity; import gregtech.common.ConfigHolder; import net.minecraft.client.resources.I18n; diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index aa6c809ef94..159322a20b0 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -3,22 +3,17 @@ import gregtech.api.graphnet.gather.GatherStructuresEvent; import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; - import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.unification.material.registry.MaterialRegistry; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.block.state.IBlockState; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; - import net.minecraftforge.common.MinecraftForge; -import org.apache.commons.lang3.tuple.Pair; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import java.util.Map; @@ -53,7 +48,7 @@ public void partialBurn(IBlockState state, World world, BlockPos pos) { CableStructure structure = (CableStructure) getStructure(); if (structure.partialBurnStructure() != null) { CableBlock newBlock = CACHE.get(registry).get(structure.partialBurnStructure()); - //noinspection deprecation + // noinspection deprecation world.setBlockState(pos, newBlock.getStateFromMeta(this.getMetaFromState(state))); } } diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java index 59dd4ea2023..48ad1673d65 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java @@ -1,15 +1,12 @@ package gregtech.common.pipelike.block.cable; -import com.github.bsideup.jabel.Desugar; - import gregtech.api.graphnet.pipenet.physical.IInsulatable; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; - import gregtech.api.unification.ore.OrePrefix; - import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.client.renderer.pipe.CableModel; +import com.github.bsideup.jabel.Desugar; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -18,31 +15,32 @@ @Desugar public record CableStructure(String name, int material, int costFactor, OrePrefix ore, @Nullable CableStructure partialBurnStructure, @Nullable Integer partialBurnThreshold, - float renderThickness, AbstractPipeModel model) implements IPipeMaterialStructure, IInsulatable { + float renderThickness, AbstractPipeModel model) + implements IPipeMaterialStructure, IInsulatable { public static final int INSULATION_BURN_TEMP = 1000; - public static final CableStructure WIRE_SINGLE = - new CableStructure("wire_single", 1, 2, OrePrefix.wireGtSingle, null, null, 0.125f, CableModel.INSTANCE); - public static final CableStructure WIRE_DOUBLE = - new CableStructure("wire_double", 2, 2, OrePrefix.wireGtDouble, null, null, 0.25f, CableModel.INSTANCE); - public static final CableStructure WIRE_QUADRUPLE = - new CableStructure("wire_quadruple", 4, 3, OrePrefix.wireGtQuadruple, null, null, 0.375f, CableModel.INSTANCE); - public static final CableStructure WIRE_OCTAL = - new CableStructure("wire_octal", 8, 3, OrePrefix.wireGtOctal, null, null, 0.5f, CableModel.INSTANCE); - public static final CableStructure WIRE_HEX = - new CableStructure("wire_hex", 16, 3, OrePrefix.wireGtHex, null, null, 0.75f, CableModel.INSTANCE); - - public static final CableStructure CABLE_SINGLE = - new CableStructure("cable_single", 1, 1, OrePrefix.cableGtSingle, WIRE_SINGLE, INSULATION_BURN_TEMP, 0.25f, CableModel.INSULATED_INSTANCES[0]); - public static final CableStructure CABLE_DOUBLE = - new CableStructure("cable_double", 2, 1, OrePrefix.cableGtDouble, WIRE_DOUBLE, INSULATION_BURN_TEMP, 0.375f, CableModel.INSULATED_INSTANCES[1]); - public static final CableStructure CABLE_QUADRUPLE = - new CableStructure("cable_quadruple", 4, 1, OrePrefix.cableGtQuadruple, WIRE_QUADRUPLE, INSULATION_BURN_TEMP, 0.5f, CableModel.INSULATED_INSTANCES[2]); - public static final CableStructure CABLE_OCTAL = - new CableStructure("cable_octal", 8, 1, OrePrefix.cableGtOctal, WIRE_OCTAL, INSULATION_BURN_TEMP, 0.75f, CableModel.INSULATED_INSTANCES[3]); - public static final CableStructure CABLE_HEX = - new CableStructure("cable_hex", 16, 1, OrePrefix.cableGtHex, WIRE_HEX, INSULATION_BURN_TEMP, 1f, CableModel.INSULATED_INSTANCES[4]); + public static final CableStructure WIRE_SINGLE = new CableStructure("wire_single", 1, 2, OrePrefix.wireGtSingle, + null, null, 0.125f, CableModel.INSTANCE); + public static final CableStructure WIRE_DOUBLE = new CableStructure("wire_double", 2, 2, OrePrefix.wireGtDouble, + null, null, 0.25f, CableModel.INSTANCE); + public static final CableStructure WIRE_QUADRUPLE = new CableStructure("wire_quadruple", 4, 3, + OrePrefix.wireGtQuadruple, null, null, 0.375f, CableModel.INSTANCE); + public static final CableStructure WIRE_OCTAL = new CableStructure("wire_octal", 8, 3, OrePrefix.wireGtOctal, null, + null, 0.5f, CableModel.INSTANCE); + public static final CableStructure WIRE_HEX = new CableStructure("wire_hex", 16, 3, OrePrefix.wireGtHex, null, null, + 0.75f, CableModel.INSTANCE); + + public static final CableStructure CABLE_SINGLE = new CableStructure("cable_single", 1, 1, OrePrefix.cableGtSingle, + WIRE_SINGLE, INSULATION_BURN_TEMP, 0.25f, CableModel.INSULATED_INSTANCES[0]); + public static final CableStructure CABLE_DOUBLE = new CableStructure("cable_double", 2, 1, OrePrefix.cableGtDouble, + WIRE_DOUBLE, INSULATION_BURN_TEMP, 0.375f, CableModel.INSULATED_INSTANCES[1]); + public static final CableStructure CABLE_QUADRUPLE = new CableStructure("cable_quadruple", 4, 1, + OrePrefix.cableGtQuadruple, WIRE_QUADRUPLE, INSULATION_BURN_TEMP, 0.5f, CableModel.INSULATED_INSTANCES[2]); + public static final CableStructure CABLE_OCTAL = new CableStructure("cable_octal", 8, 1, OrePrefix.cableGtOctal, + WIRE_OCTAL, INSULATION_BURN_TEMP, 0.75f, CableModel.INSULATED_INSTANCES[3]); + public static final CableStructure CABLE_HEX = new CableStructure("cable_hex", 16, 1, OrePrefix.cableGtHex, + WIRE_HEX, INSULATION_BURN_TEMP, 1f, CableModel.INSULATED_INSTANCES[4]); @Override public @NotNull String getName() { diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java index a5f1c40f6f2..432094aa2dc 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java @@ -2,13 +2,10 @@ import gregtech.api.graphnet.gather.GatherStructuresEvent; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; -import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; -import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.handlers.LaserNetHandler; -import gregtech.common.pipelike.handlers.OpticalNetHandler; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java index 432ffa3c3d5..8909d771f22 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java @@ -1,16 +1,13 @@ package gregtech.common.pipelike.block.laser; -import com.github.bsideup.jabel.Desugar; - import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.client.renderer.pipe.ActivablePipeModel; -import gregtech.common.pipelike.block.optical.OpticalStructure; - import net.minecraft.util.EnumFacing; +import com.github.bsideup.jabel.Desugar; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java index 49f3d2a94a6..7ace175f077 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java @@ -2,11 +2,9 @@ import gregtech.api.graphnet.gather.GatherStructuresEvent; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; -import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; - import gregtech.common.pipelike.handlers.OpticalNetHandler; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java index 21b06e40680..72efdf5a99e 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java @@ -1,16 +1,13 @@ package gregtech.common.pipelike.block.optical; -import com.github.bsideup.jabel.Desugar; - import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.client.renderer.pipe.ActivablePipeModel; -import gregtech.common.pipelike.block.cable.CableStructure; - import net.minecraft.util.EnumFacing; +import com.github.bsideup.jabel.Desugar; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; @@ -18,7 +15,8 @@ @Desugar public record OpticalStructure(String name, float renderThickness, ActivablePipeModel model) implements IPipeStructure { - public static final OpticalStructure INSTANCE = new OpticalStructure("standard", 0.375f, ActivablePipeModel.OPTICAL); + public static final OpticalStructure INSTANCE = new OpticalStructure("standard", 0.375f, + ActivablePipeModel.OPTICAL); @Override public boolean canConnectTo(EnumFacing side, byte connectionMask) { diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java index 76e3c13b980..91ae8de6e23 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java @@ -1,30 +1,13 @@ package gregtech.common.pipelike.block.pipe; import gregtech.api.graphnet.gather.GatherStructuresEvent; -import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.IFreezable; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; - -import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.unification.material.registry.MaterialRegistry; -import gregtech.api.util.EntityDamageUtil; - -import net.minecraft.block.state.IBlockState; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fml.common.FMLCommonHandler; - -import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.NotNull; - import java.util.Set; public class PipeBlock extends PipeMaterialBlock implements IBurnable, IFreezable { diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java index ddcc6bbf058..35b1716a192 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java @@ -1,16 +1,11 @@ package gregtech.common.pipelike.block.pipe; -import com.github.bsideup.jabel.Desugar; - import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.unification.ore.OrePrefix; - import gregtech.client.renderer.pipe.AbstractPipeModel; -import gregtech.client.renderer.pipe.PipeItemModel; import gregtech.client.renderer.pipe.PipeModel; -import gregtech.client.renderer.pipe.util.WoodCacheKey; - +import com.github.bsideup.jabel.Desugar; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; @@ -20,38 +15,37 @@ public record PipeStructure(String name, int material, int channelCount, boolean float renderThickness, PipeModel model) implements IPipeMaterialStructure { - public static final PipeStructure TINY = - new PipeStructure("tiny", 1, 1, false, OrePrefix.pipeTiny, 0.25f, PipeModel.INSTANCES[0]); - public static final PipeStructure SMALL = - new PipeStructure("small", 2, 1, false, OrePrefix.pipeSmall, 0.375f, PipeModel.INSTANCES[1]); - public static final PipeStructure NORMAL = - new PipeStructure("normal", 6, 1, false, OrePrefix.pipeNormal, 0.5f, PipeModel.INSTANCES[2]); - public static final PipeStructure LARGE = - new PipeStructure("large", 12, 1, false, OrePrefix.pipeLarge, 0.75f, PipeModel.INSTANCES[3]); - public static final PipeStructure HUGE = - new PipeStructure("huge", 24, 1, false, OrePrefix.pipeHuge, 0.875f, PipeModel.INSTANCES[4]); - - public static final PipeStructure QUADRUPLE = - new PipeStructure("quadruple", 8, 4, false, OrePrefix.pipeQuadruple, 0.95f, PipeModel.INSTANCES[5]); - public static final PipeStructure NONUPLE = - new PipeStructure("nonuple", 18, 9, false, OrePrefix.pipeNonuple, 0.95f, PipeModel.INSTANCES[6]); - - - public static final PipeStructure TINY_RESTRICTIVE = - new PipeStructure("tiny_restrictive", 1, 1, true, OrePrefix.pipeTinyRestrictive, 0.25f, PipeModel.RESTRICTIVE_INSTANCES[0]); - public static final PipeStructure SMALL_RESTRICTIVE = - new PipeStructure("small_restrictive", 2, 1, true, OrePrefix.pipeSmallRestrictive, 0.375f, PipeModel.RESTRICTIVE_INSTANCES[1]); - public static final PipeStructure NORMAL_RESTRICTIVE = - new PipeStructure("normal_restrictive", 6, 1, true, OrePrefix.pipeNormalRestrictive, 0.5f, PipeModel.RESTRICTIVE_INSTANCES[2]); - public static final PipeStructure LARGE_RESTRICTIVE = - new PipeStructure("large_restrictive", 12, 1, true, OrePrefix.pipeLargeRestrictive, 0.75f, PipeModel.RESTRICTIVE_INSTANCES[3]); - public static final PipeStructure HUGE_RESTRICTIVE = - new PipeStructure("huge_restrictive", 24, 1, true, OrePrefix.pipeHugeRestrictive, 0.875f, PipeModel.RESTRICTIVE_INSTANCES[4]); - - public static final PipeStructure QUADRUPLE_RESTRICTIVE = - new PipeStructure("quadruple_restrictive", 8, 4, true, OrePrefix.pipeQuadrupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[5]); - public static final PipeStructure NONUPLE_RESTRICTIVE = - new PipeStructure("nonuple_restrictive", 18, 9, true, OrePrefix.pipeNonupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[6]); + public static final PipeStructure TINY = new PipeStructure("tiny", 1, 1, false, OrePrefix.pipeTiny, 0.25f, + PipeModel.INSTANCES[0]); + public static final PipeStructure SMALL = new PipeStructure("small", 2, 1, false, OrePrefix.pipeSmall, 0.375f, + PipeModel.INSTANCES[1]); + public static final PipeStructure NORMAL = new PipeStructure("normal", 6, 1, false, OrePrefix.pipeNormal, 0.5f, + PipeModel.INSTANCES[2]); + public static final PipeStructure LARGE = new PipeStructure("large", 12, 1, false, OrePrefix.pipeLarge, 0.75f, + PipeModel.INSTANCES[3]); + public static final PipeStructure HUGE = new PipeStructure("huge", 24, 1, false, OrePrefix.pipeHuge, 0.875f, + PipeModel.INSTANCES[4]); + + public static final PipeStructure QUADRUPLE = new PipeStructure("quadruple", 8, 4, false, OrePrefix.pipeQuadruple, + 0.95f, PipeModel.INSTANCES[5]); + public static final PipeStructure NONUPLE = new PipeStructure("nonuple", 18, 9, false, OrePrefix.pipeNonuple, 0.95f, + PipeModel.INSTANCES[6]); + + public static final PipeStructure TINY_RESTRICTIVE = new PipeStructure("tiny_restrictive", 1, 1, true, + OrePrefix.pipeTinyRestrictive, 0.25f, PipeModel.RESTRICTIVE_INSTANCES[0]); + public static final PipeStructure SMALL_RESTRICTIVE = new PipeStructure("small_restrictive", 2, 1, true, + OrePrefix.pipeSmallRestrictive, 0.375f, PipeModel.RESTRICTIVE_INSTANCES[1]); + public static final PipeStructure NORMAL_RESTRICTIVE = new PipeStructure("normal_restrictive", 6, 1, true, + OrePrefix.pipeNormalRestrictive, 0.5f, PipeModel.RESTRICTIVE_INSTANCES[2]); + public static final PipeStructure LARGE_RESTRICTIVE = new PipeStructure("large_restrictive", 12, 1, true, + OrePrefix.pipeLargeRestrictive, 0.75f, PipeModel.RESTRICTIVE_INSTANCES[3]); + public static final PipeStructure HUGE_RESTRICTIVE = new PipeStructure("huge_restrictive", 24, 1, true, + OrePrefix.pipeHugeRestrictive, 0.875f, PipeModel.RESTRICTIVE_INSTANCES[4]); + + public static final PipeStructure QUADRUPLE_RESTRICTIVE = new PipeStructure("quadruple_restrictive", 8, 4, true, + OrePrefix.pipeQuadrupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[5]); + public static final PipeStructure NONUPLE_RESTRICTIVE = new PipeStructure("nonuple_restrictive", 18, 9, true, + OrePrefix.pipeNonupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[6]); @Override public @NotNull String getName() { @@ -94,5 +88,4 @@ public static void registerDefaultStructures(Consumer register) { register.accept(QUADRUPLE_RESTRICTIVE); register.accept(NONUPLE_RESTRICTIVE); } - } diff --git a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java index d79ab7d1562..2f8f1da291c 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java @@ -4,9 +4,7 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.common.pipelike.block.laser.LaserStructure; -import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.net.laser.WorldLaserNet; -import gregtech.common.pipelike.net.optical.WorldOpticalNet; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; diff --git a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java index a4907c6599c..d35e551c331 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java @@ -3,7 +3,6 @@ import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; - import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.net.optical.WorldOpticalNet; diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 3a9bc6a2aff..d01b7514e84 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -4,25 +4,23 @@ import gregtech.api.fluids.FluidBuilder; import gregtech.api.fluids.store.FluidStorageKeys; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.FluidProperty; +import gregtech.api.unification.material.properties.MaterialProperties; +import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.ore.IOreRegistrationHandler; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.util.function.TriConsumer; import gregtech.common.pipelike.block.cable.CableStructure; -import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.logic.ThroughputLogic; -import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.unification.material.properties.MaterialProperties; -import gregtech.api.unification.material.properties.PipeNetProperties; - import gregtech.common.pipelike.block.pipe.PipeStructure; - import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; import gregtech.common.pipelike.net.energy.SuperconductorLogic; import gregtech.common.pipelike.net.energy.VoltageLimitLogic; @@ -30,10 +28,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; - import net.minecraftforge.fluids.Fluid; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static gregtech.api.unification.material.info.MaterialFlags.GENERATE_FOIL; @@ -51,15 +47,19 @@ public final class MaterialEnergyProperties implements PipeNetProperties.IPipeNe /** * Generate a MaterialEnergyProperties - * @param voltageLimit the voltage limit for the cable - * @param amperageLimit the base amperage for the cable. - * @param lossPerAmp the base loss per amp per block traveled. - * @param temperatureLimit the melt temperature of the cable. If zero, autogeneration will be attempted. + * + * @param voltageLimit the voltage limit for the cable + * @param amperageLimit the base amperage for the cable. + * @param lossPerAmp the base loss per amp per block traveled. + * @param temperatureLimit the melt temperature of the cable. If zero, autogeneration will be + * attempted. * @param superconductorCriticalTemperature the superconductor temperature. When the temperature is at or below - * superconductor temperature, loss will be treated as zero. A superconductor - * temperature of 0 or less will be treated as not a superconductor. + * superconductor temperature, loss will be treated as zero. A + * superconductor + * temperature of 0 or less will be treated as not a superconductor. */ - public MaterialEnergyProperties(long voltageLimit, long amperageLimit, long lossPerAmp, int temperatureLimit, int superconductorCriticalTemperature) { + public MaterialEnergyProperties(long voltageLimit, long amperageLimit, long lossPerAmp, int temperatureLimit, + int superconductorCriticalTemperature) { this.voltageLimit = voltageLimit; this.amperageLimit = amperageLimit; this.temperatureLimit = temperatureLimit; @@ -71,19 +71,19 @@ public long getVoltageLimit() { return voltageLimit; } - public static MaterialEnergyProperties createT(long voltageLimit, long amperageLimit, long lossPerAmp, int temperatureLimit) { + public static MaterialEnergyProperties createT(long voltageLimit, long amperageLimit, long lossPerAmp, + int temperatureLimit) { return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, temperatureLimit, 0); - } - public static MaterialEnergyProperties createS(long voltageLimit, long amperageLimit, long lossPerAmp, int superconductorCriticalTemperature) { - return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, 0, superconductorCriticalTemperature); - + public static MaterialEnergyProperties createS(long voltageLimit, long amperageLimit, long lossPerAmp, + int superconductorCriticalTemperature) { + return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, 0, + superconductorCriticalTemperature); } public static MaterialEnergyProperties create(long voltageLimit, long amperageLimit, long lossPerAmp) { return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, 0, 0); - } public static IOreRegistrationHandler registrationHandler(TriConsumer handler) { @@ -111,7 +111,8 @@ public void verifyProperty(MaterialProperties properties) { if (properties.hasProperty(PropertyKey.INGOT)) { // Ensure all Materials with Cables and voltage tier IV or above have a Foil for recipe generation Material thisMaterial = properties.getMaterial(); - if (!isSuperconductor() && voltageLimit >= GTValues.V[GTValues.IV] && !thisMaterial.hasFlag(GENERATE_FOIL)) { + if (!isSuperconductor() && voltageLimit >= GTValues.V[GTValues.IV] && + !thisMaterial.hasFlag(GENERATE_FOIL)) { thisMaterial.addFlags(GENERATE_FOIL); } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index 414797c68ed..aee3ec85ac7 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -14,28 +14,19 @@ import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.FluidProperty; -import gregtech.api.unification.material.properties.IMaterialProperty; import gregtech.api.unification.material.properties.MaterialProperties; import gregtech.api.unification.material.properties.PipeNetProperties; - import gregtech.api.unification.material.properties.PropertyKey; - -import gregtech.api.unification.ore.IOreRegistrationHandler; -import gregtech.api.unification.ore.OrePrefix; -import gregtech.api.util.function.TriConsumer; import gregtech.common.pipelike.block.pipe.PipeStructure; - import gregtech.common.pipelike.net.fluid.FluidContainmentLogic; import gregtech.common.pipelike.net.fluid.WorldFluidNet; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fluids.Fluid; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnmodifiableView; @@ -44,8 +35,6 @@ import java.util.EnumSet; import java.util.Set; -import static gregtech.api.unification.material.info.MaterialFlags.NO_UNIFICATION; - public final class MaterialFluidProperties implements PipeNetProperties.IPipeNetMaterialProperty, IPropertyFluidFilter { public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>(); @@ -59,7 +48,8 @@ public final class MaterialFluidProperties implements PipeNetProperties.IPipeNet private final long baseThroughput; private final float priority; - public MaterialFluidProperties(long baseThroughput, int maxFluidTemperature, int minFluidTemperature, float priority) { + public MaterialFluidProperties(long baseThroughput, int maxFluidTemperature, int minFluidTemperature, + float priority) { this.baseThroughput = baseThroughput; this.maxFluidTemperature = maxFluidTemperature; this.minFluidTemperature = minFluidTemperature; @@ -75,7 +65,8 @@ public static MaterialFluidProperties createMax(long baseThroughput, int maxFlui } public static MaterialFluidProperties createMax(long baseThroughput, int maxFluidTemperature, float priority) { - return new MaterialFluidProperties(baseThroughput, maxFluidTemperature, FluidConstants.CRYOGENIC_FLUID_THRESHOLD + 1, priority); + return new MaterialFluidProperties(baseThroughput, maxFluidTemperature, + FluidConstants.CRYOGENIC_FLUID_THRESHOLD + 1, priority); } public static MaterialFluidProperties createMin(long baseThroughput, int minFluidTemperature) { diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index e607c58ac73..91650f40a65 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -6,16 +6,10 @@ import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.properties.IMaterialProperty; import gregtech.api.unification.material.properties.MaterialProperties; import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; -import gregtech.api.unification.ore.IOreRegistrationHandler; -import gregtech.api.unification.ore.OrePrefix; -import gregtech.api.util.function.TriConsumer; import gregtech.common.pipelike.block.pipe.PipeStructure; - import gregtech.common.pipelike.net.item.WorldItemNet; import net.minecraft.util.math.BlockPos; @@ -23,8 +17,6 @@ import org.jetbrains.annotations.Nullable; -import static gregtech.api.unification.material.info.MaterialFlags.NO_UNIFICATION; - public final class MaterialItemProperties implements PipeNetProperties.IPipeNetMaterialProperty { public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>(); @@ -36,6 +28,7 @@ public MaterialItemProperties(long baseItemsPer5Ticks, float priority) { this.baseItemsPer5Ticks = baseItemsPer5Ticks; this.priority = priority; } + public static MaterialItemProperties create(long baseThroughput) { return new MaterialItemProperties(baseThroughput, 2048f / baseThroughput); } diff --git a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java index 1541f875fcd..81cda089f63 100644 --- a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java +++ b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java @@ -1,8 +1,6 @@ package gregtech.common.pipelike.net; -import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.path.AbstractNetPath; -import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.util.TaskScheduler; @@ -21,8 +19,8 @@ public static void dispatch(World world, AbstractNetPath path, int delay, int stepSize, int activeLength) { + public static void dispatch(World world, AbstractNetPath path, int delay, + int stepSize, int activeLength) { TaskScheduler.scheduleTask(world, new SlowActiveWalker(path, delay, stepSize, activeLength)); } @@ -35,8 +33,8 @@ public static void dispatch(World world, AbstractNetPath path, int delay, int stepSize, int activeLength) { + protected SlowActiveWalker(AbstractNetPath path, int delay, int stepSize, + int activeLength) { this.path = path.getOrderedNodes(); this.delay = delay; this.stepSize = stepSize; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index f3b1a15a40c..52ff9a460dd 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -14,16 +14,13 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.TraverseHelpers; import gregtech.api.util.GTLog; - import gregtech.common.pipelikeold.cable.net.EnergyGroupData; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; - import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; @@ -41,7 +38,8 @@ public class EnergyCapabilityObject implements IPipeCapabilityObject, IEnergyCon private boolean transferring = false; - public EnergyCapabilityObject(@NotNull N net, WorldPipeNetNode node) { + public EnergyCapabilityObject(@NotNull N net, + WorldPipeNetNode node) { this.net = net; for (EnumFacing facing : EnumFacing.VALUES) { AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); @@ -76,11 +74,13 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage tile.getPos(), side); availableAmperage -= TraverseHelpers.traverseFlood(data, getPaths(data), amperage); if (availableAmperage > 0) { - availableAmperage -= TraverseHelpers.traverseDumb(data, getPaths(data), data::handleOverflow, availableAmperage); + availableAmperage -= TraverseHelpers.traverseDumb(data, getPaths(data), data::handleOverflow, + availableAmperage); } long accepted = amperage - availableAmperage; - if (internalBuffer != null) internalBuffer.consumeFlowLimit(IPredicateTestObject.INSTANCE, net, accepted, tick, simulator); + if (internalBuffer != null) + internalBuffer.consumeFlowLimit(IPredicateTestObject.INSTANCE, net, accepted, tick, simulator); if (!simulate) { EnergyGroupData group = getEnergyData(); if (group != null) { @@ -93,7 +93,8 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage private Iterator getPaths(EnergyTraverseData data) { assert tile != null; - return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), data.getQueryTick()); + return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), + data.getQueryTick()); } @Nullable @@ -143,14 +144,16 @@ public T getCapabilityForSide(Capability capability, @Nullable EnumFacing public long getInputPerSec() { EnergyGroupData data = getEnergyData(); if (data == null) return 0; - else return data.getEnergyFluxPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter())[0]; + else return data + .getEnergyFluxPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter())[0]; } @Override public long getOutputPerSec() { EnergyGroupData data = getEnergyData(); if (data == null) return 0; - else return data.getEnergyFluxPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter())[1]; + else return data + .getEnergyFluxPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter())[1]; } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index a5283bb6b6c..ae4d27b1848 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -4,25 +4,23 @@ import gregtech.api.capability.IEnergyContainer; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.NodeLossCache; -import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.NodeLossCache; import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.AbstractTraverseData; - import gregtech.api.graphnet.traverse.util.FlatLossOperator; import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; import gregtech.api.util.GTUtility; - import gregtech.common.pipelikeold.cable.net.EnergyGroupData; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import java.util.function.Supplier; public class EnergyTraverseData extends AbstractTraverseData { @@ -75,7 +73,8 @@ public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowRea temperatureLogic.getTemperature(getQueryTick()))) { return ReversibleLossOperator.IDENTITY; } - return new FlatLossOperator(node.getData().getLogicEntryDefaultable(LossAbsoluteLogic.INSTANCE).getValue()); + return new FlatLossOperator( + node.getData().getLogicEntryDefaultable(LossAbsoluteLogic.INSTANCE).getValue()); } if (result.hasPostAction()) NodeLossCache.registerLossResult(key, result); return result.getLossFunction(); @@ -98,7 +97,8 @@ public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachin long availableFlow = flowReachingDestination; for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) continue; // anti insert-to-our-source logic + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic IEnergyContainer container = capability.getValue() .getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, capability.getKey().getOpposite()); @@ -145,6 +145,5 @@ public void doHeating(WorldPipeNetNode node, long finalVoltage, long tick) { logic.applyThermalEnergy(calculateHeatV(amperage, finalVoltage, voltageCap), tick); } } - } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java index 603dcb837cc..178283b7e4a 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java @@ -6,14 +6,11 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNet; - import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.world.World; - import net.minecraftforge.common.capabilities.Capability; import org.jetbrains.annotations.NotNull; @@ -23,7 +20,8 @@ public final class WorldEnergyNet extends WorldPipeNet implements FlowWorldPipeNetPath.Provider { - public static final Capability[] CAPABILITIES = new Capability[] { GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER }; + public static final Capability[] CAPABILITIES = new Capability[] { + GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER }; private static final String DATA_ID_BASE = "gregtech.world_energy_net"; @@ -57,7 +55,8 @@ public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { } @Override - public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, long queryTick) { return backer.getPaths(node, 0, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java b/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java index aace8fff048..efc71b5fe1b 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java @@ -5,19 +5,16 @@ import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.graphnet.pipenet.NodeLossResult; - import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.traverse.util.MultLossOperator; import gregtech.api.util.EntityDamageUtil; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ResourceLocation; - import net.minecraftforge.fluids.FluidStack; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import java.util.EnumMap; @@ -52,7 +49,8 @@ static void registerFailure(FluidAttribute attribute, ContainmentFailure failure return ATTRIBUTE_FAILURES.getOrDefault(attribute, FALLBACK); } - @NotNull NodeLossResult computeLossResult(FluidStack fluid); + @NotNull + NodeLossResult computeLossResult(FluidStack fluid); static void init() { registerFailure(FluidState.GAS, stack -> { @@ -128,8 +126,8 @@ static void init() { boolean gaseous = stack.getFluid().isGaseous(stack); tile.spawnParticles(gaseous ? EnumFacing.UP : EnumFacing.DOWN, EnumParticleTypes.CRIT_MAGIC, 3 + GTValues.RNG.nextInt(2)); - tile.dealAreaDamage(gaseous ? 2 : 1, entity -> - EntityDamageUtil.applyChemicalDamage(entity, gaseous ? 2 : 3)); + tile.dealAreaDamage(gaseous ? 2 : 1, + entity -> EntityDamageUtil.applyChemicalDamage(entity, gaseous ? 2 : 3)); } }, MultLossOperator.TENTHS[9]); } else { @@ -144,8 +142,8 @@ static void init() { } tile.spawnParticles(gaseous ? EnumFacing.UP : EnumFacing.DOWN, EnumParticleTypes.CRIT_MAGIC, 6 + GTValues.RNG.nextInt(4)); - tile.dealAreaDamage(gaseous ? 2 : 1, entity -> - EntityDamageUtil.applyChemicalDamage(entity, gaseous ? 3 : 4)); + tile.dealAreaDamage(gaseous ? 2 : 1, + entity -> EntityDamageUtil.applyChemicalDamage(entity, gaseous ? 3 : 4)); } }, MultLossOperator.EIGHTHS[6]); } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index d6620d1ffd5..4522aa9ea54 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -37,7 +37,8 @@ public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandl private boolean transferring = false; - public FluidCapabilityObject(@NotNull N net, WorldPipeNetNode node) { + public FluidCapabilityObject(@NotNull N net, + WorldPipeNetNode node) { this.net = net; for (EnumFacing facing : EnumFacing.VALUES) { AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); @@ -52,7 +53,8 @@ private FlowWorldPipeNetPath.Provider getProvider() { private Iterator getPaths(FluidTraverseData data) { assert tile != null; - return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), data.getQueryTick()); + return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), + data.getQueryTick()); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java index d5a5523481a..e31d9a467ff 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java @@ -3,28 +3,20 @@ import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.graphnet.logic.INetLogicEntry; - import gregtech.api.util.GTUtility; -import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import net.minecraft.nbt.NBTTagByte; -import net.minecraft.nbt.NBTTagByteArray; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagInt; import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagString; import net.minecraft.network.PacketBuffer; - import net.minecraft.util.ResourceLocation; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.BitSet; import java.util.Collection; -import java.util.Collections; import java.util.EnumSet; import java.util.Set; @@ -83,7 +75,7 @@ public boolean contains(FluidAttribute attribute) { public @Nullable FluidContainmentLogic union(INetLogicEntry other) { if (other instanceof FluidContainmentLogic logic) { if (this.containableAttributes.equals(logic.containableAttributes) && - this.containableStates.equals(logic.containableStates)) { + this.containableStates.equals(logic.containableStates)) { return this; } else { FluidContainmentLogic returnable = getNew(); diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index cc0f83410b2..2c4bbbd8212 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -21,8 +21,6 @@ import gregtech.api.util.EntityDamageUtil; import gregtech.api.util.GTUtility; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.BlockPos; @@ -30,6 +28,8 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import java.util.function.LongConsumer; public class FluidTraverseData extends AbstractTraverseData { @@ -72,7 +72,8 @@ public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowRea return result.getLossFunction(); } else { FluidStack stack = getTestObject().recombine(); - FluidContainmentLogic containmentLogic = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.INSTANCE); + FluidContainmentLogic containmentLogic = node.getData() + .getLogicEntryDefaultable(FluidContainmentLogic.INSTANCE); FluidState state = FluidState.inferState(stack); TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); @@ -82,15 +83,17 @@ public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowRea boolean gaseous = stack.getFluid().isGaseous(stack); // prevent plasmas from melting valid pipes due to raw temperature boolean temperatureSafe = state == FluidState.PLASMA && containmentLogic.contains(FluidState.PLASMA); - temperatureUpdates.put(node, l -> temperatureLogic.moveTowardsTemperature(fluidTemp, getQueryTick(), l * TEMPERATURE_EFFECT, temperatureSafe)); + temperatureUpdates.put(node, l -> temperatureLogic.moveTowardsTemperature(fluidTemp, getQueryTick(), + l * TEMPERATURE_EFFECT, temperatureSafe)); if (temperatureLogic.isUnderMinimum(fluidTemp)) { result = NodeLossResult.combine(result, new NodeLossResult(pipe -> { PipeTileEntity tile = pipe.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); - tile.dealAreaDamage(gaseous ? 2 : 1, entity -> EntityDamageUtil.applyTemperatureDamage(entity, - fluidTemp, 2.0F, 10)); + tile.dealAreaDamage(gaseous ? 2 : 1, + entity -> EntityDamageUtil.applyTemperatureDamage(entity, + fluidTemp, 2.0F, 10)); } }, MultLossOperator.EIGHTHS[2])); } else if (temperatureLogic.isOverMaximum(fluidTemp)) { @@ -99,8 +102,9 @@ public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowRea if (tile != null) { tile.playLossSound(); tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); - tile.dealAreaDamage(gaseous ? 2 : 1, entity -> EntityDamageUtil.applyTemperatureDamage(entity, - fluidTemp, 2.0F, 10)); + tile.dealAreaDamage(gaseous ? 2 : 1, + entity -> EntityDamageUtil.applyTemperatureDamage(entity, + fluidTemp, 2.0F, 10)); tile.setNeighborsToFire(); } } : pipe -> { @@ -108,8 +112,9 @@ public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowRea if (tile != null) { tile.playLossSound(); tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); - tile.dealAreaDamage(gaseous ? 2 : 1, entity -> EntityDamageUtil.applyTemperatureDamage(entity, - fluidTemp, 2.0F, 10)); + tile.dealAreaDamage(gaseous ? 2 : 1, + entity -> EntityDamageUtil.applyTemperatureDamage(entity, + fluidTemp, 2.0F, 10)); } }, MultLossOperator.EIGHTHS[2])); } @@ -122,7 +127,8 @@ public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowRea if (stack instanceof AttributedFluid fluid) { for (FluidAttribute attribute : fluid.getAttributes()) { if (!containmentLogic.contains(attribute)) { - result = NodeLossResult.combine(result, ContainmentFailure.getFailure(attribute).computeLossResult(stack)); + result = NodeLossResult.combine(result, + ContainmentFailure.getFailure(attribute).computeLossResult(stack)); } } } @@ -138,7 +144,8 @@ public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachin long availableFlow = flowReachingDestination; for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) continue; // anti insert-to-our-source logic + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic IFluidHandler container = capability.getValue() .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index a997d9118cf..d404515fc56 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -9,12 +9,10 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - import gregtech.common.pipelike.net.item.WorldItemNet; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; - import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import org.jetbrains.annotations.NotNull; @@ -24,7 +22,8 @@ public class WorldFluidNet extends WorldPipeNet implements FlowWorldPipeNetPath.Provider { - public static final Capability[] CAPABILITIES = new Capability[] { CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY }; + public static final Capability[] CAPABILITIES = new Capability[] { + CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY }; private static final String DATA_ID_BASE = "gregtech.world_energy_net"; @@ -63,7 +62,8 @@ public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { } @Override - public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, long queryTick) { return backer.getPaths(node, 0, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index dfc1c566ae6..8c80c5f3d27 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -15,9 +15,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fml.common.FMLCommonHandler; - import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; @@ -36,7 +34,8 @@ public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler private boolean transferring = false; - public ItemCapabilityObject(@NotNull N net, WorldPipeNetNode node) { + public ItemCapabilityObject(@NotNull N net, + WorldPipeNetNode node) { this.net = net; for (EnumFacing facing : EnumFacing.VALUES) { AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); @@ -51,7 +50,8 @@ private FlowWorldPipeNetPath.Provider getProvider() { private Iterator getPaths(ItemTraverseData data) { assert tile != null; - return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), data.getQueryTick()); + return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), + data.getQueryTick()); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java index de252750808..6470626b15a 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java @@ -9,11 +9,8 @@ import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; import gregtech.api.util.GTUtility; -import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; @@ -49,13 +46,15 @@ public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachin long availableFlow = flowReachingDestination; for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) continue; // anti insert-to-our-source logic + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic IItemHandler container = capability.getValue() .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); if (container != null) { for (int i = 0; i < container.getSlots(); i++) { - int toInsert = (int) Math.min(Math.min(getTestObject().getStackLimit(), container.getSlotLimit(i)), availableFlow); + int toInsert = (int) Math.min(Math.min(getTestObject().getStackLimit(), container.getSlotLimit(i)), + availableFlow); availableFlow -= toInsert - container.insertItem(i, getTestObject().recombine(toInsert), getSimulatorKey() != null).getCount(); diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 8b473e35fe6..54bdd61006b 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -9,12 +9,10 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - import gregtech.common.pipelike.net.fluid.WorldFluidNet; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; - import net.minecraftforge.items.CapabilityItemHandler; import org.jetbrains.annotations.NotNull; @@ -24,7 +22,8 @@ public class WorldItemNet extends WorldPipeNet implements FlowWorldPipeNetPath.Provider { - public static final Capability[] CAPABILITIES = new Capability[] { CapabilityItemHandler.ITEM_HANDLER_CAPABILITY }; + public static final Capability[] CAPABILITIES = new Capability[] { + CapabilityItemHandler.ITEM_HANDLER_CAPABILITY }; private static final String DATA_ID_BASE = "gregtech.world_energy_net"; @@ -63,7 +62,8 @@ public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { } @Override - public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, long queryTick) { return backer.getPaths(node, 0, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); } diff --git a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java index 18997cd2536..d9def3c0ce0 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java @@ -7,14 +7,11 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - import gregtech.common.pipelike.net.SlowActiveWalker; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; - import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; @@ -54,7 +51,7 @@ public long receiveLaser(long laserVoltage, long laserAmperage) { transmitting = true; long available = laserAmperage; - for (Iterator it = getPaths(); it.hasNext(); ) { + for (Iterator it = getPaths(); it.hasNext();) { BasicWorldPipeNetPath path = it.next(); WorldPipeNetNode destination = path.getTargetNode(); for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index 4f276e8c858..4e0ffb919e9 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -2,22 +2,19 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.data.IDataAccess; +import gregtech.api.capability.data.query.DataAccessFormat; +import gregtech.api.capability.data.query.DataQueryObject; import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - import gregtech.api.util.GTUtility; -import gregtech.api.capability.data.query.DataAccessFormat; -import gregtech.api.capability.data.query.DataQueryObject; import gregtech.common.pipelike.net.SlowActiveWalker; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; - import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; @@ -53,12 +50,13 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { // if the add call fails (because the object already exists in the set) then do not recurse if (!recentQueries.add(queryObject)) return false; - for (Iterator it = getPaths(); it.hasNext(); ) { + for (Iterator it = getPaths(); it.hasNext();) { BasicWorldPipeNetPath path = it.next(); WorldPipeNetNode destination = path.getTargetNode(); for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { IDataAccess access = capability.getValue() - .getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, capability.getKey().getOpposite()); + .getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, + capability.getKey().getOpposite()); if (access != null) { queryObject.setShouldTriggerWalker(false); boolean cancelled = access.accessData(queryObject); diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java index d2e87e3ea7a..a34569c043f 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -1,8 +1,6 @@ package gregtech.common.pipelike.net.optical; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; -import gregtech.api.graphnet.alg.ShortestPathsAlgorithm; import gregtech.api.graphnet.alg.SinglePathAlgorithm; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; @@ -20,7 +18,8 @@ public class WorldOpticalNet extends WorldPipeNet implements BasicWorldPipeNetPath.Provider { - public static final Capability[] CAPABILITIES = new Capability[] { GregtechTileCapabilities.CAPABILITY_DATA_ACCESS }; + public static final Capability[] CAPABILITIES = new Capability[] { + GregtechTileCapabilities.CAPABILITY_DATA_ACCESS }; private static final String DATA_ID_BASE = "gregtech.world_optical_net"; diff --git a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java index eed36045dae..13beb625dd7 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java @@ -2,15 +2,12 @@ import gregtech.api.graphnet.AbstractGroupData; -import net.minecraftforge.fml.common.FMLCommonHandler; - public class EnergyGroupData extends AbstractGroupData { private final long[] lastEnergyFluxPerSec = new long[2]; private final long[] energyFluxPerSec = new long[2]; private long updateTime; - public long[] getEnergyFluxPerSec(long queryTick) { updateCache(queryTick); return lastEnergyFluxPerSec; diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java b/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java index 20934ea5f73..3757984676f 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java +++ b/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java @@ -2,10 +2,10 @@ import gregtech.api.GTValues; import gregtech.api.capability.impl.FluidHandlerDelegate; +import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; import gregtech.api.gui.ModularUI; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; import gregtech.common.metatileentities.storage.MetaTileEntityLongDistanceEndpoint; diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java b/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java index c3095875c49..d7005b163d1 100644 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java +++ b/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java @@ -2,10 +2,10 @@ import gregtech.api.GTValues; import gregtech.api.capability.impl.ItemHandlerDelegate; +import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; import gregtech.api.gui.ModularUI; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; -import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; import gregtech.common.metatileentities.storage.MetaTileEntityLongDistanceEndpoint; diff --git a/src/main/java/gregtech/integration/RecipeCompatUtil.java b/src/main/java/gregtech/integration/RecipeCompatUtil.java index f3fab3148e0..dcaa4f0fbaa 100644 --- a/src/main/java/gregtech/integration/RecipeCompatUtil.java +++ b/src/main/java/gregtech/integration/RecipeCompatUtil.java @@ -9,7 +9,6 @@ import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; import gregtech.api.unification.material.Material; -import gregtech.api.util.GTStringUtils; import gregtech.api.util.GTUtility; import gregtech.common.blocks.BlockCompressed; import gregtech.common.blocks.BlockFrame; diff --git a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java index 25e1d5f626b..7a59679d7d1 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java @@ -239,7 +239,8 @@ public CTMaterialBuilder ingotSmeltInto(Material m) { } @ZenMethod - public CTMaterialBuilder cableProperties(long voltage, int amperage, int loss, @Optional int meltTemperature, @Optional int superConTemperature) { + public CTMaterialBuilder cableProperties(long voltage, int amperage, int loss, @Optional int meltTemperature, + @Optional int superConTemperature) { backingBuilder.cableProperties(voltage, amperage, loss, meltTemperature, superConTemperature); return this; } @@ -258,7 +259,8 @@ public CTMaterialBuilder fluidPipeProperties(int maxTemp, int throughput, boolea } @ZenMethod - public CTMaterialBuilder fluidPipeProperties(int maxTemp, int minTemp, int throughput, boolean gasProof, boolean acidProof, + public CTMaterialBuilder fluidPipeProperties(int maxTemp, int minTemp, int throughput, boolean gasProof, + boolean acidProof, boolean plasmaProof) { backingBuilder.fluidPipeProperties(maxTemp, minTemp, throughput, gasProof, acidProof, plasmaProof); return this; diff --git a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java index 88c8f3db0e3..d16084980c3 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java @@ -3,21 +3,16 @@ import gregtech.api.fluids.FluidBuilder; import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; -import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.fluids.store.FluidStorage; import gregtech.api.fluids.store.FluidStorageKeys; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.*; - -import crafttweaker.annotations.ZenRegister; - import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; - import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; - import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; +import crafttweaker.annotations.ZenRegister; import stanhebben.zenscript.annotations.Optional; import stanhebben.zenscript.annotations.ZenExpansion; import stanhebben.zenscript.annotations.ZenMethod; @@ -234,11 +229,13 @@ public static void addFluidPipes(Material m, int maxFluidTemperature, int throug @ZenMethod public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof, boolean acidProof, boolean plasmaProof) { - addFluidPipes(m, maxFluidTemperature, FluidConstants.CRYOGENIC_FLUID_THRESHOLD + 1, throughput, gasProof, acidProof, plasmaProof); + addFluidPipes(m, maxFluidTemperature, FluidConstants.CRYOGENIC_FLUID_THRESHOLD + 1, throughput, gasProof, + acidProof, plasmaProof); } @ZenMethod - public static void addFluidPipes(Material m, int maxFluidTemperature, int minFluidTemperature, int throughput, boolean gasProof, + public static void addFluidPipes(Material m, int maxFluidTemperature, int minFluidTemperature, int throughput, + boolean gasProof, boolean acidProof, boolean plasmaProof) { if (checkFrozen("add fluid pipes to a material")) return; PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); diff --git a/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java b/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java index bc47b1a6f0f..8e3f0450c3c 100644 --- a/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java +++ b/src/main/java/gregtech/integration/crafttweaker/recipe/MetaItemBracketHandler.java @@ -96,13 +96,14 @@ public static void rebuildComponentRegistry() { ItemStack stack = cable.getItem(material); map.put(name, stack); } - } else if (property instanceof MaterialItemProperties || property instanceof MaterialFluidProperties) { - for (PipeMaterialBlock pipe : MetaBlocks.MATERIAL_PIPES.get(modid)) { - String name = pipe.getStructure().getOrePrefix().name + material.toCamelCaseString(); - ItemStack stack = pipe.getItem(material); - map.put(name, stack); + } else + if (property instanceof MaterialItemProperties || property instanceof MaterialFluidProperties) { + for (PipeMaterialBlock pipe : MetaBlocks.MATERIAL_PIPES.get(modid)) { + String name = pipe.getStructure().getOrePrefix().name + material.toCamelCaseString(); + ItemStack stack = pipe.getItem(material); + map.put(name, stack); + } } - } } } metaBlockNames.put(modid, map); diff --git a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java index 55ad596f058..64cb07afc01 100644 --- a/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java +++ b/src/main/java/gregtech/integration/groovy/GroovyScriptModule.java @@ -206,13 +206,14 @@ public static void loadMetaItemBracketHandler() { ItemStack stack = cable.getItem(material); map.put(name, stack); } - } else if (property instanceof MaterialItemProperties || property instanceof MaterialFluidProperties) { - for (PipeMaterialBlock pipe : MetaBlocks.MATERIAL_PIPES.get(modid)) { - String name = pipe.getStructure().getOrePrefix().name + material.toCamelCaseString(); - ItemStack stack = pipe.getItem(material); - map.put(name, stack); + } else + if (property instanceof MaterialItemProperties || property instanceof MaterialFluidProperties) { + for (PipeMaterialBlock pipe : MetaBlocks.MATERIAL_PIPES.get(modid)) { + String name = pipe.getStructure().getOrePrefix().name + material.toCamelCaseString(); + ItemStack stack = pipe.getItem(material); + map.put(name, stack); + } } - } } } metaItems.put(modid, map); diff --git a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java index 282e5518bfe..26c61beafa7 100644 --- a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java @@ -17,14 +17,13 @@ import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.properties.ToolProperty; import gregtech.api.unification.material.properties.WoodProperty; - -import com.cleanroommc.groovyscript.api.GroovyBlacklist; -import com.cleanroommc.groovyscript.api.GroovyLog; - import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; +import com.cleanroommc.groovyscript.api.GroovyBlacklist; +import com.cleanroommc.groovyscript.api.GroovyLog; + import static gregtech.integration.groovy.GroovyScriptModule.checkFrozen; @SuppressWarnings("unused") @@ -303,10 +302,12 @@ public static void addFluidPipes(Material m, int maxFluidTemperature, int throug public static void addFluidPipes(Material m, int maxFluidTemperature, int throughput, boolean gasProof, boolean acidProof, boolean plasmaProof) { - addFluidPipes(m, maxFluidTemperature, FluidConstants.CRYOGENIC_FLUID_THRESHOLD + 1, throughput, gasProof, acidProof, plasmaProof); + addFluidPipes(m, maxFluidTemperature, FluidConstants.CRYOGENIC_FLUID_THRESHOLD + 1, throughput, gasProof, + acidProof, plasmaProof); } - public static void addFluidPipes(Material m, int maxFluidTemperature, int minFluidTemperature, int throughput, boolean gasProof, + public static void addFluidPipes(Material m, int maxFluidTemperature, int minFluidTemperature, int throughput, + boolean gasProof, boolean acidProof, boolean plasmaProof) { if (checkFrozen("add fluid pipes to a material")) return; PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java index a5c9a83c64b..7e04335a339 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java @@ -1,10 +1,10 @@ package gregtech.integration.theoneprobe.provider; import gregtech.api.GTValues; -import gregtech.api.metatileentity.MetaTileEntity; -import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; import gregtech.api.graphnet.pipenetold.longdist.LongDistanceNetwork; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java index a90eaf14d9d..1064ffe7ef4 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/PartsRecipeHandler.java @@ -18,7 +18,6 @@ import gregtech.common.ConfigHolder; import gregtech.common.items.MetaItems; import gregtech.common.items.behaviors.AbstractMaterialPartBehavior; - import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; import net.minecraft.item.EnumDyeColor; diff --git a/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java index 54e271d2b09..2c646c88a21 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java @@ -12,9 +12,7 @@ import gregtech.api.unification.stack.UnificationEntry; import gregtech.api.util.GTUtility; import gregtech.common.items.MetaItems; - import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; - import gregtech.common.pipelike.handlers.properties.MaterialItemProperties; import net.minecraft.item.ItemStack; @@ -39,17 +37,19 @@ public static void register() { processStandard(OrePrefix.pipeNormal, OrePrefix.pipeNormalRestrictive, PipeRecipeHandler::processPipeNormal); processStandard(OrePrefix.pipeLarge, OrePrefix.pipeLargeRestrictive, PipeRecipeHandler::processPipeLarge); processStandard(OrePrefix.pipeHuge, OrePrefix.pipeHugeRestrictive, PipeRecipeHandler::processPipeHuge); - processStandard(OrePrefix.pipeQuadruple, OrePrefix.pipeQuadrupleRestrictive, PipeRecipeHandler::processPipeQuadruple); + processStandard(OrePrefix.pipeQuadruple, OrePrefix.pipeQuadrupleRestrictive, + PipeRecipeHandler::processPipeQuadruple); processStandard(OrePrefix.pipeNonuple, OrePrefix.pipeNonupleRestrictive, PipeRecipeHandler::processPipeNonuple); } - private static void processStandard(OrePrefix pipePrefix, OrePrefix restrictivePrefix, BiConsumer processor) { + private static void processStandard(OrePrefix pipePrefix, OrePrefix restrictivePrefix, + BiConsumer processor) { pipePrefix.addProcessingHandler(registrationHandler(processor)); restrictivePrefix.addProcessingHandler(registrationHandler((o, m) -> processRestrictivePipe(o, m, pipePrefix))); } public static IOreRegistrationHandler registrationHandler( - BiConsumer handler) { + BiConsumer handler) { return (orePrefix, material) -> { if (material.hasFlag(NO_UNIFICATION)) return; PipeNetProperties properties = material.getProperty(PropertyKey.PIPENET_PROPERTIES); diff --git a/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java index 8ce9a432e08..1e8892c10fd 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/WireCombiningHandler.java @@ -7,11 +7,9 @@ import gregtech.api.unification.material.Materials; import gregtech.api.unification.ore.OrePrefix; import gregtech.api.unification.stack.UnificationEntry; - -import com.google.common.collect.ImmutableMap; - import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; +import com.google.common.collect.ImmutableMap; import org.apache.commons.lang3.ArrayUtils; import java.util.Map; @@ -34,20 +32,24 @@ public class WireCombiningHandler { public static void register() { // Generate Wire Packer/Unpacker recipes TODO Move into generateWireCombining? - wireGtSingle.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireCombiningHandler::processWireCompression)); + wireGtSingle.addProcessingHandler( + MaterialEnergyProperties.registrationHandler(WireCombiningHandler::processWireCompression)); // Generate manual recipes for combining Wires/Cables for (OrePrefix wirePrefix : WIRE_DOUBLING_ORDER) { - wirePrefix.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireCombiningHandler::generateWireCombiningRecipe)); + wirePrefix.addProcessingHandler( + MaterialEnergyProperties.registrationHandler(WireCombiningHandler::generateWireCombiningRecipe)); } // Generate Cable -> Wire recipes in the unpacker for (OrePrefix cablePrefix : cableToWireMap.keySet()) { - cablePrefix.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireCombiningHandler::processCableStripping)); + cablePrefix.addProcessingHandler( + MaterialEnergyProperties.registrationHandler(WireCombiningHandler::processCableStripping)); } } - private static void generateWireCombiningRecipe(OrePrefix wirePrefix, Material material, MaterialEnergyProperties property) { + private static void generateWireCombiningRecipe(OrePrefix wirePrefix, Material material, + MaterialEnergyProperties property) { int wireIndex = ArrayUtils.indexOf(WIRE_DOUBLING_ORDER, wirePrefix); if (wireIndex < WIRE_DOUBLING_ORDER.length - 1) { @@ -73,7 +75,7 @@ private static void generateWireCombiningRecipe(OrePrefix wirePrefix, Material m } } - private static void processWireCompression(OrePrefix prefix, Material material,MaterialEnergyProperties property) { + private static void processWireCompression(OrePrefix prefix, Material material, MaterialEnergyProperties property) { for (int startTier = 0; startTier < 4; startTier++) { for (int i = 1; i < 5 - startTier; i++) { PACKER_RECIPES.recipeBuilder() diff --git a/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java index 44e4d3767eb..9dce295a3f3 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/WireRecipeHandler.java @@ -9,11 +9,10 @@ import gregtech.api.unification.ore.OrePrefix; import gregtech.api.unification.stack.UnificationEntry; import gregtech.api.util.GTUtility; +import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; import com.google.common.collect.ImmutableMap; -import gregtech.common.pipelike.handlers.properties.MaterialEnergyProperties; - import java.util.Map; import static gregtech.api.GTValues.*; @@ -52,14 +51,20 @@ public class WireRecipeHandler { public static void register() { // Generate 1x Wire creation recipes (Wiremill, Extruder, Wire Cutters) - wireGtSingle.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::processWireSingle)); + wireGtSingle.addProcessingHandler( + MaterialEnergyProperties.registrationHandler(WireRecipeHandler::processWireSingle)); // Generate Cable Covering Recipes - wireGtSingle.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); - wireGtDouble.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); - wireGtQuadruple.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); - wireGtOctal.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); - wireGtHex.addProcessingHandler(MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); + wireGtSingle.addProcessingHandler( + MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); + wireGtDouble.addProcessingHandler( + MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); + wireGtQuadruple.addProcessingHandler( + MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); + wireGtOctal.addProcessingHandler( + MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); + wireGtHex.addProcessingHandler( + MaterialEnergyProperties.registrationHandler(WireRecipeHandler::generateCableCovering)); } private static final OrePrefix[] wireSizes = { wireGtDouble, wireGtQuadruple, wireGtOctal, wireGtHex }; @@ -102,7 +107,8 @@ public static void processWireSingle(OrePrefix wirePrefix, Material material, Ma } } - public static void generateCableCovering(OrePrefix wirePrefix, Material material, MaterialEnergyProperties property) { + public static void generateCableCovering(OrePrefix wirePrefix, Material material, + MaterialEnergyProperties property) { // Superconductors have no Cables, so exit early if (property.isSuperconductor()) return; From cae5f3e8b9c09cfb038fe9ae4fed579a6ce90c06 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 28 Jul 2024 16:20:18 -0600 Subject: [PATCH 083/157] stability fixes --- .../gregtech/api/cover/CoverRayTracer.java | 3 +- .../java/gregtech/api/graphnet/NetNode.java | 7 +- .../graphnet/gather/GatherLogicsEvent.java | 2 +- .../gather/GatherPredicatesEvent.java | 2 +- .../graphnet/pipenet/IPipeNetNodeHandler.java | 8 + .../api/graphnet/pipenet/WorldPipeNet.java | 10 +- .../physical/IPipeChanneledStructure.java | 6 + .../physical/block/ItemMaterialPipeBlock.java | 32 +++ .../physical/block/PipeActivableBlock.java | 53 ++++ .../physical/block/PipeMaterialBlock.java | 52 +++- .../pipenet/physical/block/RayTracePair.java | 9 + .../physical/block/WorldPipeBlock.java | 252 +++++++++++++++--- .../tile/PipeActivableTileEntity.java | 4 - .../physical/tile/PipeMaterialTileEntity.java | 4 - .../pipenet/physical/tile/PipeTileEntity.java | 19 +- .../api/graphnet/worldnet/WorldNet.java | 1 + .../properties/PipeNetProperties.java | 15 ++ .../material/properties/WoodProperty.java | 8 - .../api/unification/ore/OrePrefix.java | 18 +- .../renderer/pipe/ActivablePipeModel.java | 4 +- .../client/renderer/pipe/CableModel.java | 4 +- .../client/renderer/pipe/PipeModel.java | 7 +- .../renderer/pipe/quad/PipeQuadHelper.java | 2 +- .../java/gregtech/common/CommonProxy.java | 7 +- .../gregtech/common/blocks/MetaBlocks.java | 21 +- .../pipelike/block/cable/CableBlock.java | 8 + .../pipelike/block/laser/LaserPipeBlock.java | 20 +- .../pipelike/block/laser/LaserStructure.java | 2 +- .../block/optical/OpticalPipeBlock.java | 20 +- .../block/optical/OpticalStructure.java | 2 +- .../common/pipelike/block/pipe/PipeBlock.java | 3 + .../pipelike/block/pipe/PipeStructure.java | 36 +-- .../pipelike/handlers/LaserNetHandler.java | 12 + .../pipelike/handlers/OpticalNetHandler.java | 12 + .../properties/MaterialEnergyProperties.java | 46 +++- .../properties/MaterialFluidProperties.java | 32 ++- .../properties/MaterialItemProperties.java | 30 ++- .../net/energy/EnergyCapabilityObject.java | 10 +- .../pipelike/net/energy/WorldEnergyNet.java | 3 +- .../net/fluid/FluidCapabilityObject.java | 8 +- .../pipelike/net/fluid/WorldFluidNet.java | 5 +- .../net/item/ItemCapabilityObject.java | 8 +- .../pipelike/net/item/WorldItemNet.java | 5 +- .../pipelike/net/laser/WorldLaserNet.java | 4 +- .../pipelike/net/optical/WorldOpticalNet.java | 4 +- .../recipe/handlers/PipeRecipeHandler.java | 3 +- .../89_fluid_pipe_death_cold.json | 2 +- .../steam/87_fluid_pipe_death_heat.json | 2 +- .../advancements/steam/root_steam.json | 56 ++-- .../resources/assets/gregtech/lang/en_us.lang | 40 ++- 50 files changed, 734 insertions(+), 189 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeChanneledStructure.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemMaterialPipeBlock.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/block/RayTracePair.java diff --git a/src/main/java/gregtech/api/cover/CoverRayTracer.java b/src/main/java/gregtech/api/cover/CoverRayTracer.java index b35ad4ec4b7..c31648b101f 100644 --- a/src/main/java/gregtech/api/cover/CoverRayTracer.java +++ b/src/main/java/gregtech/api/cover/CoverRayTracer.java @@ -21,7 +21,8 @@ private CoverRayTracer() {} // if the coverable view is from a blockpipe, use the proper raytrace method RayTraceResult result = coverableView.getWorld().getBlockState(coverableView.getPos()) .getBlock() instanceof WorldPipeBlock pipe ? - pipe.collisionRayTrace(player, coverableView.getWorld(), coverableView.getPos()) : + pipe.collisionRayTrace(player, coverableView.getWorld(), coverableView.getPos()) + .result() : RayTracer.retraceBlock(coverableView.getWorld(), player, coverableView.getPos()); if (result == null || result.typeOfHit != RayTraceResult.Type.BLOCK) { return null; diff --git a/src/main/java/gregtech/api/graphnet/NetNode.java b/src/main/java/gregtech/api/graphnet/NetNode.java index 60f1dd115f9..771b59d1efb 100644 --- a/src/main/java/gregtech/api/graphnet/NetNode.java +++ b/src/main/java/gregtech/api/graphnet/NetNode.java @@ -27,7 +27,7 @@ public abstract class NetNode implements INBTSerializable { private boolean isActive = false; private final IGraphNet net; - private NetLogicData data; + private @NotNull NetLogicData data; private @Nullable NetGroup group = null; @Nullable @@ -35,6 +35,7 @@ public abstract class NetNode implements INBTSerializable { public NetNode(IGraphNet net) { this.net = net; + this.data = net.getDefaultNodeData(); } public IGraphNet getNet() { @@ -55,11 +56,11 @@ public void setActive(boolean active) { isActive = active; } - public void setData(NetLogicData data) { + public void setData(@NotNull NetLogicData data) { this.data = data; } - public NetLogicData getData() { + public @NotNull NetLogicData getData() { return data; } diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java index dbabb7ae179..b075bc3adda 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java +++ b/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java @@ -13,7 +13,7 @@ public class GatherLogicsEvent extends Event { final Map>> gathered = new Object2ObjectOpenHashMap<>(); - GatherLogicsEvent() {} + public GatherLogicsEvent() {} public void registerLogic(INetLogicEntry logic) { gathered.put(logic.getName(), logic::getNew); diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java index 867da71bac5..fa6bc8bcb0f 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java +++ b/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java @@ -13,7 +13,7 @@ public class GatherPredicatesEvent extends Event { final Map>> gathered = new Object2ObjectOpenHashMap<>(); - GatherPredicatesEvent() {} + public GatherPredicatesEvent() {} public void registerPredicate(IEdgePredicate predicate) { gathered.put(predicate.getName(), predicate::getNew); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java index de46f72e5d8..ddd7e83d436 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java @@ -2,10 +2,15 @@ import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import org.jetbrains.annotations.NotNull; + import java.util.Collection; +import java.util.List; public interface IPipeNetNodeHandler { @@ -14,4 +19,7 @@ public interface IPipeNetNodeHandler { Collection getFromNets(World world, BlockPos pos, IPipeStructure structure); void removeFromNets(World world, BlockPos pos, IPipeStructure structure); + + void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn, + IPipeStructure structure); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index a32605e5905..c87f80b7589 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -41,16 +41,16 @@ public abstract class WorldPipeNet extends WorldNet { public WorldPipeNet(String name, Function graphBuilder, Function... algorithmBuilders) { super(name, graphBuilder, algorithmBuilders); - dimensionNets.compute(getDimension(), (k, v) -> { - if (v == null) v = new ObjectOpenHashSet<>(); - v.add(new WeakReference<>(this)); - return v; - }); } @SafeVarargs public WorldPipeNet(String name, boolean directed, Function... algorithmBuilders) { super(name, directed, algorithmBuilders); + } + + @Override + public void setWorld(World world) { + super.setWorld(world); dimensionNets.compute(getDimension(), (k, v) -> { if (v == null) v = new ObjectOpenHashSet<>(); v.add(new WeakReference<>(this)); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeChanneledStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeChanneledStructure.java new file mode 100644 index 00000000000..44b1a98f91d --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeChanneledStructure.java @@ -0,0 +1,6 @@ +package gregtech.api.graphnet.pipenet.physical; + +public interface IPipeChanneledStructure extends IPipeStructure { + + int getChannelCount(); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemMaterialPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemMaterialPipeBlock.java new file mode 100644 index 00000000000..3aed6208b2e --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemMaterialPipeBlock.java @@ -0,0 +1,32 @@ +package gregtech.api.graphnet.pipenet.physical.block; + +import gregtech.api.unification.material.Material; + +import net.minecraft.item.ItemStack; + +import org.jetbrains.annotations.NotNull; + +public class ItemMaterialPipeBlock extends ItemPipeBlock { + + public ItemMaterialPipeBlock(PipeMaterialBlock block) { + super(block); + setHasSubtypes(true); + } + + @Override + public int getMetadata(int damage) { + return damage; + } + + @Override + public @NotNull PipeMaterialBlock getBlock() { + return (PipeMaterialBlock) super.getBlock(); + } + + @NotNull + @Override + public String getItemStackDisplayName(@NotNull ItemStack stack) { + Material material = getBlock().getMaterialForStack(stack); + return material == null ? " " : getBlock().getStructure().getOrePrefix().getLocalNameForItem(material); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java new file mode 100644 index 00000000000..ebc836a7e05 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java @@ -0,0 +1,53 @@ +package gregtech.api.graphnet.pipenet.physical.block; + +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; + +import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; +import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.ActivablePipeModel; + +import net.minecraft.block.state.BlockStateContainer; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.WeakReference; + +public abstract class PipeActivableBlock extends WorldPipeBlock { + + public PipeActivableBlock(IPipeStructure structure) { + super(structure); + } + + @Override + protected @NotNull BlockStateContainer.Builder constructState(BlockStateContainer.@NotNull Builder builder) { + return super.constructState(builder).add(ActivablePipeModel.ACTIVE_PROPERTY); + } + + @Override + public Class getTileClass(@NotNull World world, @NotNull IBlockState state) { + return PipeActivableTileEntity.class; + } + + @Override + public @Nullable PipeActivableTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { + if (GTUtility.arePosEqual(lastTilePos, pos)) { + PipeTileEntity tile = lastTile.get(); + if (tile != null) return (PipeActivableTileEntity) tile; + } + TileEntity tile = world.getTileEntity(pos); + if (tile instanceof PipeActivableTileEntity pipe) { + lastTilePos = pos; + lastTile = new WeakReference<>(pipe); + return pipe; + } else return null; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index 445b22376fc..3711c8db734 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -6,14 +6,25 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; +import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.PipeModel; + +import gregtech.common.ConfigHolder; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.creativetab.CreativeTabs; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; @@ -24,6 +35,8 @@ import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; +import java.util.List; +import java.util.Set; public abstract class PipeMaterialBlock extends WorldPipeBlock { @@ -34,6 +47,17 @@ public PipeMaterialBlock(IPipeMaterialStructure structure, MaterialRegistry regi this.registry = registry; } + @Override + public void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList items) { + for (Material material : registry) { + if (!getStructure().getOrePrefix().doGenerateItem(material)) continue; + PipeNetProperties properties = material.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (properties != null && properties.generatesStructure(getStructure())) { + items.add(getItem(material)); + } + } + } + @Override public IPipeMaterialStructure getStructure() { return (IPipeMaterialStructure) super.getStructure(); @@ -65,8 +89,32 @@ public ItemStack getDrop(IBlockAccess world, BlockPos pos, IBlockState state) { return Materials.Aluminium.getProperty(PropertyKey.PIPENET_PROPERTIES); } + @Override + protected @NotNull IPipeNetNodeHandler getHandler(@NotNull ItemStack stack) { + Material material = getMaterialForStack(stack); + if (material == null) material = Materials.Aluminium; + return material.getProperty(PropertyKey.PIPENET_PROPERTIES); + } + + @Override + public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, + @NotNull ITooltipFlag flagIn) { + super.addInformation(stack, worldIn, tooltip, flagIn); + if (ConfigHolder.misc.debug) { + Material material = getMaterialForStack(stack); + if (material != null) + tooltip.add("MetaItem Id: " + getStructure().getOrePrefix().name + material.toCamelCaseString()); + } + } + // tile entity // + @NotNull + @Override + protected BlockStateContainer.Builder constructState(BlockStateContainer.@NotNull Builder builder) { + return super.constructState(builder).add(PipeModel.MATERIAL_PROPERTY); + } + @Override public @Nullable PipeMaterialTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { if (GTUtility.arePosEqual(lastTilePos, pos)) { @@ -82,8 +130,8 @@ public ItemStack getDrop(IBlockAccess world, BlockPos pos, IBlockState state) { } @Override - public @NotNull PipeTileEntity createTileEntity(@NotNull World world, @NotNull IBlockState state) { - return new PipeMaterialTileEntity(this); + public Class getTileClass(@NotNull World world, @NotNull IBlockState state) { + return PipeMaterialTileEntity.class; } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/RayTracePair.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/RayTracePair.java new file mode 100644 index 00000000000..d2970d3a4e5 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/RayTracePair.java @@ -0,0 +1,9 @@ +package gregtech.api.graphnet.pipenet.physical.block; + +import com.github.bsideup.jabel.Desugar; + +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.RayTraceResult; + +@Desugar +public record RayTracePair(RayTraceResult result, AxisAlignedBB bb) {} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java index 0a84f5f2122..db666f497fb 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java @@ -2,10 +2,12 @@ import gregtech.api.block.BuiltInRenderBlock; import gregtech.api.cover.Cover; +import gregtech.api.cover.CoverRayTracer; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.physical.IPipeChanneledStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.graphnet.pipenet.physical.tile.PipeCoverHolder; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; @@ -13,23 +15,30 @@ import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.util.EntityDamageUtil; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.AbstractPipeModel; +import gregtech.client.utils.TooltipHelper; import gregtech.common.ConfigHolder; import gregtech.common.blocks.BlockFrame; -import gregtech.common.creativetab.GTCreativeTabs; import net.minecraft.block.Block; import net.minecraft.block.SoundType; +import net.minecraft.block.state.BlockFaceShape; +import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.EnumDyeColor; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; import net.minecraft.util.NonNullList; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -69,7 +78,6 @@ public WorldPipeBlock(IPipeStructure structure) { setResistance(3.0f); setLightOpacity(0); disableStats(); - setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); } public IPipeStructure getStructure() { @@ -88,12 +96,12 @@ public void doPlacementLogic(PipeTileEntity tile, EnumFacing placedBlockSearchSi // second check -- connect to matching mark pipes if side matches or config allows. if (tile.getPaintingColor() == other.getPaintingColor() && (facing == placedBlockSearchSide || !ConfigHolder.machines.gt6StylePipesCables)) { - connectTiles(tile, other, facing); + connectTile(tile, other, facing); continue; } // third check -- connect to pipes with an open connection, no matter the mark status. if (tile.isConnected(facing.getOpposite())) { - connectTiles(tile, other, facing); + connectTile(tile, other, facing); } } else if (facing == placedBlockSearchSide) { // if the placed on tile supports one of our capabilities, connect to it. @@ -102,26 +110,51 @@ public void doPlacementLogic(PipeTileEntity tile, EnumFacing placedBlockSearchSi } } - public void connectTiles(@NotNull PipeTileEntity tile1, @NotNull PipeTileEntity tile2, EnumFacing facingFrom1To2) { + @Override + public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, + @NotNull EntityPlayer playerIn, @NotNull EnumHand hand, @NotNull EnumFacing facing, + float hitX, float hitY, float hitZ) { + if (isPipeTool(playerIn.getHeldItem(hand))) { + PipeTileEntity tile = getTileEntity(worldIn, pos); + if (tile != null) { + EnumFacing actualSide = CoverRayTracer.determineGridSideHit(collisionRayTrace(playerIn, worldIn, pos).result()); + if (actualSide != null) facing = actualSide; + PipeTileEntity other = tile.getPipeNeighbor(facing, true); + + if (playerIn.isSneaking() && allowsBlocking()) { + if (tile.isBlocked(facing)) unblockTile(tile, other, facing); + else blockTile(tile, other, facing); + } else { + if (tile.isConnected(facing)) disconnectTile(tile, other, facing); + else connectTile(tile, other, facing); + } + return true; + } + } + return super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ); + } + + public static void connectTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, EnumFacing facing) { // abort connection if either tile refuses it. - if (!tile1.canConnectTo(facingFrom1To2) || !tile2.canConnectTo(facingFrom1To2.getOpposite())) return; + if (!tile.canConnectTo(facing) || tileAcross != null && !tileAcross.canConnectTo(facing.getOpposite())) return; // if one of the pipes is larger than the other, render it closed. - tile1.setConnected(facingFrom1To2, - tile1.getStructure().getRenderThickness() > tile2.getStructure().getRenderThickness()); - tile2.setConnected(facingFrom1To2.getOpposite(), - tile2.getStructure().getRenderThickness() > tile1.getStructure().getRenderThickness()); - if (tile1.getWorld().isRemote) return; + tile.setConnected(facing, tileAcross != null && + tile.getStructure().getRenderThickness() > tileAcross.getStructure().getRenderThickness()); + if (tileAcross == null) return; + tileAcross.setConnected(facing.getOpposite(), + tileAcross.getStructure().getRenderThickness() > tile.getStructure().getRenderThickness()); + if (tile.getWorld().isRemote) return; - boolean blocked1 = tile1.isBlocked(facingFrom1To2); - boolean blocked2 = tile2.isBlocked(facingFrom1To2.getOpposite()); + boolean blocked1 = tile.isBlocked(facing); + boolean blocked2 = tileAcross.isBlocked(facing.getOpposite()); Map tile2Nodes = new Object2ObjectOpenHashMap<>(); - for (WorldPipeNetNode tile : getNodesForTile(tile2)) { - tile2Nodes.put(tile.getNet(), tile); + for (WorldPipeNetNode node : getNodesForTile(tileAcross)) { + tile2Nodes.put(node.getNet(), node); } - for (WorldPipeNetNode node : getNodesForTile(tile1)) { + for (WorldPipeNetNode node : getNodesForTile(tile)) { WorldPipeNet net = node.getNet(); WorldPipeNetNode other = tile2Nodes.get(net); if (other == null) continue; @@ -134,7 +167,64 @@ public void connectTiles(@NotNull PipeTileEntity tile1, @NotNull PipeTileEntity } } - public final Collection getNodesForTile(PipeTileEntity tile) { + public static void disconnectTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, EnumFacing facing) { + tile.setDisconnected(facing); + if (tileAcross == null) return; + tileAcross.setDisconnected(facing.getOpposite()); + if (tile.getWorld().isRemote) return; + + Map tile2Nodes = new Object2ObjectOpenHashMap<>(); + for (WorldPipeNetNode node : getNodesForTile(tileAcross)) { + tile2Nodes.put(node.getNet(), node); + } + + for (WorldPipeNetNode node : getNodesForTile(tile)) { + WorldPipeNet net = node.getNet(); + WorldPipeNetNode other = tile2Nodes.get(net); + if (other == null) continue; + net.removeEdge(node, other, true); + } + } + + public static void blockTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, EnumFacing facing) { + tile.setBlocked(facing); + if (tileAcross == null || tile.getWorld().isRemote) return; + + Map tile2Nodes = new Object2ObjectOpenHashMap<>(); + for (WorldPipeNetNode node : getNodesForTile(tileAcross)) { + tile2Nodes.put(node.getNet(), node); + } + + for (WorldPipeNetNode node : getNodesForTile(tile)) { + WorldPipeNet net = node.getNet(); + WorldPipeNetNode other = tile2Nodes.get(net); + if (other == null) continue; + net.removeEdge(other, node, false); + } + } + + public static void unblockTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, EnumFacing facing) { + tile.setUnblocked(facing); + if (tileAcross == null || tile.getWorld().isRemote) return; + + Map tile2Nodes = new Object2ObjectOpenHashMap<>(); + for (WorldPipeNetNode node : getNodesForTile(tileAcross)) { + tile2Nodes.put(node.getNet(), node); + } + + for (WorldPipeNetNode node : getNodesForTile(tile)) { + WorldPipeNet net = node.getNet(); + WorldPipeNetNode other = tile2Nodes.get(net); + if (other == null) continue; + net.addEdge(other, node, false); + } + } + + protected boolean allowsBlocking() { + return true; + } + + public static Collection getNodesForTile(PipeTileEntity tile) { assert !tile.getWorld().isRemote; return tile.getBlockType().getHandler(tile.getWorld(), tile.getPos()) .getFromNets(tile.getWorld(), tile.getPos(), tile.getStructure()); @@ -155,8 +245,31 @@ public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull I @NotNull protected abstract IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos); + @NotNull + protected abstract IPipeNetNodeHandler getHandler(@NotNull ItemStack stack); + // misc stuff // + @Override + public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { + if (getStructure() instanceof IPipeChanneledStructure channeledStructure) { + if (channeledStructure.getChannelCount() > 1) + tooltip.add(I18n.format("gregtech.pipe.channels", channeledStructure.getChannelCount())); + } + getHandler(stack).addInformation(stack, worldIn, tooltip, flagIn, getStructure()); + if (TooltipHelper.isShiftDown()) { + tooltip.add(I18n.format(getConnectLangKey())); + tooltip.add(I18n.format("gregtech.tool_action.screwdriver.access_covers")); + tooltip.add(I18n.format("gregtech.tool_action.crowbar")); + } else { + tooltip.add(I18n.format("gregtech.tool_action.show_tooltips")); + } + } + + protected String getConnectLangKey() { + return "gregtech.tool_action.wrench.connect_and_block"; + } + @Override public void getDrops(@NotNull NonNullList drops, @NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull IBlockState state, int fortune) { @@ -218,6 +331,14 @@ protected Pair getParticleTexture(World world, Bloc // collision boxes // + @SuppressWarnings("deprecation") + @Override + public @NotNull AxisAlignedBB getSelectedBoundingBox(@NotNull IBlockState state, @NotNull World worldIn, + @NotNull BlockPos pos) { + RayTracePair trace = this.collisionRayTrace(GTUtility.getSP(), worldIn, pos); + return (trace.bb() == null ? FULL_BLOCK_AABB : trace.bb()).offset(pos); + } + @SuppressWarnings("deprecation") @Override public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos, @@ -226,18 +347,14 @@ public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World wor PipeTileEntity tile = getTileEntity(worldIn, pos); if (tile != null) { if (tile.getFrameMaterial() != null) { - AxisAlignedBB box = BlockFrame.COLLISION_BOX.offset(pos); - if (box.intersects(entityBox)) { - collidingBoxes.add(box); - } + addCollisionBoxToList(pos, entityBox, collidingBoxes, BlockFrame.COLLISION_BOX); return; } for (AxisAlignedBB axisAlignedBB : getStructure().getPipeBoxes(tile)) { - AxisAlignedBB offsetBox = axisAlignedBB.offset(pos); - if (offsetBox.intersects(entityBox)) collidingBoxes.add(offsetBox); + addCollisionBoxToList(pos, entityBox, collidingBoxes, axisAlignedBB); } } else { - collidingBoxes.add(FULL_BLOCK_AABB); + addCollisionBoxToList(pos, entityBox, collidingBoxes, FULL_BLOCK_AABB); } } @@ -247,26 +364,26 @@ public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World wor public RayTraceResult collisionRayTrace(@NotNull IBlockState blockState, @NotNull World worldIn, @NotNull BlockPos pos, @NotNull Vec3d start, @NotNull Vec3d end) { - return collisionRayTrace(worldIn.isRemote ? GTUtility.getSP() : null, blockState, worldIn, pos, start, end); + return collisionRayTrace(worldIn.isRemote ? GTUtility.getSP() : null, worldIn, pos, start, end).result(); } - public RayTraceResult collisionRayTrace(@NotNull EntityPlayer player, @NotNull World world, @NotNull BlockPos pos) { - return collisionRayTrace(player, null, world, pos, RayTracer.getStartVec(player), RayTracer.getEndVec(player)); + public @NotNull RayTracePair collisionRayTrace(@NotNull EntityPlayer player, + @NotNull World world, @NotNull BlockPos pos) { + return collisionRayTrace(player, world, pos, RayTracer.getStartVec(player), RayTracer.getEndVec(player)); } - @SuppressWarnings("deprecation") - public RayTraceResult collisionRayTrace(@Nullable EntityPlayer player, @Nullable IBlockState blockState, - @NotNull World worldIn, @NotNull BlockPos pos, + public @NotNull RayTracePair collisionRayTrace(@Nullable EntityPlayer player, + @NotNull World worldIn, @NotNull BlockPos pos, @NotNull Vec3d start, @NotNull Vec3d end) { - if (blockState == null) blockState = worldIn.getBlockState(pos); if (hasPipeCollisionChangingItem(worldIn, pos, player)) { - return super.collisionRayTrace(blockState, worldIn, pos, start, end); + return new RayTracePair(rayTrace(pos, start, end, FULL_BLOCK_AABB), FULL_BLOCK_AABB); } PipeTileEntity tile = getTileEntity(worldIn, pos); if (tile == null) { - return super.collisionRayTrace(blockState, worldIn, pos, start, end); + return new RayTracePair(rayTrace(pos, start, end, FULL_BLOCK_AABB), FULL_BLOCK_AABB); } RayTraceResult min = null; + AxisAlignedBB minbb = null; double minDistSqrd = Double.MAX_VALUE; for (AxisAlignedBB aabb : getStructure().getPipeBoxes(tile)) { RayTraceResult result = rayTrace(pos, start, end, aabb); @@ -274,10 +391,11 @@ public RayTraceResult collisionRayTrace(@Nullable EntityPlayer player, @Nullable double distSqrd = start.squareDistanceTo(result.hitVec); if (distSqrd < minDistSqrd) { min = result; + minbb = aabb; minDistSqrd = distSqrd; } } - return min; + return new RayTracePair(min, minbb); } public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, Entity entity) { @@ -322,7 +440,31 @@ public boolean isPipeTool(@NotNull ItemStack stack) { return ToolHelper.isTool(stack, ToolClasses.WRENCH); } - // tile entity // + @SuppressWarnings("deprecation") + @Override + public @NotNull BlockFaceShape getBlockFaceShape(@NotNull IBlockAccess worldIn, @NotNull IBlockState state, + @NotNull BlockPos pos, @NotNull EnumFacing face) { + PipeTileEntity tile = getTileEntity(worldIn, pos); + if (tile != null) { + return tile.getCoverHolder().hasCover(face) ? BlockFaceShape.SOLID : + tile.isConnected(face) ? BlockFaceShape.CENTER : BlockFaceShape.UNDEFINED; + } + return super.getBlockFaceShape(worldIn, state, pos, face); + } + + // blockstate // + + @Override + protected @NotNull BlockStateContainer createBlockState() { + return constructState(new BlockStateContainer.Builder(this)).build(); + } + + protected @NotNull BlockStateContainer.Builder constructState(BlockStateContainer.@NotNull Builder builder) { + return builder.add(AbstractPipeModel.THICKNESS_PROPERTY).add(AbstractPipeModel.CONNECTION_MASK_PROPERTY) + .add(AbstractPipeModel.CLOSED_MASK_PROPERTY).add(AbstractPipeModel.BLOCKED_MASK_PROPERTY) + .add(AbstractPipeModel.COLOR_PROPERTY).add(AbstractPipeModel.FRAME_MATERIAL_PROPERTY) + .add(AbstractPipeModel.FRAME_MASK_PROPERTY); + } @Override public @NotNull IBlockState getExtendedState(@NotNull IBlockState state, @NotNull IBlockAccess world, @@ -332,8 +474,10 @@ public boolean isPipeTool(@NotNull ItemStack stack) { else return tile.getRenderInformation((IExtendedBlockState) state); } + // tile entity // + @Override - public boolean hasTileEntity(@NotNull IBlockState state) { + public final boolean hasTileEntity(@NotNull IBlockState state) { return true; } @@ -352,9 +496,21 @@ public PipeTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockP } @Override - @NotNull - public PipeTileEntity createTileEntity(@NotNull World world, @NotNull IBlockState state) { - return new PipeTileEntity(this); + public final PipeTileEntity createTileEntity(@NotNull World world, @NotNull IBlockState state) { + try { + //noinspection deprecation + return getTileClass(world, state).newInstance(); + } catch (Throwable ignored) { + return null; + } + } + + /** + * This may seem unnecessary, but it enforces empty constructors which are required due to + * {@link TileEntity#create(World, NBTTagCompound)} + */ + public Class getTileClass(@NotNull World world, @NotNull IBlockState state) { + return PipeTileEntity.class; } @Override @@ -366,6 +522,24 @@ public void onNeighborChange(@NotNull IBlockAccess world, @NotNull BlockPos pos, if (tile != null) tile.onNeighborChanged(facing); } + @Override + public int getLightValue(@NotNull IBlockState state, @NotNull IBlockAccess world, @NotNull BlockPos pos) { + PipeTileEntity tile = getTileEntity(world, pos); + if (tile != null) { + TemperatureLogic temperatureLogic = tile.getTemperatureLogic(); + int temp = temperatureLogic == null ? 0 : temperatureLogic.getTemperature(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); + // max light at 5000 K + // min light at 500 K + if (temp >= 5000) { + return 15; + } + if (temp > 500) { + return (temp - 500) * 15 / (4500); + } + } + return 0; + } + // cover compatibility annoyance // @SuppressWarnings("deprecation") diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java index 9305e345479..12dec84eaca 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java @@ -13,10 +13,6 @@ public class PipeActivableTileEntity extends PipeTileEntity implements IActivabl private boolean active; - public PipeActivableTileEntity(WorldPipeBlock block) { - super(block); - } - @Override public void setActive(boolean active) { if (this.active != active) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java index ca1c0d74db3..afd5059138c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java @@ -16,10 +16,6 @@ public class PipeMaterialTileEntity extends PipeTileEntity { private Material material; - public PipeMaterialTileEntity(PipeMaterialBlock block) { - super(block); - } - @Override public void placedBy(ItemStack stack, EntityPlayer player) { super.placedBy(stack, player); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 3720bccd04f..ea299d925a9 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -64,8 +64,6 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick private final Object2ObjectOpenHashMap netLogicDatas = new Object2ObjectOpenHashMap<>(); private final ObjectOpenHashSet listeners = new ObjectOpenHashSet<>(); - private final WorldPipeBlock block; - // information that is only required for determining graph topology should be stored on the tile entity level, // while information interacted with during graph traversal should be stored on the NetLogicData level. @@ -93,10 +91,6 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick private long nextDamageTime = 0; private long nextSoundTime = 0; - public PipeTileEntity(WorldPipeBlock block) { - this.block = block; - } - @Nullable public PipeTileEntity getPipeNeighbor(EnumFacing facing, boolean allowChunkloading) { TileEntity tile = allowChunkloading ? getNeighbor(facing) : getNeighborNoChunkloading(facing); @@ -251,6 +245,7 @@ public void update() { @Override public void onLoad() { super.onLoad(); + initialize(); // since we're an instance of ITickable, we're automatically added to the tickable list just before this exact // moment. // it would theoretically be a micro optimization to just pop the last tile from the tickable list, but that's @@ -400,25 +395,24 @@ public NetLogicData getNetLogicData(String netName) { @Override public @NotNull WorldPipeBlock getBlockType() { - return block; + return (WorldPipeBlock) super.getBlockType(); } @Override public void setWorld(@NotNull World worldIn) { if (worldIn == this.getWorld()) return; super.setWorld(worldIn); - this.initialize(worldIn); } - protected void initialize(World worldIn) { - if (!worldIn.isRemote) { + protected void initialize() { + if (!getWorld().isRemote) { this.netLogicDatas.clear(); this.capabilities.clear(); this.netCapabilities.clear(); this.listeners.forEach(NetLogicData.LogicDataListener::invalidate); this.listeners.clear(); boolean firstNode = true; - for (WorldPipeNetNode node : getBlockType().getNodesForTile(this)) { + for (WorldPipeNetNode node : WorldPipeBlock.getNodesForTile(this)) { this.addCapabilities(node.getNet().getNewCapabilityObjects(node)); this.netCapabilities.put(node, new PipeCapabilityWrapper(node.getNet().getTargetCapabilities())); String netName = node.getNet().mapName; @@ -639,6 +633,9 @@ public void markAsDirty() { else return null; } + /** + * Note - the block corresponding to this tile entity must register any new unlisted properties to the default state. + */ public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { byte frameMask = 0; for (EnumFacing facing : EnumFacing.VALUES) { diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java index dbb6e957921..9edbdf108b7 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -19,6 +19,7 @@ import net.minecraft.world.World; import net.minecraft.world.storage.WorldSavedData; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index ccc3e634e79..7452125eabd 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -3,13 +3,17 @@ import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -71,6 +75,14 @@ public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) } } + @Override + public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, + @NotNull ITooltipFlag flagIn, IPipeStructure structure) { + for (IPipeNetMaterialProperty property : properties.values()) { + property.addInformation(stack, worldIn, tooltip, flagIn, (IPipeMaterialStructure) structure); + } + } + @Override public void verifyProperty(MaterialProperties properties) { for (IPipeNetMaterialProperty p : this.properties.values()) { @@ -91,6 +103,9 @@ public interface IPipeNetMaterialProperty extends IMaterialProperty { boolean generatesStructure(IPipeStructure structure); + void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, + @NotNull ITooltipFlag flagIn, IPipeMaterialStructure structure); + MaterialPropertyKey getKey(); class MaterialPropertyKey { diff --git a/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java b/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java index 4cb6202f169..b845f067d5f 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java +++ b/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java @@ -10,13 +10,5 @@ public class WoodProperty implements IMaterialProperty { public void verifyProperty(MaterialProperties properties) { properties.ensureSet(PropertyKey.DUST); properties.getMaterial().addFlags(MaterialFlags.FLAMMABLE); - - PipeNetProperties netProperties = properties.getProperty(PropertyKey.PIPENET_PROPERTIES); - if (netProperties != null && netProperties.hasProperty(MaterialFluidProperties.KEY)) { - OrePrefix.pipeTiny.setIgnored(properties.getMaterial()); - OrePrefix.pipeHuge.setIgnored(properties.getMaterial()); - OrePrefix.pipeQuadruple.setIgnored(properties.getMaterial()); - OrePrefix.pipeNonuple.setIgnored(properties.getMaterial()); - } } } diff --git a/src/main/java/gregtech/api/unification/ore/OrePrefix.java b/src/main/java/gregtech/api/unification/ore/OrePrefix.java index f617103465c..3106991713a 100644 --- a/src/main/java/gregtech/api/unification/ore/OrePrefix.java +++ b/src/main/java/gregtech/api/unification/ore/OrePrefix.java @@ -270,7 +270,7 @@ public class OrePrefix { public static final OrePrefix pipeNonuple = new OrePrefix("pipeNonuple", M * 9, null, null, ENABLE_UNIFICATION, null); - public static final OrePrefix pipeTinyRestrictive = new OrePrefix("pipeSmallRestrictive", M / 2, null, null, + public static final OrePrefix pipeTinyRestrictive = new OrePrefix("pipeTinyRestrictive", M / 2, null, null, ENABLE_UNIFICATION, null); public static final OrePrefix pipeSmallRestrictive = new OrePrefix("pipeSmallRestrictive", M, null, null, ENABLE_UNIFICATION, null); @@ -452,10 +452,26 @@ public static void init() { toolHeadWrench.addSecondaryMaterial( new MaterialStack(Materials.Steel, ring.materialAmount + screw.materialAmount * 2)); + Predicate woodPredicate = m -> !m.hasProperty(PropertyKey.WOOD); + pipeTiny.setGenerationCondition(woodPredicate); + pipeTinyRestrictive.setGenerationCondition(woodPredicate); + pipeSmallRestrictive.setGenerationCondition(woodPredicate); + pipeNormalRestrictive.setGenerationCondition(woodPredicate); + pipeLargeRestrictive.setGenerationCondition(woodPredicate); + pipeHuge.setGenerationCondition(woodPredicate); + pipeHugeRestrictive.setGenerationCondition(woodPredicate); + pipeQuadruple.setGenerationCondition(woodPredicate); + pipeQuadrupleRestrictive.setGenerationCondition(woodPredicate); + pipeNonuple.setGenerationCondition(woodPredicate); + pipeNonupleRestrictive.setGenerationCondition(woodPredicate); + pipeSmallRestrictive.addSecondaryMaterial(new MaterialStack(Materials.Iron, ring.materialAmount * 2)); + pipeTinyRestrictive.addSecondaryMaterial(new MaterialStack(Materials.Iron, ring.materialAmount * 2)); pipeNormalRestrictive.addSecondaryMaterial(new MaterialStack(Materials.Iron, ring.materialAmount * 2)); pipeLargeRestrictive.addSecondaryMaterial(new MaterialStack(Materials.Iron, ring.materialAmount * 2)); pipeHugeRestrictive.addSecondaryMaterial(new MaterialStack(Materials.Iron, ring.materialAmount * 2)); + pipeQuadrupleRestrictive.addSecondaryMaterial(new MaterialStack(Materials.Iron, ring.materialAmount * 2)); + pipeNonupleRestrictive.addSecondaryMaterial(new MaterialStack(Materials.Iron, ring.materialAmount * 2)); cableGtSingle.addSecondaryMaterial(new MaterialStack(Materials.Rubber, plate.materialAmount)); cableGtDouble.addSecondaryMaterial(new MaterialStack(Materials.Rubber, plate.materialAmount)); diff --git a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java index 5f6aaebd3e2..144722b96d6 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java @@ -35,6 +35,8 @@ public class ActivablePipeModel extends AbstractPipeModel { + private static final ResourceLocation loc = GTUtility.gregtechId("block/pipe_activable"); + public static final UnlistedBooleanProperty ACTIVE_PROPERTY = new UnlistedBooleanProperty("active"); public static final ActivablePipeModel OPTICAL = new ActivablePipeModel(Textures.OPTICAL_PIPE_IN, @@ -44,8 +46,6 @@ public class ActivablePipeModel extends AbstractPipeModel { Textures.LASER_PIPE_SIDE, Textures.LASER_PIPE_OVERLAY, Textures.LASER_PIPE_OVERLAY_EMISSIVE, true, "laser"); - private static final ResourceLocation loc = GTUtility.gregtechId("block/pipe_activable"); - private final Supplier inTex; private final Supplier sideTex; private final Supplier overlayTex; diff --git a/src/main/java/gregtech/client/renderer/pipe/CableModel.java b/src/main/java/gregtech/client/renderer/pipe/CableModel.java index e674b3fce31..c60e98f4e9f 100644 --- a/src/main/java/gregtech/client/renderer/pipe/CableModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/CableModel.java @@ -32,11 +32,11 @@ @SideOnly(Side.CLIENT) public class CableModel extends AbstractPipeModel { + private static final ResourceLocation loc = GTUtility.gregtechId("block/cable"); + public static final CableModel INSTANCE = new CableModel("wire"); public static final CableModel[] INSULATED_INSTANCES = new CableModel[Textures.INSULATION.length]; - private static final ResourceLocation loc = GTUtility.gregtechId("block/cable"); - static { for (int i = 0; i < INSULATED_INSTANCES.length; i++) { INSULATED_INSTANCES[i] = new CableModel(Textures.INSULATION[i], Textures.INSULATION_FULL, "insulated_" + i); diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java index a42fc31e69d..e166c24ebbf 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java @@ -33,13 +33,13 @@ @SideOnly(Side.CLIENT) public class PipeModel extends AbstractPipeModel { + private static final ResourceLocation loc = GTUtility.gregtechId("block/pipe_material"); + public static final UnlistedPropertyMaterial MATERIAL_PROPERTY = new UnlistedPropertyMaterial("material"); public static final PipeModel[] INSTANCES = new PipeModel[7]; public static final PipeModel[] RESTRICTIVE_INSTANCES = new PipeModel[INSTANCES.length]; - private static final ResourceLocation loc = GTUtility.gregtechId("block/pipe_material"); - static { model(0, wood -> Textures.PIPE_TINY.get()); model(1, wood -> wood ? Textures.PIPE_SMALL_WOOD.get() : Textures.PIPE_SMALL.get()); @@ -123,5 +123,8 @@ public static void registerModels(IRegistry for (PipeModel model : INSTANCES) { registry.putObject(model.getLoc(), model); } + for (PipeModel model : RESTRICTIVE_INSTANCES) { + registry.putObject(model.getLoc(), model); + } } } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java index 538cc60db20..ee8a343f4f7 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -16,7 +16,7 @@ @SideOnly(Side.CLIENT) public final class PipeQuadHelper { - private static final VertexFormat FORMAT = DefaultVertexFormats.POSITION_TEX_COLOR_NORMAL; + private static final VertexFormat FORMAT = DefaultVertexFormats.ITEM; private final float thickness; private final float x; diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index a8f47ff0a09..0947d00a0c4 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -4,6 +4,7 @@ import gregtech.api.GregTechAPI; import gregtech.api.block.VariantItemBlock; import gregtech.api.block.machines.MachineItemBlock; +import gregtech.api.graphnet.pipenet.physical.block.ItemMaterialPipeBlock; import gregtech.api.graphnet.pipenet.physical.block.ItemPipeBlock; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.toolitem.IGTTool; @@ -12,9 +13,11 @@ import gregtech.api.recipes.ingredients.GTRecipeOreInput; import gregtech.api.recipes.recipeproperties.FusionEUToStartProperty; import gregtech.api.terminal.TerminalRegistry; +import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.info.MaterialFlags; import gregtech.api.unification.material.properties.DustProperty; +import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.unification.ore.OrePrefix; @@ -198,9 +201,9 @@ public static void registerItems(RegistryEvent.Register event) { for (MaterialRegistry materialRegistry : GregTechAPI.materialManager.getRegistries()) { for (CableBlock cable : CABLES.get(materialRegistry.getModid())) - registry.register(createItemBlock(cable, ItemPipeBlock::new)); + registry.register(createItemBlock(cable, ItemMaterialPipeBlock::new)); for (PipeBlock cable : MATERIAL_PIPES.get(materialRegistry.getModid())) - registry.register(createItemBlock(cable, ItemPipeBlock::new)); + registry.register(createItemBlock(cable, ItemMaterialPipeBlock::new)); } for (OpticalPipeBlock pipe : OPTICAL_PIPES) registry.register(createItemBlock(pipe, ItemPipeBlock::new)); for (LaserPipeBlock pipe : LASER_PIPES) registry.register(createItemBlock(pipe, ItemPipeBlock::new)); diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index cd8b67874e0..8b654695f9f 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -3,6 +3,7 @@ import gregtech.api.GTValues; import gregtech.api.GregTechAPI; import gregtech.api.block.machines.BlockMachine; +import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.pipenetold.longdist.BlockLongDistancePipe; @@ -70,6 +71,7 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.client.model.ModelLoaderRegistry; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fluids.BlockFluidBase; import net.minecraftforge.fml.client.registry.ClientRegistry; @@ -187,7 +189,7 @@ public static void init() { int i = 0; for (CableStructure struct : structuresCable) { CableBlock block = new CableBlock(struct, registry); - block.setRegistryName(modid, String.format("cable_%s", struct.getName())); + block.setRegistryName(modid, String.format(struct.getName())); cables[i] = block; i++; } @@ -198,7 +200,7 @@ public static void init() { i = 0; for (PipeStructure struct : structuresPipe) { PipeBlock block = new PipeBlock(struct, registry); - block.setRegistryName(modid, String.format("material_pipe_%s", struct.getName())); + block.setRegistryName(modid, String.format(struct.getName())); pipes[i] = block; i++; } @@ -210,7 +212,7 @@ public static void init() { int i = 0; for (OpticalStructure struct : structuresOptical) { OpticalPipeBlock block = new OpticalPipeBlock(struct); - block.setRegistryName(GTValues.MODID, String.format("optical_pipe_%s", struct.getName())); + block.setRegistryName(GTValues.MODID, String.format(struct.getName())); OPTICAL_PIPES[i] = block; i++; } @@ -219,7 +221,7 @@ public static void init() { i = 0; for (LaserStructure struct : structuresLaser) { LaserPipeBlock block = new LaserPipeBlock(struct); - block.setRegistryName(GTValues.MODID, String.format("laser_pipe_%s", struct.getName())); + block.setRegistryName(GTValues.MODID, String.format(struct.getName())); LASER_PIPES[i] = block; i++; } @@ -427,6 +429,7 @@ public static void registerTileEntity() { GameRegistry.registerTileEntity(MetaTileEntityHolder.class, gregtechId("machine")); GameRegistry.registerTileEntity(PipeTileEntity.class, gregtechId("pipe")); GameRegistry.registerTileEntity(PipeMaterialTileEntity.class, gregtechId("material_pipe")); + GameRegistry.registerTileEntity(PipeActivableTileEntity.class, gregtechId("activable_pipe")); } @SideOnly(Side.CLIENT) @@ -681,15 +684,17 @@ public static void registerOreDict() { PipeNetProperties properties = material.getProperty(PropertyKey.PIPENET_PROPERTIES); if (properties != null) { for (CableBlock cable : CABLES.get(registry.getModid())) { - if (properties.generatesStructure(cable.getStructure())) { + OrePrefix prefix = cable.getStructure().getOrePrefix(); + if (prefix.doGenerateItem(material) && properties.generatesStructure(cable.getStructure())) { ItemStack itemStack = cable.getItem(material); - OreDictUnifier.registerOre(itemStack, cable.getStructure().getOrePrefix(), material); + OreDictUnifier.registerOre(itemStack, prefix, material); } } for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) { - if (properties.generatesStructure(pipe.getStructure())) { + OrePrefix prefix = pipe.getStructure().getOrePrefix(); + if (prefix.doGenerateItem(material) && properties.generatesStructure(pipe.getStructure())) { ItemStack itemStack = pipe.getItem(material); - OreDictUnifier.registerOre(itemStack, pipe.getStructure().getOrePrefix(), material); + OreDictUnifier.registerOre(itemStack, prefix, material); } } } diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index 159322a20b0..e549c57fcd8 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -7,6 +7,8 @@ import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.unification.material.registry.MaterialRegistry; +import gregtech.common.creativetab.GTCreativeTabs; + import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; @@ -30,6 +32,7 @@ public CableBlock(CableStructure structure, MaterialRegistry registry) { v.put(structure, this); return v; }); + setCreativeTab(GTCreativeTabs.TAB_GREGTECH_CABLES); } @Override @@ -37,6 +40,11 @@ public boolean isPipeTool(@NotNull ItemStack stack) { return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); } + @Override + protected String getConnectLangKey() { + return "gregtech.tool_action.wire_cutter.connect"; + } + public static Set gatherStructures() { GatherStructuresEvent event = new GatherStructuresEvent<>(CableStructure.class); MinecraftForge.EVENT_BUS.post(event); diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java index 432094aa2dc..983b527baa3 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java @@ -2,9 +2,11 @@ import gregtech.api.graphnet.gather.GatherStructuresEvent; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; +import gregtech.api.graphnet.pipenet.physical.block.PipeActivableBlock; import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; +import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.pipelike.handlers.LaserNetHandler; import net.minecraft.item.ItemStack; @@ -16,11 +18,12 @@ import java.util.Set; -public class LaserPipeBlock extends WorldPipeBlock { +public class LaserPipeBlock extends PipeActivableBlock { public LaserPipeBlock(LaserStructure structure) { super(structure); setHarvestLevel(ToolClasses.WIRE_CUTTER, 1); + setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); } public static Set gatherStructures() { @@ -34,8 +37,23 @@ public boolean isPipeTool(@NotNull ItemStack stack) { return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); } + @Override + protected String getConnectLangKey() { + return "gregtech.tool_action.wire_cutter.connect"; + } + + @Override + protected boolean allowsBlocking() { + return false; + } + @Override protected @NotNull IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos) { return LaserNetHandler.INSTANCE; } + + @Override + protected @NotNull IPipeNetNodeHandler getHandler(@NotNull ItemStack stack) { + return LaserNetHandler.INSTANCE; + } } diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java index 8909d771f22..235959a84a1 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java @@ -15,7 +15,7 @@ @Desugar public record LaserStructure(String name, float renderThickness, ActivablePipeModel model) implements IPipeStructure { - public static final LaserStructure INSTANCE = new LaserStructure("standard", 0.375f, ActivablePipeModel.LASER); + public static final LaserStructure INSTANCE = new LaserStructure("laser_pipe_normal", 0.375f, ActivablePipeModel.LASER); @Override public boolean canConnectTo(EnumFacing side, byte connectionMask) { diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java index 7ace175f077..338d5f1f11d 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java @@ -2,9 +2,11 @@ import gregtech.api.graphnet.gather.GatherStructuresEvent; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; +import gregtech.api.graphnet.pipenet.physical.block.PipeActivableBlock; import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; +import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.pipelike.handlers.OpticalNetHandler; import net.minecraft.item.ItemStack; @@ -16,11 +18,12 @@ import java.util.Set; -public class OpticalPipeBlock extends WorldPipeBlock { +public class OpticalPipeBlock extends PipeActivableBlock { public OpticalPipeBlock(OpticalStructure structure) { super(structure); setHarvestLevel(ToolClasses.WIRE_CUTTER, 1); + setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); } public static Set gatherStructures() { @@ -34,8 +37,23 @@ public boolean isPipeTool(@NotNull ItemStack stack) { return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); } + @Override + protected String getConnectLangKey() { + return "gregtech.tool_action.wire_cutter.connect"; + } + + @Override + protected boolean allowsBlocking() { + return false; + } + @Override protected @NotNull IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos) { return OpticalNetHandler.INSTANCE; } + + @Override + protected @NotNull IPipeNetNodeHandler getHandler(@NotNull ItemStack stack) { + return OpticalNetHandler.INSTANCE; + } } diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java index 72efdf5a99e..12fb705179c 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java @@ -15,7 +15,7 @@ @Desugar public record OpticalStructure(String name, float renderThickness, ActivablePipeModel model) implements IPipeStructure { - public static final OpticalStructure INSTANCE = new OpticalStructure("standard", 0.375f, + public static final OpticalStructure INSTANCE = new OpticalStructure("optical_pipe_normal", 0.375f, ActivablePipeModel.OPTICAL); @Override diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java index 91ae8de6e23..3423feaeaac 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java @@ -6,6 +6,8 @@ import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.unification.material.registry.MaterialRegistry; +import gregtech.common.creativetab.GTCreativeTabs; + import net.minecraftforge.common.MinecraftForge; import java.util.Set; @@ -14,6 +16,7 @@ public class PipeBlock extends PipeMaterialBlock implements IBurnable, IFreezabl public PipeBlock(PipeStructure structure, MaterialRegistry registry) { super(structure, registry); + setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); } public static Set gatherStructures() { diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java index 35b1716a192..9655da3f6f8 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java @@ -1,5 +1,6 @@ package gregtech.common.pipelike.block.pipe; +import gregtech.api.graphnet.pipenet.physical.IPipeChanneledStructure; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.unification.ore.OrePrefix; import gregtech.client.renderer.pipe.AbstractPipeModel; @@ -13,38 +14,38 @@ @Desugar public record PipeStructure(String name, int material, int channelCount, boolean restrictive, OrePrefix ore, float renderThickness, PipeModel model) - implements IPipeMaterialStructure { + implements IPipeMaterialStructure, IPipeChanneledStructure { - public static final PipeStructure TINY = new PipeStructure("tiny", 1, 1, false, OrePrefix.pipeTiny, 0.25f, + public static final PipeStructure TINY = new PipeStructure("pipe_tiny", 1, 1, false, OrePrefix.pipeTiny, 0.25f, PipeModel.INSTANCES[0]); - public static final PipeStructure SMALL = new PipeStructure("small", 2, 1, false, OrePrefix.pipeSmall, 0.375f, + public static final PipeStructure SMALL = new PipeStructure("pipe_small", 2, 1, false, OrePrefix.pipeSmall, 0.375f, PipeModel.INSTANCES[1]); - public static final PipeStructure NORMAL = new PipeStructure("normal", 6, 1, false, OrePrefix.pipeNormal, 0.5f, + public static final PipeStructure NORMAL = new PipeStructure("pipe_normal", 6, 1, false, OrePrefix.pipeNormal, 0.5f, PipeModel.INSTANCES[2]); - public static final PipeStructure LARGE = new PipeStructure("large", 12, 1, false, OrePrefix.pipeLarge, 0.75f, + public static final PipeStructure LARGE = new PipeStructure("pipe_large", 12, 1, false, OrePrefix.pipeLarge, 0.75f, PipeModel.INSTANCES[3]); - public static final PipeStructure HUGE = new PipeStructure("huge", 24, 1, false, OrePrefix.pipeHuge, 0.875f, + public static final PipeStructure HUGE = new PipeStructure("pipe_huge", 24, 1, false, OrePrefix.pipeHuge, 0.875f, PipeModel.INSTANCES[4]); - public static final PipeStructure QUADRUPLE = new PipeStructure("quadruple", 8, 4, false, OrePrefix.pipeQuadruple, + public static final PipeStructure QUADRUPLE = new PipeStructure("pipe_quadruple", 8, 4, false, OrePrefix.pipeQuadruple, 0.95f, PipeModel.INSTANCES[5]); - public static final PipeStructure NONUPLE = new PipeStructure("nonuple", 18, 9, false, OrePrefix.pipeNonuple, 0.95f, + public static final PipeStructure NONUPLE = new PipeStructure("pipe_nonuple", 18, 9, false, OrePrefix.pipeNonuple, 0.95f, PipeModel.INSTANCES[6]); - public static final PipeStructure TINY_RESTRICTIVE = new PipeStructure("tiny_restrictive", 1, 1, true, + public static final PipeStructure TINY_RESTRICTIVE = new PipeStructure("pipe_tiny_restrictive", 1, 1, true, OrePrefix.pipeTinyRestrictive, 0.25f, PipeModel.RESTRICTIVE_INSTANCES[0]); - public static final PipeStructure SMALL_RESTRICTIVE = new PipeStructure("small_restrictive", 2, 1, true, + public static final PipeStructure SMALL_RESTRICTIVE = new PipeStructure("pipe_small_restrictive", 2, 1, true, OrePrefix.pipeSmallRestrictive, 0.375f, PipeModel.RESTRICTIVE_INSTANCES[1]); - public static final PipeStructure NORMAL_RESTRICTIVE = new PipeStructure("normal_restrictive", 6, 1, true, + public static final PipeStructure NORMAL_RESTRICTIVE = new PipeStructure("pipe_normal_restrictive", 6, 1, true, OrePrefix.pipeNormalRestrictive, 0.5f, PipeModel.RESTRICTIVE_INSTANCES[2]); - public static final PipeStructure LARGE_RESTRICTIVE = new PipeStructure("large_restrictive", 12, 1, true, + public static final PipeStructure LARGE_RESTRICTIVE = new PipeStructure("pipe_large_restrictive", 12, 1, true, OrePrefix.pipeLargeRestrictive, 0.75f, PipeModel.RESTRICTIVE_INSTANCES[3]); - public static final PipeStructure HUGE_RESTRICTIVE = new PipeStructure("huge_restrictive", 24, 1, true, + public static final PipeStructure HUGE_RESTRICTIVE = new PipeStructure("pipe_huge_restrictive", 24, 1, true, OrePrefix.pipeHugeRestrictive, 0.875f, PipeModel.RESTRICTIVE_INSTANCES[4]); - public static final PipeStructure QUADRUPLE_RESTRICTIVE = new PipeStructure("quadruple_restrictive", 8, 4, true, + public static final PipeStructure QUADRUPLE_RESTRICTIVE = new PipeStructure("pipe_quadruple_restrictive", 8, 4, true, OrePrefix.pipeQuadrupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[5]); - public static final PipeStructure NONUPLE_RESTRICTIVE = new PipeStructure("nonuple_restrictive", 18, 9, true, + public static final PipeStructure NONUPLE_RESTRICTIVE = new PipeStructure("pipe_nonuple_restrictive", 18, 9, true, OrePrefix.pipeNonupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[6]); @Override @@ -62,6 +63,11 @@ public float getRenderThickness() { return renderThickness; } + @Override + public int getChannelCount() { + return channelCount; + } + @Override public AbstractPipeModel getModel() { return model; diff --git a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java index 2f8f1da291c..b727b01f55d 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java @@ -6,11 +6,17 @@ import gregtech.common.pipelike.block.laser.LaserStructure; import gregtech.common.pipelike.net.laser.WorldLaserNet; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import org.jetbrains.annotations.NotNull; + import java.util.Collection; import java.util.Collections; +import java.util.List; public final class LaserNetHandler implements IPipeNetNodeHandler { @@ -40,4 +46,10 @@ public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) if (node != null) net.removeNode(node); } } + + @Override + public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, + @NotNull ITooltipFlag flagIn, IPipeStructure structure) { + tooltip.add(I18n.format("tile.laser_pipe_normal.tooltip1")); + } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java index d35e551c331..76d2471c7a6 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java @@ -6,11 +6,17 @@ import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.net.optical.WorldOpticalNet; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import org.jetbrains.annotations.NotNull; + import java.util.Collection; import java.util.Collections; +import java.util.List; public final class OpticalNetHandler implements IPipeNetNodeHandler { @@ -40,4 +46,10 @@ public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) if (node != null) net.removeNode(node); } } + + @Override + public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, + @NotNull ITooltipFlag flagIn, IPipeStructure structure) { + tooltip.add(I18n.format("tile.optical_pipe_normal.tooltip1")); + } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index d01b7514e84..ae7d9c3f979 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -10,6 +10,7 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; +import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.FluidProperty; @@ -18,6 +19,7 @@ import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.ore.IOreRegistrationHandler; import gregtech.api.unification.ore.OrePrefix; +import gregtech.api.util.GTUtility; import gregtech.api.util.function.TriConsumer; import gregtech.common.pipelike.block.cable.CableStructure; import gregtech.common.pipelike.block.pipe.PipeStructure; @@ -26,12 +28,18 @@ import gregtech.common.pipelike.net.energy.VoltageLimitLogic; import gregtech.common.pipelike.net.energy.WorldEnergyNet; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fluids.Fluid; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + import static gregtech.api.unification.material.info.MaterialFlags.GENERATE_FOIL; import static gregtech.api.unification.material.info.MaterialFlags.NO_UNIFICATION; @@ -105,6 +113,20 @@ public MaterialPropertyKey getKey() { return KEY; } + @Override + public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, + @NotNull ITooltipFlag flagIn, IPipeMaterialStructure structure) { + + int tier = GTUtility.getTierByVoltage(voltageLimit); + if (isSuperconductor()) + tooltip.add(I18n.format("gregtech.cable.superconductor", GTValues.VN[tier])); + tooltip.add(I18n.format("gregtech.cable.voltage", voltageLimit, GTValues.VNF[tier])); + tooltip.add(I18n.format("gregtech.cable.amperage", getAmperage(structure))); + tooltip.add(I18n.format("gregtech.cable.loss_per_block", getLoss(structure))); + if (isSuperconductor()) + tooltip.add(I18n.format("gregtech.cable.superconductor_loss", superconductorCriticalTemperature)); + } + @Override public void verifyProperty(MaterialProperties properties) { properties.ensureSet(PropertyKey.DUST, true); @@ -147,8 +169,8 @@ public void addToNet(World world, BlockPos pos, IPipeStructure structure) { @Override public void mutateData(NetLogicData data, IPipeStructure structure) { if (structure instanceof CableStructure cable) { - long loss = lossPerAmp * cable.costFactor(); - long amperage = amperageLimit * cable.material(); + long loss = getLoss(structure); + long amperage = getAmperage(structure); boolean insulated = cable.partialBurnStructure() != null; // insulated cables cool down half as fast float coolingFactor = (float) (Math.sqrt(cable.material()) / (insulated ? 8 : 4)); @@ -163,9 +185,9 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { data.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorCriticalTemperature)); } } else if (structure instanceof PipeStructure pipe) { - long amperage = amperageLimit * pipe.material() / 2; + long amperage = getAmperage(structure); if (amperage == 0) return; // skip pipes that are too small - long loss = lossPerAmp * (pipe.material() > 6 ? 3 : 2); + long loss = getLoss(structure); float coolingFactor = (float) Math.sqrt((double) pipe.material() / (4 + pipe.channelCount())); data.setLogicEntry(LossAbsoluteLogic.INSTANCE.getWith(loss)) .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) @@ -180,6 +202,22 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { } } + private long getLoss(IPipeStructure structure) { + if (structure instanceof CableStructure cable) { + return lossPerAmp * cable.costFactor(); + } else if (structure instanceof PipeStructure pipe) { + return lossPerAmp * (pipe.material() > 6 ? 3 : 2); + } else return lossPerAmp; + } + + private long getAmperage(IPipeStructure structure) { + if (structure instanceof CableStructure cable) { + return amperageLimit * cable.material(); + } else if (structure instanceof PipeStructure pipe) { + return amperageLimit * pipe.material() / 2; + } else return amperageLimit; + } + @Override @Nullable public WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index aee3ec85ac7..3f09b91933e 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -13,15 +13,20 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; +import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.unification.material.properties.FluidProperty; import gregtech.api.unification.material.properties.MaterialProperties; import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.util.TextFormattingUtil; import gregtech.common.pipelike.block.pipe.PipeStructure; import gregtech.common.pipelike.net.fluid.FluidContainmentLogic; import gregtech.common.pipelike.net.fluid.WorldFluidNet; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fluids.Fluid; @@ -33,6 +38,7 @@ import java.util.Collection; import java.util.EnumSet; +import java.util.List; import java.util.Set; public final class MaterialFluidProperties implements PipeNetProperties.IPipeNetMaterialProperty, IPropertyFluidFilter { @@ -143,6 +149,15 @@ public MaterialPropertyKey getKey() { return KEY; } + @Override + public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, + @NotNull ITooltipFlag flagIn, IPipeMaterialStructure structure) { + tooltip.add(I18n.format("gregtech.universal.tooltip.fluid_transfer_rate", getThroughput(structure))); + tooltip.add(I18n.format("gregtech.fluid_pipe.max_temperature", getMaxFluidTemperature())); + tooltip.add(I18n.format("gregtech.fluid_pipe.min_temperature", getMinFluidTemperature())); + tooltip.add(I18n.format("gregtech.fluid_pipe.priority", TextFormattingUtil.formatNumbers(getFlowPriority(structure)))); + } + @Override public void verifyProperty(MaterialProperties properties) { if (!properties.hasProperty(PropertyKey.WOOD)) { @@ -175,10 +190,9 @@ public void addToNet(World world, BlockPos pos, IPipeStructure structure) { @Override public void mutateData(NetLogicData data, IPipeStructure structure) { if (structure instanceof PipeStructure pipe) { - long throughput = baseThroughput * pipe.material(); + long throughput = getThroughput(structure); float coolingFactor = (float) Math.sqrt((double) pipe.material() / (4 + pipe.channelCount())); - double weight = priority * (pipe.restrictive() ? 100d : 1d) * pipe.channelCount() / pipe.material(); - data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(weight)) + data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(getFlowPriority(structure))) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)) .setLogicEntry(FluidContainmentLogic.INSTANCE.getWith(containableStates, containableAttributes)) .setLogicEntry(TemperatureLogic.INSTANCE @@ -187,6 +201,18 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { } } + private long getThroughput(IPipeStructure structure) { + if (structure instanceof PipeStructure pipe) { + return baseThroughput * pipe.material(); + } else return baseThroughput; + } + + private double getFlowPriority(IPipeStructure structure) { + if (structure instanceof PipeStructure pipe) { + return priority * (pipe.restrictive() ? 100d : 1d) * pipe.channelCount() / pipe.material(); + } else return priority; + } + @Override public @Nullable WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof PipeStructure) diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index 91650f40a65..6ef302fbfc6 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -5,18 +5,26 @@ import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.unification.material.properties.MaterialProperties; import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.util.TextFormattingUtil; import gregtech.common.pipelike.block.pipe.PipeStructure; import gregtech.common.pipelike.net.item.WorldItemNet; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + public final class MaterialItemProperties implements PipeNetProperties.IPipeNetMaterialProperty { public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>(); @@ -38,6 +46,19 @@ public MaterialPropertyKey getKey() { return KEY; } + @Override + public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, + @NotNull ITooltipFlag flagIn, IPipeMaterialStructure structure) { + if (baseItemsPer5Ticks % 16 != 0) { + tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate", + baseItemsPer5Ticks * 4)); + } else { + tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate_stacks", + baseItemsPer5Ticks / 16)); + } + tooltip.add(I18n.format("gregtech.item_pipe.priority", TextFormattingUtil.formatNumbers(getFlowPriority(structure)))); + } + @Override public void verifyProperty(MaterialProperties properties) { if (!properties.hasProperty(PropertyKey.WOOD)) { @@ -57,12 +78,17 @@ public void addToNet(World world, BlockPos pos, IPipeStructure structure) { public void mutateData(NetLogicData data, IPipeStructure structure) { if (structure instanceof PipeStructure pipe) { long throughput = baseItemsPer5Ticks * pipe.material(); - double weight = priority * (pipe.restrictive() ? 100d : 1d) * pipe.channelCount() / pipe.material(); - data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(weight)) + data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(getFlowPriority(structure))) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)); } } + private double getFlowPriority(IPipeStructure structure) { + if (structure instanceof PipeStructure pipe) { + return priority * (pipe.restrictive() ? 100d : 1d) * pipe.channelCount() / pipe.material(); + } else return priority; + } + @Override public @Nullable WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof PipeStructure) diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 52ff9a460dd..56f67378d2b 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -52,9 +52,15 @@ private FlowWorldPipeNetPath.Provider getProvider() { return (FlowWorldPipeNetPath.Provider) net; } + private boolean inputDisallowed(EnumFacing side) { + if (side == null) return false; + if (tile == null) return true; + else return tile.isBlocked(side); + } + @Override public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { - if (tile == null || this.transferring) return 0; + if (tile == null || this.transferring || inputDisallowed(side)) return 0; this.transferring = true; SimulatorKey simulator = null; @@ -158,7 +164,7 @@ public long getOutputPerSec() { @Override public boolean inputsEnergy(EnumFacing side) { - return true; + return !inputDisallowed(side); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java index 178283b7e4a..1d317991ce1 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java @@ -25,13 +25,14 @@ public final class WorldEnergyNet extends WorldPipeNet implements FlowWorldPipeN private static final String DATA_ID_BASE = "gregtech.world_energy_net"; - public static WorldEnergyNet getWorldNet(World world) { + public static @NotNull WorldEnergyNet getWorldNet(World world) { final String DATA_ID = getDataID(DATA_ID_BASE, world); WorldEnergyNet net = (WorldEnergyNet) world.loadData(WorldEnergyNet.class, DATA_ID); if (net == null) { net = new WorldEnergyNet(DATA_ID); world.setData(DATA_ID, net); } + net.setWorld(world); return net; } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index 4522aa9ea54..90a4a18881e 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -51,6 +51,12 @@ private FlowWorldPipeNetPath.Provider getProvider() { return (FlowWorldPipeNetPath.Provider) net; } + private boolean inputDisallowed(EnumFacing side) { + if (side == null) return false; + if (tile == null) return true; + else return tile.isBlocked(side); + } + private Iterator getPaths(FluidTraverseData data) { assert tile != null; return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), @@ -81,7 +87,7 @@ public int fill(FluidStack resource, boolean doFill) { } public int fill(FluidStack resource, boolean doFill, EnumFacing side) { - if (tile == null || this.transferring) return 0; + if (tile == null || this.transferring || inputDisallowed(side)) return 0; this.transferring = true; SimulatorKey simulator = null; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index d404515fc56..34c14193b03 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -25,15 +25,16 @@ public class WorldFluidNet extends WorldPipeNet implements FlowWorldPipeNetPath. public static final Capability[] CAPABILITIES = new Capability[] { CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY }; - private static final String DATA_ID_BASE = "gregtech.world_energy_net"; + private static final String DATA_ID_BASE = "gregtech.world_fluid_net"; - public static WorldFluidNet getWorldNet(World world) { + public static @NotNull WorldFluidNet getWorldNet(World world) { final String DATA_ID = getDataID(DATA_ID_BASE, world); WorldFluidNet net = (WorldFluidNet) world.loadData(WorldFluidNet.class, DATA_ID); if (net == null) { net = new WorldFluidNet(DATA_ID); world.setData(DATA_ID, net); } + net.setWorld(world); return net; } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index 8c80c5f3d27..69e022e2f12 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -48,6 +48,12 @@ private FlowWorldPipeNetPath.Provider getProvider() { return (FlowWorldPipeNetPath.Provider) net; } + private boolean inputDisallowed(EnumFacing side) { + if (side == null) return false; + if (tile == null) return true; + else return tile.isBlocked(side); + } + private Iterator getPaths(ItemTraverseData data) { assert tile != null; return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), @@ -73,7 +79,7 @@ public T getCapabilityForSide(Capability capability, @Nullable EnumFacing } public @NotNull ItemStack insertItem(@NotNull ItemStack stack, boolean simulate, EnumFacing side) { - if (tile == null || this.transferring) return stack; + if (tile == null || this.transferring || inputDisallowed(side)) return stack; this.transferring = true; SimulatorKey simulator = null; diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 54bdd61006b..eedb02d65f6 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -25,15 +25,16 @@ public class WorldItemNet extends WorldPipeNet implements FlowWorldPipeNetPath.P public static final Capability[] CAPABILITIES = new Capability[] { CapabilityItemHandler.ITEM_HANDLER_CAPABILITY }; - private static final String DATA_ID_BASE = "gregtech.world_energy_net"; + private static final String DATA_ID_BASE = "gregtech.world_item_net"; - public static WorldItemNet getWorldNet(World world) { + public static @NotNull WorldItemNet getWorldNet(World world) { final String DATA_ID = getDataID(DATA_ID_BASE, world); WorldItemNet net = (WorldItemNet) world.loadData(WorldItemNet.class, DATA_ID); if (net == null) { net = new WorldItemNet(DATA_ID); world.setData(DATA_ID, net); } + net.setWorld(world); return net; } diff --git a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java index d04f9bce2ae..cb61572b4e7 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java @@ -12,6 +12,7 @@ import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Iterator; @@ -22,13 +23,14 @@ public class WorldLaserNet extends WorldPipeNet implements BasicWorldPipeNetPath private static final String DATA_ID_BASE = "gregtech.world_laser_net"; - public static WorldLaserNet getWorldNet(World world) { + public static @NotNull WorldLaserNet getWorldNet(World world) { final String DATA_ID = getDataID(DATA_ID_BASE, world); WorldLaserNet net = (WorldLaserNet) world.loadData(WorldLaserNet.class, DATA_ID); if (net == null) { net = new WorldLaserNet(DATA_ID); world.setData(DATA_ID, net); } + net.setWorld(world); return net; } diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java index a34569c043f..34bdbfe91f3 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -12,6 +12,7 @@ import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Iterator; @@ -23,13 +24,14 @@ public class WorldOpticalNet extends WorldPipeNet implements BasicWorldPipeNetPa private static final String DATA_ID_BASE = "gregtech.world_optical_net"; - public static WorldOpticalNet getWorldNet(World world) { + public static @NotNull WorldOpticalNet getWorldNet(World world) { final String DATA_ID = getDataID(DATA_ID_BASE, world); WorldOpticalNet net = (WorldOpticalNet) world.loadData(WorldOpticalNet.class, DATA_ID); if (net == null) { net = new WorldOpticalNet(DATA_ID); world.setData(DATA_ID, net); } + net.setWorld(world); return net; } diff --git a/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java b/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java index 2c646c88a21..b244c6e9de6 100644 --- a/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java +++ b/src/main/java/gregtech/loaders/recipe/handlers/PipeRecipeHandler.java @@ -48,8 +48,7 @@ private static void processStandard(OrePrefix pipePrefix, OrePrefix restrictiveP restrictivePrefix.addProcessingHandler(registrationHandler((o, m) -> processRestrictivePipe(o, m, pipePrefix))); } - public static IOreRegistrationHandler registrationHandler( - BiConsumer handler) { + public static IOreRegistrationHandler registrationHandler(BiConsumer handler) { return (orePrefix, material) -> { if (material.hasFlag(NO_UNIFICATION)) return; PipeNetProperties properties = material.getProperty(PropertyKey.PIPENET_PROPERTIES); diff --git a/src/main/resources/assets/gregtech/advancements/high_voltage/89_fluid_pipe_death_cold.json b/src/main/resources/assets/gregtech/advancements/high_voltage/89_fluid_pipe_death_cold.json index f6015410807..293b952654c 100644 --- a/src/main/resources/assets/gregtech/advancements/high_voltage/89_fluid_pipe_death_cold.json +++ b/src/main/resources/assets/gregtech/advancements/high_voltage/89_fluid_pipe_death_cold.json @@ -7,7 +7,7 @@ "translate": "gregtech.advancement.high_voltage.89_fluid_pipe_death_cold.name" }, "icon": { - "item": "gregtech:fluid_pipe_normal", + "item": "gregtech:pipe_normal", "data": 323 } }, diff --git a/src/main/resources/assets/gregtech/advancements/steam/87_fluid_pipe_death_heat.json b/src/main/resources/assets/gregtech/advancements/steam/87_fluid_pipe_death_heat.json index 69967e69dd8..338da0bde33 100644 --- a/src/main/resources/assets/gregtech/advancements/steam/87_fluid_pipe_death_heat.json +++ b/src/main/resources/assets/gregtech/advancements/steam/87_fluid_pipe_death_heat.json @@ -7,7 +7,7 @@ "translate": "gregtech.advancement.steam.87_fluid_pipe_death_heat.name" }, "icon": { - "item": "gregtech:fluid_pipe_normal", + "item": "gregtech:pipe_normal", "data": 260 } }, diff --git a/src/main/resources/assets/gregtech/advancements/steam/root_steam.json b/src/main/resources/assets/gregtech/advancements/steam/root_steam.json index 117381122f5..1d8ae826608 100644 --- a/src/main/resources/assets/gregtech/advancements/steam/root_steam.json +++ b/src/main/resources/assets/gregtech/advancements/steam/root_steam.json @@ -1,28 +1,28 @@ -{ - "display": { - "description": { - "translate": "gregtech.advancement.root_steam.desc" - }, - "title": { - "translate": "gregtech.advancement.root_steam.name" - }, - "icon": { - "item": "gregtech:fluid_pipe_normal", - "data": 260 - }, - "background": "gregtech:textures/blocks/casings/solid/machine_bronze_plated_bricks.png" - }, - "criteria": { - "location": { - "trigger": "minecraft:inventory_changed", - "conditions": { - "items": [ - { - "type": "forge:ore_dict", - "ore": "ingotCopper" - } - ] - } - } - } -} +{ + "display": { + "description": { + "translate": "gregtech.advancement.root_steam.desc" + }, + "title": { + "translate": "gregtech.advancement.root_steam.name" + }, + "icon": { + "item": "gregtech:pipe_normal", + "data": 260 + }, + "background": "gregtech:textures/blocks/casings/solid/machine_bronze_plated_bricks.png" + }, + "criteria": { + "location": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "type": "forge:ore_dict", + "ore": "ingotCopper" + } + ] + } + } + } +} diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 19210c952b4..8c37abd5075 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -1453,23 +1453,20 @@ item.material.oreprefix.toolHeadWrench=%s Wrench Tip item.material.oreprefix.turbineBlade=%s Turbine Blade item.material.oreprefix.block=Block of %s item.material.oreprefix.frameGt=%s Frame Box -item.material.oreprefix.pipeTinyFluid=Tiny %s Fluid Pipe -item.material.oreprefix.pipeSmallFluid=Small %s Fluid Pipe -item.material.oreprefix.pipeNormalFluid=%s Fluid Pipe -item.material.oreprefix.pipeLargeFluid=Large %s Fluid Pipe -item.material.oreprefix.pipeHugeFluid=Huge %s Fluid Pipe -item.material.oreprefix.pipeQuadrupleFluid=Quadruple %s Fluid Pipe -item.material.oreprefix.pipeNonupleFluid=Nonuple %s Fluid Pipe -item.material.oreprefix.pipeTinyItem=Tiny %s Item Pipe -item.material.oreprefix.pipeSmallItem=Small %s Item Pipe -item.material.oreprefix.pipeNormalItem=%s Item Pipe -item.material.oreprefix.pipeLargeItem=Large %s Item Pipe -item.material.oreprefix.pipeHugeItem=Huge %s Item Pipe -item.material.oreprefix.pipeTinyRestrictive=Tiny Restrictive %s Item Pipe -item.material.oreprefix.pipeSmallRestrictive=Small Restrictive %s Item Pipe -item.material.oreprefix.pipeNormalRestrictive=Restrictive %s Item Pipe -item.material.oreprefix.pipeLargeRestrictive=Large Restrictive %s Item Pipe -item.material.oreprefix.pipeHugeRestrictive=Huge Restrictive %s Item Pipe +item.material.oreprefix.pipeTiny=Tiny %s Pipe +item.material.oreprefix.pipeSmall=Small %s Pipe +item.material.oreprefix.pipeNormal=%s Pipe +item.material.oreprefix.pipeLarge=Large %s Pipe +item.material.oreprefix.pipeHuge=Huge %s Pipe +item.material.oreprefix.pipeQuadruple=Quadruple %s Pipe +item.material.oreprefix.pipeNonuple=Nonuple %s Pipe +item.material.oreprefix.pipeTinyRestrictive=Tiny Restrictive %s Pipe +item.material.oreprefix.pipeSmallRestrictive=Small Restrictive %s Pipe +item.material.oreprefix.pipeNormalRestrictive=Restrictive %s Pipe +item.material.oreprefix.pipeLargeRestrictive=Large Restrictive %s Pipe +item.material.oreprefix.pipeHugeRestrictive=Huge Restrictive %s Pipe +item.material.oreprefix.pipeQuadrupleRestrictive=Quadruple Restrictive %s Pipe +item.material.oreprefix.pipeNonupleRestrictive=Nonuple Restrictive %s Pipe item.material.oreprefix.wireGtHex=16x %s Wire item.material.oreprefix.wireGtOctal=8x %s Wire item.material.oreprefix.wireGtQuadruple=4x %s Wire @@ -5561,18 +5558,19 @@ gregtech.item_filter.footer=§eClick with item to override gregtech.cable.voltage=§aMax Voltage: §f%,d §f(%s§f) gregtech.cable.amperage=§eMax Amperage: §f%,d gregtech.cable.loss_per_block=§cLoss/Meter/Ampere: §f%,d§f EU-Volt +gregtech.cable.superconductor_loss=§cLoss is set to §f0§c under critical temperature §f%,d§f K gregtech.cable.superconductor=§d%s Superconductor -gregtech.fluid_pipe.capacity=§9Capacity: §f%,d L gregtech.fluid_pipe.max_temperature=§cTemperature Limit: §f%,d K -gregtech.fluid_pipe.min_temperature=§6Can handle fluids below §f%,d K -gregtech.fluid_pipe.channels=§eChannels: §f%d +gregtech.fluid_pipe.min_temperature=§6Can handle fluids above §f%,d K +gregtech.pipe.channels=§eChannels: §f%d gregtech.fluid_pipe.gas_proof=§6Can handle Gases gregtech.fluid_pipe.acid_proof=§6Can handle Acids gregtech.fluid_pipe.plasma_proof=§6Can handle all Plasmas gregtech.fluid_pipe.not_gas_proof=§4Gases may leak! -gregtech.item_pipe.priority=§9Priority: §f%,d +gregtech.fluid_pipe.priority=§9Priority: §f%s +gregtech.item_pipe.priority=§9Priority: §f%s gregtech.multiblock.work_paused=Work Paused. gregtech.multiblock.running=Running perfectly. From 7e0c6bb5bde472e1ed7765adc52a652bd9ebe5fc Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 29 Jul 2024 21:04:12 -0600 Subject: [PATCH 084/157] baffled by normals --- .../physical/block/PipeActivableBlock.java | 8 +-- .../physical/block/PipeMaterialBlock.java | 11 ++-- .../physical/block/WorldPipeBlock.java | 14 ++-- .../pipenet/physical/tile/PipeTileEntity.java | 36 ++++++---- .../renderer/pipe/AbstractPipeModel.java | 46 +++++++++---- .../renderer/pipe/ActivablePipeModel.java | 13 +++- .../client/renderer/pipe/CableModel.java | 7 +- .../client/renderer/pipe/PipeItemModel.java | 54 +++++++++++++++ .../client/renderer/pipe/PipeModel.java | 13 +++- .../pipe/cache/StructureQuadCache.java | 2 +- .../renderer/pipe/quad/PipeQuadHelper.java | 66 ++++++++++++------- .../pipe/quad/RecolorableBakedQuad.java | 14 +++- .../renderer/pipe/util/ActivableCacheKey.java | 8 +++ .../client/renderer/pipe/util/CacheKey.java | 6 ++ .../renderer/pipe/util/WoodCacheKey.java | 17 +++++ .../gregtech/common/blocks/MetaBlocks.java | 40 +++++++---- 16 files changed, 266 insertions(+), 89 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java index ebc836a7e05..6c4e27272b8 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java @@ -39,14 +39,14 @@ public Class getTileClass(@NotNull World worl @Override public @Nullable PipeActivableTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { - if (GTUtility.arePosEqual(lastTilePos, pos)) { - PipeTileEntity tile = lastTile.get(); + if (GTUtility.arePosEqual(lastTilePos.get(), pos)) { + PipeTileEntity tile = lastTile.get().get(); if (tile != null) return (PipeActivableTileEntity) tile; } TileEntity tile = world.getTileEntity(pos); if (tile instanceof PipeActivableTileEntity pipe) { - lastTilePos = pos; - lastTile = new WeakReference<>(pipe); + lastTilePos.set(pos); + lastTile.set(new WeakReference<>(pipe)); return pipe; } else return null; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index 3711c8db734..5e1784224e0 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -117,14 +117,14 @@ protected BlockStateContainer.Builder constructState(BlockStateContainer.@NotNul @Override public @Nullable PipeMaterialTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { - if (GTUtility.arePosEqual(lastTilePos, pos)) { - PipeTileEntity tile = lastTile.get(); + if (GTUtility.arePosEqual(lastTilePos.get(), pos)) { + PipeTileEntity tile = lastTile.get().get(); if (tile != null) return (PipeMaterialTileEntity) tile; } TileEntity tile = world.getTileEntity(pos); if (tile instanceof PipeMaterialTileEntity pipe) { - lastTilePos = pos; - lastTile = new WeakReference<>(pipe); + lastTilePos.set(pos); + lastTile.set(new WeakReference<>(pipe)); return pipe; } else return null; } @@ -138,8 +138,7 @@ public Class getTileClass(@NotNull World world protected Pair getParticleTexture(World world, BlockPos blockPos) { PipeMaterialTileEntity tile = getTileEntity(world, blockPos); if (tile != null) { - return ImmutablePair.of(getStructure().getModel().getParticleTexture(tile.getMaterial()), - tile.getPaintingColor()); + return getStructure().getModel().getParticleTexture(tile.getPaintingColor(), tile.getMaterial()); } return null; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java index db666f497fb..c4a3b5318d5 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java @@ -64,8 +64,8 @@ public abstract class WorldPipeBlock extends BuiltInRenderBlock { // do not touch these two unless you know what you are doing - protected BlockPos lastTilePos = new BlockPos(0, 0, 0); - protected WeakReference lastTile = new WeakReference<>(null); + protected ThreadLocal lastTilePos = ThreadLocal.withInitial(() -> new BlockPos(0, 0, 0)); + protected ThreadLocal> lastTile = ThreadLocal.withInitial(() -> new WeakReference<>(null)); private final IPipeStructure structure; @@ -324,7 +324,7 @@ public boolean canRenderInLayer(@NotNull IBlockState state, @NotNull BlockRender protected Pair getParticleTexture(World world, BlockPos blockPos) { PipeTileEntity tile = getTileEntity(world, blockPos); if (tile != null) { - return ImmutablePair.of(getStructure().getModel().getParticleTexture(), tile.getPaintingColor()); + return getStructure().getModel().getParticleTexture(tile.getPaintingColor(), null); } return null; } @@ -483,14 +483,14 @@ public final boolean hasTileEntity(@NotNull IBlockState state) { @Nullable public PipeTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { - if (GTUtility.arePosEqual(lastTilePos, pos)) { - PipeTileEntity tile = lastTile.get(); + if (GTUtility.arePosEqual(lastTilePos.get(), pos)) { + PipeTileEntity tile = lastTile.get().get(); if (tile != null) return tile; } TileEntity tile = world.getTileEntity(pos); if (tile instanceof PipeTileEntity pipe) { - lastTilePos = pos; - lastTile = new WeakReference<>(pipe); + lastTilePos.set(pos); + lastTile.set(new WeakReference<>(pipe)); return pipe; } else return null; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index ea299d925a9..4cc2a2e8367 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -143,10 +143,12 @@ public void setDisconnected(EnumFacing facing) { } private void syncConnected() { - writeCustomData(UPDATE_CONNECTIONS, buffer -> { - buffer.writeByte(connectionMask); - buffer.writeByte(renderMask); - }); + if (!getWorld().isRemote) { + writeCustomData(UPDATE_CONNECTIONS, buffer -> { + buffer.writeByte(connectionMask); + buffer.writeByte(renderMask); + }); + } else scheduleRenderUpdate(); markDirty(); } @@ -173,7 +175,9 @@ public void setUnblocked(EnumFacing facing) { } private void syncBlocked() { - writeCustomData(UPDATE_BLOCKED_CONNECTIONS, buffer -> buffer.writeByte(blockedMask)); + if (!getWorld().isRemote) { + writeCustomData(UPDATE_BLOCKED_CONNECTIONS, buffer -> buffer.writeByte(blockedMask)); + } else scheduleRenderUpdate(); markDirty(); } @@ -199,7 +203,7 @@ public void setPaintingColor(int paintingColor, boolean alphaSensitive) { if (!getWorld().isRemote) { writeCustomData(UPDATE_PAINT, buffer -> buffer.writeInt(this.paintingColor)); markDirty(); - } + } else scheduleRenderUpdate(); } public boolean isPainted() { @@ -218,10 +222,12 @@ public void setFrameMaterial(@Nullable Material frameMaterial) { } private void syncFrameMaterial() { - writeCustomData(UPDATE_FRAME_MATERIAL, buffer -> { - if (frameMaterial != null) buffer.writeString(this.frameMaterial.getRegistryName()); - else buffer.writeString(""); - }); + if (!getWorld().isRemote) { + writeCustomData(UPDATE_FRAME_MATERIAL, buffer -> { + if (frameMaterial != null) buffer.writeString(this.frameMaterial.getRegistryName()); + else buffer.writeString(""); + }); + } else scheduleRenderUpdate(); markDirty(); } @@ -265,6 +271,7 @@ public boolean isTicking() { // cover // + @NotNull public PipeCoverHolder getCoverHolder() { return covers; } @@ -366,8 +373,10 @@ public T getCapability(@NotNull Capability capability, @Nullable EnumFaci if (capability == GregtechTileCapabilities.CAPABILITY_COVER_HOLDER) { return GregtechTileCapabilities.CAPABILITY_COVER_HOLDER.cast(getCoverHolder()); } - T pipeCapability = capabilities.get(capability).getCapabilityForSide(capability, facing); - if (pipeCapability == null) pipeCapability = super.getCapability(capability, facing); + T pipeCapability; + IPipeCapabilityObject object = capabilities.get(capability); + if (object == null || (pipeCapability = object.getCapabilityForSide(capability, facing)) == null) + pipeCapability = super.getCapability(capability, facing); Cover cover = facing == null ? null : getCoverHolder().getCoverAtSide(facing); if (cover == null) { @@ -446,6 +455,7 @@ protected void initialize() { public @NotNull NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { super.writeToNBT(compound); compound.setByte("ConnectionMask", connectionMask); + compound.setByte("RenderMask", renderMask); compound.setByte("BlockedMask", blockedMask); compound.setInteger("Paint", paintingColor); if (frameMaterial != null) compound.setString("Frame", frameMaterial.getRegistryName()); @@ -457,12 +467,14 @@ protected void initialize() { public void readFromNBT(@NotNull NBTTagCompound compound) { super.readFromNBT(compound); connectionMask = compound.getByte("ConnectionMask"); + renderMask = compound.getByte("RenderMask"); blockedMask = compound.getByte("BlockedMask"); paintingColor = compound.getInteger("Paint"); if (compound.hasKey("Frame")) this.frameMaterial = GregTechAPI.materialManager.getMaterial(compound.getString("Frame")); else this.frameMaterial = null; this.getCoverHolder().deserializeNBT(compound.getCompoundTag("Covers")); + scheduleRenderUpdate(); } @Override diff --git a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java index ff0c90df0f5..94bd282b681 100644 --- a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java @@ -12,10 +12,13 @@ import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.util.CacheKey; +import gregtech.client.renderer.pipe.util.SpriteInformation; + import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.block.model.ItemOverrideList; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -32,11 +35,18 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.vecmath.Matrix4f; +import javax.vecmath.Vector3f; import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumMap; import java.util.List; +import java.util.stream.Collectors; @SideOnly(Side.CLIENT) public abstract class AbstractPipeModel implements IBakedModel { @@ -51,8 +61,6 @@ public abstract class AbstractPipeModel implements IBakedMod public static UnlistedByteProperty BLOCKED_MASK_PROPERTY = new UnlistedByteProperty("blocked_mask"); public static UnlistedIntegerProperty COLOR_PROPERTY = new UnlistedIntegerProperty("color"); - private static final List EMPTY = new ArrayList<>(); - protected final Object2ObjectOpenHashMap frameCache = new Object2ObjectOpenHashMap<>(); protected final Object2ObjectOpenHashMap pipeCache = new Object2ObjectOpenHashMap<>(); @@ -64,14 +72,21 @@ public AbstractPipeModel(ModelResourceLocation loc) { @Override public @NotNull List getQuads(IBlockState state, EnumFacing side, long rand) { - if (state instanceof IExtendedBlockState ext) { - K key = toKey(ext); - Material frameMaterial = ext.getValue(FRAME_MATERIAL_PROPERTY); - byte frameMask = ext.getValue(FRAME_MASK_PROPERTY); - return getQuads(key, ext.getValue(CONNECTION_MASK_PROPERTY), ext.getValue(CLOSED_MASK_PROPERTY), - ext.getValue(BLOCKED_MASK_PROPERTY), ext.getValue(COLOR_PROPERTY), frameMaterial, frameMask); + if (side == null && state instanceof IExtendedBlockState ext) { + return getQuads(toKey(ext), safeByte(ext.getValue(CONNECTION_MASK_PROPERTY)), + safeByte(ext.getValue(CLOSED_MASK_PROPERTY)), safeByte(ext.getValue(BLOCKED_MASK_PROPERTY)), + safeInt(ext.getValue(COLOR_PROPERTY)), ext.getValue(FRAME_MATERIAL_PROPERTY), + safeByte(ext.getValue(FRAME_MASK_PROPERTY))); } - return EMPTY; + return Collections.emptyList(); + } + + protected static byte safeByte(@Nullable Byte abyte) { + return abyte == null ? 0 : abyte; + } + + protected static int safeInt(@Nullable Integer integer) { + return integer == null ? 0 : integer; } public @NotNull List getQuads(K key, byte connectionMask, byte closedMask, byte blockedMask, int argb, @@ -107,23 +122,26 @@ public AbstractPipeModel(ModelResourceLocation loc) { protected abstract @NotNull K toKey(@NotNull IExtendedBlockState state); protected final @NotNull CacheKey defaultKey(@NotNull IExtendedBlockState state) { - return new CacheKey(state.getValue(THICKNESS_PROPERTY)); + return CacheKey.of(state.getValue(THICKNESS_PROPERTY)); } protected abstract StructureQuadCache constructForKey(K key); - public @NotNull TextureAtlasSprite getParticleTexture(Material material) { - return getParticleTexture(); + public Pair getParticleTexture(int paintColor, @Nullable Material material) { + SpriteInformation spriteInformation = getParticleSprite(material); + return new ImmutablePair<>(spriteInformation.sprite(), spriteInformation.colorable() ? paintColor : 0xFFFFFFFF); } + public abstract SpriteInformation getParticleSprite(@Nullable Material material); + @Override public boolean isAmbientOcclusion() { - return false; + return true; } @Override public boolean isGui3d() { - return true; + return false; } @Override diff --git a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java index 144722b96d6..3b7859d2aee 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java @@ -12,6 +12,7 @@ import gregtech.client.renderer.pipe.util.SpriteInformation; import gregtech.client.renderer.texture.Textures; import gregtech.client.utils.BloomEffectUtil; +import gregtech.client.utils.RenderUtil; import gregtech.common.ConfigHolder; import net.minecraft.client.renderer.block.model.BakedQuad; @@ -32,6 +33,7 @@ import java.util.List; import java.util.function.Supplier; +import java.util.stream.Collectors; public class ActivablePipeModel extends AbstractPipeModel { @@ -79,6 +81,8 @@ public ActivablePipeModel(@NotNull Supplier inTex, @NotNull S } else { if (emissiveActive && bloomLayer) { ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, argb, true); + // TODO bake this into the original quads + quads = quads.stream().map(RenderUtil::makeEmissive).collect(Collectors.toList()); } else if (!emissiveActive && getCurrentRenderLayer() == BlockRenderLayer.CUTOUT_MIPPED) { ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, argb, true); } @@ -86,14 +90,19 @@ public ActivablePipeModel(@NotNull Supplier inTex, @NotNull S return quads; } + @Override + public SpriteInformation getParticleSprite(@Nullable Material material) { + return sideTex.get(); + } + @Override public @NotNull TextureAtlasSprite getParticleTexture() { - return sideTex.get().sprite(); + return getParticleSprite(null).sprite(); } @Override protected @NotNull ActivableCacheKey toKey(@NotNull IExtendedBlockState state) { - return new ActivableCacheKey(state.getValue(THICKNESS_PROPERTY), state.getValue(ACTIVE_PROPERTY)); + return ActivableCacheKey.of(state.getValue(THICKNESS_PROPERTY), state.getValue(ACTIVE_PROPERTY)); } @Override diff --git a/src/main/java/gregtech/client/renderer/pipe/CableModel.java b/src/main/java/gregtech/client/renderer/pipe/CableModel.java index c60e98f4e9f..af05023efc7 100644 --- a/src/main/java/gregtech/client/renderer/pipe/CableModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/CableModel.java @@ -64,9 +64,14 @@ public CableModel(String variant) { this(null, null, variant); } + @Override + public SpriteInformation getParticleSprite(@Nullable Material material) { + return wireTex.get(); + } + @Override public @NotNull TextureAtlasSprite getParticleTexture() { - return wireTex.get().sprite(); + return getParticleSprite(null).sprite(); } @Override diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java index f16be3ede76..b926c823040 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java @@ -5,16 +5,64 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.block.model.ItemOverrideList; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.EnumFacing; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; +import javax.vecmath.Matrix4f; +import javax.vecmath.Vector3f; +import java.util.EnumMap; import java.util.List; public class PipeItemModel implements IBakedModel { + private static final EnumMap CAMERA_TRANSFORMS = + new EnumMap<>(ItemCameraTransforms.TransformType.class); + + static { + // TODO these transforms are atrocious + Matrix4f matrix4f = new Matrix4f(); + matrix4f.setIdentity(); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.NONE, matrix4f); + matrix4f = new Matrix4f(); + matrix4f.rotY((float) Math.toRadians(225)); + matrix4f.rotX((float) Math.toRadians(30)); + matrix4f.setScale(0.625f); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.GUI, matrix4f); + matrix4f = new Matrix4f(); + matrix4f.setTranslation(new Vector3f(0, 3, 0)); + matrix4f.setScale(0.25f); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.GROUND, matrix4f); + matrix4f = new Matrix4f(); + matrix4f.setScale(0.5f); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.FIXED, matrix4f); + matrix4f = new Matrix4f(); + matrix4f.rotY((float) Math.toRadians(45)); + matrix4f.rotX((float) Math.toRadians(75)); + matrix4f.setTranslation(new Vector3f(0, 2.5f, 0)); + matrix4f.setScale(0.375f); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.THIRD_PERSON_RIGHT_HAND, matrix4f); + matrix4f = new Matrix4f(); + matrix4f.rotY((float) Math.toRadians(45)); + matrix4f.rotX((float) Math.toRadians(75)); + matrix4f.setTranslation(new Vector3f(0, 2.5f, 0)); + matrix4f.setScale(0.375f); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.THIRD_PERSON_LEFT_HAND, matrix4f); + matrix4f = new Matrix4f(); + matrix4f.rotY((float) Math.toRadians(45)); + matrix4f.setScale(0.4f); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND, matrix4f); + matrix4f = new Matrix4f(); + matrix4f.rotY((float) Math.toRadians(225)); + matrix4f.setScale(0.4f); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND, matrix4f); + } + private final AbstractPipeModel basis; private final K key; private final int argb; @@ -45,6 +93,12 @@ public boolean isBuiltInRenderer() { return false; } + @Override + public @NotNull Pair handlePerspective( + ItemCameraTransforms.@NotNull TransformType cameraTransformType) { + return ImmutablePair.of(this, CAMERA_TRANSFORMS.get(cameraTransformType)); + } + @Override public @NotNull TextureAtlasSprite getParticleTexture() { return basis.getParticleTexture(); diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java index e166c24ebbf..1049f8be689 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java @@ -12,6 +12,7 @@ import gregtech.client.renderer.pipe.cache.StructureQuadCache; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.util.PipeSpriteWoodClarifier; +import gregtech.client.renderer.pipe.util.SpriteInformation; import gregtech.client.renderer.pipe.util.WoodCacheKey; import gregtech.client.renderer.texture.Textures; @@ -27,6 +28,8 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -80,9 +83,14 @@ public PipeModel(@NotNull PipeSpriteWoodClarifier inTex, boolean restrictive, St this(inTex, wood -> wood ? Textures.PIPE_SIDE_WOOD.get() : Textures.PIPE_SIDE.get(), restrictive, variant); } + @Override + public SpriteInformation getParticleSprite(@Nullable Material material) { + return sideTex.getSprite(material != null && material.hasProperty(PropertyKey.WOOD)); + } + @Override public @NotNull TextureAtlasSprite getParticleTexture() { - return sideTex.getSprite(false).sprite(); + return getParticleSprite(null).sprite(); } public @NotNull TextureAtlasSprite getParticleTexture(Material material) { @@ -91,8 +99,7 @@ public PipeModel(@NotNull PipeSpriteWoodClarifier inTex, boolean restrictive, St @Override protected @NotNull WoodCacheKey toKey(@NotNull IExtendedBlockState state) { - return new WoodCacheKey(state.getValue(THICKNESS_PROPERTY), - state.getValue(MATERIAL_PROPERTY).hasProperty(PropertyKey.WOOD)); + return WoodCacheKey.of(state.getValue(THICKNESS_PROPERTY), state.getValue(MATERIAL_PROPERTY)); } @Override diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java index d2a33670557..f5f31c53645 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java @@ -69,7 +69,7 @@ protected void buildTube(List list) { } protected void buildCore(List list) { - helper.setTargetSprite(endTex); + helper.setTargetSprite(sideTex); for (EnumFacing facing : EnumFacing.VALUES) { int start = list.size(); list.add(helper.visitCore(facing)); diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java index ee8a343f4f7..17717d7abf2 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -5,18 +5,33 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.client.renderer.vertex.VertexFormatElement; import net.minecraft.util.EnumFacing; +import net.minecraftforge.client.model.pipeline.IVertexConsumer; +import net.minecraftforge.client.model.pipeline.TRSRTransformer; +import net.minecraftforge.common.model.TRSRTransformation; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import javax.vecmath.Matrix4f; +import javax.vecmath.Vector3f; +import javax.vecmath.Vector4f; import java.util.List; @SideOnly(Side.CLIENT) public final class PipeQuadHelper { - private static final VertexFormat FORMAT = DefaultVertexFormats.ITEM; + private static final VertexFormatElement NORMAL_4F = new VertexFormatElement(0, VertexFormatElement.EnumType.FLOAT, VertexFormatElement.EnumUsage.NORMAL, 4); + private static final VertexFormat FORMAT = new VertexFormat(DefaultVertexFormats.BLOCK).addElement(NORMAL_4F); + private static final TRSRTransformation INVERTER; + static { + Matrix4f matrix4f = new Matrix4f(); + matrix4f.setIdentity(); + matrix4f.mul(-1); + INVERTER = new TRSRTransformation(matrix4f); + } private final float thickness; private final float x; @@ -29,7 +44,7 @@ public final class PipeQuadHelper { private final UVMapper tallMapper; private final UVMapper wideMapper; - private RecolorableBakedQuad.Builder building; + private IVertexConsumer building; private SpriteInformation targetSprite; @@ -95,8 +110,8 @@ public List visitTube(EnumFacing facing) { } list.add(visitQuad(EnumFacing.UP, x1, x2, y + large, 0, z + small, z + large, wideMapper)); list.add(visitQuad(EnumFacing.DOWN, x1, x2, y + small, 0, z + small, z + large, wideMapper)); - list.add(visitQuad(EnumFacing.SOUTH, x1, x2, y + small, y + large, z + large, 0, wideMapper)); - list.add(visitQuad(EnumFacing.NORTH, x1, x2, y + small, y + large, z + small, 0, wideMapper)); + list.add(visitQuad(EnumFacing.SOUTH, x1, x2, y + small, y + large, z + large, 0, tallMapper)); + list.add(visitQuad(EnumFacing.NORTH, x1, x2, y + small, y + large, z + small, 0, tallMapper)); } case Y -> { float y1; @@ -108,8 +123,8 @@ public List visitTube(EnumFacing facing) { y1 = this.y + small; y2 = 0; } - list.add(visitQuad(EnumFacing.EAST, x + large, 0, y1, y2, z + small, z + large, tallMapper)); - list.add(visitQuad(EnumFacing.WEST, x + small, 0, y1, y2, z + small, z + large, tallMapper)); + list.add(visitQuad(EnumFacing.EAST, x + large, 0, y1, y2, z + small, z + large, wideMapper)); + list.add(visitQuad(EnumFacing.WEST, x + small, 0, y1, y2, z + small, z + large, wideMapper)); list.add(visitQuad(EnumFacing.SOUTH, x + small, x + large, y1, y2, z + large, 0, wideMapper)); list.add(visitQuad(EnumFacing.NORTH, x + small, x + large, y1, y2, z + small, 0, wideMapper)); } @@ -145,32 +160,33 @@ public RecolorableBakedQuad visitCapper(EnumFacing facing) { public RecolorableBakedQuad visitQuad(EnumFacing normal, float x1, float x2, float y1, float y2, float z1, float z2, UVMapper mapper) { - building = new RecolorableBakedQuad.Builder(FORMAT); + RecolorableBakedQuad.Builder builder = new RecolorableBakedQuad.Builder(FORMAT); + building = builder; + UVCorner[] array = UVCorner.VALUES; switch (normal.getAxis()) { case X -> { - visitVertex(normal, x1, y1, z1, mapper.map(UVCorner.VALUES[0], targetSprite.sprite())); - visitVertex(normal, x1, y1, z2, mapper.map(UVCorner.VALUES[1], targetSprite.sprite())); - visitVertex(normal, x1, y2, z2, mapper.map(UVCorner.VALUES[2], targetSprite.sprite())); - visitVertex(normal, x1, y2, z1, mapper.map(UVCorner.VALUES[3], targetSprite.sprite())); + visitVertex(normal, x1, y1, z1, mapper.map(array[0], targetSprite.sprite())); + visitVertex(normal, x1, y1, z2, mapper.map(array[1], targetSprite.sprite())); + visitVertex(normal, x1, y2, z2, mapper.map(array[2], targetSprite.sprite())); + visitVertex(normal, x1, y2, z1, mapper.map(array[3], targetSprite.sprite())); } case Y -> { - visitVertex(normal, x1, y1, z1, mapper.map(UVCorner.VALUES[0], targetSprite.sprite())); - visitVertex(normal, x1, y1, z2, mapper.map(UVCorner.VALUES[1], targetSprite.sprite())); - visitVertex(normal, x2, y1, z2, mapper.map(UVCorner.VALUES[2], targetSprite.sprite())); - visitVertex(normal, x2, y1, z1, mapper.map(UVCorner.VALUES[3], targetSprite.sprite())); + visitVertex(normal, x1, y1, z1, mapper.map(array[0], targetSprite.sprite())); + visitVertex(normal, x1, y1, z2, mapper.map(array[1], targetSprite.sprite())); + visitVertex(normal, x2, y1, z2, mapper.map(array[2], targetSprite.sprite())); + visitVertex(normal, x2, y1, z1, mapper.map(array[3], targetSprite.sprite())); } case Z -> { - visitVertex(normal, x1, y1, z1, mapper.map(UVCorner.VALUES[0], targetSprite.sprite())); - visitVertex(normal, x2, y1, z1, mapper.map(UVCorner.VALUES[1], targetSprite.sprite())); - visitVertex(normal, x2, y2, z1, mapper.map(UVCorner.VALUES[2], targetSprite.sprite())); - visitVertex(normal, x1, y2, z1, mapper.map(UVCorner.VALUES[3], targetSprite.sprite())); + visitVertex(normal, x1, y1, z1, mapper.map(array[0], targetSprite.sprite())); + visitVertex(normal, x2, y1, z1, mapper.map(array[1], targetSprite.sprite())); + visitVertex(normal, x2, y2, z1, mapper.map(array[2], targetSprite.sprite())); + visitVertex(normal, x1, y2, z1, mapper.map(array[3], targetSprite.sprite())); } } - building.setQuadOrientation(normal); - building.setTexture(targetSprite); - RecolorableBakedQuad quad = building.build(); building = null; - return quad; + builder.setQuadOrientation(normal); + builder.setTexture(targetSprite); + return builder.build(); } private void visitVertex(EnumFacing normal, float x, float y, float z, UVMapper.UVPair pair) { @@ -196,7 +212,7 @@ public static UVMapper createRotatedMapper(double u1, double v1, double u2, doub } @SuppressWarnings("SameParameterValue") - private static void putVertex(RecolorableBakedQuad.Builder consumer, VertexFormat format, EnumFacing normal, + private static void putVertex(IVertexConsumer consumer, VertexFormat format, EnumFacing normal, float x, float y, float z, float u, float v, int argb) { for (int e = 0; e < format.getElementCount(); e++) { switch (format.getElement(e).getUsage()) { @@ -214,7 +230,7 @@ private static void putVertex(RecolorableBakedQuad.Builder consumer, VertexForma float offX = (float) normal.getXOffset(); float offY = (float) normal.getYOffset(); float offZ = (float) normal.getZOffset(); - consumer.put(e, offX, offY, offZ, 0f); + consumer.put(e, offX, offY, offZ, -1f); break; case UV: if (format.getElement(e).getIndex() == 0) { diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java index 6e3e2d0c6df..b9110d60bdf 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java @@ -2,9 +2,12 @@ import gregtech.client.renderer.pipe.util.SpriteInformation; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.client.renderer.vertex.VertexFormatElement; import net.minecraft.util.EnumFacing; +import net.minecraftforge.client.model.pipeline.IVertexConsumer; import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -45,7 +48,13 @@ public RecolorableBakedQuad withColor(int argb) { this.applyDiffuseLighting, this.format); } - public static class Builder { + public static RecolorableBakedQuad.Builder of(BakedQuad quad) { + Builder builder = new Builder(quad.getFormat()); + quad.pipe(builder); + return builder; + } + + public static class Builder implements IVertexConsumer { private final VertexFormat format; private final float[][][] unpackedData; @@ -84,6 +93,9 @@ public void setTexture(@NotNull SpriteInformation texture) { this.texture = texture; } + @Override + public void setTexture(@NotNull TextureAtlasSprite texture) {} + public void setApplyDiffuseLighting(boolean diffuse) { this.applyDiffuseLighting = diffuse; } diff --git a/src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java index 9c9f9d21acd..69044f5ee2f 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java @@ -1,5 +1,7 @@ package gregtech.client.renderer.pipe.util; +import org.jetbrains.annotations.Nullable; + public class ActivableCacheKey extends CacheKey { private final boolean active; @@ -9,6 +11,12 @@ public ActivableCacheKey(float thickness, boolean active) { this.active = active; } + public static ActivableCacheKey of(@Nullable Float thickness, @Nullable Boolean active) { + float thick = thickness == null ? 0.5f : thickness; + boolean act = active != null && active; + return new ActivableCacheKey(thick, act); + } + public boolean isActive() { return active; } diff --git a/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java index 4da26329bb4..ad2197c9a9a 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java @@ -3,6 +3,7 @@ import net.minecraft.util.IStringSerializable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Objects; @@ -17,6 +18,11 @@ public CacheKey(float thickness) { this.hash = computeHash(); } + public static CacheKey of(@Nullable Float thickness) { + float thick = thickness == null ? 0.5f : thickness; + return new CacheKey(thick); + } + public float getThickness() { return thickness; } diff --git a/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java index 2fd2cd1d78c..54c83841515 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java @@ -1,6 +1,11 @@ package gregtech.client.renderer.pipe.util; +import gregtech.api.unification.material.Material; + +import gregtech.api.unification.material.properties.PropertyKey; + import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Objects; @@ -12,6 +17,18 @@ public WoodCacheKey(float thickness, boolean wood) { super(thickness); this.wood = wood; } + + public static WoodCacheKey of(@Nullable Float thickness, @Nullable Boolean wood) { + float thick = thickness == null ? 0.5f : thickness; + boolean wd = wood != null && wood; + return new WoodCacheKey(thick, wd); + } + + public static WoodCacheKey of(@Nullable Float thickness, @Nullable Material material) { + float thick = thickness == null ? 0.5f : thickness; + boolean wood = material != null && material.hasProperty(PropertyKey.WOOD); + return new WoodCacheKey(thick, wood); + } public boolean isWood() { return wood; diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 8b654695f9f..64e78ef6f10 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -61,6 +61,7 @@ import net.minecraft.block.properties.IProperty; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.block.model.ModelBakery; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.block.statemap.IStateMapper; import net.minecraft.client.renderer.block.statemap.StateMapperBase; @@ -70,6 +71,7 @@ import net.minecraft.item.EnumDyeColor; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.client.model.ModelLoaderRegistry; import net.minecraftforge.common.MinecraftForge; @@ -436,20 +438,32 @@ public static void registerTileEntity() { public static void registerItemModels() { ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(MACHINE), stack -> MetaTileEntityRenderer.MODEL_LOCATION); + + // prevent the loader from trying to locate the model files as only the IBakedModels exist, and + // they are created during runtime. + ResourceLocation decoy = new ResourceLocation("minecraft:builtin/generated"); for (MaterialRegistry registry : GregTechAPI.materialManager.getRegistries()) { - for (CableBlock cable : CABLES.get(registry.getModid())) - ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(cable), - stack -> cable.getStructure().getModel().getLoc()); - for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) - ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(pipe), - stack -> pipe.getStructure().getModel().getLoc()); - } - for (OpticalPipeBlock pipe : OPTICAL_PIPES) - ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(pipe), - stack -> pipe.getStructure().getModel().getLoc()); - for (LaserPipeBlock pipe : LASER_PIPES) - ModelLoader.setCustomMeshDefinition(Item.getItemFromBlock(pipe), - stack -> pipe.getStructure().getModel().getLoc()); + for (CableBlock cable : CABLES.get(registry.getModid())) { + Item item = Item.getItemFromBlock(cable); + ModelLoader.setCustomMeshDefinition(item, stack -> cable.getStructure().getModel().getLoc()); + ModelBakery.registerItemVariants(item, decoy); + } + for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) { + Item item = Item.getItemFromBlock(pipe); + ModelLoader.setCustomMeshDefinition(item, stack -> pipe.getStructure().getModel().getLoc()); + ModelBakery.registerItemVariants(item, decoy); + } + } + for (OpticalPipeBlock pipe : OPTICAL_PIPES) { + Item item = Item.getItemFromBlock(pipe); + ModelLoader.setCustomMeshDefinition(item, stack -> pipe.getStructure().getModel().getLoc()); + ModelBakery.registerItemVariants(item, decoy); + } + for (LaserPipeBlock pipe : LASER_PIPES) { + Item item = Item.getItemFromBlock(pipe); + ModelLoader.setCustomMeshDefinition(item, stack -> pipe.getStructure().getModel().getLoc()); + ModelBakery.registerItemVariants(item, decoy); + } registerItemModel(BOILER_CASING); registerItemModel(METAL_CASING); From f1abfec91240dde95c55f2d9eeb5800b59b92b90 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 30 Jul 2024 20:29:53 -0600 Subject: [PATCH 085/157] Functional normals. Also some misc fixes. --- src/main/java/gregtech/api/cover/Cover.java | 10 +- .../gregtech/api/cover/CoverRayTracer.java | 3 +- .../physical/block/PipeMaterialBlock.java | 19 +- .../pipenet/physical/block/RayTraceAABB.java | 35 +++ .../pipenet/physical/block/RayTracePair.java | 9 - .../physical/block/WorldPipeBlock.java | 96 +++++-- .../tile/PipeActivableTileEntity.java | 12 + .../physical/tile/PipeMaterialTileEntity.java | 40 +++ .../pipenet/physical/tile/PipeTileEntity.java | 36 ++- .../properties/PipeNetProperties.java | 17 +- .../api/unification/ore/OrePrefix.java | 36 +-- .../renderer/pipe/quad/PipeQuadHelper.java | 253 +++++------------- .../client/renderer/pipe/quad/UVCorner.java | 15 -- .../client/renderer/pipe/quad/UVMapper.java | 21 -- .../gregtech/common/covers/CoverConveyor.java | 4 +- .../common/covers/CoverDigitalInterface.java | 7 +- .../covers/CoverDigitalInterfaceWireless.java | 4 +- .../common/covers/CoverEnderFluidLink.java | 4 +- .../common/covers/CoverFluidFilter.java | 4 +- .../common/covers/CoverFluidVoiding.java | 4 +- .../common/covers/CoverItemFilter.java | 4 +- .../common/covers/CoverItemVoiding.java | 4 +- .../common/covers/CoverMachineController.java | 4 +- .../gregtech/common/covers/CoverPump.java | 4 +- .../gregtech/common/covers/CoverShutter.java | 8 +- .../gregtech/common/covers/CoverStorage.java | 6 +- .../covers/detector/CoverDetectorBase.java | 4 +- .../detector/CoverDetectorEnergyAdvanced.java | 6 +- .../detector/CoverDetectorFluidAdvanced.java | 4 +- .../detector/CoverDetectorItemAdvanced.java | 4 +- .../pipelike/block/cable/CableBlock.java | 4 +- .../pipelike/block/laser/LaserPipeBlock.java | 5 +- .../pipelike/block/laser/LaserStructure.java | 1 + .../block/optical/OpticalPipeBlock.java | 5 +- .../block/optical/OpticalStructure.java | 1 + .../properties/MaterialEnergyProperties.java | 5 + .../properties/MaterialFluidProperties.java | 6 + .../properties/MaterialItemProperties.java | 5 + 38 files changed, 359 insertions(+), 350 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/block/RayTraceAABB.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/block/RayTracePair.java delete mode 100644 src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java delete mode 100644 src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java diff --git a/src/main/java/gregtech/api/cover/Cover.java b/src/main/java/gregtech/api/cover/Cover.java index 0257544c99a..6823672d9e0 100644 --- a/src/main/java/gregtech/api/cover/Cover.java +++ b/src/main/java/gregtech/api/cover/Cover.java @@ -9,12 +9,12 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.*; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -157,7 +157,7 @@ default boolean canPipePassThrough() { * @param hitResult the HitResult of the click * @return the action's result */ - default boolean onLeftClick(@NotNull EntityPlayer player, @NotNull CuboidRayTraceResult hitResult) { + default boolean onLeftClick(@NotNull EntityPlayer player, @NotNull RayTraceResult hitResult) { return false; } @@ -168,7 +168,7 @@ default boolean onLeftClick(@NotNull EntityPlayer player, @NotNull CuboidRayTrac * @return the action's result */ default @NotNull EnumActionResult onRightClick(@NotNull EntityPlayer player, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { return EnumActionResult.PASS; } @@ -179,7 +179,7 @@ default boolean onLeftClick(@NotNull EntityPlayer player, @NotNull CuboidRayTrac * @return the action's result */ default @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer player, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { return EnumActionResult.PASS; } @@ -190,7 +190,7 @@ default boolean onLeftClick(@NotNull EntityPlayer player, @NotNull CuboidRayTrac * @return the action's result */ default @NotNull EnumActionResult onSoftMalletClick(@NotNull EntityPlayer player, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { return EnumActionResult.PASS; } diff --git a/src/main/java/gregtech/api/cover/CoverRayTracer.java b/src/main/java/gregtech/api/cover/CoverRayTracer.java index c31648b101f..b35ad4ec4b7 100644 --- a/src/main/java/gregtech/api/cover/CoverRayTracer.java +++ b/src/main/java/gregtech/api/cover/CoverRayTracer.java @@ -21,8 +21,7 @@ private CoverRayTracer() {} // if the coverable view is from a blockpipe, use the proper raytrace method RayTraceResult result = coverableView.getWorld().getBlockState(coverableView.getPos()) .getBlock() instanceof WorldPipeBlock pipe ? - pipe.collisionRayTrace(player, coverableView.getWorld(), coverableView.getPos()) - .result() : + pipe.collisionRayTrace(player, coverableView.getWorld(), coverableView.getPos()) : RayTracer.retraceBlock(coverableView.getWorld(), player, coverableView.getPos()); if (result == null || result.typeOfHit != RayTraceResult.Type.BLOCK) { return null; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index 5e1784224e0..fed7d3c28cf 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -22,10 +22,12 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; @@ -58,6 +60,14 @@ public void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList null; !null, _ -> new") + public static RayTraceAABB of(@Nullable RayTraceResult result, AxisAlignedBB bb) { + if (result == null) return null; + if (result.typeOfHit == Type.ENTITY) + throw new IllegalArgumentException("Cannot create a RayTraceAABB for an entity hit!"); + return new RayTraceAABB(result.typeOfHit, result.hitVec, result.sideHit, result.getBlockPos(), bb); + } + + public AxisAlignedBB getBB() { + return bb; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/RayTracePair.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/RayTracePair.java deleted file mode 100644 index d2970d3a4e5..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/RayTracePair.java +++ /dev/null @@ -1,9 +0,0 @@ -package gregtech.api.graphnet.pipenet.physical.block; - -import com.github.bsideup.jabel.Desugar; - -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.RayTraceResult; - -@Desugar -public record RayTracePair(RayTraceResult result, AxisAlignedBB bb) {} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java index c4a3b5318d5..3d2dbbce149 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java @@ -37,6 +37,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.NonNullList; @@ -51,7 +52,6 @@ import codechicken.lib.raytracer.RayTracer; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -75,8 +75,9 @@ public WorldPipeBlock(IPipeStructure structure) { setTranslationKey(structure.getName()); setSoundType(SoundType.METAL); setHardness(2.0f); + setHarvestLevel(getToolClass(), 1); setResistance(3.0f); - setLightOpacity(0); + setLightOpacity(1); disableStats(); } @@ -114,11 +115,37 @@ public void doPlacementLogic(PipeTileEntity tile, EnumFacing placedBlockSearchSi public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, @NotNull EntityPlayer playerIn, @NotNull EnumHand hand, @NotNull EnumFacing facing, float hitX, float hitY, float hitZ) { - if (isPipeTool(playerIn.getHeldItem(hand))) { - PipeTileEntity tile = getTileEntity(worldIn, pos); - if (tile != null) { - EnumFacing actualSide = CoverRayTracer.determineGridSideHit(collisionRayTrace(playerIn, worldIn, pos).result()); - if (actualSide != null) facing = actualSide; + ItemStack item = playerIn.getHeldItem(hand); + PipeTileEntity tile = getTileEntity(worldIn, pos); + if (tile != null) { + RayTraceAABB trace = collisionRayTrace(playerIn, worldIn, pos); + if (trace == null) return super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ); + + EnumFacing actualSide = CoverRayTracer.determineGridSideHit(trace); + if (actualSide != null) facing = actualSide; + + // cover comes first + PipeCoverHolder coverable = tile.getCoverHolder(); + Cover cover = coverable.getCoverAtSide(facing); + if (cover != null) { + if (ToolHelper.isTool(item, ToolClasses.SCREWDRIVER)) { + EnumActionResult result = cover.onScrewdriverClick(playerIn, hand, trace); + if (result != EnumActionResult.PASS) return result == EnumActionResult.SUCCESS; + } + if (ToolHelper.isTool(item, ToolClasses.SOFT_MALLET)) { + EnumActionResult result = cover.onSoftMalletClick(playerIn, hand, trace); + if (result != EnumActionResult.PASS) return result == EnumActionResult.SUCCESS; + } + EnumActionResult result = cover.onRightClick(playerIn, hand, trace); + if (result != EnumActionResult.PASS) return result == EnumActionResult.SUCCESS; + + if (ToolHelper.isTool(item, ToolClasses.CROWBAR)) { + coverable.dropCover(facing); + return true; + } + } + + if (isPipeTool(item)) { PipeTileEntity other = tile.getPipeNeighbor(facing, true); if (playerIn.isSneaking() && allowsBlocking()) { @@ -134,6 +161,22 @@ public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @ return super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ); } + @Override + public void onBlockClicked(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull EntityPlayer playerIn) { + PipeTileEntity tile = getTileEntity(worldIn, pos); + if (tile != null) { + RayTraceAABB trace = collisionRayTrace(playerIn, worldIn, pos); + EnumFacing facing = trace.sideHit; + EnumFacing actualSide = CoverRayTracer.determineGridSideHit(trace); + if (actualSide != null) facing = actualSide; + Cover cover = tile.getCoverHolder().getCoverAtSide(facing); + if (cover != null) { + if (cover.onLeftClick(playerIn, trace)) return; + } + } + super.onBlockClicked(worldIn, pos, playerIn); + } + public static void connectTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, EnumFacing facing) { // abort connection if either tile refuses it. if (!tile.canConnectTo(facing) || tileAcross != null && !tileAcross.canConnectTo(facing.getOpposite())) return; @@ -239,7 +282,9 @@ public void onBlockAdded(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull @Override public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { super.breakBlock(worldIn, pos, state); - if (!worldIn.isRemote) getHandler(worldIn, pos).removeFromNets(worldIn, pos, getStructure()); + if (!worldIn.isRemote) { + getHandler(worldIn, pos).removeFromNets(worldIn, pos, getStructure()); + } } @NotNull @@ -274,12 +319,7 @@ protected String getConnectLangKey() { public void getDrops(@NotNull NonNullList drops, @NotNull IBlockAccess world, @NotNull BlockPos pos, @NotNull IBlockState state, int fortune) { PipeTileEntity tile = getTileEntity(world, pos); - if (tile == null) drops.add(getDrop(world, pos, state)); - else tile.getDrops(drops, state); - } - - public ItemStack getDrop(IBlockAccess world, BlockPos pos, IBlockState state) { - return new ItemStack(this, 1, damageDropped(state)); + if (tile != null) tile.getDrops(drops, state); } @Override @@ -335,8 +375,8 @@ protected Pair getParticleTexture(World world, Bloc @Override public @NotNull AxisAlignedBB getSelectedBoundingBox(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos) { - RayTracePair trace = this.collisionRayTrace(GTUtility.getSP(), worldIn, pos); - return (trace.bb() == null ? FULL_BLOCK_AABB : trace.bb()).offset(pos); + RayTraceAABB trace = this.collisionRayTrace(GTUtility.getSP(), worldIn, pos); + return (trace == null || trace.getBB() == null ? FULL_BLOCK_AABB : trace.getBB()).offset(pos); } @SuppressWarnings("deprecation") @@ -345,6 +385,10 @@ public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World wor @NotNull AxisAlignedBB entityBox, @NotNull List collidingBoxes, @Nullable Entity entityIn, boolean isActualState) { PipeTileEntity tile = getTileEntity(worldIn, pos); + if (hasPipeCollisionChangingItem(worldIn, pos, entityIn)) { + addCollisionBoxToList(pos, entityBox, collidingBoxes, FULL_BLOCK_AABB); + return; + } if (tile != null) { if (tile.getFrameMaterial() != null) { addCollisionBoxToList(pos, entityBox, collidingBoxes, BlockFrame.COLLISION_BOX); @@ -364,23 +408,23 @@ public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World wor public RayTraceResult collisionRayTrace(@NotNull IBlockState blockState, @NotNull World worldIn, @NotNull BlockPos pos, @NotNull Vec3d start, @NotNull Vec3d end) { - return collisionRayTrace(worldIn.isRemote ? GTUtility.getSP() : null, worldIn, pos, start, end).result(); + return collisionRayTrace(worldIn.isRemote ? GTUtility.getSP() : null, worldIn, pos, start, end); } - public @NotNull RayTracePair collisionRayTrace(@NotNull EntityPlayer player, + public @Nullable RayTraceAABB collisionRayTrace(@NotNull EntityPlayer player, @NotNull World world, @NotNull BlockPos pos) { return collisionRayTrace(player, world, pos, RayTracer.getStartVec(player), RayTracer.getEndVec(player)); } - public @NotNull RayTracePair collisionRayTrace(@Nullable EntityPlayer player, + public @Nullable RayTraceAABB collisionRayTrace(@Nullable EntityPlayer player, @NotNull World worldIn, @NotNull BlockPos pos, - @NotNull Vec3d start, @NotNull Vec3d end) { + @NotNull Vec3d start, @NotNull Vec3d end) { if (hasPipeCollisionChangingItem(worldIn, pos, player)) { - return new RayTracePair(rayTrace(pos, start, end, FULL_BLOCK_AABB), FULL_BLOCK_AABB); + return RayTraceAABB.of(rayTrace(pos, start, end, FULL_BLOCK_AABB), FULL_BLOCK_AABB); } PipeTileEntity tile = getTileEntity(worldIn, pos); if (tile == null) { - return new RayTracePair(rayTrace(pos, start, end, FULL_BLOCK_AABB), FULL_BLOCK_AABB); + return RayTraceAABB.of(rayTrace(pos, start, end, FULL_BLOCK_AABB), FULL_BLOCK_AABB); } RayTraceResult min = null; AxisAlignedBB minbb = null; @@ -395,7 +439,7 @@ public RayTraceResult collisionRayTrace(@NotNull IBlockState blockState, @NotNul minDistSqrd = distSqrd; } } - return new RayTracePair(min, minbb); + return RayTraceAABB.of(min, minbb); } public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, Entity entity) { @@ -437,7 +481,11 @@ public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, It } public boolean isPipeTool(@NotNull ItemStack stack) { - return ToolHelper.isTool(stack, ToolClasses.WRENCH); + return ToolHelper.isTool(stack, getToolClass()); + } + + public String getToolClass() { + return ToolClasses.WRENCH; } @SuppressWarnings("deprecation") diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java index 12dec84eaca..9bdee8c97c7 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java @@ -44,5 +44,17 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { } } + @Override + public void writeInitialSyncData(@NotNull PacketBuffer buf) { + buf.writeBoolean(active); + super.writeInitialSyncData(buf); + } + + @Override + public void receiveInitialSyncData(@NotNull PacketBuffer buf) { + active = buf.readBoolean(); + super.receiveInitialSyncData(buf); + } + // do not save activeness to nbt, it should go away on world save & load. } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java index afd5059138c..a3f34369218 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java @@ -1,13 +1,20 @@ package gregtech.api.graphnet.pipenet.physical.tile; +import gregtech.api.GregTechAPI; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.PipeModel; +import gregtech.common.blocks.MetaBlocks; + +import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.NonNullList; import net.minecraftforge.common.property.IExtendedBlockState; import org.jetbrains.annotations.NotNull; @@ -36,6 +43,11 @@ public Material getMaterial() { return material; } + @Override + public ItemStack getMainDrop(@NotNull IBlockState state) { + return getBlockType().getItem(getMaterial()); + } + @Override public int getDefaultPaintingColor() { return GTUtility.convertRGBtoARGB(getMaterial().getMaterialRGB()); @@ -45,4 +57,32 @@ public int getDefaultPaintingColor() { public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { return super.getRenderInformation(state).withProperty(PipeModel.MATERIAL_PROPERTY, getMaterial()); } + + @Override + public @NotNull NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { + compound = super.writeToNBT(compound); + if (material != null) compound.setString("Material", material.getRegistryName()); + return compound; + } + + @Override + public void readFromNBT(@NotNull NBTTagCompound compound) { + super.readFromNBT(compound); + if (compound.hasKey("Material")) + this.material = GregTechAPI.materialManager.getMaterial(compound.getString("Material")); + else this.material = null; + } + + @Override + public void writeInitialSyncData(@NotNull PacketBuffer buf) { + buf.writeBoolean(material != null); + if (material != null) buf.writeString(material.getRegistryName()); + super.writeInitialSyncData(buf); + } + + @Override + public void receiveInitialSyncData(@NotNull PacketBuffer buf) { + if (buf.readBoolean()) material = GregTechAPI.materialManager.getMaterial(buf.readString(255)); + super.receiveInitialSyncData(buf); + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 4cc2a2e8367..90a340a390e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -1,5 +1,8 @@ package gregtech.api.graphnet.pipenet.physical.tile; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.vec.Matrix4; + import gregtech.api.GTValues; import gregtech.api.GregTechAPI; import gregtech.api.capability.GregtechTileCapabilities; @@ -28,6 +31,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ITickable; @@ -37,6 +41,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldServer; +import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.property.IExtendedBlockState; @@ -70,7 +75,7 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick private byte connectionMask; private byte renderMask; private byte blockedMask; - private int paintingColor; + private int paintingColor = -1; private @Nullable Material frameMaterial; @@ -98,12 +103,23 @@ public PipeTileEntity getPipeNeighbor(EnumFacing facing, boolean allowChunkloadi else return null; } - public void getDrops(NonNullList drops, @NotNull IBlockState state) { - drops.add(this.getBlockType().getDrop(this.getWorld(), this.getPos(), state)); + public void getDrops(@NotNull NonNullList drops, @NotNull IBlockState state) { + drops.add(getMainDrop(state)); if (getFrameMaterial() != null) drops.add(MetaBlocks.FRAMES.get(getFrameMaterial()).getItem(getFrameMaterial())); } + @Override + public void invalidate() { + super.invalidate(); + // TODO I hate this so much can someone please make it so that covers go through getDrops()? + getCoverHolder().dropAllCovers(); + } + + public ItemStack getMainDrop(@NotNull IBlockState state) { + return new ItemStack(state.getBlock(), 1); + } + public ItemStack getDrop() { return new ItemStack(getBlockType(), 1, getBlockType().damageDropped(getBlockState())); } @@ -474,11 +490,16 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { this.frameMaterial = GregTechAPI.materialManager.getMaterial(compound.getString("Frame")); else this.frameMaterial = null; this.getCoverHolder().deserializeNBT(compound.getCompoundTag("Covers")); - scheduleRenderUpdate(); } @Override public void writeInitialSyncData(@NotNull PacketBuffer buf) { + buf.writeByte(connectionMask); + buf.writeByte(renderMask); + buf.writeByte(blockedMask); + buf.writeInt(paintingColor); + buf.writeBoolean(frameMaterial != null); + if (frameMaterial != null) buf.writeString(frameMaterial.getRegistryName()); buf.writeVarInt(netLogicDatas.size()); for (Map.Entry entry : netLogicDatas.entrySet()) { buf.writeString(entry.getKey()); @@ -489,6 +510,12 @@ public void writeInitialSyncData(@NotNull PacketBuffer buf) { @Override public void receiveInitialSyncData(@NotNull PacketBuffer buf) { if (world.isRemote) { + connectionMask = buf.readByte(); + renderMask = buf.readByte(); + blockedMask = buf.readByte(); + paintingColor = buf.readInt(); + if (buf.readBoolean()) frameMaterial = GregTechAPI.materialManager.getMaterial(buf.readString(255)); + else frameMaterial = null; netLogicDatas.clear(); int count = buf.readVarInt(); for (int i = 0; i < count; i++) { @@ -498,6 +525,7 @@ public void receiveInitialSyncData(@NotNull PacketBuffer buf) { netLogicDatas.put(key, data); } } + scheduleRenderUpdate(); } @Override diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index 7452125eabd..910c71bf7fd 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -54,7 +54,7 @@ public boolean generatesStructure(IPipeStructure structure) { @Override public void addToNets(World world, BlockPos pos, IPipeStructure structure) { for (IPipeNetMaterialProperty p : properties.values()) { - p.addToNet(world, pos, structure); + if (p.supportsStructure(structure)) p.addToNet(world, pos, structure); } } @@ -62,8 +62,10 @@ public void addToNets(World world, BlockPos pos, IPipeStructure structure) { public Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { List list = new ObjectArrayList<>(); for (IPipeNetMaterialProperty p : properties.values()) { - WorldPipeNetNode node = p.getFromNet(world, pos, structure); - if (node != null) list.add(node); + if (p.supportsStructure(structure)) { + WorldPipeNetNode node = p.getFromNet(world, pos, structure); + if (node != null) list.add(node); + } } return list; } @@ -71,15 +73,16 @@ public Collection getFromNets(World world, BlockPos pos, IPipe @Override public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) { for (IPipeNetMaterialProperty p : properties.values()) { - p.removeFromNet(world, pos, structure); + if (p.supportsStructure(structure)) p.removeFromNet(world, pos, structure); } } @Override public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn, IPipeStructure structure) { - for (IPipeNetMaterialProperty property : properties.values()) { - property.addInformation(stack, worldIn, tooltip, flagIn, (IPipeMaterialStructure) structure); + for (IPipeNetMaterialProperty p : properties.values()) { + if (p.supportsStructure(structure)) + p.addInformation(stack, worldIn, tooltip, flagIn, (IPipeMaterialStructure) structure); } } @@ -103,6 +106,8 @@ public interface IPipeNetMaterialProperty extends IMaterialProperty { boolean generatesStructure(IPipeStructure structure); + boolean supportsStructure(IPipeStructure structure); + void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn, IPipeMaterialStructure structure); diff --git a/src/main/java/gregtech/api/unification/ore/OrePrefix.java b/src/main/java/gregtech/api/unification/ore/OrePrefix.java index 3106991713a..4e0dbfe7589 100644 --- a/src/main/java/gregtech/api/unification/ore/OrePrefix.java +++ b/src/main/java/gregtech/api/unification/ore/OrePrefix.java @@ -256,7 +256,7 @@ public class OrePrefix { material -> material.hasFlag(GENERATE_FRAME)); public static final OrePrefix pipeTiny = new OrePrefix("pipeTiny", M / 2, null, null, ENABLE_UNIFICATION, - null); + hasNoWoodProperty); public static final OrePrefix pipeSmall = new OrePrefix("pipeSmall", M, null, null, ENABLE_UNIFICATION, null); public static final OrePrefix pipeNormal = new OrePrefix("pipeNormal", M * 3, null, null, @@ -264,27 +264,27 @@ public class OrePrefix { public static final OrePrefix pipeLarge = new OrePrefix("pipeLarge", M * 6, null, null, ENABLE_UNIFICATION, null); public static final OrePrefix pipeHuge = new OrePrefix("pipeHuge", M * 12, null, null, ENABLE_UNIFICATION, - null); + hasNoWoodProperty); public static final OrePrefix pipeQuadruple = new OrePrefix("pipeQuadruple", M * 4, null, null, - ENABLE_UNIFICATION, null); + ENABLE_UNIFICATION, hasNoWoodProperty); public static final OrePrefix pipeNonuple = new OrePrefix("pipeNonuple", M * 9, null, null, - ENABLE_UNIFICATION, null); + ENABLE_UNIFICATION, hasNoWoodProperty); public static final OrePrefix pipeTinyRestrictive = new OrePrefix("pipeTinyRestrictive", M / 2, null, null, - ENABLE_UNIFICATION, null); + ENABLE_UNIFICATION, hasNoWoodProperty); public static final OrePrefix pipeSmallRestrictive = new OrePrefix("pipeSmallRestrictive", M, null, null, - ENABLE_UNIFICATION, null); + ENABLE_UNIFICATION, hasNoWoodProperty); public static final OrePrefix pipeNormalRestrictive = new OrePrefix("pipeNormalRestrictive", M * 3, null, null, - ENABLE_UNIFICATION, null); + ENABLE_UNIFICATION, hasNoWoodProperty); public static final OrePrefix pipeLargeRestrictive = new OrePrefix("pipeLargeRestrictive", M * 6, null, null, - ENABLE_UNIFICATION, null); + ENABLE_UNIFICATION, hasNoWoodProperty); public static final OrePrefix pipeHugeRestrictive = new OrePrefix("pipeHugeRestrictive", M * 12, null, null, - ENABLE_UNIFICATION, null); + ENABLE_UNIFICATION, hasNoWoodProperty); public static final OrePrefix pipeQuadrupleRestrictive = new OrePrefix("pipeQuadrupleRestrictive", M * 4, null, null, - ENABLE_UNIFICATION, null); + ENABLE_UNIFICATION, hasNoWoodProperty); public static final OrePrefix pipeNonupleRestrictive = new OrePrefix("pipeNonupleRestrictive", M * 9, null, null, - ENABLE_UNIFICATION, null); + ENABLE_UNIFICATION, hasNoWoodProperty); public static final OrePrefix wireGtHex = new OrePrefix("wireGtHex", M * 8, null, null, ENABLE_UNIFICATION, null); public static final OrePrefix wireGtOctal = new OrePrefix("wireGtOctal", M * 4, null, null, ENABLE_UNIFICATION, @@ -338,6 +338,7 @@ public static class Conditions { public static final Predicate hasIngotProperty = mat -> mat.hasProperty(PropertyKey.INGOT); public static final Predicate hasBlastProperty = mat -> mat.hasProperty(PropertyKey.BLAST); public static final Predicate hasRotorProperty = mat -> mat.hasProperty(PropertyKey.ROTOR); + public static final Predicate hasNoWoodProperty = mat -> !mat.hasProperty(PropertyKey.WOOD); } public static void init() { @@ -452,19 +453,6 @@ public static void init() { toolHeadWrench.addSecondaryMaterial( new MaterialStack(Materials.Steel, ring.materialAmount + screw.materialAmount * 2)); - Predicate woodPredicate = m -> !m.hasProperty(PropertyKey.WOOD); - pipeTiny.setGenerationCondition(woodPredicate); - pipeTinyRestrictive.setGenerationCondition(woodPredicate); - pipeSmallRestrictive.setGenerationCondition(woodPredicate); - pipeNormalRestrictive.setGenerationCondition(woodPredicate); - pipeLargeRestrictive.setGenerationCondition(woodPredicate); - pipeHuge.setGenerationCondition(woodPredicate); - pipeHugeRestrictive.setGenerationCondition(woodPredicate); - pipeQuadruple.setGenerationCondition(woodPredicate); - pipeQuadrupleRestrictive.setGenerationCondition(woodPredicate); - pipeNonuple.setGenerationCondition(woodPredicate); - pipeNonupleRestrictive.setGenerationCondition(woodPredicate); - pipeSmallRestrictive.addSecondaryMaterial(new MaterialStack(Materials.Iron, ring.materialAmount * 2)); pipeTinyRestrictive.addSecondaryMaterial(new MaterialStack(Materials.Iron, ring.materialAmount * 2)); pipeNormalRestrictive.addSecondaryMaterial(new MaterialStack(Materials.Iron, ring.materialAmount * 2)); diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java index 17717d7abf2..8d8363dc31d 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -2,77 +2,55 @@ import gregtech.client.renderer.pipe.util.SpriteInformation; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.BlockFaceUV; +import net.minecraft.client.renderer.block.model.BlockPartFace; +import net.minecraft.client.renderer.block.model.FaceBakery; +import net.minecraft.client.renderer.block.model.ModelRotation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.client.renderer.vertex.VertexFormat; -import net.minecraft.client.renderer.vertex.VertexFormatElement; import net.minecraft.util.EnumFacing; -import net.minecraftforge.client.model.pipeline.IVertexConsumer; -import net.minecraftforge.client.model.pipeline.TRSRTransformer; -import net.minecraftforge.common.model.TRSRTransformation; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Range; +import org.lwjgl.util.vector.Vector3f; -import javax.vecmath.Matrix4f; -import javax.vecmath.Vector3f; -import javax.vecmath.Vector4f; +import java.util.EnumMap; import java.util.List; @SideOnly(Side.CLIENT) public final class PipeQuadHelper { - private static final VertexFormatElement NORMAL_4F = new VertexFormatElement(0, VertexFormatElement.EnumType.FLOAT, VertexFormatElement.EnumUsage.NORMAL, 4); - private static final VertexFormat FORMAT = new VertexFormat(DefaultVertexFormats.BLOCK).addElement(NORMAL_4F); - private static final TRSRTransformation INVERTER; - static { - Matrix4f matrix4f = new Matrix4f(); - matrix4f.setIdentity(); - matrix4f.mul(-1); - INVERTER = new TRSRTransformation(matrix4f); - } - - private final float thickness; - private final float x; - private final float y; - private final float z; - private final int argb; - private final float small; - private final float large; - private final UVMapper squareMapper; - private final UVMapper tallMapper; - private final UVMapper wideMapper; - - private IVertexConsumer building; + private static final FaceBakery BAKERY = new FaceBakery(); private SpriteInformation targetSprite; - public PipeQuadHelper(float thickness, float x, float y, float z, int argb, float small, float large, - UVMapper squareMapper, UVMapper tallMapper, UVMapper wideMapper) { - this.thickness = thickness; - this.x = x; - this.y = y; - this.z = z; - this.argb = argb; - this.small = small; - this.large = large; - this.squareMapper = squareMapper; - this.tallMapper = tallMapper; - this.wideMapper = wideMapper; + private final Pair coreBox; + private final EnumMap> sideBoxes = new EnumMap<>(EnumFacing.class); + + public PipeQuadHelper(float x, float y, float z, int argb, float small, float large) { + float xS = (x + small) * 16; + float xL = (x + large) * 16; + float yS = (y + small) * 16; + float yL = (y + large) * 16; + float zS = (z + small) * 16; + float zL = (z + large) * 16; + coreBox = ImmutablePair.of(new Vector3f(xS, yS, zS), new Vector3f(xL, yL, zL)); + sideBoxes.put(EnumFacing.DOWN, ImmutablePair.of(new Vector3f(xS, 0, zS), new Vector3f(xL, yS, zL))); + sideBoxes.put(EnumFacing.UP, ImmutablePair.of(new Vector3f(xS, yL, zS), new Vector3f(xL, 16, zL))); + sideBoxes.put(EnumFacing.NORTH, ImmutablePair.of(new Vector3f(xS, yS, 0), new Vector3f(xL, yL, zS))); + sideBoxes.put(EnumFacing.SOUTH, ImmutablePair.of(new Vector3f(xS, yS, zL), new Vector3f(xL, yL, 16))); + sideBoxes.put(EnumFacing.WEST, ImmutablePair.of(new Vector3f(0, yS, zS), new Vector3f(xS, yL, zL))); + sideBoxes.put(EnumFacing.EAST, ImmutablePair.of(new Vector3f(xL, yS, zS), new Vector3f(16, yL, zL))); } - public static PipeQuadHelper create(float thickness, double x, double y, double z, - int argb) { + public static PipeQuadHelper create(float thickness, double x, double y, double z, int argb) { float small = 0.5f - thickness / 2; float large = 0.5f + thickness / 2; - float small16 = small * 16; - float large16 = large * 16; - UVMapper squareMapper = createMapper(small16, small16, large16, large16); - UVMapper tallMapper = createMapper(large16, small16, 16, large16); - UVMapper wideMapper = createRotatedMapper(large16, small16, 16, large16); - return new PipeQuadHelper(thickness, (float) x, (float) y, (float) z, argb, small, large, squareMapper, - tallMapper, wideMapper); + return new PipeQuadHelper((float) x, (float) y, (float) z, argb, small, large); } public static PipeQuadHelper create(float thickness) { @@ -84,167 +62,64 @@ public void setTargetSprite(SpriteInformation sprite) { } public RecolorableBakedQuad visitCore(EnumFacing facing) { - return switch (facing.getAxis()) { - case X -> visitQuad(facing, 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, y + small, - y + large, z + small, z + large, squareMapper); - case Y -> visitQuad(facing, x + small, x + large, - 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, z + small, z + large, - squareMapper); - case Z -> visitQuad(facing, x + small, x + large, y + small, y + large, - 0.5f + thickness / 2 * facing.getAxisDirection().getOffset(), 0, squareMapper); - }; + return visitQuad(facing, coreBox, uvMapper(0)); } public List visitTube(EnumFacing facing) { List list = new ObjectArrayList<>(); + Pair box = sideBoxes.get(facing); switch (facing.getAxis()) { case X -> { - float x1; - float x2; - if (facing == EnumFacing.EAST) { - x1 = this.x + large; - x2 = 1; - } else { - x1 = this.x + small; - x2 = 0; - } - list.add(visitQuad(EnumFacing.UP, x1, x2, y + large, 0, z + small, z + large, wideMapper)); - list.add(visitQuad(EnumFacing.DOWN, x1, x2, y + small, 0, z + small, z + large, wideMapper)); - list.add(visitQuad(EnumFacing.SOUTH, x1, x2, y + small, y + large, z + large, 0, tallMapper)); - list.add(visitQuad(EnumFacing.NORTH, x1, x2, y + small, y + large, z + small, 0, tallMapper)); + UVMapper mapper = uvMapper(0); + list.add(visitQuad(EnumFacing.UP, box, mapper)); + list.add(visitQuad(EnumFacing.DOWN, box, mapper)); + list.add(visitQuad(EnumFacing.SOUTH, box, mapper)); + list.add(visitQuad(EnumFacing.NORTH, box, uvMapper(180))); } case Y -> { - float y1; - float y2; - if (facing == EnumFacing.UP) { - y1 = this.y + large; - y2 = 1; - } else { - y1 = this.y + small; - y2 = 0; - } - list.add(visitQuad(EnumFacing.EAST, x + large, 0, y1, y2, z + small, z + large, wideMapper)); - list.add(visitQuad(EnumFacing.WEST, x + small, 0, y1, y2, z + small, z + large, wideMapper)); - list.add(visitQuad(EnumFacing.SOUTH, x + small, x + large, y1, y2, z + large, 0, wideMapper)); - list.add(visitQuad(EnumFacing.NORTH, x + small, x + large, y1, y2, z + small, 0, wideMapper)); + UVMapper mapper = uvMapper(0); + list.add(visitQuad(EnumFacing.EAST, box, uvMapper(270))); + list.add(visitQuad(EnumFacing.WEST, box, uvMapper(270))); + list.add(visitQuad(EnumFacing.SOUTH, box, mapper)); + list.add(visitQuad(EnumFacing.NORTH, box, mapper)); } case Z -> { - float z1; - float z2; - if (facing == EnumFacing.SOUTH) { - z1 = this.z + large; - z2 = 1; - } else { - z1 = this.z + small; - z2 = 0; - } - list.add(visitQuad(EnumFacing.UP, x + small, x + large, y + large, 0, z1, z2, tallMapper)); - list.add(visitQuad(EnumFacing.DOWN, x + small, x + large, y + small, 0, z1, z2, tallMapper)); - list.add(visitQuad(EnumFacing.EAST, x + large, 0, y + small, y + large, z1, z2, tallMapper)); - list.add(visitQuad(EnumFacing.WEST, x + small, 0, y + small, y + large, z1, z2, tallMapper)); + list.add(visitQuad(EnumFacing.UP, box, uvMapper(180))); + list.add(visitQuad(EnumFacing.DOWN, box, uvMapper(0))); + list.add(visitQuad(EnumFacing.EAST, box, uvMapper(270))); + list.add(visitQuad(EnumFacing.WEST, box, uvMapper(90))); } } return list; } public RecolorableBakedQuad visitCapper(EnumFacing facing) { - return switch (facing.getAxis()) { - case X -> visitQuad(facing, 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, y + small, y + large, - z + small, z + large, squareMapper); - case Y -> visitQuad(facing, x + small, x + large, 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, - z + small, z + large, squareMapper); - case Z -> visitQuad(facing, x + small, x + large, y + small, y + large, - 0.5f + 0.5f * facing.getAxisDirection().getOffset(), 0, squareMapper); - }; + return visitQuad(facing, sideBoxes.get(facing), uvMapper(0)); } - public RecolorableBakedQuad visitQuad(EnumFacing normal, float x1, float x2, float y1, float y2, float z1, float z2, - UVMapper mapper) { - RecolorableBakedQuad.Builder builder = new RecolorableBakedQuad.Builder(FORMAT); - building = builder; - UVCorner[] array = UVCorner.VALUES; - switch (normal.getAxis()) { - case X -> { - visitVertex(normal, x1, y1, z1, mapper.map(array[0], targetSprite.sprite())); - visitVertex(normal, x1, y1, z2, mapper.map(array[1], targetSprite.sprite())); - visitVertex(normal, x1, y2, z2, mapper.map(array[2], targetSprite.sprite())); - visitVertex(normal, x1, y2, z1, mapper.map(array[3], targetSprite.sprite())); - } - case Y -> { - visitVertex(normal, x1, y1, z1, mapper.map(array[0], targetSprite.sprite())); - visitVertex(normal, x1, y1, z2, mapper.map(array[1], targetSprite.sprite())); - visitVertex(normal, x2, y1, z2, mapper.map(array[2], targetSprite.sprite())); - visitVertex(normal, x2, y1, z1, mapper.map(array[3], targetSprite.sprite())); - } - case Z -> { - visitVertex(normal, x1, y1, z1, mapper.map(array[0], targetSprite.sprite())); - visitVertex(normal, x2, y1, z1, mapper.map(array[1], targetSprite.sprite())); - visitVertex(normal, x2, y2, z1, mapper.map(array[2], targetSprite.sprite())); - visitVertex(normal, x1, y2, z1, mapper.map(array[3], targetSprite.sprite())); - } - } - building = null; - builder.setQuadOrientation(normal); + public RecolorableBakedQuad visitQuad(EnumFacing normal, Pair box, UVMapper uv) { + BlockPartFace face = new BlockPartFace(null, -1, targetSprite.sprite().getIconName(), uv.map(normal, box)); + BakedQuad quad = BAKERY.makeBakedQuad(box.getLeft(), box.getRight(), face, targetSprite.sprite(), normal, ModelRotation.X0_Y0, null, false, true); + RecolorableBakedQuad.Builder builder = new RecolorableBakedQuad.Builder(quad.getFormat()); builder.setTexture(targetSprite); + quad.pipe(builder); return builder.build(); } - private void visitVertex(EnumFacing normal, float x, float y, float z, UVMapper.UVPair pair) { - putVertex(building, FORMAT, normal, x, y, z, pair.u(), pair.v(), argb); - } - - public static UVMapper createMapper(double u1, double v1, double u2, double v2) { - return (corner, sprite) -> switch (corner) { - case UL -> UVMapper.uvPair(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)); - case UR -> UVMapper.uvPair(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)); - case DR -> UVMapper.uvPair(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)); - case DL -> UVMapper.uvPair(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)); - }; + private static UVMapper uvMapper(int rot) { + return (normal, box) -> uv(normal, box, rot); } - public static UVMapper createRotatedMapper(double u1, double v1, double u2, double v2) { - return (corner, sprite) -> switch (corner) { - case UR -> UVMapper.uvPair(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)); - case DR -> UVMapper.uvPair(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)); - case DL -> UVMapper.uvPair(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)); - case UL -> UVMapper.uvPair(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)); + private static BlockFaceUV uv(EnumFacing normal, Pair box, int rot) { + Vector3f small = box.getLeft(); + Vector3f large = box.getRight(); + return switch (normal.getAxis()) { + case X -> new BlockFaceUV(new float[] {small.y, large.z, large.y, small.z}, rot); + case Y -> new BlockFaceUV(new float[] {small.x, large.z, large.x, small.z}, rot); + case Z -> new BlockFaceUV(new float[] {small.x, large.y, large.x, small.y}, rot); }; } - @SuppressWarnings("SameParameterValue") - private static void putVertex(IVertexConsumer consumer, VertexFormat format, EnumFacing normal, - float x, float y, float z, float u, float v, int argb) { - for (int e = 0; e < format.getElementCount(); e++) { - switch (format.getElement(e).getUsage()) { - case POSITION: - consumer.put(e, x, y, z, 1f); - break; - case COLOR: - float a = ((argb >> 24) & 0xFF) / 255f; // alpha - float r = ((argb >> 16) & 0xFF) / 255f; // red - float g = ((argb >> 8) & 0xFF) / 255f; // green - float b = ((argb) & 0xFF) / 255f; // blue - consumer.put(e, r, g, b, a); - break; - case NORMAL: - float offX = (float) normal.getXOffset(); - float offY = (float) normal.getYOffset(); - float offZ = (float) normal.getZOffset(); - consumer.put(e, offX, offY, offZ, -1f); - break; - case UV: - if (format.getElement(e).getIndex() == 0) { - consumer.put(e, u, v, 0f, 1f); - break; - } - // else fallthrough to default - default: - consumer.put(e); - break; - } - } - } - public static List createFrame(TextureAtlasSprite sprite) { PipeQuadHelper helper = PipeQuadHelper.create(0.998f); helper.setTargetSprite(new SpriteInformation(sprite, true)); @@ -254,4 +129,10 @@ public static List createFrame(TextureAtlasSprite sprite) } return list; } + + @FunctionalInterface + public interface UVMapper { + + BlockFaceUV map(EnumFacing normal, Pair box); + } } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java b/src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java deleted file mode 100644 index 2c4849333be..00000000000 --- a/src/main/java/gregtech/client/renderer/pipe/quad/UVCorner.java +++ /dev/null @@ -1,15 +0,0 @@ -package gregtech.client.renderer.pipe.quad; - -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -@SideOnly(Side.CLIENT) -public enum UVCorner { - - UL, - UR, - DR, - DL; - - public static final UVCorner[] VALUES = values(); -} diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java deleted file mode 100644 index 9d3ef087010..00000000000 --- a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java +++ /dev/null @@ -1,21 +0,0 @@ -package gregtech.client.renderer.pipe.quad; - -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import com.github.bsideup.jabel.Desugar; - -@SideOnly(Side.CLIENT) -@FunctionalInterface -interface UVMapper { - - UVPair map(UVCorner corner, TextureAtlasSprite sprite); - - static UVPair uvPair(float u, float v) { - return new UVPair(u, v); - } - - @Desugar - record UVPair(float u, float v) {} -} diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 98025ecf825..182ad11b130 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -30,13 +30,13 @@ import net.minecraft.util.IStringSerializable; import net.minecraft.util.ITickable; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -462,7 +462,7 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!getCoverableView().getWorld().isRemote) { openUI((EntityPlayerMP) playerIn); } diff --git a/src/main/java/gregtech/common/covers/CoverDigitalInterface.java b/src/main/java/gregtech/common/covers/CoverDigitalInterface.java index e5ffa6b2a9e..d8797b4af8c 100644 --- a/src/main/java/gregtech/common/covers/CoverDigitalInterface.java +++ b/src/main/java/gregtech/common/covers/CoverDigitalInterface.java @@ -54,7 +54,6 @@ import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -299,7 +298,7 @@ public void update() { @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!this.getWorld().isRemote) { this.openUI((EntityPlayerMP) playerIn); } @@ -308,7 +307,7 @@ public void update() { @Override public @NotNull EnumActionResult onRightClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult rayTraceResult) { + @NotNull RayTraceResult rayTraceResult) { if (!isRemote()) { if (this.getWorld().getTotalWorldTime() - lastClickTime < 2 && playerIn.getPersistentID().equals(lastClickUUID)) { @@ -349,7 +348,7 @@ public void update() { } @Override - public boolean onLeftClick(@NotNull EntityPlayer entityPlayer, @NotNull CuboidRayTraceResult hitResult) { + public boolean onLeftClick(@NotNull EntityPlayer entityPlayer, @NotNull RayTraceResult hitResult) { if (!isRemote()) { if (this.getWorld().getTotalWorldTime() - lastClickTime < 2 && entityPlayer.getPersistentID().equals(lastClickUUID)) { diff --git a/src/main/java/gregtech/common/covers/CoverDigitalInterfaceWireless.java b/src/main/java/gregtech/common/covers/CoverDigitalInterfaceWireless.java index 329085dc55c..7ed51c30bef 100644 --- a/src/main/java/gregtech/common/covers/CoverDigitalInterfaceWireless.java +++ b/src/main/java/gregtech/common/covers/CoverDigitalInterfaceWireless.java @@ -20,11 +20,11 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; +import net.minecraft.util.math.RayTraceResult; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -92,7 +92,7 @@ public void update() { @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { return EnumActionResult.SUCCESS; } diff --git a/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java b/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java index ffe2f9ed8a0..a1aae68ace1 100644 --- a/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java +++ b/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java @@ -24,11 +24,11 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.ITickable; +import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -107,7 +107,7 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!getWorld().isRemote) { openUI((EntityPlayerMP) playerIn); } diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index ee751436bc8..45298e8371d 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -23,12 +23,12 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -130,7 +130,7 @@ public boolean canPipePassThrough() { } public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!playerIn.world.isRemote) { this.openUI((EntityPlayerMP) playerIn); } diff --git a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java index c781f816bef..4807811357f 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java +++ b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java @@ -12,6 +12,7 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextComponentTranslation; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.FluidStack; @@ -19,7 +20,6 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -104,7 +104,7 @@ protected boolean createThroughputRow() { @Override public @NotNull EnumActionResult onSoftMalletClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { this.isWorkingAllowed = !this.isWorkingAllowed; if (!playerIn.world.isRemote) { playerIn.sendStatusMessage(new TextComponentTranslation(isWorkingEnabled() ? diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 4ce80925012..0938de42de7 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -23,11 +23,11 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -129,7 +129,7 @@ public boolean canPipePassThrough() { @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!playerIn.world.isRemote) { openUI((EntityPlayerMP) playerIn); } diff --git a/src/main/java/gregtech/common/covers/CoverItemVoiding.java b/src/main/java/gregtech/common/covers/CoverItemVoiding.java index 977968bbab1..950761911e8 100644 --- a/src/main/java/gregtech/common/covers/CoverItemVoiding.java +++ b/src/main/java/gregtech/common/covers/CoverItemVoiding.java @@ -11,12 +11,12 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextComponentTranslation; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -117,7 +117,7 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO @Override public @NotNull EnumActionResult onSoftMalletClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { this.isWorkingAllowed = !this.isWorkingAllowed; if (!playerIn.world.isRemote) { playerIn.sendStatusMessage(new TextComponentTranslation(isWorkingEnabled() ? diff --git a/src/main/java/gregtech/common/covers/CoverMachineController.java b/src/main/java/gregtech/common/covers/CoverMachineController.java index 517a9bc5711..ca4b16f4968 100644 --- a/src/main/java/gregtech/common/covers/CoverMachineController.java +++ b/src/main/java/gregtech/common/covers/CoverMachineController.java @@ -13,9 +13,9 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.util.*; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextFormatting; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -98,7 +98,7 @@ public boolean canAttach(@NotNull CoverableView coverable, @NotNull EnumFacing s @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!getCoverableView().getWorld().isRemote) { openUI((EntityPlayerMP) playerIn); } diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index e91a59118a6..bc8e2de1811 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -28,6 +28,7 @@ import net.minecraft.util.IStringSerializable; import net.minecraft.util.ITickable; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; @@ -35,7 +36,6 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -292,7 +292,7 @@ protected int getMaxTransferRate() { @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!getWorld().isRemote) { openUI((EntityPlayerMP) playerIn); } diff --git a/src/main/java/gregtech/common/covers/CoverShutter.java b/src/main/java/gregtech/common/covers/CoverShutter.java index 00807fc0d95..0431f1b4408 100644 --- a/src/main/java/gregtech/common/covers/CoverShutter.java +++ b/src/main/java/gregtech/common/covers/CoverShutter.java @@ -13,10 +13,10 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextComponentTranslation; import net.minecraftforge.common.capabilities.Capability; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -45,13 +45,13 @@ public boolean canAttach(@NotNull CoverableView coverable, @NotNull EnumFacing s @Override public @NotNull EnumActionResult onRightClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { return EnumActionResult.FAIL; } @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { return EnumActionResult.FAIL; } @@ -75,7 +75,7 @@ public boolean canPipePassThrough() { @Override public @NotNull EnumActionResult onSoftMalletClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { setWorkingEnabled(!this.isWorkingAllowed); if (!playerIn.world.isRemote) { playerIn.sendMessage(new TextComponentTranslation(isWorkingEnabled() ? diff --git a/src/main/java/gregtech/common/covers/CoverStorage.java b/src/main/java/gregtech/common/covers/CoverStorage.java index a63fe3cbd56..0d8b7e3cf6a 100644 --- a/src/main/java/gregtech/common/covers/CoverStorage.java +++ b/src/main/java/gregtech/common/covers/CoverStorage.java @@ -14,10 +14,10 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemStackHandler; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -66,7 +66,7 @@ public void onRemoval() { @Override public @NotNull EnumActionResult onRightClick(@NotNull EntityPlayer player, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!getCoverableView().getWorld().isRemote) { openUI((EntityPlayerMP) player); } @@ -75,7 +75,7 @@ public void onRemoval() { @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer player, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!getWorld().isRemote) { openUI((EntityPlayerMP) player); } diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorBase.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorBase.java index b4df7c1822a..a369e87311d 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorBase.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorBase.java @@ -10,9 +10,9 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextComponentTranslation; -import codechicken.lib.raytracer.CuboidRayTraceResult; import org.jetbrains.annotations.NotNull; import static gregtech.api.capability.GregtechDataCodes.UPDATE_INVERTED; @@ -96,7 +96,7 @@ public boolean canConnectRedstone() { @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (getWorld().isRemote) { return EnumActionResult.SUCCESS; } diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java index 95ebec138aa..91ada6c3e9f 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java @@ -19,11 +19,13 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; + +import net.minecraft.util.math.RayTraceResult; + import org.jetbrains.annotations.NotNull; public class CoverDetectorEnergyAdvanced extends CoverDetectorEnergy implements CoverWithUI { @@ -52,7 +54,7 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!getWorld().isRemote) { openUI((EntityPlayerMP) playerIn); } diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java index 56d7eb246c9..869656a0fc9 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java @@ -18,12 +18,12 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidTankProperties; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -51,7 +51,7 @@ public CoverDetectorFluidAdvanced(@NotNull CoverDefinition definition, @NotNull @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!getWorld().isRemote) { openUI((EntityPlayerMP) playerIn); } diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java index e2475756fd5..1cf4c875038 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java @@ -18,10 +18,10 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import codechicken.lib.raytracer.CuboidRayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; @@ -133,7 +133,7 @@ public boolean isLatched() { @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, - @NotNull CuboidRayTraceResult hitResult) { + @NotNull RayTraceResult hitResult) { if (!getWorld().isRemote) { openUI((EntityPlayerMP) playerIn); } diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index e549c57fcd8..0bf807bba9b 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -36,8 +36,8 @@ public CableBlock(CableStructure structure, MaterialRegistry registry) { } @Override - public boolean isPipeTool(@NotNull ItemStack stack) { - return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); + public String getToolClass() { + return ToolClasses.WIRE_CUTTER; } @Override diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java index 983b527baa3..18d4c1d8fd2 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java @@ -22,7 +22,6 @@ public class LaserPipeBlock extends PipeActivableBlock { public LaserPipeBlock(LaserStructure structure) { super(structure); - setHarvestLevel(ToolClasses.WIRE_CUTTER, 1); setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); } @@ -33,8 +32,8 @@ public static Set gatherStructures() { } @Override - public boolean isPipeTool(@NotNull ItemStack stack) { - return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); + public String getToolClass() { + return ToolClasses.WIRE_CUTTER; } @Override diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java index 235959a84a1..64d653d6524 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java @@ -20,6 +20,7 @@ public record LaserStructure(String name, float renderThickness, ActivablePipeMo @Override public boolean canConnectTo(EnumFacing side, byte connectionMask) { for (EnumFacing facing : EnumFacing.VALUES) { + if (facing == side) continue; if (GTUtility.evalMask(facing, connectionMask)) { return facing.getOpposite() == side; } diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java index 338d5f1f11d..e26555dc06c 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java @@ -22,7 +22,6 @@ public class OpticalPipeBlock extends PipeActivableBlock { public OpticalPipeBlock(OpticalStructure structure) { super(structure); - setHarvestLevel(ToolClasses.WIRE_CUTTER, 1); setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); } @@ -33,8 +32,8 @@ public static Set gatherStructures() { } @Override - public boolean isPipeTool(@NotNull ItemStack stack) { - return ToolHelper.isTool(stack, ToolClasses.WIRE_CUTTER); + public String getToolClass() { + return ToolClasses.WIRE_CUTTER; } @Override diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java index 12fb705179c..4416b5e9e4b 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java @@ -22,6 +22,7 @@ public record OpticalStructure(String name, float renderThickness, ActivablePipe public boolean canConnectTo(EnumFacing side, byte connectionMask) { byte connectionCount = 0; for (EnumFacing facing : EnumFacing.VALUES) { + if (facing == side) continue; if (GTUtility.evalMask(facing, connectionMask)) { connectionCount++; } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index ae7d9c3f979..57317068e08 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -239,4 +239,9 @@ public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { public boolean generatesStructure(IPipeStructure structure) { return structure.getClass() == CableStructure.class; } + + @Override + public boolean supportsStructure(IPipeStructure structure) { + return structure instanceof CableStructure || structure instanceof PipeStructure; + } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index 3f09b91933e..f0855ca2713 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -20,6 +20,7 @@ import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.util.TextFormattingUtil; +import gregtech.common.pipelike.block.cable.CableStructure; import gregtech.common.pipelike.block.pipe.PipeStructure; import gregtech.common.pipelike.net.fluid.FluidContainmentLogic; import gregtech.common.pipelike.net.fluid.WorldFluidNet; @@ -233,4 +234,9 @@ public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { public boolean generatesStructure(IPipeStructure structure) { return structure.getClass() == PipeStructure.class; } + + @Override + public boolean supportsStructure(IPipeStructure structure) { + return structure instanceof PipeStructure; + } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index 6ef302fbfc6..408d482e7cd 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -109,4 +109,9 @@ public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { public boolean generatesStructure(IPipeStructure structure) { return structure.getClass() == PipeStructure.class; } + + @Override + public boolean supportsStructure(IPipeStructure structure) { + return structure instanceof PipeStructure; + } } From 50cf37e728ba3b291f1c9cb7f3cdf2bda8ebba0f Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 1 Aug 2024 12:30:13 -0600 Subject: [PATCH 086/157] fixes & improvements --- .../data/query/DataAccessFormat.java | 26 ++++-- .../data/query/DataQueryFormat.java | 26 ++++-- .../gregtech/api/graphnet/GraphNetBacker.java | 16 ++-- .../java/gregtech/api/graphnet/IGraphNet.java | 14 ++++ .../api/graphnet/MultiNodeHelper.java | 61 ++++++++++++-- .../java/gregtech/api/graphnet/NetGroup.java | 18 ++-- .../java/gregtech/api/graphnet/NetNode.java | 21 ++--- .../graphnet/edge/AbstractNetFlowEdge.java | 2 +- .../gregtech/api/graphnet/edge/NetEdge.java | 8 +- .../api/graphnet/edge/NetFlowEdge.java | 2 +- .../api/graphnet/edge/NetFlowSharedEdge.java | 4 +- .../graphnet/gather/GTGraphGatherables.java | 7 +- .../api/graphnet/logic/NetLogicData.java | 23 ++++- .../graphnet/pipenet/IPipeNetNodeHandler.java | 4 +- .../api/graphnet/pipenet/WorldPipeNet.java | 44 ++++++---- .../graphnet/pipenet/WorldPipeNetNode.java | 3 +- .../physical/block/PipeActivableBlock.java | 2 +- .../physical/block/PipeMaterialBlock.java | 10 +-- .../physical/block/WorldPipeBlock.java | 24 ++++-- .../physical/tile/PipeCapabilityWrapper.java | 18 ++-- .../physical/tile/PipeMaterialTileEntity.java | 7 +- .../pipenet/physical/tile/PipeTileEntity.java | 25 ++++-- .../api/graphnet/worldnet/WorldNetNode.java | 4 +- .../properties/PipeNetProperties.java | 14 +++- .../java/gregtech/api/util/GTUtility.java | 2 +- .../renderer/pipe/AbstractPipeModel.java | 15 +++- .../renderer/pipe/ActivablePipeModel.java | 13 +-- .../client/renderer/pipe/CableModel.java | 22 ++++- .../client/renderer/pipe/PipeItemModel.java | 9 +- .../client/renderer/pipe/PipeModel.java | 9 +- .../renderer/pipe/cache/ActivableSQC.java | 11 ++- .../renderer/pipe/cache/BlockableSQC.java | 9 +- .../renderer/pipe/cache/ColorQuadCache.java | 17 ++-- .../renderer/pipe/cache/ExtraCappedSQC.java | 9 +- .../renderer/pipe/cache/RestrictiveSQC.java | 10 ++- .../pipe/cache/StructureQuadCache.java | 38 ++++++++- .../client/renderer/pipe/quad/ColorData.java | 6 ++ .../pipe/quad/OverlayLayerDefinition.java | 13 +++ .../renderer/pipe/quad/PipeQuadHelper.java | 83 +++++++++++++++---- .../pipe/quad/RecolorableBakedQuad.java | 3 +- .../renderer/pipe/util/SpriteInformation.java | 6 +- .../pipe/util/SpriteInformationWrapper.java | 6 +- .../client/renderer/texture/Textures.java | 50 +++++------ .../pipelike/handlers/LaserNetHandler.java | 7 +- .../pipelike/handlers/OpticalNetHandler.java | 7 +- .../properties/MaterialEnergyProperties.java | 14 ++-- .../properties/MaterialFluidProperties.java | 5 +- .../properties/MaterialItemProperties.java | 5 +- .../net/energy/EnergyTraverseData.java | 19 ++--- ...soluteLogic.java => VoltageLossLogic.java} | 12 +-- .../net/fluid/FluidCapabilityObject.java | 80 ++++++++++++++++-- .../pipelike/net/fluid/FluidTraverseData.java | 3 +- .../pipelike/net/fluid/WorldFluidNet.java | 2 +- .../net/item/ItemCapabilityObject.java | 2 +- .../pipelike/net/item/ItemTraverseData.java | 2 +- 55 files changed, 620 insertions(+), 252 deletions(-) create mode 100644 src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java rename src/main/java/gregtech/common/pipelike/net/energy/{LossAbsoluteLogic.java => VoltageLossLogic.java} (53%) diff --git a/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java b/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java index 0d550c9fd03..4eef544d137 100644 --- a/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java +++ b/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java @@ -1,27 +1,39 @@ package gregtech.api.capability.data.query; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraft.util.IStringSerializable; + import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; import java.util.Set; -public final class DataAccessFormat { +public final class DataAccessFormat implements IStringSerializable { - public static final DataAccessFormat STANDARD = create(DataQueryFormat.RECIPE); - public static final DataAccessFormat COMPUTATION = create(DataQueryFormat.COMPUTATION); + public static final DataAccessFormat STANDARD = create("gregtech.data_format.access.standard", DataQueryFormat.RECIPE); + public static final DataAccessFormat COMPUTATION = create("gregtech.data_format.access.computation", DataQueryFormat.COMPUTATION); - public static final DataAccessFormat UNIVERSAL = new DataAccessFormat(null); + public static final DataAccessFormat UNIVERSAL = new DataAccessFormat("gregtech.data_format.access.universal", null); private final Set supportedFormats; - public static DataAccessFormat create(DataQueryFormat... allowedFormats) { - return new DataAccessFormat(new ObjectOpenHashSet<>(allowedFormats)); + public static DataAccessFormat create(@NotNull String name, DataQueryFormat... allowedFormats) { + return new DataAccessFormat(name, new ObjectOpenHashSet<>(allowedFormats)); } - private DataAccessFormat(Set supportedFormats) { + private final @NotNull String name; + + private DataAccessFormat(@NotNull String name, Set supportedFormats) { + this.name = name; this.supportedFormats = supportedFormats; } + @Override + public @NotNull String getName() { + return name; + } + @Contract("_ -> this") public DataAccessFormat support(DataQueryFormat format) { if (supportedFormats != null) this.supportedFormats.add(format); diff --git a/src/main/java/gregtech/api/capability/data/query/DataQueryFormat.java b/src/main/java/gregtech/api/capability/data/query/DataQueryFormat.java index 5603aa3d5a7..5d4ca93814e 100644 --- a/src/main/java/gregtech/api/capability/data/query/DataQueryFormat.java +++ b/src/main/java/gregtech/api/capability/data/query/DataQueryFormat.java @@ -1,14 +1,26 @@ package gregtech.api.capability.data.query; -public final class DataQueryFormat { +import net.minecraft.util.IStringSerializable; - public static final DataQueryFormat RECIPE = create(); - public static final DataQueryFormat COMPUTATION = create(); +import org.jetbrains.annotations.NotNull; - @SuppressWarnings("InstantiationOfUtilityClass") - public static DataQueryFormat create() { - return new DataQueryFormat(); +public final class DataQueryFormat implements IStringSerializable { + + public static final DataQueryFormat RECIPE = create("gregtech.data_format.query.recipe"); + public static final DataQueryFormat COMPUTATION = create("gregtech.data_format.query.computation"); + + public static DataQueryFormat create(@NotNull String name) { + return new DataQueryFormat(name); + } + + private final @NotNull String name; + + private DataQueryFormat(@NotNull String name) { + this.name = name; } - private DataQueryFormat() {} + @Override + public @NotNull String getName() { + return name; + } } diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index 430726823f3..70498cfbfe7 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -68,8 +68,9 @@ public NetNode getNode(Object equivalencyData) { public boolean removeNode(@Nullable NetNode node) { if (node != null) { if (this.getGraph().edgesOf(node.wrapper).size() != 0) this.invalidateAlgs(); - if (node.getGroupUnsafe() != null) { - node.getGroupUnsafe().splitNode(node); + NetGroup group = node.getGroupUnsafe(); + if (group != null) { + group.splitNode(node); } else this.removeVertex(node.wrapper); return true; } else return false; @@ -85,7 +86,10 @@ public void removeVertex(GraphVertex vertex) { @Nullable public NetEdge addEdge(NetNode source, NetNode target, double weight) { GraphEdge graphEdge = getGraph().addEdge(source.wrapper, target.wrapper); - if (graphEdge != null) getGraph().setEdgeWeight(graphEdge, weight); + if (graphEdge != null) { + getGraph().setEdgeWeight(graphEdge, weight); + NetGroup.mergeEdge(source, target); + } return graphEdge == null ? null : graphEdge.wrapped; } @@ -96,9 +100,11 @@ public NetEdge getEdge(NetNode source, NetNode target) { } public boolean removeEdge(NetNode source, NetNode target) { - if (source.getGroupUnsafe() == null) { + NetGroup group = source.getGroupUnsafe(); + if (group == null) { + // weird since there should always be a group for two joined nodes, but whatever return removeEdge(source.wrapper, target.wrapper) != null; - } else return source.getGroupUnsafe().splitEdge(source, target); + } else return group.splitEdge(source, target); } @ApiStatus.Internal diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index 11de718d620..f4ee4d5c654 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -70,6 +70,20 @@ default boolean usesDynamicWeights(int algorithmID) { @Nullable NetEdge getEdge(@NotNull NetNode source, @NotNull NetNode target); + /** + * Returns the edge linking two nodes together, if one exists and both provided nodes are not null. + * + * @param source Source node. + * @param target Target node. + * @return the linking edge, if one exists. + */ + @Contract("null, _ -> null; _, null -> null; _, _ -> _") + @Nullable + default NetEdge getEdgeNullSafe(@Nullable NetNode source, @Nullable NetNode target) { + if (source == null || target == null) return null; + else return getEdge(source, target); + } + /** * Removes the edge linking two nodes together, if one exists. * diff --git a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java index 5ca7558bec1..0dff6ab4828 100644 --- a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java +++ b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java @@ -8,6 +8,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; +import java.lang.ref.WeakReference; import java.util.List; /** @@ -15,7 +16,7 @@ * this by
* A) keeping a record of traversals to allow for blocking traversal when another net has been traversed * recently and
- * B) make sure that logic entries requiring it are the same object across all synced nodes.
+ * B) making sure that logic entries requiring it are the same object across all synced nodes.
*
* MultiNodeHelpers have no standard implementation and must be handled by a net and its nodes; see * {@link gregtech.api.graphnet.pipenet.WorldPipeNet} and {@link gregtech.api.graphnet.pipenet.WorldPipeNetNode} @@ -23,7 +24,7 @@ */ public class MultiNodeHelper implements INetLogicEntryListener { - protected final Object2ObjectOpenHashMap handledNodes = new Object2ObjectOpenHashMap<>(); + protected final Object2ObjectOpenHashMap handledDatas = new Object2ObjectOpenHashMap<>(); protected final Object2ObjectOpenHashMap recentTransferNets = new Object2ObjectOpenHashMap<>(); protected final int transferTimeout; @@ -57,11 +58,10 @@ public boolean traverse(IGraphNet net, long queryTick, boolean simulate) { @Override public void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChange) { // TODO have a helper or something on clientside to avoid redundant packets - handledNodes.forEach((k, v) -> v.getData().markLogicEntryAsUpdated(entry, fullChange)); + handledDatas.forEach((k, v) -> v.data.markLogicEntryAsUpdated(entry, fullChange)); } - public void addNode(NetNode node) { - handledNodes.put(node.getNet(), node); + public void addNode(@NotNull NetNode node) { List> toSet = new ObjectArrayList<>(); for (INetLogicEntry entry : node.getData().getEntries()) { if (entry.mergedToMultiNodeHelper()) { @@ -71,22 +71,67 @@ public void addNode(NetNode node) { // don't put it into the data yet because we're currently iterating through the data's entries. toSet.add(existing); } else { - entry.registerToMultiNodeHelper(this); - mergedData.setLogicEntry(entry); + addNewLogicEntry(entry); } } } + handledDatas.put(node.getNet(), new LogicDataHandler(node)); for (INetLogicEntry entry : toSet) { node.getData().setLogicEntry(entry); } } public void removeNode(NetNode node) { - if (handledNodes.remove(node.getNet(), node)) { + LogicDataHandler removed = handledDatas.remove(node.getNet()); + if (removed != null) { + removed.invalidate(); for (INetLogicEntry entry : this.mergedData.getEntries()) { node.getData().removeLogicEntry(entry); entry.unmerge(node); } } } + + private void addNewLogicEntry(@NotNull INetLogicEntry entry) { + entry.registerToMultiNodeHelper(this); + mergedData.setLogicEntry(entry); + handledDatas.values().forEach(h -> h.data.setLogicEntry(entry)); + } + + protected class LogicDataHandler implements NetLogicData.ILogicDataListener { + + public final WeakReference nodeRef; + public final @NotNull NetLogicData.LogicDataListener listener; + public final @NotNull NetLogicData data; + + public LogicDataHandler(@NotNull NetNode node) { + this.data = node.getData(); + this.listener = data.createListener(this); + this.nodeRef = new WeakReference<>(node); + } + + public void invalidate() { + this.listener.invalidate(); + } + + @Override + public void markChanged(INetLogicEntry updatedEntry, boolean removed, boolean fullChange) { + if (!fullChange || !updatedEntry.mergedToMultiNodeHelper()) return; + NetNode node = nodeRef.get(); + if (node == null) return; + INetLogicEntry existing = mergedData.getLogicEntryNullable(updatedEntry); + if (removed) { + if (existing != null) mergedData.removeLogicEntry(existing); + } else { + if (existing != null) { + if (existing != updatedEntry) { + existing.merge(node, updatedEntry); + data.setLogicEntry(existing); + } + } else { + addNewLogicEntry(updatedEntry); + } + } + } + } } diff --git a/src/main/java/gregtech/api/graphnet/NetGroup.java b/src/main/java/gregtech/api/graphnet/NetGroup.java index 19268f21b1a..a5b8393cdc5 100644 --- a/src/main/java/gregtech/api/graphnet/NetGroup.java +++ b/src/main/java/gregtech/api/graphnet/NetGroup.java @@ -60,7 +60,7 @@ protected void onAddedToGroup(NetNode node) { } /** - * Merges the groups of an edge if necessary. + * Merges the groups of an edge if necessary. Does not actually perform the edge creation. * * @param source the source node of the edge * @param target the target node of the edge @@ -79,7 +79,6 @@ public static void mergeEdge(NetNode source, NetNode target) { if (sourceGroup != null) { sourceGroup.mergeNode(target); } else { - assert targetGroup != null; targetGroup.mergeNode(source); } } @@ -102,10 +101,11 @@ public void splitNode(NetNode source) { if (!this.net.containsNode(source)) return; this.clearPathCaches(); List targets = this.net.getGraph().outgoingEdgesOf(source.wrapper).stream().map(a -> { + GraphVertex target = a.getTarget(); // handling so undirected graphs don't throw an error - if (net.getGraph().isDirected() || Objects.equals(getTarget(a).wrapped, source)) - return getTarget(a).wrapped; - return getSource(a).wrapped; + if (!net.getGraph().isDirected() && target == source.wrapper) + return a.getSource().wrapped; + return target.wrapped; }).collect(Collectors.toList()); this.net.getBacker().removeVertex(source.wrapper); this.removeNode(source); @@ -128,14 +128,6 @@ public void splitNode(NetNode source) { } } - private GraphVertex getSource(GraphEdge graphEdge) { - return this.net.getGraph().getEdgeSource(graphEdge); - } - - private GraphVertex getTarget(GraphEdge graphEdge) { - return this.net.getGraph().getEdgeTarget(graphEdge); - } - /** * Split this group by removing an edge. Automatically removes the edge from the graph. * diff --git a/src/main/java/gregtech/api/graphnet/NetNode.java b/src/main/java/gregtech/api/graphnet/NetNode.java index 771b59d1efb..822a92b5696 100644 --- a/src/main/java/gregtech/api/graphnet/NetNode.java +++ b/src/main/java/gregtech/api/graphnet/NetNode.java @@ -26,19 +26,19 @@ public abstract class NetNode implements INBTSerializable { private boolean isActive = false; - private final IGraphNet net; - private @NotNull NetLogicData data; + private final @NotNull IGraphNet net; + private final @NotNull NetLogicData data; private @Nullable NetGroup group = null; @Nullable private ICacheableIterator> pathCache = null; - public NetNode(IGraphNet net) { + public NetNode(@NotNull IGraphNet net) { this.net = net; this.data = net.getDefaultNodeData(); } - public IGraphNet getNet() { + public @NotNull IGraphNet getNet() { return net; } @@ -53,11 +53,12 @@ public boolean isActive() { * Sets whether the node should be treated as a valid destination of pathing algorithms */ public void setActive(boolean active) { - isActive = active; - } - - public void setData(@NotNull NetLogicData data) { - this.data = data; + if (isActive != active) { + isActive = active; + NetGroup group = getGroupUnsafe(); + if (group != null) group.clearPathCaches(); + else this.clearPathCache(); + } } public @NotNull NetLogicData getData() { @@ -125,7 +126,7 @@ public NBTTagCompound serializeNBT() { @Override public void deserializeNBT(NBTTagCompound nbt) { this.isActive = nbt.getBoolean("IsActive"); - this.data = this.net.getDefaultNodeData(); + this.data.clearData(); this.data.deserializeNBT((NBTTagList) nbt.getTag("Data")); } diff --git a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java index 188f346efb4..f0385f11d16 100644 --- a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java @@ -53,7 +53,7 @@ protected int getChannelCount() { return getData().getLogicEntryDefaultable(ChannelCountLogic.INSTANCE).getValue(); } - protected long getThroughput() { + public long getThroughput() { return getData().getLogicEntryDefaultable(ThroughputLogic.INSTANCE).getValue(); } diff --git a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java index 069f5c32708..8560ed1f337 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java @@ -21,17 +21,19 @@ public class NetEdge implements INBTSerializable { * For interacting with the internal graph representation ONLY, do not use or set this field otherwise. */ @ApiStatus.Internal - public GraphEdge wrapper; + public @Nullable GraphEdge wrapper; private EdgePredicateHandler predicateHandler; private NetLogicData data; - protected NetNode getSource() { + protected @Nullable NetNode getSource() { + if (wrapper == null) return null; return wrapper.getSource().wrapped; } - protected NetNode getTarget() { + protected @Nullable NetNode getTarget() { + if (wrapper == null) return null; return wrapper.getTarget().wrapped; } diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java index e8068f3b22b..8824ce8fac1 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java @@ -50,7 +50,7 @@ protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, @Nullable private NetFlowEdge getInverse(IGraphNet graph) { - NetEdge edge = graph.getEdge(getTarget(), getSource()); + NetEdge edge = graph.getEdgeNullSafe(getTarget(), getSource()); if (edge instanceof NetFlowEdge i && i != this) { return i; } diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java index 0d05db60155..6df5ce5d1c0 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java @@ -36,7 +36,7 @@ protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, @Nullable private NetFlowSharedEdge getInverse(IGraphNet graph) { - NetEdge edge = graph.getEdge(getTarget(), getSource()); + NetEdge edge = graph.getEdgeNullSafe(getTarget(), getSource()); if (edge instanceof NetFlowSharedEdge i && i != this) { return i; } @@ -118,7 +118,7 @@ void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount @Override public void recalculateFlowLimits(long queryTick) { if (!this.init) { - this.maxCapacity = (long) getThroughput() * flowBufferTicks; + this.maxCapacity = getThroughput() * flowBufferTicks; this.init = true; } int time = (int) (queryTick - this.lastQueryTick); diff --git a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java index 61e724c7fa7..3bd4161067b 100644 --- a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java +++ b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java @@ -13,10 +13,12 @@ import gregtech.common.pipelike.block.laser.LaserStructure; import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.block.pipe.PipeStructure; -import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; +import gregtech.common.pipelike.net.energy.VoltageLossLogic; import gregtech.common.pipelike.net.energy.SuperconductorLogic; import gregtech.common.pipelike.net.energy.VoltageLimitLogic; +import gregtech.common.pipelike.net.fluid.FluidContainmentLogic; + import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; @@ -59,10 +61,11 @@ public static void gatherLogics(GatherLogicsEvent event) { event.registerLogic(ThroughputLogic.INSTANCE); event.registerLogic(ChannelCountLogic.INSTANCE); event.registerLogic(MultiNetCountLogic.INSTANCE); - event.registerLogic(LossAbsoluteLogic.INSTANCE); + event.registerLogic(VoltageLossLogic.INSTANCE); event.registerLogic(VoltageLimitLogic.INSTANCE); event.registerLogic(SuperconductorLogic.INSTANCE); event.registerLogic(TemperatureLogic.INSTANCE); + event.registerLogic(FluidContainmentLogic.INSTANCE); } @SubscribeEvent diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index d5ca8c4c2c3..964ccb66896 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -71,6 +71,11 @@ public NetLogicData setLogicEntry(INetLogicEntry entry) { return logicEntrySet.values(); } + public void clearData() { + logicEntrySet.clear(); + logicEntrySet.trim(4); + } + public NetLogicData removeLogicEntry(@NotNull INetLogicEntry key) { return removeLogicEntry(key.getName()); } @@ -184,7 +189,6 @@ public void decode(PacketBuffer buf) { for (int i = 0; i < entryCount; i++) { String name = buf.readString(255); INetLogicEntry existing = getSupplier(name).get(); - // is there a softer exception I can throw that'll disconnect from server but not crash the game? if (existing == null) throw new RuntimeException("Could not find a matching supplier for an encoded INetLogicEntry. " + "This suggests that the server and client have different GT versions or modifications."); @@ -199,20 +203,31 @@ public void decode(PacketBuffer buf) { return GTGraphGatherables.getLogicsRegistry().getOrDefault(identifier, () -> null); } + public LogicDataListener createListener(ILogicDataListener listener) { + return new LogicDataListener(listener); + } + public final class LogicDataListener { - private final TriConsumer, Boolean, Boolean> listener; + private final ILogicDataListener listener; - public LogicDataListener(TriConsumer, Boolean, Boolean> listener) { + private LogicDataListener(ILogicDataListener listener) { this.listener = listener; } private void markChanged(INetLogicEntry updatedEntry, boolean removed, boolean fullChange) { - this.listener.accept(updatedEntry, removed, fullChange); + this.listener.markChanged(updatedEntry, removed, fullChange); } + // TODO would a weak set be better? public void invalidate() { listeners.remove(this); } } + + @FunctionalInterface + public interface ILogicDataListener { + + void markChanged(INetLogicEntry updatedEntry, boolean removed, boolean fullChange); + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java index ddd7e83d436..3c08f16bcde 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java @@ -14,8 +14,10 @@ public interface IPipeNetNodeHandler { - void addToNets(World world, BlockPos pos, IPipeStructure structure); + @NotNull + Collection getOrCreateFromNets(World world, BlockPos pos, IPipeStructure structure); + @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure); void removeFromNets(World world, BlockPos pos, IPipeStructure structure); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index c87f80b7589..64f0fefa64e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -11,21 +11,22 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.pipenet.predicate.ShutterPredicate; import gregtech.api.graphnet.worldnet.WorldNet; +import gregtech.api.util.GTUtility; import gregtech.api.util.IDirtyNotifiable; import gregtech.common.covers.CoverShutter; +import it.unimi.dsi.fastutil.Hash; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; + import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.ref.WeakReference; import java.util.Objects; import java.util.Set; import java.util.function.Function; @@ -35,7 +36,7 @@ public abstract class WorldPipeNet extends WorldNet { public static final int MULTI_NET_TIMEOUT = 10; - private static final Object2ObjectOpenHashMap>> dimensionNets = new Object2ObjectOpenHashMap<>(); + private static final Object2ObjectOpenHashMap> dimensionNets = new Object2ObjectOpenHashMap<>(); @SafeVarargs public WorldPipeNet(String name, Function graphBuilder, @@ -50,10 +51,11 @@ public WorldPipeNet(String name, boolean directed, Function { - if (v == null) v = new ObjectOpenHashSet<>(); - v.add(new WeakReference<>(this)); + if (v == null) v = GTUtility.createWeakHashSet(); + v.add(this); return v; }); } @@ -124,15 +126,7 @@ protected final void shutterify(@NotNull NetEdge edge, @Nullable Cover a, @Nulla } protected Stream<@NotNull WorldPipeNet> sameDimensionNetsStream() { - ObjectArrayList> expired = new ObjectArrayList<>(); - Stream<@NotNull WorldPipeNet> returnable = dimensionNets.get(this.getDimension()).stream() - .map(ref -> { - WorldPipeNet net = ref.get(); - if (net == null) expired.add(ref); - return net; - }).filter(Objects::nonNull); - expired.forEach(dimensionNets.get(this.getDimension())::remove); - return returnable; + return dimensionNets.get(this.getDimension()).stream().filter(Objects::nonNull); } public void synchronizeNode(WorldPipeNetNode node) { @@ -151,6 +145,7 @@ public void synchronizeNode(WorldPipeNetNode node) { } else if (n.overlapHelper == null) { // both handlers are null node.overlapHelper = new MultiNodeHelper(MULTI_NET_TIMEOUT); + node.overlapHelper.addNode(n); } // n handler does not match cast handler n.overlapHelper = node.overlapHelper; @@ -174,4 +169,23 @@ public final Class getNodeClass() { public final @NotNull WorldPipeNetNode getNewNode() { return new WorldPipeNetNode(this); } + + public static Object2ObjectOpenCustomHashMap getSensitiveHashMap() { + return new Object2ObjectOpenCustomHashMap<>(SensitiveStrategy.INSTANCE); + } + + protected static class SensitiveStrategy implements Hash.Strategy { + + public static final SensitiveStrategy INSTANCE = new SensitiveStrategy(); + + @Override + public int hashCode(WorldPipeNetNode o) { + return Objects.hash(o, o.getNet()); + } + + @Override + public boolean equals(WorldPipeNetNode a, WorldPipeNetNode b) { + return a.equals(b) && a.getNet().equals(b.getNet()); + } + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java index 9588e4ad39e..4f8da146a5c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java @@ -8,6 +8,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; @@ -55,7 +56,7 @@ public void onRemove() { } @Override - public WorldPipeNet getNet() { + public @NotNull WorldPipeNet getNet() { return (WorldPipeNet) super.getNet(); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java index 6c4e27272b8..46fd94c0207 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java @@ -41,7 +41,7 @@ public Class getTileClass(@NotNull World worl public @Nullable PipeActivableTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { if (GTUtility.arePosEqual(lastTilePos.get(), pos)) { PipeTileEntity tile = lastTile.get().get(); - if (tile != null) return (PipeActivableTileEntity) tile; + if (tile != null && !tile.isInvalid()) return (PipeActivableTileEntity) tile; } TileEntity tile = world.getTileEntity(pos); if (tile instanceof PipeActivableTileEntity pipe) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index fed7d3c28cf..2174146dd1d 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -11,12 +11,10 @@ import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.util.GTUtility; -import gregtech.client.renderer.pipe.PipeModel; +import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.common.ConfigHolder; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -31,14 +29,12 @@ import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; import java.util.List; -import java.util.Set; public abstract class PipeMaterialBlock extends WorldPipeBlock { @@ -113,14 +109,14 @@ public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull Lis @NotNull @Override protected BlockStateContainer.Builder constructState(BlockStateContainer.@NotNull Builder builder) { - return super.constructState(builder).add(PipeModel.MATERIAL_PROPERTY); + return super.constructState(builder).add(AbstractPipeModel.MATERIAL_PROPERTY); } @Override public @Nullable PipeMaterialTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { if (GTUtility.arePosEqual(lastTilePos.get(), pos)) { PipeTileEntity tile = lastTile.get().get(); - if (tile != null) return (PipeMaterialTileEntity) tile; + if (tile != null && !tile.isInvalid()) return (PipeMaterialTileEntity) tile; } TileEntity tile = world.getTileEntity(pos); if (tile instanceof PipeMaterialTileEntity pipe) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java index 3d2dbbce149..410e3b7019c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java @@ -64,8 +64,8 @@ public abstract class WorldPipeBlock extends BuiltInRenderBlock { // do not touch these two unless you know what you are doing - protected ThreadLocal lastTilePos = ThreadLocal.withInitial(() -> new BlockPos(0, 0, 0)); - protected ThreadLocal> lastTile = ThreadLocal.withInitial(() -> new WeakReference<>(null)); + protected final ThreadLocal lastTilePos = ThreadLocal.withInitial(() -> new BlockPos(0, 0, 0)); + protected final ThreadLocal> lastTile = ThreadLocal.withInitial(() -> new WeakReference<>(null)); private final IPipeStructure structure; @@ -101,7 +101,7 @@ public void doPlacementLogic(PipeTileEntity tile, EnumFacing placedBlockSearchSi continue; } // third check -- connect to pipes with an open connection, no matter the mark status. - if (tile.isConnected(facing.getOpposite())) { + if (other.isConnected(facing.getOpposite())) { connectTile(tile, other, facing); } } else if (facing == placedBlockSearchSide) { @@ -166,6 +166,10 @@ public void onBlockClicked(@NotNull World worldIn, @NotNull BlockPos pos, @NotNu PipeTileEntity tile = getTileEntity(worldIn, pos); if (tile != null) { RayTraceAABB trace = collisionRayTrace(playerIn, worldIn, pos); + if (trace == null) { + super.onBlockClicked(worldIn, pos, playerIn); + return; + } EnumFacing facing = trace.sideHit; EnumFacing actualSide = CoverRayTracer.determineGridSideHit(trace); if (actualSide != null) facing = actualSide; @@ -270,13 +274,13 @@ protected boolean allowsBlocking() { public static Collection getNodesForTile(PipeTileEntity tile) { assert !tile.getWorld().isRemote; return tile.getBlockType().getHandler(tile.getWorld(), tile.getPos()) - .getFromNets(tile.getWorld(), tile.getPos(), tile.getStructure()); + .getOrCreateFromNets(tile.getWorld(), tile.getPos(), tile.getStructure()); } @Override public void onBlockAdded(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { super.onBlockAdded(worldIn, pos, state); - if (!worldIn.isRemote) getHandler(worldIn, pos).addToNets(worldIn, pos, getStructure()); +// if (!worldIn.isRemote) getHandler(worldIn, pos).getOrCreateFromNets(worldIn, pos, getStructure()); } @Override @@ -533,7 +537,7 @@ public final boolean hasTileEntity(@NotNull IBlockState state) { public PipeTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockPos pos) { if (GTUtility.arePosEqual(lastTilePos.get(), pos)) { PipeTileEntity tile = lastTile.get().get(); - if (tile != null) return tile; + if (tile != null && !tile.isInvalid()) return tile; } TileEntity tile = world.getTileEntity(pos); if (tile instanceof PipeTileEntity pipe) { @@ -588,14 +592,18 @@ public int getLightValue(@NotNull IBlockState state, @NotNull IBlockAccess world return 0; } - // cover compatibility annoyance // + // cover compatibility // @SuppressWarnings("deprecation") @Override public void neighborChanged(@NotNull IBlockState state, @NotNull World worldIn, @NotNull BlockPos pos, @NotNull Block blockIn, @NotNull BlockPos fromPos) { PipeTileEntity tile = getTileEntity(worldIn, pos); - if (tile != null) tile.getCoverHolder().updateInputRedstoneSignals(); + if (tile != null) { + EnumFacing facing = GTUtility.getFacingToNeighbor(pos, fromPos); + if (facing != null) tile.onNeighborChanged(facing); + tile.getCoverHolder().updateInputRedstoneSignals(); + } } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java index 2d6e0cb03b0..55d8dcdad1c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java @@ -1,26 +1,34 @@ package gregtech.api.graphnet.pipenet.physical.tile; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; + import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; +import org.jetbrains.annotations.NotNull; + public class PipeCapabilityWrapper { private byte activeMask; + private final WorldPipeNetNode node; public final Capability[] capabilities; - public PipeCapabilityWrapper(Capability[] capabilities) { - this.capabilities = capabilities; + public PipeCapabilityWrapper(WorldPipeNetNode node) { + this.node = node; + this.capabilities = node.getNet().getTargetCapabilities(); } - public void setActive(EnumFacing facing) { + public void setActive(@NotNull EnumFacing facing) { this.activeMask |= 1 << facing.ordinal(); + this.node.setActive(this.activeMask > 0); } - public void setIdle(EnumFacing facing) { + public void setIdle(@NotNull EnumFacing facing) { this.activeMask &= ~(1 << facing.ordinal()); + this.node.setActive(this.activeMask > 0); } - public boolean isActive(EnumFacing facing) { + public boolean isActive(@NotNull EnumFacing facing) { return (this.activeMask & 1 << facing.ordinal()) > 0; } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java index a3f34369218..7346f392cd3 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java @@ -5,16 +5,13 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; import gregtech.api.util.GTUtility; -import gregtech.client.renderer.pipe.PipeModel; - -import gregtech.common.blocks.MetaBlocks; +import gregtech.client.renderer.pipe.AbstractPipeModel; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; -import net.minecraft.util.NonNullList; import net.minecraftforge.common.property.IExtendedBlockState; import org.jetbrains.annotations.NotNull; @@ -55,7 +52,7 @@ public int getDefaultPaintingColor() { @Override public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { - return super.getRenderInformation(state).withProperty(PipeModel.MATERIAL_PROPERTY, getMaterial()); + return super.getRenderInformation(state).withProperty(AbstractPipeModel.MATERIAL_PROPERTY, getMaterial()); } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 90a340a390e..851e8fac3b2 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -10,6 +10,7 @@ import gregtech.api.graphnet.gather.GTGraphGatherables; import gregtech.api.graphnet.logic.INetLogicEntry; import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.IInsulatable; @@ -22,6 +23,9 @@ import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.common.blocks.MetaBlocks; +import it.unimi.dsi.fastutil.Hash; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; + import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; @@ -57,6 +61,7 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.function.Consumer; @@ -83,7 +88,7 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick protected final PipeCoverHolder covers = new PipeCoverHolder(this); private final Object2ObjectOpenHashMap, IPipeCapabilityObject> capabilities = new Object2ObjectOpenHashMap<>(); - private final Object2ObjectOpenHashMap netCapabilities = new Object2ObjectOpenHashMap<>(); + private final Object2ObjectOpenCustomHashMap netCapabilities = WorldPipeNet.getSensitiveHashMap(); @Nullable private TemperatureLogic temperatureLogic; @@ -109,6 +114,12 @@ public void getDrops(@NotNull NonNullList drops, @NotNull IBlockState drops.add(MetaBlocks.FRAMES.get(getFrameMaterial()).getItem(getFrameMaterial())); } + @Override + public void validate() { + super.validate(); + scheduleRenderUpdate(); + } + @Override public void invalidate() { super.invalidate(); @@ -348,23 +359,20 @@ public void updateActiveStatus(@Nullable EnumFacing facing, boolean canOpenConne boolean oneActive = false; for (var netCapability : netCapabilities.entrySet()) { - boolean oneMatch = false; for (Capability cap : netCapability.getValue().capabilities) { if (tile.hasCapability(cap, facing.getOpposite())) { - oneMatch = true; oneActive = true; + netCapability.getValue().setActive(facing); break; } } - netCapability.getKey().setActive(oneMatch); } - if (oneActive) this.setConnected(facing, false); + if (canOpenConnection && oneActive) this.setConnected(facing, false); } private void setAllIdle(EnumFacing facing) { for (var netCapability : netCapabilities.entrySet()) { netCapability.getValue().setIdle(facing); - netCapability.getKey().setActive(false); } } @@ -439,10 +447,10 @@ protected void initialize() { boolean firstNode = true; for (WorldPipeNetNode node : WorldPipeBlock.getNodesForTile(this)) { this.addCapabilities(node.getNet().getNewCapabilityObjects(node)); - this.netCapabilities.put(node, new PipeCapabilityWrapper(node.getNet().getTargetCapabilities())); + this.netCapabilities.put(node, new PipeCapabilityWrapper(node)); String netName = node.getNet().mapName; netLogicDatas.put(netName, node.getData()); - var listener = node.getData().new LogicDataListener( + var listener = node.getData().createListener( (e, r, f) -> writeCustomData(UPDATE_PIPE_LOGIC, buf -> { buf.writeString(netName); buf.writeString(e.getName()); @@ -464,6 +472,7 @@ protected void initialize() { this.listeners.trim(); this.capabilities.trim(); this.netCapabilities.trim(); + updateActiveStatus(null, false); } } diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java index 449211fc581..8086db069b4 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java @@ -5,6 +5,8 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; +import org.jetbrains.annotations.NotNull; + public class WorldNetNode extends NetNode { private BlockPos pos; @@ -14,7 +16,7 @@ public WorldNetNode(WorldNet net) { } @Override - public WorldNet getNet() { + public @NotNull WorldNet getNet() { return (WorldNet) super.getNet(); } diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index 910c71bf7fd..541492e7123 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -52,14 +52,19 @@ public boolean generatesStructure(IPipeStructure structure) { } @Override - public void addToNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, IPipeStructure structure) { + List list = new ObjectArrayList<>(); for (IPipeNetMaterialProperty p : properties.values()) { - if (p.supportsStructure(structure)) p.addToNet(world, pos, structure); + if (p.supportsStructure(structure)) { + WorldPipeNetNode node = p.getOrCreateFromNet(world, pos, structure); + if (node != null) list.add(node); + } } + return list; } @Override - public Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { List list = new ObjectArrayList<>(); for (IPipeNetMaterialProperty p : properties.values()) { if (p.supportsStructure(structure)) { @@ -95,7 +100,8 @@ public void verifyProperty(MaterialProperties properties) { public interface IPipeNetMaterialProperty extends IMaterialProperty { - void addToNet(World world, BlockPos pos, IPipeStructure structure); + @Nullable + WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure); @Nullable WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure); diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index b5501a2c9f2..a0d98bc351b 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -971,7 +971,7 @@ public static BitSet setToMask(@NotNull EnumSet enumSet) { return mask; } - @Contract(pure = true, value = "->new") + @Contract(pure = true, value = "-> new") @NotNull public static Set createWeakHashSet() { return Collections.newSetFromMap(new WeakHashMap<>()); diff --git a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java index 94bd282b681..77a8bc17f91 100644 --- a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java @@ -9,6 +9,7 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.cache.ColorQuadCache; import gregtech.client.renderer.pipe.cache.StructureQuadCache; +import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.util.CacheKey; @@ -59,7 +60,9 @@ public abstract class AbstractPipeModel implements IBakedMod public static UnlistedByteProperty CONNECTION_MASK_PROPERTY = new UnlistedByteProperty("connection_mask"); public static UnlistedByteProperty CLOSED_MASK_PROPERTY = new UnlistedByteProperty("closed_mask"); public static UnlistedByteProperty BLOCKED_MASK_PROPERTY = new UnlistedByteProperty("blocked_mask"); + public static UnlistedIntegerProperty COLOR_PROPERTY = new UnlistedIntegerProperty("color"); + public static final UnlistedPropertyMaterial MATERIAL_PROPERTY = new UnlistedPropertyMaterial("material"); protected final Object2ObjectOpenHashMap frameCache = new Object2ObjectOpenHashMap<>(); protected final Object2ObjectOpenHashMap pipeCache = new Object2ObjectOpenHashMap<>(); @@ -75,12 +78,16 @@ public AbstractPipeModel(ModelResourceLocation loc) { if (side == null && state instanceof IExtendedBlockState ext) { return getQuads(toKey(ext), safeByte(ext.getValue(CONNECTION_MASK_PROPERTY)), safeByte(ext.getValue(CLOSED_MASK_PROPERTY)), safeByte(ext.getValue(BLOCKED_MASK_PROPERTY)), - safeInt(ext.getValue(COLOR_PROPERTY)), ext.getValue(FRAME_MATERIAL_PROPERTY), + computeColorData(ext), ext.getValue(FRAME_MATERIAL_PROPERTY), safeByte(ext.getValue(FRAME_MASK_PROPERTY))); } return Collections.emptyList(); } + protected ColorData computeColorData(IExtendedBlockState ext) { + return new ColorData(safeInt(ext.getValue(COLOR_PROPERTY))); + } + protected static byte safeByte(@Nullable Byte abyte) { return abyte == null ? 0 : abyte; } @@ -89,7 +96,7 @@ protected static int safeInt(@Nullable Integer integer) { return integer == null ? 0 : integer; } - public @NotNull List getQuads(K key, byte connectionMask, byte closedMask, byte blockedMask, int argb, + public @NotNull List getQuads(K key, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, @Nullable Material frameMaterial, byte frameMask) { List quads = new ObjectArrayList<>(); @@ -99,7 +106,7 @@ protected static int safeInt(@Nullable Integer integer) { pipeCache.put(key, cache); } cache.addToList(quads, connectionMask, closedMask, - blockedMask, argb); + blockedMask, data); if (frameMaterial != null) { ResourceLocation rl = MaterialIconType.frameGt.getBlockTexturePath(frameMaterial.getMaterialIconSet()); @@ -109,7 +116,7 @@ protected static int safeInt(@Nullable Integer integer) { .createFrame(Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(rl.toString()))); frameCache.put(rl, frame); } - List frameQuads = frame.getQuads(GTUtility.convertRGBtoARGB(frameMaterial.getMaterialRGB())); + List frameQuads = frame.getQuads(new ColorData(GTUtility.convertRGBtoARGB(frameMaterial.getMaterialRGB()))); for (int i = 0; i < 6; i++) { if ((frameMask & (1 << i)) > 0) { quads.add(frameQuads.get(i)); diff --git a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java index 3b7859d2aee..2a7188b7b75 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java @@ -7,6 +7,7 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.cache.ActivableSQC; import gregtech.client.renderer.pipe.cache.StructureQuadCache; +import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.util.ActivableCacheKey; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -69,22 +70,22 @@ public ActivablePipeModel(@NotNull Supplier inTex, @NotNull S @Override public @NotNull List getQuads(ActivableCacheKey key, byte connectionMask, byte closedMask, - byte blockedMask, int argb, @Nullable Material frameMaterial, + byte blockedMask, ColorData data, @Nullable Material frameMaterial, byte frameMask) { boolean bloomLayer = getCurrentRenderLayer() == BloomEffectUtil.getEffectiveBloomLayer(); // don't render the main shape to the bloom layer List quads = bloomLayer ? new ObjectArrayList<>() : - super.getQuads(key, connectionMask, closedMask, blockedMask, argb, frameMaterial, frameMask); + super.getQuads(key, connectionMask, closedMask, blockedMask, data, frameMaterial, frameMask); if (!bloomLayer && (!key.isActive() || !allowActive())) { - ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, argb, false); + ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, data, false); } else { if (emissiveActive && bloomLayer) { - ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, argb, true); + ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, data, true); // TODO bake this into the original quads quads = quads.stream().map(RenderUtil::makeEmissive).collect(Collectors.toList()); } else if (!emissiveActive && getCurrentRenderLayer() == BlockRenderLayer.CUTOUT_MIPPED) { - ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, argb, true); + ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, data, true); } } return quads; @@ -127,7 +128,7 @@ public boolean allowActive() { WorldPipeBlock block = WorldPipeBlock.getBlockFromItem(stack); if (block == null) return null; return new PipeItemModel<>(this, new ActivableCacheKey(block.getStructure().getRenderThickness(), false), - PipeTileEntity.DEFAULT_COLOR); + new ColorData(PipeTileEntity.DEFAULT_COLOR)); } public static void registerModels(IRegistry registry) { diff --git a/src/main/java/gregtech/client/renderer/pipe/CableModel.java b/src/main/java/gregtech/client/renderer/pipe/CableModel.java index af05023efc7..f3b02aecfc9 100644 --- a/src/main/java/gregtech/client/renderer/pipe/CableModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/CableModel.java @@ -7,6 +7,7 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.cache.ExtraCappedSQC; import gregtech.client.renderer.pipe.cache.StructureQuadCache; +import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.util.CacheKey; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -32,6 +33,8 @@ @SideOnly(Side.CLIENT) public class CableModel extends AbstractPipeModel { + public static final int DEFAULT_INSULATION_COLOR = 0xFF404040; + private static final ResourceLocation loc = GTUtility.gregtechId("block/cable"); public static final CableModel INSTANCE = new CableModel("wire"); @@ -64,6 +67,22 @@ public CableModel(String variant) { this(null, null, variant); } + @Override + protected ColorData computeColorData(IExtendedBlockState ext) { + if (insulationTex == null) return super.computeColorData(ext); + Material material = ext.getValue(AbstractPipeModel.MATERIAL_PROPERTY); + int insulationColor = safeInt(ext.getValue(COLOR_PROPERTY)); + if (material != null) { + int matColor = GTUtility.convertRGBtoARGB(material.getMaterialRGB()); + if (insulationColor == 0 || insulationColor == matColor) { + // unpainted + insulationColor = DEFAULT_INSULATION_COLOR; + } + return new ColorData(matColor, insulationColor); + } + return new ColorData(0, 0); + } + @Override public SpriteInformation getParticleSprite(@Nullable Material material) { return wireTex.get(); @@ -97,7 +116,8 @@ protected StructureQuadCache constructForKey(CacheKey key) { if (block == null) return null; Material mater = block instanceof PipeMaterialBlock mat ? mat.getMaterialForStack(stack) : null; return new PipeItemModel<>(this, new CacheKey(block.getStructure().getRenderThickness()), - mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : PipeTileEntity.DEFAULT_COLOR); + new ColorData(mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : + PipeTileEntity.DEFAULT_COLOR, DEFAULT_INSULATION_COLOR)); } public static void registerModels(IRegistry registry) { diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java index b926c823040..3be48cce4b8 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java @@ -1,5 +1,6 @@ package gregtech.client.renderer.pipe; +import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.util.CacheKey; import net.minecraft.block.state.IBlockState; @@ -65,17 +66,17 @@ public class PipeItemModel implements IBakedModel { private final AbstractPipeModel basis; private final K key; - private final int argb; + private final ColorData data; - public PipeItemModel(AbstractPipeModel basis, K key, int argb) { + public PipeItemModel(AbstractPipeModel basis, K key, ColorData data) { this.basis = basis; this.key = key; - this.argb = argb; + this.data = data; } @Override public @NotNull List getQuads(IBlockState state, EnumFacing side, long rand) { - return basis.getQuads(key, (byte) 0b1100, (byte) 0b0, (byte) 0b0, argb, null, (byte) 0b0); + return basis.getQuads(key, (byte) 0b1100, (byte) 0b0, (byte) 0b0, data, null, (byte) 0b0); } @Override diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java index 1049f8be689..1e0d48c87ba 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java @@ -1,6 +1,5 @@ package gregtech.client.renderer.pipe; -import gregtech.api.block.UnlistedPropertyMaterial; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; @@ -10,6 +9,7 @@ import gregtech.client.renderer.pipe.cache.BlockableSQC; import gregtech.client.renderer.pipe.cache.RestrictiveSQC; import gregtech.client.renderer.pipe.cache.StructureQuadCache; +import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.util.PipeSpriteWoodClarifier; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -28,8 +28,6 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,8 +36,6 @@ public class PipeModel extends AbstractPipeModel { private static final ResourceLocation loc = GTUtility.gregtechId("block/pipe_material"); - public static final UnlistedPropertyMaterial MATERIAL_PROPERTY = new UnlistedPropertyMaterial("material"); - public static final PipeModel[] INSTANCES = new PipeModel[7]; public static final PipeModel[] RESTRICTIVE_INSTANCES = new PipeModel[INSTANCES.length]; @@ -123,7 +119,8 @@ protected PipeItemModel getItemModel(@NotNull ItemStack stack, Wor boolean wood = block instanceof PipeMaterialBlock mat && (mater = mat.getMaterialForStack(stack)) != null && mater.hasProperty(PropertyKey.WOOD); return new PipeItemModel<>(this, new WoodCacheKey(block.getStructure().getRenderThickness(), wood), - mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : PipeTileEntity.DEFAULT_COLOR); + new ColorData(mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : + PipeTileEntity.DEFAULT_COLOR)); } public static void registerModels(IRegistry registry) { diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java index 64243ed1742..32539f51f54 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java @@ -1,6 +1,7 @@ package gregtech.client.renderer.pipe.cache; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -26,11 +27,13 @@ protected ActivableSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteIn super(helper, endTex, sideTex); this.overlayTex = overlayTex; this.overlayActiveTex = overlayActiveTex; + if (helper.getLayerCount() < 2) throw new IllegalStateException("Cannot create an ActivableSQC without 2 or more layers present on the helper!"); } public static @NotNull ActivableSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation overlayTex, SpriteInformation overlayActiveTex) { + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> StructureQuadCache.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); ActivableSQC cache = new ActivableSQC(helper, endTex, sideTex, overlayTex, overlayActiveTex); cache.buildPrototype(); return cache; @@ -48,7 +51,7 @@ protected void buildOverlay(List list) { helper.setTargetSprite(overlayTex); for (EnumFacing facing : EnumFacing.VALUES) { int start = list.size(); - list.addAll(helper.visitTube(facing)); + list.addAll(helper.visitTube(facing, 1)); overlayCoords.put(facing, new SubListAddress(start, list.size())); } } @@ -57,13 +60,13 @@ protected void buildOverlayActive(List list) { helper.setTargetSprite(overlayActiveTex); for (EnumFacing facing : EnumFacing.VALUES) { int start = list.size(); - list.addAll(helper.visitTube(facing)); + list.addAll(helper.visitTube(facing, 1)); overlayActiveCoords.put(facing, new SubListAddress(start, list.size())); } } - public void addOverlay(List list, byte overlayMask, int argb, boolean active) { - List quads = cache.getQuads(argb); + public void addOverlay(List list, byte overlayMask, ColorData data, boolean active) { + List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, overlayMask)) { if (active) { diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java index ca214627eaf..e1b5393a1c5 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java @@ -1,6 +1,7 @@ package gregtech.client.renderer.pipe.cache; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -26,10 +27,12 @@ protected BlockableSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteIn SpriteInformation blockedTex) { super(helper, endTex, sideTex); this.blockedTex = blockedTex; + if (helper.getLayerCount() < 2) throw new IllegalStateException("Cannot create a BlockableSQC without 2 or more layers present on the helper!"); } public static @NotNull BlockableSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation blockedTex) { + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> StructureQuadCache.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); BlockableSQC cache = new BlockableSQC(helper, endTex, sideTex, blockedTex); cache.buildPrototype(); return cache; @@ -46,14 +49,14 @@ protected void buildBlocked(List list) { helper.setTargetSprite(blockedTex); for (EnumFacing facing : EnumFacing.VALUES) { int start = list.size(); - list.addAll(helper.visitTube(facing)); + list.addAll(helper.visitTube(facing, 1)); blockedCoords.put(facing, new SubListAddress(start, list.size())); } } @Override - public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, int argb) { - List quads = cache.getQuads(argb); + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data) { + List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, connectionMask)) { list.addAll(tubeCoords.get(facing).getSublist(quads)); diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java index c0c7f4cb9de..463cb7b3b18 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java @@ -1,12 +1,14 @@ package gregtech.client.renderer.pipe.cache; +import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; + import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.List; @@ -19,23 +21,24 @@ public final class ColorQuadCache { private final List prototypes; - private final Int2ObjectLinkedOpenHashMap> cache; + private final Object2ObjectLinkedOpenHashMap> cache; public ColorQuadCache(List prototypes) { this.prototypes = prototypes; - this.cache = new Int2ObjectLinkedOpenHashMap<>(); + this.cache = new Object2ObjectLinkedOpenHashMap<>(); } - public List getQuads(int argb) { - List existing = cache.getAndMoveToFirst(argb); + public List getQuads(ColorData data) { + List existing = cache.getAndMoveToFirst(data); if (existing == null) { existing = new ObjectArrayList<>(); for (RecolorableBakedQuad quad : prototypes) { - existing.add(quad.withColor(argb)); + existing.add(quad.withColor(data)); } - cache.put(argb, existing); + cache.put(data, existing); if (cache.size() > CACHE_LIMIT) cache.removeLast(); } return existing; } + } diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java index a5a424c818c..5a766238f28 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java @@ -1,6 +1,7 @@ package gregtech.client.renderer.pipe.cache; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -26,10 +27,12 @@ protected ExtraCappedSQC(PipeQuadHelper helper, SpriteInformation endTex, Sprite SpriteInformation extraEndTex) { super(helper, endTex, sideTex); this.extraEndTex = extraEndTex; + if (helper.getLayerCount() < 2) throw new IllegalStateException("Cannot create an ExtraCappedSQC without 2 or more layers present on the helper!"); } public static @NotNull ExtraCappedSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation extraEndTex) { + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> StructureQuadCache.capOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); ExtraCappedSQC cache = new ExtraCappedSQC(helper, endTex, sideTex, extraEndTex); cache.buildPrototype(); return cache; @@ -46,14 +49,14 @@ protected void buildExtraCapper(List list) { helper.setTargetSprite(extraEndTex); for (EnumFacing facing : EnumFacing.VALUES) { int start = list.size(); - list.addAll(helper.visitTube(facing)); + list.add(helper.visitCapper(facing, 1)); extraCapperCoords.put(facing, new SubListAddress(start, list.size())); } } @Override - public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, int argb) { - List quads = cache.getQuads(argb); + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data) { + List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, connectionMask)) { list.addAll(tubeCoords.get(facing).getSublist(quads)); diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java index fe09d954bc1..ebabb9c985b 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java @@ -1,6 +1,7 @@ package gregtech.client.renderer.pipe.cache; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -26,11 +27,14 @@ protected RestrictiveSQC(PipeQuadHelper helper, SpriteInformation endTex, Sprite SpriteInformation blockedTex, SpriteInformation restrictiveTex) { super(helper, endTex, sideTex, blockedTex); this.restrictiveTex = restrictiveTex; + if (helper.getLayerCount() < 3) throw new IllegalStateException("Cannot create a RestrictiveSQC without 3 or more layers present on the helper!"); } public static @NotNull RestrictiveSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation blockedTex, SpriteInformation restrictiveTex) { + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> StructureQuadCache.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_2), + (facing, x1, y1, z1, x2, y2, z2) -> StructureQuadCache.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); RestrictiveSQC sqc = new RestrictiveSQC(helper, endTex, sideTex, blockedTex, restrictiveTex); sqc.buildPrototype(); return sqc; @@ -47,14 +51,14 @@ protected void buildRestrictive(List list) { helper.setTargetSprite(restrictiveTex); for (EnumFacing facing : EnumFacing.VALUES) { int start = list.size(); - list.addAll(helper.visitTube(facing)); + list.addAll(helper.visitTube(facing, 2)); restrictiveCoords.put(facing, new SubListAddress(start, list.size())); } } @Override - public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, int argb) { - List quads = cache.getQuads(argb); + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data) { + List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, connectionMask)) { list.addAll(tubeCoords.get(facing).getSublist(quads)); diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java index f5f31c53645..fd38187e504 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java @@ -1,6 +1,8 @@ package gregtech.client.renderer.pipe.cache; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.quad.ColorData; +import gregtech.client.renderer.pipe.quad.OverlayLayerDefinition; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -12,7 +14,11 @@ import com.github.bsideup.jabel.Desugar; import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.util.vector.Vector3f; import java.util.EnumMap; import java.util.List; @@ -20,6 +26,9 @@ @SideOnly(Side.CLIENT) public class StructureQuadCache { + public static final float OVERLAY_DIST_1 = 0.001f; + public static final float OVERLAY_DIST_2 = 0.002f; + protected final PipeQuadHelper helper; protected ColorQuadCache cache; @@ -37,11 +46,12 @@ protected StructureQuadCache(PipeQuadHelper helper, SpriteInformation endTex, Sp this.helper = helper; this.endTex = endTex; this.sideTex = sideTex; + if (helper.getLayerCount() < 1) throw new IllegalStateException("Cannot create an SQC without at least one layer present on the helper!"); } public static @NotNull StructureQuadCache create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex) { - StructureQuadCache cache = new StructureQuadCache(helper, endTex, sideTex); + StructureQuadCache cache = new StructureQuadCache(helper.initialize(), endTex, sideTex); cache.buildPrototype(); return cache; } @@ -95,8 +105,8 @@ protected void buildCapperClosed(List list) { } } - public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, int argb) { - List quads = cache.getQuads(argb); + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data) { + List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, connectionMask)) { list.addAll(tubeCoords.get(facing).getSublist(quads)); @@ -118,4 +128,26 @@ protected record SubListAddress(int startInclusive, int endExclusive) { return list.subList(startInclusive, endExclusive); } } + + public static ImmutablePair capOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { + if (facing == null) return PipeQuadHelper.pair(x1 - g, y1 - g, z1 - g, x2 + g, y2 + g, z2 + g); + return switch (facing.getAxis()) { + case X -> PipeQuadHelper.pair(x1 - g, y1, z1, x2 + g, y2, z2); + case Y -> PipeQuadHelper.pair(x1, y1 - g, z1, x2, y2 + g, z2); + case Z -> PipeQuadHelper.pair(x1, y1, z1 - g, x2, y2, z2 + g); + }; + } + + public static ImmutablePair tubeOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { + if (facing == null) return PipeQuadHelper.pair(x1, y1, z1, x2, y2, z2); + return switch (facing.getAxis()) { + case X -> PipeQuadHelper.pair(x1, y1 - g, z1 - g, x2, y2 + g, z2 + g); + case Y -> PipeQuadHelper.pair(x1 - g, y1, z1 - g, x2 + g, y2, z2 + g); + case Z -> PipeQuadHelper.pair(x1 - g, y1 - g, z1, x2 + g, y2 + g, z2); + }; + } + + public static ImmutablePair fullOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { + return PipeQuadHelper.pair(x1 - g, y1 - g, z1 - g, x2 + g, y2 + g, z2 + g); + } } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java b/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java new file mode 100644 index 00000000000..b650383a14a --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java @@ -0,0 +1,6 @@ +package gregtech.client.renderer.pipe.quad; + +import com.github.bsideup.jabel.Desugar; + +@Desugar +public record ColorData(int... colorsARGB) {} diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java b/src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java new file mode 100644 index 00000000000..b6a9f468a4e --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java @@ -0,0 +1,13 @@ +package gregtech.client.renderer.pipe.quad; + +import net.minecraft.util.EnumFacing; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.util.vector.Vector3f; + +@FunctionalInterface +public interface OverlayLayerDefinition { + + ImmutablePair computeBox(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2); +} diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java index 8d8363dc31d..f3c7494d307 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -15,7 +15,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; -import org.jetbrains.annotations.Range; +import org.jetbrains.annotations.Contract; import org.lwjgl.util.vector.Vector3f; import java.util.EnumMap; @@ -28,33 +28,68 @@ public final class PipeQuadHelper { private SpriteInformation targetSprite; - private final Pair coreBox; - private final EnumMap> sideBoxes = new EnumMap<>(EnumFacing.class); + private final List> coreBoxList = new ObjectArrayList<>(); + private final List>> sideBoxesList = new ObjectArrayList<>(); - public PipeQuadHelper(float x, float y, float z, int argb, float small, float large) { + private float[] definition; + + public static ImmutablePair pair(float x1, float y1, float z1, float x2, float y2, float z2) { + return ImmutablePair.of(new Vector3f(x1, y1, z1), new Vector3f(x2, y2, z2)); + } + + public PipeQuadHelper(float x, float y, float z, float small, float large) { float xS = (x + small) * 16; float xL = (x + large) * 16; float yS = (y + small) * 16; float yL = (y + large) * 16; float zS = (z + small) * 16; float zL = (z + large) * 16; - coreBox = ImmutablePair.of(new Vector3f(xS, yS, zS), new Vector3f(xL, yL, zL)); - sideBoxes.put(EnumFacing.DOWN, ImmutablePair.of(new Vector3f(xS, 0, zS), new Vector3f(xL, yS, zL))); - sideBoxes.put(EnumFacing.UP, ImmutablePair.of(new Vector3f(xS, yL, zS), new Vector3f(xL, 16, zL))); - sideBoxes.put(EnumFacing.NORTH, ImmutablePair.of(new Vector3f(xS, yS, 0), new Vector3f(xL, yL, zS))); - sideBoxes.put(EnumFacing.SOUTH, ImmutablePair.of(new Vector3f(xS, yS, zL), new Vector3f(xL, yL, 16))); - sideBoxes.put(EnumFacing.WEST, ImmutablePair.of(new Vector3f(0, yS, zS), new Vector3f(xS, yL, zL))); - sideBoxes.put(EnumFacing.EAST, ImmutablePair.of(new Vector3f(xL, yS, zS), new Vector3f(16, yL, zL))); + definition = new float[] {xS, xL, yS, yL, zS, zL}; + } + + @Contract("_ -> this") + public PipeQuadHelper initialize(OverlayLayerDefinition... overlayLayers) { + if (definition != null) { + float xS = definition[0]; + float xL = definition[1]; + float yS = definition[2]; + float yL = definition[3]; + float zS = definition[4]; + float zL = definition[5]; + definition = null; + generateBox(xS, xL, yS, yL, zS, zL, (facing, x1, y1, z1, x2, y2, z2) -> + ImmutablePair.of(new Vector3f(x1, y1, z1), new Vector3f(x2, y2, z2))); + for (OverlayLayerDefinition definition : overlayLayers) { + generateBox(xS, xL, yS, yL, zS, zL, definition); + } + } + return this; + } + + public int getLayerCount() { + return coreBoxList.size(); } - public static PipeQuadHelper create(float thickness, double x, double y, double z, int argb) { + private void generateBox(float xS, float xL, float yS, float yL, float zS, float zL, OverlayLayerDefinition definition) { + coreBoxList.add(definition.computeBox(null, xS, yS, zS, xL, yL, zL)); + EnumMap> sideBoxes = new EnumMap<>(EnumFacing.class); + sideBoxes.put(EnumFacing.DOWN, definition.computeBox(EnumFacing.DOWN, xS, 0, zS, xL, yS, zL)); + sideBoxes.put(EnumFacing.UP, definition.computeBox(EnumFacing.UP, xS, yL, zS, xL, 16, zL)); + sideBoxes.put(EnumFacing.NORTH, definition.computeBox(EnumFacing.NORTH, xS, yS, 0, xL, yL, zS)); + sideBoxes.put(EnumFacing.SOUTH, definition.computeBox(EnumFacing.SOUTH, xS, yS, zL, xL, yL, 16)); + sideBoxes.put(EnumFacing.WEST, definition.computeBox(EnumFacing.WEST, 0, yS, zS, xS, yL, zL)); + sideBoxes.put(EnumFacing.EAST, definition.computeBox(EnumFacing.EAST, xL, yS, zS, 16, yL, zL)); + sideBoxesList.add(sideBoxes); + } + + public static PipeQuadHelper create(float thickness, double x, double y, double z) { float small = 0.5f - thickness / 2; float large = 0.5f + thickness / 2; - return new PipeQuadHelper((float) x, (float) y, (float) z, argb, small, large); + return new PipeQuadHelper((float) x, (float) y, (float) z, small, large); } public static PipeQuadHelper create(float thickness) { - return create(thickness, 0, 0, 0, 0xFFFFFFFF); + return create(thickness, 0, 0, 0); } public void setTargetSprite(SpriteInformation sprite) { @@ -62,12 +97,20 @@ public void setTargetSprite(SpriteInformation sprite) { } public RecolorableBakedQuad visitCore(EnumFacing facing) { - return visitQuad(facing, coreBox, uvMapper(0)); + return visitCore(facing, 0); + } + + public RecolorableBakedQuad visitCore(EnumFacing facing, int overlayLayer) { + return visitQuad(facing, coreBoxList.get(overlayLayer), uvMapper(0)); } public List visitTube(EnumFacing facing) { + return visitTube(facing, 0); + } + + public List visitTube(EnumFacing facing, int overlayLayer) { List list = new ObjectArrayList<>(); - Pair box = sideBoxes.get(facing); + Pair box = sideBoxesList.get(overlayLayer).get(facing); switch (facing.getAxis()) { case X -> { UVMapper mapper = uvMapper(0); @@ -94,7 +137,11 @@ public List visitTube(EnumFacing facing) { } public RecolorableBakedQuad visitCapper(EnumFacing facing) { - return visitQuad(facing, sideBoxes.get(facing), uvMapper(0)); + return visitCapper(facing, 0); + } + + public RecolorableBakedQuad visitCapper(EnumFacing facing, int overlayLayer) { + return visitQuad(facing, sideBoxesList.get(overlayLayer).get(facing), uvMapper(0)); } public RecolorableBakedQuad visitQuad(EnumFacing normal, Pair box, UVMapper uv) { @@ -122,7 +169,7 @@ private static BlockFaceUV uv(EnumFacing normal, Pair box, i public static List createFrame(TextureAtlasSprite sprite) { PipeQuadHelper helper = PipeQuadHelper.create(0.998f); - helper.setTargetSprite(new SpriteInformation(sprite, true)); + helper.setTargetSprite(new SpriteInformation(sprite, 0)); List list = new ObjectArrayList<>(); for (EnumFacing facing : EnumFacing.VALUES) { list.add(helper.visitCore(facing)); diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java index b9110d60bdf..ffcdfbda141 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java @@ -25,8 +25,9 @@ public RecolorableBakedQuad(float[][][] unpackedData, int tint, EnumFacing orien this.spriteInformation = texture; } - public RecolorableBakedQuad withColor(int argb) { + public RecolorableBakedQuad withColor(ColorData data) { if (!spriteInformation.colorable()) return this; + int argb = data.colorsARGB()[spriteInformation.colorID()]; float[][][] newData = new float[4][format.getElementCount()][]; diff --git a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java index 284f34d77df..76b6dd9869e 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java @@ -8,4 +8,8 @@ @SideOnly(Side.CLIENT) @Desugar -public record SpriteInformation(TextureAtlasSprite sprite, boolean colorable) {} +public record SpriteInformation(TextureAtlasSprite sprite, int colorID) { + public boolean colorable() { + return colorID >= 0; + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java index e964e19c7a0..8f33845d353 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java @@ -7,13 +7,13 @@ import java.util.function.Supplier; public class SpriteInformationWrapper implements Supplier, Consumer, - BiConsumer { + BiConsumer { private SpriteInformation sprite; @Override - public void accept(TextureAtlasSprite sprite, Boolean colorable) { - accept(new SpriteInformation(sprite, colorable)); + public void accept(TextureAtlasSprite sprite, Integer colorID) { + accept(new SpriteInformation(sprite, colorID)); } @Override diff --git a/src/main/java/gregtech/client/renderer/texture/Textures.java b/src/main/java/gregtech/client/renderer/texture/Textures.java index 18063be72f6..09e64603a00 100644 --- a/src/main/java/gregtech/client/renderer/texture/Textures.java +++ b/src/main/java/gregtech/client/renderer/texture/Textures.java @@ -632,30 +632,30 @@ public static void register(TextureMap textureMap) { iconRegister.registerIcons(textureMap); } - WIRE.accept(textureMap.registerSprite(gregtechId("blocks/cable/wire")), true); - INSULATION_FULL.accept(textureMap.registerSprite(gregtechId("blocks/cable/insulation_full")), false); + WIRE.accept(textureMap.registerSprite(gregtechId("blocks/cable/wire")), 0); + INSULATION_FULL.accept(textureMap.registerSprite(gregtechId("blocks/cable/insulation_full")), 1); for (int i = 0; i < INSULATION.length; i++) { - INSULATION[i].accept(textureMap.registerSprite(gregtechId("blocks/cable/insulation_" + i)), false); + INSULATION[i].accept(textureMap.registerSprite(gregtechId("blocks/cable/insulation_" + i)), 1); } - RESTRICTIVE_OVERLAY.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_restrictive")), false); - PIPE_TINY.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_tiny_in")), true); - PIPE_SMALL.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_small_in")), true); - PIPE_NORMAL.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_normal_in")), true); - PIPE_LARGE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_large_in")), true); - PIPE_HUGE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_huge_in")), true); - PIPE_QUADRUPLE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_quadruple_in")), true); - PIPE_NONUPLE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_nonuple_in")), true); - PIPE_SIDE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_side")), true); - PIPE_SMALL_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_small_in_wood")), true); - PIPE_NORMAL_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_normal_in_wood")), true); - PIPE_LARGE_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_large_in_wood")), true); - PIPE_SIDE_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_side_wood")), true); + RESTRICTIVE_OVERLAY.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_restrictive")), -1); + PIPE_TINY.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_tiny_in")), 0); + PIPE_SMALL.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_small_in")), 0); + PIPE_NORMAL.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_normal_in")), 0); + PIPE_LARGE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_large_in")), 0); + PIPE_HUGE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_huge_in")), 0); + PIPE_QUADRUPLE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_quadruple_in")), 0); + PIPE_NONUPLE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_nonuple_in")), 0); + PIPE_SIDE.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_side")), 0); + PIPE_SMALL_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_small_in_wood")), 0); + PIPE_NORMAL_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_normal_in_wood")), 0); + PIPE_LARGE_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_large_in_wood")), 0); + PIPE_SIDE_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_side_wood")), 0); // Fluid Pipe Blocked overlay textures // PIPE_BLOCKED_OVERLAY = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked")); PIPE_BLOCKED_OVERLAY_UP.accept(textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_up")), - false); + -1); // PIPE_BLOCKED_OVERLAY_DOWN = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_down")); // PIPE_BLOCKED_OVERLAY_LEFT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_left")); // PIPE_BLOCKED_OVERLAY_RIGHT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_right")); @@ -671,24 +671,24 @@ public static void register(TextureMap textureMap) { // PIPE_BLOCKED_OVERLAY_LR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_lr")); OPTICAL_PIPE_IN.accept(textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_in")), false); + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_in")), -1); OPTICAL_PIPE_SIDE.accept(textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side")), false); + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side")), -1); OPTICAL_PIPE_SIDE_OVERLAY.accept(textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side_overlay")), true); + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side_overlay")), 0); OPTICAL_PIPE_SIDE_OVERLAY_ACTIVE.accept(textureMap .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_side_overlay_active")), - true); + 0); LASER_PIPE_IN.accept( - textureMap.registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_in")), false); + textureMap.registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_in")), -1); LASER_PIPE_SIDE.accept(textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side")), false); + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side")), -1); LASER_PIPE_OVERLAY.accept(textureMap - .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side_overlay")), true); + .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side_overlay")), 0); LASER_PIPE_OVERLAY_EMISSIVE.accept(textureMap .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_laser_side_overlay_emissive")), - true); + 0); for (MaterialIconSet iconSet : MaterialIconSet.ICON_SETS.values()) { textureMap.registerSprite(MaterialIconType.frameGt.getBlockTexturePath(iconSet)); diff --git a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java index b727b01f55d..788f630fcca 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java @@ -23,14 +23,15 @@ public final class LaserNetHandler implements IPipeNetNodeHandler { public static final LaserNetHandler INSTANCE = new LaserNetHandler(); @Override - public void addToNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof LaserStructure) { - WorldLaserNet.getWorldNet(world).getOrCreateNode(pos); + return Collections.singletonList(WorldLaserNet.getWorldNet(world).getOrCreateNode(pos)); } + return Collections.emptyList(); } @Override - public Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof LaserStructure) { WorldPipeNetNode node = WorldLaserNet.getWorldNet(world).getNode(pos); if (node != null) return Collections.singletonList(node); diff --git a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java index 76d2471c7a6..16353cd7702 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java @@ -23,14 +23,15 @@ public final class OpticalNetHandler implements IPipeNetNodeHandler { public static final OpticalNetHandler INSTANCE = new OpticalNetHandler(); @Override - public void addToNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof OpticalStructure) { - WorldOpticalNet.getWorldNet(world).getOrCreateNode(pos); + return Collections.singletonList(WorldOpticalNet.getWorldNet(world).getOrCreateNode(pos)); } + return Collections.emptyList(); } @Override - public Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof OpticalStructure) { WorldPipeNetNode node = WorldOpticalNet.getWorldNet(world).getNode(pos); if (node != null) return Collections.singletonList(node); diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 57317068e08..58274501404 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -23,7 +23,7 @@ import gregtech.api.util.function.TriConsumer; import gregtech.common.pipelike.block.cable.CableStructure; import gregtech.common.pipelike.block.pipe.PipeStructure; -import gregtech.common.pipelike.net.energy.LossAbsoluteLogic; +import gregtech.common.pipelike.net.energy.VoltageLossLogic; import gregtech.common.pipelike.net.energy.SuperconductorLogic; import gregtech.common.pipelike.net.energy.VoltageLimitLogic; import gregtech.common.pipelike.net.energy.WorldEnergyNet; @@ -154,16 +154,20 @@ public void verifyProperty(MaterialProperties properties) { } @Override - public void addToNet(World world, BlockPos pos, IPipeStructure structure) { + @Nullable + public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof CableStructure) { WorldPipeNetNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); mutateData(node.getData(), structure); + return node; } else if (structure instanceof PipeStructure pipe) { long amperage = amperageLimit * pipe.material() / 2; - if (amperage == 0) return; // skip pipes that are too small + if (amperage == 0) return null; // skip pipes that are too small WorldPipeNetNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); mutateData(node.getData(), pipe); + return node; } + return null; } @Override @@ -174,7 +178,7 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { boolean insulated = cable.partialBurnStructure() != null; // insulated cables cool down half as fast float coolingFactor = (float) (Math.sqrt(cable.material()) / (insulated ? 8 : 4)); - data.setLogicEntry(LossAbsoluteLogic.INSTANCE.getWith(loss)) + data.setLogicEntry(VoltageLossLogic.INSTANCE.getWith(loss)) .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) @@ -189,7 +193,7 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { if (amperage == 0) return; // skip pipes that are too small long loss = getLoss(structure); float coolingFactor = (float) Math.sqrt((double) pipe.material() / (4 + pipe.channelCount())); - data.setLogicEntry(LossAbsoluteLogic.INSTANCE.getWith(loss)) + data.setLogicEntry(VoltageLossLogic.INSTANCE.getWith(loss)) .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index f0855ca2713..caf68afa959 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -181,11 +181,14 @@ public void verifyProperty(MaterialProperties properties) { } @Override - public void addToNet(World world, BlockPos pos, IPipeStructure structure) { + @Nullable + public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof PipeStructure) { WorldPipeNetNode node = WorldFluidNet.getWorldNet(world).getOrCreateNode(pos); mutateData(node.getData(), structure); + return node; } + return null; } @Override diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index 408d482e7cd..014d64fc000 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -67,11 +67,14 @@ public void verifyProperty(MaterialProperties properties) { } @Override - public void addToNet(World world, BlockPos pos, IPipeStructure structure) { + @Nullable + public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof PipeStructure) { WorldPipeNetNode node = WorldItemNet.getWorldNet(world).getOrCreateNode(pos); mutateData(node.getData(), structure); + return node; } + return null; } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index ae4d27b1848..55ae45826c5 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -11,7 +11,6 @@ import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.AbstractTraverseData; -import gregtech.api.graphnet.traverse.util.FlatLossOperator; import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; import gregtech.api.util.GTUtility; import gregtech.common.pipelikeold.cable.net.EnergyGroupData; @@ -59,22 +58,21 @@ public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowRea if (voltage < pathVoltage) overVoltageInformation.put(node, new OverVoltageInformation(voltage, flowReachingNode)); } + TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + if (!node.getData().getLogicEntryDefaultable(SuperconductorLogic.INSTANCE) + .canSuperconduct(temperatureLogic == null ? TemperatureLogic.DEFAULT_TEMPERATURE : + temperatureLogic.getTemperature(getQueryTick()))) { + pathVoltage -= node.getData().getLogicEntryDefaultable(VoltageLossLogic.INSTANCE).getValue(); + } NodeLossCache.Key key = NodeLossCache.key(node, this); NodeLossResult result = NodeLossCache.getLossResult(key); if (result != null) { return result.getLossFunction(); } else { - TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); result = temperatureLogic == null ? null : temperatureLogic.getLossResult(getQueryTick()); if (result == null) { - if (node.getData().getLogicEntryDefaultable(SuperconductorLogic.INSTANCE) - .canSuperconduct(temperatureLogic == null ? TemperatureLogic.DEFAULT_TEMPERATURE : - temperatureLogic.getTemperature(getQueryTick()))) { - return ReversibleLossOperator.IDENTITY; - } - return new FlatLossOperator( - node.getData().getLogicEntryDefaultable(LossAbsoluteLogic.INSTANCE).getValue()); + return ReversibleLossOperator.IDENTITY; } if (result.hasPostAction()) NodeLossCache.registerLossResult(key, result); return result.getLossFunction(); @@ -92,7 +90,8 @@ public void handleOverflow(WorldPipeNetNode node, long overflow) { @Override public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachingDestination) { this.pathVoltage = (long) GTUtility.geometricMean(pathVoltage, - overVoltageInformation.values().stream().mapToDouble(o -> (double) o.voltageCap).toArray()); + overVoltageInformation.values().stream().filter(o -> o.voltageCap < this.pathVoltage) + .mapToDouble(o -> (double) o.voltageCap).toArray()); overVoltageInformation.forEach((k, v) -> v.doHeating(k, pathVoltage, getQueryTick())); long availableFlow = flowReachingDestination; for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { diff --git a/src/main/java/gregtech/common/pipelike/net/energy/LossAbsoluteLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java similarity index 53% rename from src/main/java/gregtech/common/pipelike/net/energy/LossAbsoluteLogic.java rename to src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java index 3589621d041..5fd2ace2c21 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/LossAbsoluteLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java @@ -5,9 +5,9 @@ import org.jetbrains.annotations.NotNull; -public final class LossAbsoluteLogic extends AbstractLongLogicData { +public final class VoltageLossLogic extends AbstractLongLogicData { - public static final LossAbsoluteLogic INSTANCE = new LossAbsoluteLogic().setValue(0); + public static final VoltageLossLogic INSTANCE = new VoltageLossLogic().setValue(0); @Override public @NotNull String getName() { @@ -15,13 +15,13 @@ public final class LossAbsoluteLogic extends AbstractLongLogicData other) { - if (other instanceof LossAbsoluteLogic l) { + public VoltageLossLogic union(INetLogicEntry other) { + if (other instanceof VoltageLossLogic l) { return this.getWith(this.getValue() + l.getValue()); } else return this; } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index 90a4a18881e..6089faaf72c 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -2,6 +2,7 @@ import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNet; @@ -23,23 +24,25 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; import java.util.EnumMap; import java.util.Iterator; -public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler { - - private static final IFluidTankProperties[] EMPTY = new IFluidTankProperties[0]; +public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler, IFluidTankProperties { private final WorldPipeNet net; private @Nullable PipeTileEntity tile; private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); + private final IFluidTankProperties[] properties; private boolean transferring = false; public FluidCapabilityObject(@NotNull N net, WorldPipeNetNode node) { this.net = net; + properties = new IFluidTankProperties[node.getData().getLogicEntryDefaultable(ChannelCountLogic.INSTANCE).getValue()]; + Arrays.fill(properties, this); for (EnumFacing facing : EnumFacing.VALUES) { AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); edge.setData(NetLogicData.union(node.getData(), (NetLogicData) null)); @@ -70,7 +73,7 @@ public void setTile(@Nullable PipeTileEntity tile) { @Override public Capability[] getCapabilities() { - return WorldEnergyNet.CAPABILITIES; + return WorldFluidNet.CAPABILITIES; } @Override @@ -114,7 +117,7 @@ public int fill(FluidStack resource, boolean doFill, EnumFacing side) { @Override public IFluidTankProperties[] getTankProperties() { - return EMPTY; + return properties; } @Override @@ -127,14 +130,47 @@ public FluidStack drain(FluidStack resource, boolean doDrain) { return null; } - protected class Wrapper implements IFluidHandler { + @Override + public FluidStack getContents() { + return null; + } + + @Override + public int getCapacity() { + return Integer.MAX_VALUE; + } + + @Override + public boolean canFill() { + return true; + } + + @Override + public boolean canDrain() { + return false; + } + + @Override + public boolean canFillFluidType(FluidStack fluidStack) { + return true; + } + + @Override + public boolean canDrainFluidType(FluidStack fluidStack) { + return false; + } + + protected class Wrapper implements IFluidHandler, IFluidTankProperties { private final EnumFacing facing; private final AbstractNetFlowEdge buffer; + private final IFluidTankProperties[] properties; public Wrapper(EnumFacing facing, AbstractNetFlowEdge buffer) { this.facing = facing; this.buffer = buffer; + properties = new IFluidTankProperties[FluidCapabilityObject.this.properties.length]; + Arrays.fill(properties, this); } public AbstractNetFlowEdge getBuffer() { @@ -143,7 +179,7 @@ public AbstractNetFlowEdge getBuffer() { @Override public IFluidTankProperties[] getTankProperties() { - return EMPTY; + return properties; } @Override @@ -160,5 +196,35 @@ public FluidStack drain(FluidStack resource, boolean doDrain) { public FluidStack drain(int maxDrain, boolean doDrain) { return null; } + + @Override + public FluidStack getContents() { + return null; + } + + @Override + public int getCapacity() { + return (int) Math.min(Integer.MAX_VALUE, buffer.getThroughput()); + } + + @Override + public boolean canFill() { + return true; + } + + @Override + public boolean canDrain() { + return false; + } + + @Override + public boolean canFillFluidType(FluidStack fluidStack) { + return true; + } + + @Override + public boolean canDrainFluidType(FluidStack fluidStack) { + return false; + } } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index 2c4bbbd8212..eb91ccbc422 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -59,9 +59,10 @@ public FluidTestObject getTestObject() { @Override public boolean prepareForPathWalk(FlowWorldPipeNetPath path, long flow) { + if (flow <= 0) return true; temperatureUpdates.clear(); temperatureUpdates.trim(16); - return flow > 0; + return false; } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 34c14193b03..be0cce716e1 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -33,8 +33,8 @@ public class WorldFluidNet extends WorldPipeNet implements FlowWorldPipeNetPath. if (net == null) { net = new WorldFluidNet(DATA_ID); world.setData(DATA_ID, net); + net.setWorld(world); } - net.setWorld(world); return net; } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index 69e022e2f12..572bd1359c0 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -67,7 +67,7 @@ public void setTile(@Nullable PipeTileEntity tile) { @Override public Capability[] getCapabilities() { - return WorldEnergyNet.CAPABILITIES; + return WorldItemNet.CAPABILITIES; } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java index 6470626b15a..dcb8f304faf 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java @@ -33,7 +33,7 @@ public ItemTestObject getTestObject() { @Override public boolean prepareForPathWalk(FlowWorldPipeNetPath path, long flow) { - return flow > 0; + return flow <= 0; } @Override From 570da02861f5df7bf3e550cd85a858221820bde8 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 3 Aug 2024 09:16:52 -0600 Subject: [PATCH 087/157] refactors and improvements --- src/main/java/gregtech/api/cover/Cover.java | 2 + .../gregtech/api/cover/CoverRayTracer.java | 4 +- .../cover/filter/CoverWithFluidFilter.java | 18 +++ .../api/cover/filter/CoverWithItemFilter.java | 19 +++ .../gregtech/api/graphnet/GraphNetBacker.java | 75 ++++++------ .../java/gregtech/api/graphnet/IGraphNet.java | 10 +- .../api/graphnet/MultiNodeHelper.java | 20 ++-- .../java/gregtech/api/graphnet/NetNode.java | 18 +-- .../DynamicWeightsShortestPathsAlgorithm.java | 55 ++++----- .../api/graphnet/alg/INetAlgorithm.java | 5 +- .../api/graphnet/alg/NetAlgorithmWrapper.java | 11 +- .../graphnet/alg/ShortestPathsAlgorithm.java | 26 +++-- .../api/graphnet/alg/SinglePathAlgorithm.java | 60 ++++++---- .../graphnet/alg/iter/ICacheableIterator.java | 10 -- .../graphnet/alg/iter/IteratorFactory.java | 28 +++++ .../alg/iter/SimpleCacheableIterator.java | 45 ------- .../alg/iter/SimpleIteratorFactories.java | 50 ++++++++ .../gregtech/api/graphnet/edge/NetEdge.java | 27 +++-- .../graphnet/gather/GTGraphGatherables.java | 90 -------------- .../graphnet/gather/GatherLogicsEvent.java | 21 ---- .../gather/GatherPredicatesEvent.java | 21 ---- .../gather/GatherStructuresEvent.java | 32 ----- .../api/graphnet/graph/GraphEdge.java | 10 ++ .../api/graphnet/graph/NetDirectedGraph.java | 4 +- .../graphnet/graph/NetUndirectedGraph.java | 4 +- .../logic/AbstractDoubleLogicData.java | 8 +- .../graphnet/logic/AbstractIntLogicData.java | 8 +- .../graphnet/logic/AbstractLongLogicData.java | 8 +- .../api/graphnet/logic/ChannelCountLogic.java | 9 +- .../logic/INetLogicEntryListener.java | 2 +- .../graphnet/logic/MultiNetCountLogic.java | 9 +- .../api/graphnet/logic/NetLogicData.java | 64 +++++----- ...INetLogicEntry.java => NetLogicEntry.java} | 57 +++++---- .../api/graphnet/logic/NetLogicRegistry.java | 36 ++++++ .../api/graphnet/logic/ThroughputLogic.java | 11 +- .../api/graphnet/logic/WeightFactorLogic.java | 11 +- .../api/graphnet/pipenet/WorldPipeNet.java | 49 +++++--- .../logic/EdgeCoverReferenceLogic.java | 15 ++- .../pipenet/logic/TemperatureLogic.java | 21 ++-- .../logic/TemperatureLossFunction.java | 2 +- .../physical/PipeStructureRegistry.java | 38 ++++++ .../pipenet/physical/block/ItemPipeBlock.java | 6 +- .../physical/block/PipeActivableBlock.java | 3 +- .../{WorldPipeBlock.java => PipeBlock.java} | 81 ++++++++++--- .../physical/block/PipeMaterialBlock.java | 2 +- .../tile/PipeActivableTileEntity.java | 1 - .../pipenet/physical/tile/PipeTileEntity.java | 34 +++--- .../pipenet/predicate/BlockedPredicate.java | 52 +++++++++ .../pipenet/predicate/FilterPredicate.java | 107 +++++++++++++++++ .../pipenet/predicate/ShutterPredicate.java | 44 ------- .../api/graphnet/predicate/EdgePredicate.java | 63 ++++++++++ .../predicate/EdgePredicateHandler.java | 60 +++++----- .../graphnet/predicate/IEdgePredicate.java | 42 ------- .../predicate/NetPredicateRegistry.java | 40 +++++++ .../api/graphnet/servernet/ServerNet.java | 8 +- .../api/graphnet/worldnet/WorldNet.java | 16 ++- .../properties/PipeNetProperties.java | 30 ++++- .../java/gregtech/api/util/GTUtility.java | 15 +++ .../api/util/function/NullableSupplier.java | 12 ++ .../renderer/pipe/AbstractPipeModel.java | 2 +- .../renderer/pipe/ActivablePipeModel.java | 4 +- .../client/renderer/pipe/CableModel.java | 4 +- .../client/renderer/pipe/PipeItemModel.java | 49 +++----- .../client/renderer/pipe/PipeModel.java | 6 +- .../pipe/cache/StructureQuadCache.java | 4 +- .../client/renderer/texture/Textures.java | 49 +------- .../java/gregtech/common/CommonProxy.java | 8 +- .../gregtech/common/ToolEventHandlers.java | 4 +- .../gregtech/common/blocks/BlockFrame.java | 4 +- .../gregtech/common/blocks/MetaBlocks.java | 28 ++--- .../gregtech/common/covers/CoverConveyor.java | 20 +++- .../common/covers/CoverFluidFilter.java | 13 ++- .../common/covers/CoverItemFilter.java | 13 ++- .../gregtech/common/covers/CoverPump.java | 18 ++- .../pipelike/block/cable/CableBlock.java | 12 -- .../pipelike/block/cable/CableStructure.java | 15 +++ .../pipelike/block/laser/LaserPipeBlock.java | 12 -- .../pipelike/block/laser/LaserStructure.java | 8 ++ .../block/optical/OpticalPipeBlock.java | 12 -- .../block/optical/OpticalStructure.java | 8 ++ .../block/pipe/MaterialPipeBlock.java | 16 +++ .../block/pipe/MaterialPipeStructure.java | 110 ++++++++++++++++++ .../common/pipelike/block/pipe/PipeBlock.java | 27 ----- .../pipelike/block/pipe/PipeStructure.java | 97 --------------- .../properties/MaterialEnergyProperties.java | 18 +-- .../properties/MaterialFluidProperties.java | 21 ++-- .../properties/MaterialItemProperties.java | 18 +-- .../net/energy/EnergyCapabilityObject.java | 5 +- .../net/energy/SuperconductorLogic.java | 13 +-- .../net/energy/VoltageLimitLogic.java | 11 +- .../pipelike/net/energy/VoltageLossLogic.java | 11 +- .../net/fluid/FluidCapabilityObject.java | 5 +- .../net/fluid/FluidContainmentLogic.java | 19 ++- .../pipelike/net/fluid/WorldFluidNet.java | 39 ++++++- .../net/item/ItemCapabilityObject.java | 5 +- .../pipelike/net/item/WorldItemNet.java | 37 ++++++ .../net/laser/LaserCapabilityObject.java | 11 +- .../pipelike/net/laser/WorldLaserNet.java | 2 +- .../pipelike/net/optical/WorldOpticalNet.java | 2 +- .../resources/assets/gregtech/lang/en_us.lang | 2 +- .../blocks/pipe/blocked/pipe_blocked_dl.png | Bin 283 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_down.png | Bin 220 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_dr.png | Bin 268 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_left.png | Bin 224 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_lr.png | Bin 281 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_nd.png | Bin 331 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_nl.png | Bin 319 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_nr.png | Bin 322 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_nu.png | Bin 334 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_rd.png | Bin 268 -> 0 bytes .../pipe/blocked/pipe_blocked_right.png | Bin 220 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_ud.png | Bin 278 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_ul.png | Bin 270 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_up.png | Bin 222 -> 0 bytes .../blocks/pipe/blocked/pipe_blocked_ur.png | Bin 279 -> 0 bytes .../pipe/{blocked => }/pipe_blocked.png | Bin 116 files changed, 1393 insertions(+), 998 deletions(-) create mode 100644 src/main/java/gregtech/api/cover/filter/CoverWithFluidFilter.java create mode 100644 src/main/java/gregtech/api/cover/filter/CoverWithItemFilter.java delete mode 100644 src/main/java/gregtech/api/graphnet/alg/iter/ICacheableIterator.java create mode 100644 src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java delete mode 100644 src/main/java/gregtech/api/graphnet/alg/iter/SimpleCacheableIterator.java create mode 100644 src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java delete mode 100644 src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java delete mode 100644 src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java delete mode 100644 src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java delete mode 100644 src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java rename src/main/java/gregtech/api/graphnet/logic/{INetLogicEntry.java => NetLogicEntry.java} (61%) create mode 100644 src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java rename src/main/java/gregtech/api/graphnet/pipenet/physical/block/{WorldPipeBlock.java => PipeBlock.java} (88%) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/predicate/ShutterPredicate.java create mode 100644 src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java delete mode 100644 src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java create mode 100644 src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java create mode 100644 src/main/java/gregtech/api/util/function/NullableSupplier.java create mode 100644 src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java create mode 100644 src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java delete mode 100644 src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java delete mode 100644 src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_dl.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_down.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_dr.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_left.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_lr.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_nd.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_nl.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_nr.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_nu.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_rd.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_right.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_ud.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_ul.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_up.png delete mode 100644 src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_ur.png rename src/main/resources/assets/gregtech/textures/blocks/pipe/{blocked => }/pipe_blocked.png (100%) diff --git a/src/main/java/gregtech/api/cover/Cover.java b/src/main/java/gregtech/api/cover/Cover.java index 6823672d9e0..e4bc8d9b3c4 100644 --- a/src/main/java/gregtech/api/cover/Cover.java +++ b/src/main/java/gregtech/api/cover/Cover.java @@ -1,5 +1,7 @@ package gregtech.api.cover; +import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.client.utils.BloomEffectUtil; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/gregtech/api/cover/CoverRayTracer.java b/src/main/java/gregtech/api/cover/CoverRayTracer.java index b35ad4ec4b7..bbd1dded0ff 100644 --- a/src/main/java/gregtech/api/cover/CoverRayTracer.java +++ b/src/main/java/gregtech/api/cover/CoverRayTracer.java @@ -1,6 +1,6 @@ package gregtech.api.cover; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.util.GTUtility; import net.minecraft.entity.player.EntityPlayer; @@ -20,7 +20,7 @@ private CoverRayTracer() {} @NotNull EntityPlayer player) { // if the coverable view is from a blockpipe, use the proper raytrace method RayTraceResult result = coverableView.getWorld().getBlockState(coverableView.getPos()) - .getBlock() instanceof WorldPipeBlock pipe ? + .getBlock() instanceof PipeBlock pipe ? pipe.collisionRayTrace(player, coverableView.getWorld(), coverableView.getPos()) : RayTracer.retraceBlock(coverableView.getWorld(), player, coverableView.getPos()); if (result == null || result.typeOfHit != RayTraceResult.Type.BLOCK) { diff --git a/src/main/java/gregtech/api/cover/filter/CoverWithFluidFilter.java b/src/main/java/gregtech/api/cover/filter/CoverWithFluidFilter.java new file mode 100644 index 00000000000..85737dbdc81 --- /dev/null +++ b/src/main/java/gregtech/api/cover/filter/CoverWithFluidFilter.java @@ -0,0 +1,18 @@ +package gregtech.api.cover.filter; + +import gregtech.api.cover.Cover; +import gregtech.common.covers.FluidFilterMode; +import gregtech.common.covers.ManualImportExportMode; +import gregtech.common.covers.filter.FluidFilterContainer; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface CoverWithFluidFilter extends Cover { + + @Nullable FluidFilterContainer getFluidFilter(); + + FluidFilterMode getFilterMode(); + + ManualImportExportMode getManualMode(); +} diff --git a/src/main/java/gregtech/api/cover/filter/CoverWithItemFilter.java b/src/main/java/gregtech/api/cover/filter/CoverWithItemFilter.java new file mode 100644 index 00000000000..f1b2b75f672 --- /dev/null +++ b/src/main/java/gregtech/api/cover/filter/CoverWithItemFilter.java @@ -0,0 +1,19 @@ +package gregtech.api.cover.filter; + +import gregtech.api.cover.Cover; +import gregtech.common.covers.FluidFilterMode; +import gregtech.common.covers.ItemFilterMode; +import gregtech.common.covers.ManualImportExportMode; +import gregtech.common.covers.filter.ItemFilterContainer; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface CoverWithItemFilter extends Cover { + + @Nullable ItemFilterContainer getItemFilter(); + + ItemFilterMode getFilterMode(); + + ManualImportExportMode getManualMode(); +} diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index 70498cfbfe7..cca5d2bb0ae 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -3,7 +3,7 @@ import gregtech.api.graphnet.alg.INetAlgorithm; import gregtech.api.graphnet.alg.NetAlgorithmWrapper; import gregtech.api.graphnet.alg.NetPathMapper; -import gregtech.api.graphnet.alg.iter.ICacheableIterator; +import gregtech.api.graphnet.alg.iter.IteratorFactory; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphEdge; @@ -57,6 +57,7 @@ public void addNode(NetNode node) { GraphVertex vertex = new GraphVertex(node); getGraph().addVertex(vertex); this.vertexMap.put(node.getEquivalencyData(), vertex); + backedNet.markDirty(); } @Nullable @@ -72,15 +73,18 @@ public boolean removeNode(@Nullable NetNode node) { if (group != null) { group.splitNode(node); } else this.removeVertex(node.wrapper); + backedNet.markDirty(); return true; } else return false; } @ApiStatus.Internal public void removeVertex(GraphVertex vertex) { - this.getGraph().removeVertex(vertex); - this.vertexMap.remove(vertex.wrapped.getEquivalencyData()); - vertex.wrapped.onRemove(); + if (this.getGraph().removeVertex(vertex)) { + this.vertexMap.remove(vertex.wrapped.getEquivalencyData()); + vertex.wrapped.onRemove(); + backedNet.markDirty(); + } } @Nullable @@ -89,6 +93,7 @@ public NetEdge addEdge(NetNode source, NetNode target, double weight) { if (graphEdge != null) { getGraph().setEdgeWeight(graphEdge, weight); NetGroup.mergeEdge(source, target); + backedNet.markDirty(); } return graphEdge == null ? null : graphEdge.wrapped; } @@ -109,12 +114,20 @@ public boolean removeEdge(NetNode source, NetNode target) { @ApiStatus.Internal public GraphEdge removeEdge(GraphVertex source, GraphVertex target) { - return this.getGraph().removeEdge(source, target); + GraphEdge edge = this.getGraph().removeEdge(source, target); + if (edge != null) { + backedNet.markDirty(); + } + return edge; } @ApiStatus.Internal - public void removeEdge(GraphEdge edge) { - this.getGraph().removeEdge(edge); + public boolean removeEdge(GraphEdge edge) { + if (this.getGraph().removeEdge(edge)) { + backedNet.markDirty(); + return true; + } + return false; } /** @@ -127,16 +140,15 @@ public void removeEdge(GraphEdge edge) { IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { if (node == null) return Collections.emptyIterator(); + this.getGraph().setupInternal(this, backedNet.usesDynamicWeights(algorithmID)); - Iterator> cache = node.getPathCache(); + Iterator> cache = node.getPathCache(testObject, simulator, queryTick); if (cache != null) return (Iterator) cache; - this.getGraph().setupInternal(this, backedNet.usesDynamicWeights(algorithmID)); - Iterator iter = this.netAlgorithms[algorithmID].getPathsIterator(node.wrapper, remapper, testObject, - simulator, queryTick); - if (iter instanceof ICacheableIterator) { - return (Iterator) node.setPathCache((ICacheableIterator) iter); - } else return iter; + IteratorFactory factory = this.netAlgorithms[algorithmID].getPathsIterator(node.wrapper, remapper); + if (factory.cacheable()) { + return (Iterator) (node.setPathCache(factory).getPathCache(testObject, simulator, queryTick)); + } else return factory.newIterator(getGraph(), testObject, simulator, queryTick); } public void invalidateAlg(int algorithmID) { @@ -221,50 +233,41 @@ public NBTTagCompound writeToNBT(NBTTagCompound compound) { // tag of autogenerated edge ids -> edge nbt & source/target ids Object2IntOpenHashMap groupMap = new Object2IntOpenHashMap<>(); Object2IntOpenHashMap vertexMap = new Object2IntOpenHashMap<>(); - int i = -1; + int i = 0; int g = 0; NBTTagCompound vertices = new NBTTagCompound(); for (GraphVertex graphVertex : this.getGraph().vertexSet()) { - vertexMap.put(graphVertex, i++); + vertexMap.put(graphVertex, i); NetGroup group = graphVertex.wrapped.getGroupUnsafe(); NBTTagCompound tag = graphVertex.wrapped.serializeNBT(); if (group != null) { int groupID; if (!groupMap.containsKey(group)) { - groupMap.put(group, g++); + groupMap.put(group, g); groupID = g; + g++; } else groupID = groupMap.getInt(group); tag.setInteger("GroupID", groupID); } vertices.setTag(String.valueOf(i), tag); + i++; } - vertices.setInteger("Count", i + 1); + vertices.setInteger("Count", i); compound.setTag("Vertices", vertices); - i = -1; + i = 0; NBTTagCompound edges = new NBTTagCompound(); for (GraphEdge graphEdge : this.getGraph().edgeSet()) { NBTTagCompound tag = graphEdge.wrapped.serializeNBT(); - tag.setInteger("SourceID", vertexMap.getInt(getSource(graphEdge))); - tag.setInteger("TargetID", vertexMap.getInt(getTarget(graphEdge))); - tag.setDouble("Weight", getWeight(graphEdge)); - edges.setTag(String.valueOf(i++), tag); + tag.setInteger("SourceID", vertexMap.getInt(graphEdge.getSource())); + tag.setInteger("TargetID", vertexMap.getInt(graphEdge.getTarget())); + tag.setDouble("Weight", graphEdge.getWeight()); + edges.setTag(String.valueOf(i), tag); + i++; } - edges.setInteger("Count", i + 1); + edges.setInteger("Count", i); compound.setTag("Edges", edges); return compound; } - - private GraphVertex getSource(GraphEdge graphEdge) { - return this.getGraph().getEdgeSource(graphEdge); - } - - private GraphVertex getTarget(GraphEdge graphEdge) { - return this.getGraph().getEdgeTarget(graphEdge); - } - - private double getWeight(GraphEdge graphEdge) { - return this.getGraph().getEdgeWeight(graphEdge); - } } diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index f4ee4d5c654..8a81ee72c29 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -94,7 +94,7 @@ default NetEdge getEdgeNullSafe(@Nullable NetNode source, @Nullable NetNode targ void removeEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays); /** - * Gets the net graph backing this graphnet. This should NEVER be modified directly, but can be queried. + * Gets the {@link INetGraph} backing this graphnet. This should NEVER be modified directly, but can be queried. * * @return the backing net graph */ @@ -104,7 +104,7 @@ default INetGraph getGraph() { } /** - * Gets the GraphNetBacker backing this graphnet. This should NEVER be used except inside the graphnet impl. + * Gets the {@link GraphNetBacker} backing this graphnet. This should NEVER be used except inside the graphnet impl. * * @return the backing graphnet backer */ @@ -208,4 +208,10 @@ default void nodeClassCheck(NetNode node) { default NetEdge getNewEdge() { return new NetEdge(); } + + /** + * Should only be used by the internal {@link GraphNetBacker} backing this graphnet. + */ + @ApiStatus.Internal + void markDirty(); } diff --git a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java index 0dff6ab4828..078b71f80dd 100644 --- a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java +++ b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet; -import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.INetLogicEntryListener; import gregtech.api.graphnet.logic.NetLogicData; @@ -56,16 +56,16 @@ public boolean traverse(IGraphNet net, long queryTick, boolean simulate) { } @Override - public void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChange) { + public void markLogicEntryAsUpdated(NetLogicEntry entry, boolean fullChange) { // TODO have a helper or something on clientside to avoid redundant packets handledDatas.forEach((k, v) -> v.data.markLogicEntryAsUpdated(entry, fullChange)); } public void addNode(@NotNull NetNode node) { - List> toSet = new ObjectArrayList<>(); - for (INetLogicEntry entry : node.getData().getEntries()) { + List> toSet = new ObjectArrayList<>(); + for (NetLogicEntry entry : node.getData().getEntries()) { if (entry.mergedToMultiNodeHelper()) { - INetLogicEntry existing = mergedData.getLogicEntryNullable(entry); + NetLogicEntry existing = mergedData.getLogicEntryNullable(entry); if (existing != null) { existing.merge(node, entry); // don't put it into the data yet because we're currently iterating through the data's entries. @@ -76,7 +76,7 @@ public void addNode(@NotNull NetNode node) { } } handledDatas.put(node.getNet(), new LogicDataHandler(node)); - for (INetLogicEntry entry : toSet) { + for (NetLogicEntry entry : toSet) { node.getData().setLogicEntry(entry); } } @@ -85,14 +85,14 @@ public void removeNode(NetNode node) { LogicDataHandler removed = handledDatas.remove(node.getNet()); if (removed != null) { removed.invalidate(); - for (INetLogicEntry entry : this.mergedData.getEntries()) { + for (NetLogicEntry entry : this.mergedData.getEntries()) { node.getData().removeLogicEntry(entry); entry.unmerge(node); } } } - private void addNewLogicEntry(@NotNull INetLogicEntry entry) { + private void addNewLogicEntry(@NotNull NetLogicEntry entry) { entry.registerToMultiNodeHelper(this); mergedData.setLogicEntry(entry); handledDatas.values().forEach(h -> h.data.setLogicEntry(entry)); @@ -115,11 +115,11 @@ public void invalidate() { } @Override - public void markChanged(INetLogicEntry updatedEntry, boolean removed, boolean fullChange) { + public void markChanged(NetLogicEntry updatedEntry, boolean removed, boolean fullChange) { if (!fullChange || !updatedEntry.mergedToMultiNodeHelper()) return; NetNode node = nodeRef.get(); if (node == null) return; - INetLogicEntry existing = mergedData.getLogicEntryNullable(updatedEntry); + NetLogicEntry existing = mergedData.getLogicEntryNullable(updatedEntry); if (removed) { if (existing != null) mergedData.removeLogicEntry(existing); } else { diff --git a/src/main/java/gregtech/api/graphnet/NetNode.java b/src/main/java/gregtech/api/graphnet/NetNode.java index 822a92b5696..236a9b0acd0 100644 --- a/src/main/java/gregtech/api/graphnet/NetNode.java +++ b/src/main/java/gregtech/api/graphnet/NetNode.java @@ -1,10 +1,13 @@ package gregtech.api.graphnet; -import gregtech.api.graphnet.alg.iter.ICacheableIterator; +import gregtech.api.graphnet.alg.iter.IteratorFactory; +import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraftforge.common.util.INBTSerializable; @@ -31,7 +34,7 @@ public abstract class NetNode implements INBTSerializable { private @Nullable NetGroup group = null; @Nullable - private ICacheableIterator> pathCache = null; + private IteratorFactory> pathCache = null; public NetNode(@NotNull IGraphNet net) { this.net = net; @@ -70,20 +73,21 @@ public boolean traverse(long queryTick, boolean simulate) { } @Nullable - public Iterator> getPathCache() { + public Iterator> getPathCache(IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, long queryTick) { if (pathCache == null) return null; - return pathCache.newIterator(); + return pathCache.newIterator(net.getGraph(), testObject, simulator, queryTick); } /** - * Sets the path cache to the provided cache. Returns a new iterator from the cache for convenience. + * Sets the path cache to the provided iterator factory. Returns itself for convenience. * * @param pathCache The new cache. * @return The new cache. */ - public Iterator> setPathCache(ICacheableIterator> pathCache) { + public NetNode setPathCache(IteratorFactory> pathCache) { this.pathCache = pathCache; - return getPathCache(); + return this; } public void clearPathCache() { diff --git a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java index a054c9fc336..725982bf4c4 100644 --- a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java @@ -2,12 +2,17 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.alg.iter.ICacheableIterator; +import gregtech.api.graphnet.alg.iter.IteratorFactory; +import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jetbrains.annotations.Nullable; import org.jgrapht.alg.shortestpath.DefaultManyToManyShortestPaths; import java.util.Collections; @@ -15,6 +20,7 @@ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -26,39 +32,40 @@ public DynamicWeightsShortestPathsAlgorithm(IGraphNet net) { } @Override - public > Iterator getPathsIterator(GraphVertex source, - NetPathMapper remapper) { + public > IteratorFactory getPathsIteratorFactory(GraphVertex source, + NetPathMapper remapper) { Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream().filter(NetNode::isActive) .map(n -> n.wrapper).filter(node -> !source.equals(node)).collect(Collectors.toSet()); - return new LimitedIterator<>(source, searchSpace, remapper); + return (graph, testObject, simulator, queryTick) -> { + IteratorFactory.defaultPrepareRun(graph, testObject, simulator, queryTick); + return new LimitedIterator<>(source, searchSpace, remapper, testObject, simulator, queryTick); + }; } - protected class LimitedIterator> implements ICacheableIterator { + protected class LimitedIterator> implements Iterator { private static final int MAX_ITERATIONS = 100; + private final IPredicateTestObject testObject; + private final SimulatorKey simulator; + private final long queryTick; + private final GraphVertex source; private final Set searchSpace; private final NetPathMapper remapper; private int iterationCount = 0; private final ObjectArrayList visited = new ObjectArrayList<>(); - private Path next; + private @Nullable Path next; - public LimitedIterator(GraphVertex source, Set searchSpace, NetPathMapper remapper) { + public LimitedIterator(GraphVertex source, Set searchSpace, NetPathMapper remapper, + IPredicateTestObject testObject, SimulatorKey simulator, long queryTick) { this.source = source; this.searchSpace = searchSpace; this.remapper = remapper; - } - - @Override - public ICacheableIterator newCacheableIterator() { - return new LimitedIterator<>(source, searchSpace, remapper); - } - - @Override - public Iterator newIterator() { - return newCacheableIterator(); + this.testObject = testObject; + this.simulator = simulator; + this.queryTick = queryTick; } @Override @@ -83,16 +90,10 @@ private void calculateNext() { } ManyToManyShortestPaths paths = getManyToManyPaths(Collections.singleton(source), searchSpace); - var iter = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) - .map(remapper::map).sorted(Comparator.comparingDouble(INetPath::getWeight)).iterator(); - while (iter.hasNext()) { - var next = iter.next(); - if (isUnique(next)) { - this.next = next; - break; - } - } - if (next != null) visited.add(next); + Optional next = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) + .map(remapper::map).filter(this::isUnique).min(Comparator.comparingDouble(INetPath::getWeight)); + this.next = next.orElse(null); + next.ifPresent(this.visited::add); } private boolean isUnique(Path path) { diff --git a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java index 14219738f00..b10f8e01299 100644 --- a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java @@ -1,11 +1,10 @@ package gregtech.api.graphnet.alg; +import gregtech.api.graphnet.alg.iter.IteratorFactory; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.path.INetPath; -import java.util.Iterator; - public interface INetAlgorithm { - > Iterator getPathsIterator(GraphVertex source, NetPathMapper remapper); + > IteratorFactory getPathsIteratorFactory(GraphVertex source, NetPathMapper remapper); } diff --git a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java index 710ad6576d2..dd85c752f6b 100644 --- a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java +++ b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java @@ -1,6 +1,7 @@ package gregtech.api.graphnet.alg; import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.alg.iter.IteratorFactory; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.path.INetPath; @@ -33,13 +34,9 @@ public void invalidate() { this.alg = null; } - public > Iterator getPathsIterator(GraphVertex source, - NetPathMapper remapper, - IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, - long queryTick) { - net.getGraph().prepareForAlgorithmRun(testObject, simulator, queryTick); + public > IteratorFactory getPathsIterator(GraphVertex source, + NetPathMapper remapper) { if (alg == null) alg = builder.apply(net); - return alg.getPathsIterator(source, remapper); + return alg.getPathsIteratorFactory(source, remapper); } } diff --git a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java index 42e285fdf37..096605f280c 100644 --- a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java @@ -2,7 +2,8 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.alg.iter.SimpleCacheableIterator; +import gregtech.api.graphnet.alg.iter.IteratorFactory; +import gregtech.api.graphnet.alg.iter.SimpleIteratorFactories; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.path.INetPath; @@ -12,7 +13,6 @@ import java.util.Collections; import java.util.Comparator; -import java.util.Iterator; import java.util.Set; import java.util.stream.Collectors; @@ -24,20 +24,26 @@ public ShortestPathsAlgorithm(IGraphNet net) { } @Override - public > Iterator getPathsIterator(GraphVertex source, - NetPathMapper remapper) { + public > IteratorFactory getPathsIteratorFactory(GraphVertex source, + NetPathMapper remapper) { if (!graph.containsVertex(source)) { throw new IllegalArgumentException("Graph must contain the source vertex"); } // if the source has no group, it has no paths other than the path to itself. - if (source.wrapped.getGroupUnsafe() == null) return Collections.singletonList(remapper.map(source)).iterator(); + if (source.wrapped.getGroupUnsafe() == null) { + Path path = remapper.map(source); + return SimpleIteratorFactories.fromSingleton(path); + } Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream() .filter(NetNode::isActive).map(n -> n.wrapper).collect(Collectors.toSet()); - ManyToManyShortestPaths manyToManyPaths = getManyToManyPaths( - Collections.singleton(source), searchSpace); - return new SimpleCacheableIterator<>(searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)) - .map(remapper::map).sorted(Comparator.comparingDouble(INetPath::getWeight)) - .collect(Collectors.toCollection(ObjectArrayList::new))); + Set singleton = Collections.singleton(source); + return (graph1, testObject, simulator, queryTick) -> { + IteratorFactory.defaultPrepareRun(graph1, testObject, simulator, queryTick); + ManyToManyShortestPaths manyToManyPaths = getManyToManyPaths(singleton, + searchSpace); + return searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)) + .map(remapper::map).sorted(Comparator.comparingDouble(INetPath::getWeight)).iterator(); + }; } } diff --git a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java index 2513229e4bc..0609e9265ba 100644 --- a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java @@ -1,34 +1,54 @@ package gregtech.api.graphnet.alg; +import com.github.bsideup.jabel.Desugar; + import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.alg.iter.SimpleCacheableIterator; +import gregtech.api.graphnet.alg.iter.IteratorFactory; +import gregtech.api.graphnet.alg.iter.SimpleIteratorFactories; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.path.INetPath; -import com.google.common.collect.ImmutableList; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; public final class SinglePathAlgorithm implements INetAlgorithm { private final IGraphNet net; + private final boolean needsRecalculation; - public SinglePathAlgorithm(IGraphNet pipenet) { + public SinglePathAlgorithm(IGraphNet pipenet, boolean needsRecalculation) { this.net = pipenet; + this.needsRecalculation = needsRecalculation; } @Override - public > Iterator getPathsIterator(GraphVertex source, - NetPathMapper remapper) { - if (!this.net.getGraph().containsVertex(source)) { - throw new IllegalArgumentException("Graph must contain the source vertex"); + public > IteratorFactory getPathsIteratorFactory(GraphVertex source, + NetPathMapper remapper) { + if (needsRecalculation) { + return (graph, testObject, simulator, queryTick) -> { + IteratorFactory.defaultPrepareRun(graph, testObject, simulator, queryTick); + List graphEdges = new ObjectArrayList<>(); + List nodes = new ObjectArrayList<>(); + Results results = compute(source, nodes, graphEdges); + if (!results.valid()) return SimpleIteratorFactories.getSingletonIterator(null); + if (graphEdges.isEmpty()) return SimpleIteratorFactories.getSingletonIterator(remapper.map(source)); + return SimpleIteratorFactories.getSingletonIterator(remapper.map(nodes, graphEdges, results.weight())); + }; + } else { + List graphEdges = new ObjectArrayList<>(); + List nodes = new ObjectArrayList<>(); + Results results = compute(source, nodes, graphEdges); + if (!results.valid()) return SimpleIteratorFactories.emptyFactory(); + if (graphEdges.isEmpty()) return SimpleIteratorFactories.fromSingleton(remapper.map(source)); + return SimpleIteratorFactories.fromSingleton(remapper.map(nodes, graphEdges, results.weight())); } - List graphEdges = new ObjectArrayList<>(); - List nodes = new ObjectArrayList<>(); + } + + private Results compute(GraphVertex source, + List nodes, List graphEdges) { nodes.add(source); GraphVertex lastNode = null; GraphVertex node = source; @@ -41,31 +61,25 @@ public SinglePathAlgorithm(IGraphNet pipenet) { graphEdge = i.next(); // if we are directed, we know that the target is the target. // if we aren't directed, we need to see if the graphEdge's source was secretly the target - boolean reversedEdge = !this.net.getGraph().isDirected() && getSource(graphEdge) == lastNode; - if (getTarget(graphEdge) == lastNode || reversedEdge) { + boolean reversedEdge = !this.net.getGraph().isDirected() && graphEdge.getSource() == lastNode; + if (graphEdge.getTarget() == lastNode || reversedEdge) { if (i.hasNext()) graphEdge = i.next(); else break; // we've reached the end, exit the loop while still valid } else if (i.hasNext()) i.next(); if (i.hasNext()) valid = false; // third graphEdge detected - that's an invalid group lastNode = node; - node = reversedEdge ? getSource(graphEdge) : getTarget(graphEdge); + node = reversedEdge ? graphEdge.getSource() : graphEdge.getTarget(); graphEdges.add(graphEdge); nodes.add(node); sumWeight += getWeight(graphEdge); } - if (!valid) return Collections.emptyIterator(); - return new SimpleCacheableIterator<>(ImmutableList.of(remapper.map(nodes, graphEdges, sumWeight))); - } - - private GraphVertex getSource(GraphEdge graphEdge) { - return this.net.getGraph().getEdgeSource(graphEdge); - } - - private GraphVertex getTarget(GraphEdge graphEdge) { - return this.net.getGraph().getEdgeTarget(graphEdge); + return new Results(sumWeight, valid); } private double getWeight(GraphEdge graphEdge) { return this.net.getGraph().getEdgeWeight(graphEdge); } + + @Desugar + private record Results(double weight, boolean valid) {} } diff --git a/src/main/java/gregtech/api/graphnet/alg/iter/ICacheableIterator.java b/src/main/java/gregtech/api/graphnet/alg/iter/ICacheableIterator.java deleted file mode 100644 index 4b5031bfbd8..00000000000 --- a/src/main/java/gregtech/api/graphnet/alg/iter/ICacheableIterator.java +++ /dev/null @@ -1,10 +0,0 @@ -package gregtech.api.graphnet.alg.iter; - -import java.util.Iterator; - -public interface ICacheableIterator extends Iterator { - - ICacheableIterator newCacheableIterator(); - - Iterator newIterator(); -} diff --git a/src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java b/src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java new file mode 100644 index 00000000000..4a98d516671 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java @@ -0,0 +1,28 @@ +package gregtech.api.graphnet.alg.iter; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.graph.INetGraph; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; + +public interface IteratorFactory { + + /** + * The provided iterator must always be used and discarded before the end of the tick. + */ + @Contract("_, _, _, _ -> new") + Iterator newIterator(INetGraph graph, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick); + + static void defaultPrepareRun(INetGraph graph, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + graph.prepareForAlgorithmRun(testObject, simulator, queryTick); + } + + default boolean cacheable() { + return true; + } +} diff --git a/src/main/java/gregtech/api/graphnet/alg/iter/SimpleCacheableIterator.java b/src/main/java/gregtech/api/graphnet/alg/iter/SimpleCacheableIterator.java deleted file mode 100644 index e60be5f8eb5..00000000000 --- a/src/main/java/gregtech/api/graphnet/alg/iter/SimpleCacheableIterator.java +++ /dev/null @@ -1,45 +0,0 @@ -package gregtech.api.graphnet.alg.iter; - -import java.util.Iterator; -import java.util.function.Consumer; - -public class SimpleCacheableIterator implements ICacheableIterator { - - private final Iterable prototype; - private final Iterator backingIterator; - - public SimpleCacheableIterator(Iterable prototype) { - this.prototype = prototype; - this.backingIterator = prototype.iterator(); - } - - @Override - public SimpleCacheableIterator newCacheableIterator() { - return new SimpleCacheableIterator<>(prototype); - } - - @Override - public Iterator newIterator() { - return prototype.iterator(); - } - - @Override - public boolean hasNext() { - return backingIterator.hasNext(); - } - - @Override - public T next() { - return backingIterator.next(); - } - - @Override - public void remove() { - backingIterator.remove(); - } - - @Override - public void forEachRemaining(Consumer action) { - backingIterator.forEachRemaining(action); - } -} diff --git a/src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java b/src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java new file mode 100644 index 00000000000..e7118d6b11c --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java @@ -0,0 +1,50 @@ +package gregtech.api.graphnet.alg.iter; + +import com.cleanroommc.modularui.utils.math.functions.trig.Sin; + +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; + +public final class SimpleIteratorFactories { + + public static IteratorFactory emptyFactory() { + return (graph, testObject, simulator, queryTick) -> new SingletonIterator<>(null); + } + + public static IteratorFactory fromIterable(Iterable prototype) { + return (graph, testObject, simulator, queryTick) -> prototype.iterator(); + } + + public static IteratorFactory fromSingleton(T singleton) { + return (graph, testObject, simulator, queryTick) -> new SingletonIterator<>(singleton); + } + + public static SingletonIterator getSingletonIterator(T singleton) { + return new SingletonIterator<>(singleton); + } + + private static class SingletonIterator implements Iterator { + + private T singleton; + + public SingletonIterator(T singleton) { + this.singleton = singleton; + } + + @Override + public boolean hasNext() { + return singleton != null; + } + + @Override + public T next() { + T temp = singleton; + singleton = null; + return temp; + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java index 8560ed1f337..e7d2be4d3ab 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java @@ -23,9 +23,9 @@ public class NetEdge implements INBTSerializable { @ApiStatus.Internal public @Nullable GraphEdge wrapper; - private EdgePredicateHandler predicateHandler; + private @Nullable EdgePredicateHandler predicateHandler; - private NetLogicData data; + private @Nullable NetLogicData data; protected @Nullable NetNode getSource() { if (wrapper == null) return null; @@ -37,18 +37,23 @@ public class NetEdge implements INBTSerializable { return wrapper.getTarget().wrapped; } - public void setData(NetLogicData data) { - this.data = data; + /** + * Should only be used on fake edges that are not registered to the graph. + */ + public void setData(@NotNull NetLogicData data) { + if (this.wrapper == null) this.data = data; } - public NetLogicData getData() { + public @NotNull NetLogicData getData() { + if (this.data == null) { + this.data = NetLogicData.unionNullable(getSource() == null ? null : getSource().getData(), + getTarget() == null ? null : getTarget().getData()); + // if we can't calculate it, create a new one just to guarantee nonnullness + if (this.data == null) this.data = new NetLogicData(); + } return this.data; } - public void setPredicateHandler(EdgePredicateHandler predicateHandler) { - this.predicateHandler = predicateHandler; - } - @NotNull public EdgePredicateHandler getPredicateHandler() { if (predicateHandler == null) predicateHandler = new EdgePredicateHandler(); @@ -68,7 +73,9 @@ public double getDynamicWeight(IPredicateTestObject channel, IGraphNet graph, @N @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); - if (predicateHandler != null) tag.setTag("Predicate", predicateHandler.serializeNBT()); + // we don't need to write our NetLogicData to NBT because we can regenerate it from our nodes + if (predicateHandler != null && !predicateHandler.shouldIgnore()) + tag.setTag("Predicate", predicateHandler.serializeNBT()); return tag; } diff --git a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java b/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java deleted file mode 100644 index 3bd4161067b..00000000000 --- a/src/main/java/gregtech/api/graphnet/gather/GTGraphGatherables.java +++ /dev/null @@ -1,90 +0,0 @@ -package gregtech.api.graphnet.gather; - -import gregtech.api.GTValues; -import gregtech.api.graphnet.logic.ChannelCountLogic; -import gregtech.api.graphnet.logic.INetLogicEntry; -import gregtech.api.graphnet.logic.MultiNetCountLogic; -import gregtech.api.graphnet.logic.ThroughputLogic; -import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; -import gregtech.api.graphnet.pipenet.predicate.ShutterPredicate; -import gregtech.api.graphnet.predicate.IEdgePredicate; -import gregtech.common.pipelike.block.cable.CableStructure; -import gregtech.common.pipelike.block.laser.LaserStructure; -import gregtech.common.pipelike.block.optical.OpticalStructure; -import gregtech.common.pipelike.block.pipe.PipeStructure; -import gregtech.common.pipelike.net.energy.VoltageLossLogic; -import gregtech.common.pipelike.net.energy.SuperconductorLogic; -import gregtech.common.pipelike.net.energy.VoltageLimitLogic; - -import gregtech.common.pipelike.net.fluid.FluidContainmentLogic; - -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; - -import java.util.Map; -import java.util.function.Supplier; - -@Mod.EventBusSubscriber(modid = GTValues.MODID) -public final class GTGraphGatherables { - - private static Map>> PREDICATES_REGISTRY; - private static Map>> LOGICS_REGISTRY; - - public static Map>> getPredicatesRegistry() { - if (PREDICATES_REGISTRY == null) { - GatherPredicatesEvent predicates = new GatherPredicatesEvent(); - MinecraftForge.EVENT_BUS.post(predicates); - PREDICATES_REGISTRY = predicates.gathered; - } - return PREDICATES_REGISTRY; - } - - public static Map>> getLogicsRegistry() { - if (LOGICS_REGISTRY == null) { - GatherLogicsEvent logics = new GatherLogicsEvent(); - MinecraftForge.EVENT_BUS.post(logics); - LOGICS_REGISTRY = logics.gathered; - } - return LOGICS_REGISTRY; - } - - @SubscribeEvent - public static void gatherPredicates(GatherPredicatesEvent event) { - event.registerPredicate(ShutterPredicate.INSTANCE); - } - - @SubscribeEvent - public static void gatherLogics(GatherLogicsEvent event) { - event.registerLogic(WeightFactorLogic.INSTANCE); - event.registerLogic(ThroughputLogic.INSTANCE); - event.registerLogic(ChannelCountLogic.INSTANCE); - event.registerLogic(MultiNetCountLogic.INSTANCE); - event.registerLogic(VoltageLossLogic.INSTANCE); - event.registerLogic(VoltageLimitLogic.INSTANCE); - event.registerLogic(SuperconductorLogic.INSTANCE); - event.registerLogic(TemperatureLogic.INSTANCE); - event.registerLogic(FluidContainmentLogic.INSTANCE); - } - - @SubscribeEvent - public static void gatherStructures(GatherStructuresEvent event) { - if (event.getStructure() == PipeStructure.class) { - GatherStructuresEvent cast = (GatherStructuresEvent) event; - PipeStructure.registerDefaultStructures(cast::registerMaterialStructure); - } - if (event.getStructure() == CableStructure.class) { - GatherStructuresEvent cast = (GatherStructuresEvent) event; - CableStructure.registerDefaultStructures(cast::registerMaterialStructure); - } - if (event.getStructure() == OpticalStructure.class) { - GatherStructuresEvent cast = (GatherStructuresEvent) event; - OpticalStructure.registerDefaultStructures(cast::registerMaterialStructure); - } - if (event.getStructure() == LaserStructure.class) { - GatherStructuresEvent cast = (GatherStructuresEvent) event; - LaserStructure.registerDefaultStructures(cast::registerMaterialStructure); - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java deleted file mode 100644 index b075bc3adda..00000000000 --- a/src/main/java/gregtech/api/graphnet/gather/GatherLogicsEvent.java +++ /dev/null @@ -1,21 +0,0 @@ -package gregtech.api.graphnet.gather; - -import gregtech.api.graphnet.logic.INetLogicEntry; - -import net.minecraftforge.fml.common.eventhandler.Event; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import java.util.Map; -import java.util.function.Supplier; - -public class GatherLogicsEvent extends Event { - - final Map>> gathered = new Object2ObjectOpenHashMap<>(); - - public GatherLogicsEvent() {} - - public void registerLogic(INetLogicEntry logic) { - gathered.put(logic.getName(), logic::getNew); - } -} diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java deleted file mode 100644 index fa6bc8bcb0f..00000000000 --- a/src/main/java/gregtech/api/graphnet/gather/GatherPredicatesEvent.java +++ /dev/null @@ -1,21 +0,0 @@ -package gregtech.api.graphnet.gather; - -import gregtech.api.graphnet.predicate.IEdgePredicate; - -import net.minecraftforge.fml.common.eventhandler.Event; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import java.util.Map; -import java.util.function.Supplier; - -public class GatherPredicatesEvent extends Event { - - final Map>> gathered = new Object2ObjectOpenHashMap<>(); - - public GatherPredicatesEvent() {} - - public void registerPredicate(IEdgePredicate predicate) { - gathered.put(predicate.getName(), predicate::getNew); - } -} diff --git a/src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java b/src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java deleted file mode 100644 index ba3e1eb5297..00000000000 --- a/src/main/java/gregtech/api/graphnet/gather/GatherStructuresEvent.java +++ /dev/null @@ -1,32 +0,0 @@ -package gregtech.api.graphnet.gather; - -import gregtech.api.graphnet.pipenet.physical.IPipeStructure; - -import net.minecraftforge.fml.common.eventhandler.Event; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - -import java.util.Set; - -public class GatherStructuresEvent extends Event { - - final Set gathered = new ObjectOpenHashSet<>(); - - final Class structure; - - public GatherStructuresEvent(Class structure) { - this.structure = structure; - } - - public void registerMaterialStructure(T materialStructure) { - gathered.add(materialStructure); - } - - public Set getGathered() { - return gathered; - } - - public Class getStructure() { - return structure; - } -} diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java index 9dd71345f5e..0e13ac497d7 100644 --- a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java +++ b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java @@ -30,6 +30,16 @@ public GraphVertex getTarget() { return (GraphVertex) super.getTarget(); } + /** + * Use this very sparingly. It's significantly better to go through {@link org.jgrapht.Graph#getEdgeWeight(Object)} + * instead, unless you are doing nbt serialization for example. + * @return the edge weight. + */ + @Override + public double getWeight() { + return super.getWeight(); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java index 626494eb0b3..e86b5709fc8 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java @@ -50,8 +50,8 @@ public double getEdgeWeight(GraphEdge graphEdge) { if (graphEdge.wrapped.test(testObject)) { if (dynamicWeights) { return graphEdge.wrapped.getDynamicWeight(testObject, net, simulator, queryTick, - super.getEdgeWeight(graphEdge)); - } else return super.getEdgeWeight(graphEdge); + graphEdge.getWeight()); + } else return graphEdge.getWeight(); } else return Double.POSITIVE_INFINITY; } diff --git a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java index 41754af6b3b..8946773f418 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java @@ -50,8 +50,8 @@ public double getEdgeWeight(GraphEdge graphEdge) { if (graphEdge.wrapped.test(testObject)) { if (dynamicWeights) { return graphEdge.wrapped.getDynamicWeight(testObject, net, simulator, queryTick, - super.getEdgeWeight(graphEdge)); - } else return super.getEdgeWeight(graphEdge); + graphEdge.getWeight()); + } else return graphEdge.getWeight(); } else return Double.POSITIVE_INFINITY; } diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java index a0965ab4523..c46f823505a 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java @@ -3,11 +3,17 @@ import net.minecraft.nbt.NBTTagDouble; import net.minecraft.network.PacketBuffer; +import org.jetbrains.annotations.NotNull; + public abstract class AbstractDoubleLogicData> - implements INetLogicEntry { + extends NetLogicEntry { private double value; + protected AbstractDoubleLogicData(@NotNull String name) { + super(name); + } + public T getWith(double value) { return getNew().setValue(value); } diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java index d1ff2c58ef9..d71c8e00b54 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java @@ -3,10 +3,16 @@ import net.minecraft.nbt.NBTTagInt; import net.minecraft.network.PacketBuffer; -public abstract class AbstractIntLogicData> implements INetLogicEntry { +import org.jetbrains.annotations.NotNull; + +public abstract class AbstractIntLogicData> extends NetLogicEntry { private int value; + protected AbstractIntLogicData(@NotNull String name) { + super(name); + } + public T getWith(int value) { return getNew().setValue(value); } diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java index 108862b603b..07773f1a978 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java @@ -4,12 +4,16 @@ import net.minecraft.network.PacketBuffer; import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; -public abstract class AbstractLongLogicData> - implements INetLogicEntry { +public abstract class AbstractLongLogicData> extends NetLogicEntry { private long value; + protected AbstractLongLogicData(@NotNull String name) { + super(name); + } + public T getWith(long value) { return getNew().setValue(value); } diff --git a/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java b/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java index a33c86448e5..65420e09c84 100644 --- a/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java @@ -6,18 +6,17 @@ public final class ChannelCountLogic extends AbstractIntLogicData other) { + public ChannelCountLogic union(NetLogicEntry other) { if (other instanceof ChannelCountLogic l) { return this.getValue() < l.getValue() ? this : l; } else return this; diff --git a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntryListener.java b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntryListener.java index 91097246bcc..14a9361e018 100644 --- a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntryListener.java +++ b/src/main/java/gregtech/api/graphnet/logic/INetLogicEntryListener.java @@ -2,5 +2,5 @@ public interface INetLogicEntryListener { - void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChange); + void markLogicEntryAsUpdated(NetLogicEntry entry, boolean fullChange); } diff --git a/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java b/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java index cbd9370546c..ec0d40cc1a2 100644 --- a/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java @@ -6,18 +6,17 @@ public final class MultiNetCountLogic extends AbstractIntLogicData other) { + public MultiNetCountLogic union(NetLogicEntry other) { if (other instanceof MultiNetCountLogic l) { return this.getValue() < l.getValue() ? this : l; } else return this; diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index 964ccb66896..b75b43a0b9b 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -1,9 +1,6 @@ package gregtech.api.graphnet.logic; -import gregtech.api.graphnet.gather.GTGraphGatherables; -import gregtech.api.graphnet.gather.GatherLogicsEvent; import gregtech.api.network.IPacket; -import gregtech.api.util.function.TriConsumer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -19,18 +16,15 @@ import org.jetbrains.annotations.Nullable; import java.util.Set; -import java.util.function.Supplier; /** * Note - since the internal map representation encodes keys using {@link IStringSerializable#getName()} on logics, - * making a logics class return two different names is a valid way to register multiple instances.
- * Just make sure that a supplier is registered to {@link GatherLogicsEvent} for all - * associated names, so that decoding from nbt and packets is possible. + * making a logics class return two different names is a valid way to register multiple instances. */ public final class NetLogicData implements INBTSerializable, IPacket, INetLogicEntryListener { // TODO caching logic on simple logics to reduce amount of reduntant creation? - private final Object2ObjectOpenHashMap> logicEntrySet; + private final Object2ObjectOpenHashMap> logicEntrySet; private final Set listeners = new ObjectOpenHashSet<>(); @@ -38,16 +32,16 @@ public NetLogicData() { logicEntrySet = new Object2ObjectOpenHashMap<>(4); } - private NetLogicData(Object2ObjectOpenHashMap> logicEntrySet) { + private NetLogicData(Object2ObjectOpenHashMap> logicEntrySet) { this.logicEntrySet = logicEntrySet; } /** - * If the {@link INetLogicEntry#union(INetLogicEntry)} operation is not supported for this entry, + * If the {@link NetLogicEntry#union(NetLogicEntry)} operation is not supported for this entry, * nothing happens if an entry is already present. */ - public NetLogicData mergeLogicEntry(INetLogicEntry entry) { - INetLogicEntry current = logicEntrySet.get(entry.getName()); + public NetLogicData mergeLogicEntry(NetLogicEntry entry) { + NetLogicEntry current = logicEntrySet.get(entry.getName()); if (current == null) return setLogicEntry(entry); if (entry.getClass().isInstance(current)) { @@ -57,7 +51,7 @@ public NetLogicData mergeLogicEntry(INetLogicEntry entry) { return setLogicEntry(entry); } - public NetLogicData setLogicEntry(INetLogicEntry entry) { + public NetLogicData setLogicEntry(NetLogicEntry entry) { entry.registerToNetLogicData(this); logicEntrySet.put(entry.getName(), entry); this.markLogicEntryAsUpdated(entry, true); @@ -67,7 +61,7 @@ public NetLogicData setLogicEntry(INetLogicEntry entry) { /** * Returns all registered logic entries; this should be treated in read-only manner. */ - public ObjectCollection> getEntries() { + public ObjectCollection> getEntries() { return logicEntrySet.values(); } @@ -76,12 +70,12 @@ public void clearData() { logicEntrySet.trim(4); } - public NetLogicData removeLogicEntry(@NotNull INetLogicEntry key) { + public NetLogicData removeLogicEntry(@NotNull NetLogicEntry key) { return removeLogicEntry(key.getName()); } public NetLogicData removeLogicEntry(@NotNull String key) { - INetLogicEntry entry = logicEntrySet.remove(key); + NetLogicEntry entry = logicEntrySet.remove(key); if (entry != null) { entry.deregisterFromNetLogicData(this); this.listeners.forEach(l -> l.markChanged(entry, true, true)); @@ -91,17 +85,17 @@ public NetLogicData removeLogicEntry(@NotNull String key) { } @Override - public void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChange) { + public void markLogicEntryAsUpdated(NetLogicEntry entry, boolean fullChange) { this.listeners.forEach(l -> l.markChanged(entry, false, fullChange)); } @Nullable - public INetLogicEntry getLogicEntryNullable(@NotNull String key) { + public NetLogicEntry getLogicEntryNullable(@NotNull String key) { return logicEntrySet.get(key); } @Nullable - public > T getLogicEntryNullable(@NotNull T key) { + public > T getLogicEntryNullable(@NotNull T key) { try { return (T) logicEntrySet.get(key.getName()); } catch (ClassCastException ignored) { @@ -110,7 +104,7 @@ public void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChan } @NotNull - public > T getLogicEntryDefaultable(@NotNull T key) { + public > T getLogicEntryDefaultable(@NotNull T key) { try { T returnable = (T) logicEntrySet.get(key.getName()); return returnable == null ? key : returnable; @@ -119,9 +113,15 @@ public void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChan } } + @Contract("null, null -> null; !null, _ -> new; _, !null -> new") + public static @Nullable NetLogicData unionNullable(@Nullable NetLogicData sourceData, @Nullable NetLogicData targetData) { + if (sourceData == null && targetData == null) return null; + return union(sourceData == null ? targetData : sourceData, sourceData == null ? null : targetData); + } + @Contract("_, _ -> new") public static @NotNull NetLogicData union(@NotNull NetLogicData sourceData, @Nullable NetLogicData targetData) { - Object2ObjectOpenHashMap> newLogic = new Object2ObjectOpenHashMap<>( + Object2ObjectOpenHashMap> newLogic = new Object2ObjectOpenHashMap<>( sourceData.logicEntrySet); if (targetData != null) { for (String key : newLogic.keySet()) { @@ -134,7 +134,7 @@ public void markLogicEntryAsUpdated(INetLogicEntry entry, boolean fullChan @Contract("_, _ -> new") public static @NotNull NetLogicData union(@NotNull NetLogicData first, @NotNull NetLogicData... others) { - Object2ObjectOpenHashMap> newLogic = new Object2ObjectOpenHashMap<>( + Object2ObjectOpenHashMap> newLogic = new Object2ObjectOpenHashMap<>( first.logicEntrySet); for (NetLogicData other : others) { for (String key : newLogic.keySet()) { @@ -152,7 +152,7 @@ public void addListener(LogicDataListener listener) { @Override public NBTTagList serializeNBT() { NBTTagList list = new NBTTagList(); - for (INetLogicEntry entry : getEntries()) { + for (NetLogicEntry entry : getEntries()) { NBTTagCompound tag = new NBTTagCompound(); tag.setTag("Tag", entry.serializeNBT()); tag.setString("Name", entry.getName()); @@ -166,8 +166,8 @@ public void deserializeNBT(NBTTagList nbt) { for (int i = 0; i < nbt.tagCount(); i++) { NBTTagCompound tag = nbt.getCompoundTagAt(i); String key = tag.getString("Name"); - INetLogicEntry entry = this.logicEntrySet.get(key); - if (entry == null) entry = getSupplier(key).get(); + NetLogicEntry entry = this.logicEntrySet.get(key); + if (entry == null) entry = NetLogicRegistry.getSupplierNotNull(key).get(); if (entry == null) continue; entry.deserializeNBTNaive(tag.getTag("Tag")); } @@ -176,7 +176,7 @@ public void deserializeNBT(NBTTagList nbt) { @Override public void encode(PacketBuffer buf) { buf.writeVarInt(getEntries().size()); - for (INetLogicEntry entry : getEntries()) { + for (NetLogicEntry entry : getEntries()) { buf.writeString(entry.getName()); entry.encode(buf, true); } @@ -188,9 +188,9 @@ public void decode(PacketBuffer buf) { int entryCount = buf.readVarInt(); for (int i = 0; i < entryCount; i++) { String name = buf.readString(255); - INetLogicEntry existing = getSupplier(name).get(); + NetLogicEntry existing = NetLogicRegistry.getSupplierErroring(name).get(); if (existing == null) - throw new RuntimeException("Could not find a matching supplier for an encoded INetLogicEntry. " + + throw new RuntimeException("Could not find a matching supplier for an encoded NetLogicEntry. " + "This suggests that the server and client have different GT versions or modifications."); existing.registerToNetLogicData(this); existing.decode(buf); @@ -199,10 +199,6 @@ public void decode(PacketBuffer buf) { this.logicEntrySet.trim(); } - private static Supplier> getSupplier(String identifier) { - return GTGraphGatherables.getLogicsRegistry().getOrDefault(identifier, () -> null); - } - public LogicDataListener createListener(ILogicDataListener listener) { return new LogicDataListener(listener); } @@ -215,7 +211,7 @@ private LogicDataListener(ILogicDataListener listener) { this.listener = listener; } - private void markChanged(INetLogicEntry updatedEntry, boolean removed, boolean fullChange) { + private void markChanged(NetLogicEntry updatedEntry, boolean removed, boolean fullChange) { this.listener.markChanged(updatedEntry, removed, fullChange); } @@ -228,6 +224,6 @@ public void invalidate() { @FunctionalInterface public interface ILogicDataListener { - void markChanged(INetLogicEntry updatedEntry, boolean removed, boolean fullChange); + void markChanged(NetLogicEntry updatedEntry, boolean removed, boolean fullChange); } } diff --git a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java similarity index 61% rename from src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java rename to src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java index f95edba34c7..75b7b95091e 100644 --- a/src/main/java/gregtech/api/graphnet/logic/INetLogicEntry.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java @@ -10,17 +10,30 @@ import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** - * Note - all implementers of this interface are suggested to be final, in order to avoid unexpected - * {@link #union(INetLogicEntry)} behavior. + * Note - all extenders of this class are suggested to be final, in order to avoid unexpected + * {@link #union(NetLogicEntry)} behavior. */ -public interface INetLogicEntry, N extends NBTBase> extends INBTSerializable, - IStringSerializable, - IPacket { +public abstract class NetLogicEntry, N extends NBTBase> + implements INBTSerializable, IStringSerializable, IPacket { - default void deserializeNBTNaive(NBTBase nbt) { + private final @NotNull String name; + + protected NetLogicEntry(@NotNull String name) { + this.name = name; + NetLogicRegistry.register(this); + } + + @Override + public final @NotNull String getName() { + return name; + } + + public void deserializeNBTNaive(NBTBase nbt) { deserializeNBT((N) nbt); } @@ -28,13 +41,13 @@ default void deserializeNBTNaive(NBTBase nbt) { * Returns null if the operation is not supported. */ @Nullable - default T union(INetLogicEntry other) { + public T union(NetLogicEntry other) { return null; } /** * Controls whether this logic entry should be merged to a MultiNodeHelper, if one is declared. - * The data entry must support {@link #merge(NetNode, INetLogicEntry)} with other entries of the same type, + * The data entry must support {@link #merge(NetNode, NetLogicEntry)} with other entries of the same type, * so that new nodes being added to the MultiNodeHelper can merge in. The multi node helper will ensure that * all nodes registered to it contain the same object that their entries have been merged to, and when a node * leaves the multi node helper {@link #unmerge(NetNode)} will be called for it. Server-Client sync is handled @@ -42,7 +55,7 @@ default T union(INetLogicEntry other) { * * @return whether logic entry should be merged to a MultiNodeHelper. */ - default boolean mergedToMultiNodeHelper() { + public boolean mergedToMultiNodeHelper() { return false; } @@ -50,7 +63,7 @@ default boolean mergedToMultiNodeHelper() { * Called when this logic entry is added to a MultiNodeHelper. Any data syncing should go through the * MultiNodeHelper after this method is called. */ - default void registerToMultiNodeHelper(MultiNodeHelper helper) {} + public void registerToMultiNodeHelper(MultiNodeHelper helper) {} /** * Should be used exclusively for {@link gregtech.api.graphnet.MultiNodeHelper} logic. @@ -58,30 +71,30 @@ default void registerToMultiNodeHelper(MultiNodeHelper helper) {} * @param otherOwner the net node being merged in * @param other the logic being merged in */ - default void merge(NetNode otherOwner, INetLogicEntry other) {} + public void merge(NetNode otherOwner, NetLogicEntry other) {} /** * Should be used exclusively for {@link gregtech.api.graphnet.MultiNodeHelper} logic.
* Cannot be passed a logic entry since said logic entry would just be the instance this is being called for; - * if your logic needs to keep track then populate a map during {@link #merge(NetNode, INetLogicEntry)}. + * if your logic needs to keep track then populate a map during {@link #merge(NetNode, NetLogicEntry)}. * Keep in mind that this can be called for the data's original owner, despite - * {@link #merge(NetNode, INetLogicEntry)} not being called for the original owner. + * {@link #merge(NetNode, NetLogicEntry)} not being called for the original owner. * * @param entryOwner the node being unmerged. */ - default void unmerge(NetNode entryOwner) {} + public void unmerge(NetNode entryOwner) {} - default void registerToNetLogicData(NetLogicData data) {} + public void registerToNetLogicData(NetLogicData data) {} - default void deregisterFromNetLogicData(NetLogicData data) {} + public void deregisterFromNetLogicData(NetLogicData data) {} - T getNew(); + public abstract @NotNull T getNew(); - default T cast(INetLogicEntry entry) { + public T cast(NetLogicEntry entry) { return (T) entry; } - default void encode(PacketBuffer buf) { + public void encode(PacketBuffer buf) { encode(buf, true); } @@ -89,9 +102,9 @@ default void encode(PacketBuffer buf) { * @param fullChange allows for less-full buffers to be sent and received. * Useful for logics that can be partially modified, see {@link TemperatureLogic} */ - void encode(PacketBuffer buf, boolean fullChange); + public abstract void encode(PacketBuffer buf, boolean fullChange); - default void decode(PacketBuffer buf) { + public void decode(PacketBuffer buf) { decode(buf, true); } @@ -99,5 +112,5 @@ default void decode(PacketBuffer buf) { * @param fullChange allows for less-full buffers to be sent and received. * Useful for logics that can be partially modified, see {@link TemperatureLogic} */ - void decode(PacketBuffer buf, boolean fullChange); + public abstract void decode(PacketBuffer buf, boolean fullChange); } diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java new file mode 100644 index 00000000000..4e3ea2f3ccf --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java @@ -0,0 +1,36 @@ +package gregtech.api.graphnet.logic; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.Supplier; + +public final class NetLogicRegistry { + + private static final Map>> REGISTRY = new Object2ObjectOpenHashMap<>(); + + static void register(NetLogicEntry entry) { + REGISTRY.putIfAbsent(entry.getName(), entry::getNew); + } + + public static @Nullable Supplier<@NotNull NetLogicEntry> getSupplierNullable(String name) { + return REGISTRY.get(name); + } + + public static @NotNull Supplier<@Nullable NetLogicEntry> getSupplierNotNull(String name) { + return REGISTRY.getOrDefault(name, () -> null); + } + + public static @NotNull Supplier<@NotNull NetLogicEntry> getSupplierErroring(String name) { + Supplier> supplier = REGISTRY.get(name); + if (supplier == null) throwNonexistenceError(); + return supplier; + } + + public static void throwNonexistenceError() { + throw new RuntimeException("Could not find a matching supplier for an encoded NetLogicEntry. " + + "This suggests that the server and client have different GT versions or modifications."); + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java b/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java index 020645598e0..6d6f47ce1a2 100644 --- a/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java @@ -6,20 +6,17 @@ public final class ThroughputLogic extends AbstractLongLogicData other) { + public ThroughputLogic union(NetLogicEntry other) { if (other instanceof ThroughputLogic l) { return this.getValue() < l.getValue() ? this : l; } else return this; diff --git a/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java index abe13884fd4..7ebcfb12121 100644 --- a/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java @@ -6,20 +6,17 @@ public final class WeightFactorLogic extends AbstractDoubleLogicData other) { + public WeightFactorLogic union(NetLogicEntry other) { if (other instanceof WeightFactorLogic l) { return getWith(this.getValue() + l.getValue()); } else return this; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 64f0fefa64e..7f25a8a7274 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -9,11 +9,10 @@ import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.pipenet.predicate.ShutterPredicate; +import gregtech.api.graphnet.predicate.EdgePredicate; import gregtech.api.graphnet.worldnet.WorldNet; import gregtech.api.util.GTUtility; import gregtech.api.util.IDirtyNotifiable; -import gregtech.common.covers.CoverShutter; import it.unimi.dsi.fastutil.Hash; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; @@ -27,6 +26,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Function; @@ -68,6 +69,7 @@ public void setWorld(World world) { * @param node the associated node. */ public void updatePredication(@NotNull WorldPipeNetNode node, @NotNull PipeTileEntity tile) { + boolean dirty = false; for (EnumFacing facing : EnumFacing.VALUES) { PipeTileEntity neighbor = tile.getPipeNeighbor(facing, false); if (neighbor == null) continue; @@ -75,9 +77,10 @@ public void updatePredication(@NotNull WorldPipeNetNode node, @NotNull PipeTileE if (neighborNode == null) continue; NetEdge edge = getEdge(node, neighborNode); if (edge == null) continue; - predicateEdge(edge, node, tile.getCoverHolder().getCoverAtSide(facing), neighborNode, + dirty |= predicateEdge(edge, node, tile.getCoverHolder().getCoverAtSide(facing), neighborNode, neighbor.getCoverHolder().getCoverAtSide(facing.getOpposite())); } + if (dirty) markDirty(); } /** @@ -88,28 +91,40 @@ public void updatePredication(@NotNull WorldPipeNetNode node, @NotNull PipeTileE * @param coverSource the cover on the source facing the target. * @param target the target of the edge. * @param coverTarget the cover on the target facing the source. + * @return whether the predication state has changed and this net needs to be marked dirty. */ - public void predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode source, @Nullable Cover coverSource, + public boolean predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode source, @Nullable Cover coverSource, @NotNull WorldPipeNetNode target, @Nullable Cover coverTarget) { + Map> prevValue = + new Object2ObjectOpenHashMap<>(edge.getPredicateHandler().getPredicateSet()); edge.getPredicateHandler().clearPredicates(); - shutterify(edge, coverSource, coverTarget); + coverPredication(edge, coverSource, coverTarget); + boolean edgeSame = !prevValue.equals(edge.getPredicateHandler().getPredicateSet()); if (getGraph().isDirected()) { edge = getEdge(target, source); - if (edge == null) return; + if (edge == null) return edgeSame; + if (edgeSame) { + prevValue.clear(); + prevValue.putAll(edge.getPredicateHandler().getPredicateSet()); + } edge.getPredicateHandler().clearPredicates(); - shutterify(edge, coverSource, coverTarget); + coverPredication(edge, coverSource, coverTarget); + if (edgeSame) { + edgeSame = !prevValue.equals(edge.getPredicateHandler().getPredicateSet()); + } } + return edgeSame; } - protected final void shutterify(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { - if (a instanceof CoverShutter s && !s.canPipePassThrough()) { - edge.getPredicateHandler().setPredicate(ShutterPredicate.INSTANCE); - return; - } - if (b instanceof CoverShutter s && !s.canPipePassThrough()) { - edge.getPredicateHandler().setPredicate(ShutterPredicate.INSTANCE); - } - } + /** + * Preferred method to override if your net has custom predication rules that only depend on covers. + * If the net is directed, this method will be called twice, so special handling for directedness is not needed. + * + * @param edge the edge to predicate + * @param a the cover on the source of the edge + * @param b the cover on the sink of the edge + */ + protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) {} public abstract Capability[] getTargetCapabilities(); @@ -126,7 +141,7 @@ protected final void shutterify(@NotNull NetEdge edge, @Nullable Cover a, @Nulla } protected Stream<@NotNull WorldPipeNet> sameDimensionNetsStream() { - return dimensionNets.get(this.getDimension()).stream().filter(Objects::nonNull); + return dimensionNets.getOrDefault(this.getDimension(), Collections.emptySet()).stream().filter(Objects::nonNull); } public void synchronizeNode(WorldPipeNetNode node) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java index 1652dbbe765..de0a1cd21fb 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.pipenet.logic; import gregtech.api.cover.Cover; -import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.util.DimensionFacingPos; @@ -19,7 +19,7 @@ import java.lang.ref.WeakReference; -public class EdgeCoverReferenceLogic implements INetLogicEntry { +public final class EdgeCoverReferenceLogic extends NetLogicEntry { public static final EdgeCoverReferenceLogic INSTANCE = new EdgeCoverReferenceLogic(); @@ -30,6 +30,10 @@ public class EdgeCoverReferenceLogic implements INetLogicEntry coverTarget; private DimensionFacingPos coverTargetPos; + public EdgeCoverReferenceLogic() { + super("EdgeCoverReference"); + } + @Contract("_,_ -> this") public EdgeCoverReferenceLogic coverSource(@NotNull DimensionFacingPos pos, @NotNull Cover cover) { this.coverSource = new WeakReference<>(cover); @@ -102,11 +106,6 @@ public EdgeCoverReferenceLogic coverTarget(@NotNull DimensionFacingPos pos, @Not } } - @Override - public @NotNull String getName() { - return "EdgeCoverReference"; - } - @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); @@ -130,7 +129,7 @@ public void deserializeNBT(NBTTagCompound nbt) { } @Override - public EdgeCoverReferenceLogic getNew() { + public @NotNull EdgeCoverReferenceLogic getNew() { return new EdgeCoverReferenceLogic(); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index adc11af9d07..2328e4b3811 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -2,7 +2,7 @@ import gregtech.api.graphnet.MultiNodeHelper; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.INetLogicEntryListener; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.pipenet.NodeLossResult; @@ -24,7 +24,7 @@ import java.lang.ref.WeakReference; -public final class TemperatureLogic implements INetLogicEntry { +public final class TemperatureLogic extends NetLogicEntry { public static final TemperatureLogic INSTANCE = new TemperatureLogic(); @@ -43,7 +43,9 @@ public final class TemperatureLogic implements INetLogicEntry(null); } - public TemperatureLogic getNew() { + public @NotNull TemperatureLogic getNew() { return new TemperatureLogic(); } @@ -239,22 +241,17 @@ public int getThermalMass() { return thermalMass; } - @Override - public @NotNull String getName() { - return "Temperature"; - } - @Override public boolean mergedToMultiNodeHelper() { return true; } @Override - public void merge(NetNode otherOwner, INetLogicEntry unknown) { + public void merge(NetNode otherOwner, NetLogicEntry unknown) { if (!(unknown instanceof TemperatureLogic other)) return; - if (other.getTemperatureMinimum() > this.getTemperatureMinimum()) + if (other.getTemperatureMinimum() < this.getTemperatureMinimum()) this.setTemperatureMinimum(other.getTemperatureMinimum()); - if (other.getTemperatureMaximum() < this.getTemperatureMaximum()) + if (other.getTemperatureMaximum() > this.getTemperatureMaximum()) this.setTemperatureMaximum(other.getTemperatureMaximum()); // since merge also occurs during nbt load, ignore the other's thermal energy. if (other.getThermalMass() < this.getThermalMass()) this.setThermalMass(other.getThermalMass()); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java index cd56daac40f..acefce9b259 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java @@ -65,7 +65,7 @@ public NBTTagCompound serializeNBT() { tag.setInteger("Ordinal", function.ordinal()); tag.setFloat("X", factorX); if (factorY != 0) tag.setFloat("Y", factorY); - return null; + return tag; } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java new file mode 100644 index 00000000000..5981e24685b --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java @@ -0,0 +1,38 @@ +package gregtech.api.graphnet.pipenet.physical; + +import gregtech.api.util.GTUtility; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.Comparator; +import java.util.Map; +import java.util.Set; + +public final class PipeStructureRegistry { + + private static final Map, ObjectAVLTreeSet> REGISTRY = new Object2ObjectOpenHashMap<>(); + + private static final Comparator comparator = Comparator.comparing(IPipeStructure::getName); + + public static void register(@NotNull T structure) { + ObjectAVLTreeSet structures = (ObjectAVLTreeSet) REGISTRY.get(structure.getClass()); + if (structures == null) { + structures = new ObjectAVLTreeSet<>(comparator); + REGISTRY.put(structure.getClass(), structures); + } + structures.add(structure); + } + + /** + * Do not modify the returned set. + */ + public static @NotNull Set getStructures(Class structureClass) { + GTUtility.forceInitialization(structureClass); + ObjectAVLTreeSet structures = (ObjectAVLTreeSet) REGISTRY.get(structureClass); + if (structures == null) return Collections.emptySet(); + return structures; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java index 095f8dae786..5911e31339e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeBlock.java @@ -17,13 +17,13 @@ public class ItemPipeBlock extends ItemBlock { - public ItemPipeBlock(WorldPipeBlock block) { + public ItemPipeBlock(PipeBlock block) { super(block); } @Override - public @NotNull WorldPipeBlock getBlock() { - return (WorldPipeBlock) super.getBlock(); + public @NotNull PipeBlock getBlock() { + return (PipeBlock) super.getBlock(); } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java index 46fd94c0207..c6123e0c347 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java @@ -3,7 +3,6 @@ import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; -import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.ActivablePipeModel; @@ -21,7 +20,7 @@ import java.lang.ref.WeakReference; -public abstract class PipeActivableBlock extends WorldPipeBlock { +public abstract class PipeActivableBlock extends PipeBlock { public PipeActivableBlock(IPipeStructure structure) { super(structure); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java similarity index 88% rename from src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java rename to src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 410e3b7019c..4e299d4761e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/WorldPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -1,5 +1,7 @@ package gregtech.api.graphnet.pipenet.physical.block; +import codechicken.lib.raytracer.IndexedCuboid6; + import gregtech.api.block.BuiltInRenderBlock; import gregtech.api.cover.Cover; import gregtech.api.cover.CoverRayTracer; @@ -20,6 +22,8 @@ import gregtech.common.ConfigHolder; import gregtech.common.blocks.BlockFrame; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import net.minecraft.block.Block; import net.minecraft.block.SoundType; import net.minecraft.block.state.BlockFaceShape; @@ -61,7 +65,7 @@ import java.util.List; import java.util.Map; -public abstract class WorldPipeBlock extends BuiltInRenderBlock { +public abstract class PipeBlock extends BuiltInRenderBlock { // do not touch these two unless you know what you are doing protected final ThreadLocal lastTilePos = ThreadLocal.withInitial(() -> new BlockPos(0, 0, 0)); @@ -69,7 +73,7 @@ public abstract class WorldPipeBlock extends BuiltInRenderBlock { private final IPipeStructure structure; - public WorldPipeBlock(IPipeStructure structure) { + public PipeBlock(IPipeStructure structure) { super(net.minecraft.block.material.Material.IRON); this.structure = structure; setTranslationKey(structure.getName()); @@ -97,12 +101,12 @@ public void doPlacementLogic(PipeTileEntity tile, EnumFacing placedBlockSearchSi // second check -- connect to matching mark pipes if side matches or config allows. if (tile.getPaintingColor() == other.getPaintingColor() && (facing == placedBlockSearchSide || !ConfigHolder.machines.gt6StylePipesCables)) { - connectTile(tile, other, facing); + if (coverCheck(tile, other, facing)) connectTile(tile, other, facing); continue; } // third check -- connect to pipes with an open connection, no matter the mark status. if (other.isConnected(facing.getOpposite())) { - connectTile(tile, other, facing); + if (coverCheck(tile, other, facing)) connectTile(tile, other, facing); } } else if (facing == placedBlockSearchSide) { // if the placed on tile supports one of our capabilities, connect to it. @@ -130,30 +134,58 @@ public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @ if (cover != null) { if (ToolHelper.isTool(item, ToolClasses.SCREWDRIVER)) { EnumActionResult result = cover.onScrewdriverClick(playerIn, hand, trace); - if (result != EnumActionResult.PASS) return result == EnumActionResult.SUCCESS; + if (result != EnumActionResult.PASS) { + if (result == EnumActionResult.SUCCESS) { + ToolHelper.damageItem(item, playerIn); + ToolHelper.playToolSound(item, playerIn); + return true; + } + return false; + } } if (ToolHelper.isTool(item, ToolClasses.SOFT_MALLET)) { EnumActionResult result = cover.onSoftMalletClick(playerIn, hand, trace); - if (result != EnumActionResult.PASS) return result == EnumActionResult.SUCCESS; + if (result != EnumActionResult.PASS) { + if (result == EnumActionResult.SUCCESS) { + ToolHelper.damageItem(item, playerIn); + ToolHelper.playToolSound(item, playerIn); + return true; + } + return false; + } } EnumActionResult result = cover.onRightClick(playerIn, hand, trace); - if (result != EnumActionResult.PASS) return result == EnumActionResult.SUCCESS; + if (result == EnumActionResult.SUCCESS) return true; + // allow crowbar to run even if the right click returns a failure if (ToolHelper.isTool(item, ToolClasses.CROWBAR)) { - coverable.dropCover(facing); + coverable.removeCover(facing); + ToolHelper.damageItem(item, playerIn); + ToolHelper.playToolSound(item, playerIn); return true; } - } + if (result == EnumActionResult.FAIL) return false; + } if (isPipeTool(item)) { PipeTileEntity other = tile.getPipeNeighbor(facing, true); if (playerIn.isSneaking() && allowsBlocking()) { + ToolHelper.damageItem(item, playerIn); + ToolHelper.playToolSound(item, playerIn); if (tile.isBlocked(facing)) unblockTile(tile, other, facing); else blockTile(tile, other, facing); } else { - if (tile.isConnected(facing)) disconnectTile(tile, other, facing); - else connectTile(tile, other, facing); + if (tile.isConnected(facing)) { + ToolHelper.damageItem(item, playerIn); + ToolHelper.playToolSound(item, playerIn); + disconnectTile(tile, other, facing); + } + else if (coverCheck(tile, other, facing)) { + ToolHelper.damageItem(item, playerIn); + ToolHelper.playToolSound(item, playerIn); + connectTile(tile, other, facing); + } } return true; } @@ -181,6 +213,17 @@ public void onBlockClicked(@NotNull World worldIn, @NotNull BlockPos pos, @NotNu super.onBlockClicked(worldIn, pos, playerIn); } + /** + * Should be called to verify if a connection can be formed before + * {@link #connectTile(PipeTileEntity, PipeTileEntity, EnumFacing)} is called. + * @return whether the connection is allowed. + */ + public static boolean coverCheck(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, EnumFacing facing) { + Cover tileCover = tile.getCoverHolder().getCoverAtSide(facing); + Cover acrossCover = tileAcross != null ? tileAcross.getCoverHolder().getCoverAtSide(facing.getOpposite()) : null; + return (tileCover == null || tileCover.canPipePassThrough()) && (acrossCover == null || acrossCover.canPipePassThrough()); + } + public static void connectTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, EnumFacing facing) { // abort connection if either tile refuses it. if (!tile.canConnectTo(facing) || tileAcross != null && !tileAcross.canConnectTo(facing.getOpposite())) return; @@ -389,14 +432,18 @@ public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World wor @NotNull AxisAlignedBB entityBox, @NotNull List collidingBoxes, @Nullable Entity entityIn, boolean isActualState) { PipeTileEntity tile = getTileEntity(worldIn, pos); - if (hasPipeCollisionChangingItem(worldIn, pos, entityIn)) { - addCollisionBoxToList(pos, entityBox, collidingBoxes, FULL_BLOCK_AABB); - return; - } if (tile != null) { + if (hasPipeCollisionChangingItem(worldIn, pos, entityIn)) { + addCollisionBoxToList(pos, entityBox, collidingBoxes, FULL_BLOCK_AABB); + } else { + List covers = new ObjectArrayList<>(); + tile.getCoverHolder().addCoverCollisionBoundingBox(covers); + for (IndexedCuboid6 cuboid6 : covers) { + addCollisionBoxToList(pos, entityBox, collidingBoxes, cuboid6.aabb()); + } + } if (tile.getFrameMaterial() != null) { addCollisionBoxToList(pos, entityBox, collidingBoxes, BlockFrame.COLLISION_BOX); - return; } for (AxisAlignedBB axisAlignedBB : getStructure().getPipeBoxes(tile)) { addCollisionBoxToList(pos, entityBox, collidingBoxes, axisAlignedBB); @@ -464,7 +511,7 @@ public boolean isPipeItem(ItemStack stack) { } @Nullable - public static WorldPipeBlock getBlockFromItem(@NotNull ItemStack stack) { + public static PipeBlock getBlockFromItem(@NotNull ItemStack stack) { if (stack.getItem() instanceof ItemPipeBlock block) return block.getBlock(); else return null; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index 2174146dd1d..8415ec0c419 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -36,7 +36,7 @@ import java.lang.ref.WeakReference; import java.util.List; -public abstract class PipeMaterialBlock extends WorldPipeBlock { +public abstract class PipeMaterialBlock extends PipeBlock { public final MaterialRegistry registry; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java index 9bdee8c97c7..91f69fe336d 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java @@ -1,7 +1,6 @@ package gregtech.api.graphnet.pipenet.physical.tile; import gregtech.api.capability.GregtechDataCodes; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.client.renderer.pipe.ActivablePipeModel; import net.minecraft.network.PacketBuffer; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 851e8fac3b2..ab0c0455ee1 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -1,29 +1,26 @@ package gregtech.api.graphnet.pipenet.physical.tile; -import codechicken.lib.render.CCRenderState; -import codechicken.lib.vec.Matrix4; - import gregtech.api.GTValues; import gregtech.api.GregTechAPI; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; -import gregtech.api.graphnet.gather.GTGraphGatherables; -import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.NetLogicRegistry; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.IInsulatable; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.metatileentity.NeighborCacheTileEntityBase; import gregtech.api.unification.material.Material; +import gregtech.api.util.GTUtility; import gregtech.client.particle.GTOverheatParticle; import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.common.blocks.MetaBlocks; -import it.unimi.dsi.fastutil.Hash; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import net.minecraft.block.state.IBlockState; @@ -35,7 +32,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ITickable; @@ -45,7 +41,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldServer; -import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.property.IExtendedBlockState; @@ -61,7 +56,6 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.function.Consumer; @@ -427,8 +421,8 @@ public NetLogicData getNetLogicData(String netName) { } @Override - public @NotNull WorldPipeBlock getBlockType() { - return (WorldPipeBlock) super.getBlockType(); + public @NotNull PipeBlock getBlockType() { + return (PipeBlock) super.getBlockType(); } @Override @@ -445,7 +439,7 @@ protected void initialize() { this.listeners.forEach(NetLogicData.LogicDataListener::invalidate); this.listeners.clear(); boolean firstNode = true; - for (WorldPipeNetNode node : WorldPipeBlock.getNodesForTile(this)) { + for (WorldPipeNetNode node : PipeBlock.getNodesForTile(this)) { this.addCapabilities(node.getNet().getNewCapabilityObjects(node)); this.netCapabilities.put(node, new PipeCapabilityWrapper(node)); String netName = node.getNet().mapName; @@ -514,6 +508,7 @@ public void writeInitialSyncData(@NotNull PacketBuffer buf) { buf.writeString(entry.getKey()); entry.getValue().encode(buf); } + this.getCoverHolder().writeInitialSyncData(buf); } @Override @@ -533,6 +528,7 @@ public void receiveInitialSyncData(@NotNull PacketBuffer buf) { data.decode(buf); netLogicDatas.put(key, data); } + this.getCoverHolder().readInitialSyncData(buf); } scheduleRenderUpdate(); } @@ -550,8 +546,7 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { this.netLogicDatas.computeIfPresent(netName, (k, v) -> v.removeLogicEntry(identifier)); } else { if (fullChange) { - INetLogicEntry logic = GTGraphGatherables.getLogicsRegistry() - .getOrDefault(identifier, () -> null).get(); + NetLogicEntry logic = NetLogicRegistry.getSupplierErroring(identifier).get(); logic.decode(buf, fullChange); this.netLogicDatas.compute(netName, (k, v) -> { if (v == null) v = new NetLogicData(); @@ -561,7 +556,7 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { } else { NetLogicData data = this.netLogicDatas.get(netName); if (data != null) { - INetLogicEntry entry = data.getLogicEntryNullable(identifier); + NetLogicEntry entry = data.getLogicEntryNullable(identifier); if (entry != null) entry.decode(buf); } else return; } @@ -668,6 +663,13 @@ public void markDirty() { public void markAsDirty() { markDirty(); // this most notably gets called when the covers of a pipe get updated, aka the edge predicates need syncing. + for (EnumFacing facing : EnumFacing.VALUES) { + if (!GTUtility.evalMask(facing, connectionMask)) continue; + Cover cover = getCoverHolder().getCoverAtSide(facing); + if (cover != null && !cover.canPipePassThrough()) { + PipeBlock.disconnectTile(this, getPipeNeighbor(facing, true), facing); + } + } for (var node : this.netCapabilities.keySet()) { node.getNet().updatePredication(node, this); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java b/src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java new file mode 100644 index 00000000000..638606598bb --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java @@ -0,0 +1,52 @@ +package gregtech.api.graphnet.pipenet.predicate; + +import gregtech.api.graphnet.predicate.EdgePredicate; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import net.minecraft.nbt.NBTTagByte; +import net.minecraft.nbt.NBTTagString; + +import org.jetbrains.annotations.NotNull; + +public final class BlockedPredicate extends EdgePredicate { + + public static final BlockedPredicate INSTANCE = new BlockedPredicate(); + + private BlockedPredicate() { + super("Blocked"); + } + + @Override + @Deprecated + public @NotNull BlockedPredicate getNew() { + return INSTANCE; + } + + @Override + public NBTTagByte serializeNBT() { + return new NBTTagByte((byte) 0); + } + + @Override + public void deserializeNBT(NBTTagByte nbt) {} + + @Override + public boolean andy() { + return true; + } + + @Override + public boolean test(IPredicateTestObject object) { + return false; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof BlockedPredicate; + } + + @Override + public int hashCode() { + return 0; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java b/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java new file mode 100644 index 00000000000..877588e5a8b --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java @@ -0,0 +1,107 @@ +package gregtech.api.graphnet.pipenet.predicate; + +import gregtech.api.graphnet.predicate.EdgePredicate; + +import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import gregtech.common.covers.filter.BaseFilterContainer; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import net.minecraftforge.fluids.FluidStack; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +public final class FilterPredicate extends EdgePredicate { + + public static final FilterPredicate INSTANCE = new FilterPredicate(); + + private @Nullable BaseFilterContainer sourceFilter; + private @Nullable BaseFilterContainer targetFilter; + + private FilterPredicate() { + super("FluidFilter"); + } + + public void setSourceFilter(@Nullable BaseFilterContainer sourceFilter) { + this.sourceFilter = sourceFilter; + } + + public void setTargetFilter(@Nullable BaseFilterContainer targetFilter) { + this.targetFilter = targetFilter; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = new NBTTagCompound(); + if (sourceFilter != null) tag.setTag("Source", sourceFilter.serializeNBT()); + if (targetFilter != null) tag.setTag("Target", targetFilter.serializeNBT()); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + if (nbt.hasKey("Source")) { + sourceFilter = new GenericFilterContainer(); + sourceFilter.deserializeNBT(nbt.getCompoundTag("Source")); + } else sourceFilter = null; + if (nbt.hasKey("Target")) { + targetFilter = new GenericFilterContainer(); + targetFilter.deserializeNBT(nbt.getCompoundTag("Target")); + } else targetFilter = null; + } + + @Override + public boolean andy() { + return true; + } + + @Override + public @NotNull FilterPredicate getNew() { + return new FilterPredicate(); + } + + @Override + public boolean test(IPredicateTestObject object) { + if (!(object instanceof FluidTestObject fluid)) return false; + FluidStack stack = fluid.recombine(); + if (sourceFilter != null && !sourceFilter.test(stack)) return false; + return targetFilter == null || targetFilter.test(stack); + } + + private static class GenericFilterContainer extends BaseFilterContainer { + + protected GenericFilterContainer() { + super(() -> {}); + } + + @Override + protected boolean isItemValid(ItemStack stack) { + return true; + } + + @Override + protected String getFilterName() { + return ""; + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + FilterPredicate predicate = (FilterPredicate) o; + return Objects.equals(sourceFilter, predicate.sourceFilter) && + Objects.equals(targetFilter, predicate.targetFilter); + } + + @Override + public int hashCode() { + return Objects.hash(sourceFilter, targetFilter); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/predicate/ShutterPredicate.java b/src/main/java/gregtech/api/graphnet/pipenet/predicate/ShutterPredicate.java deleted file mode 100644 index 3a4edda56b3..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/predicate/ShutterPredicate.java +++ /dev/null @@ -1,44 +0,0 @@ -package gregtech.api.graphnet.pipenet.predicate; - -import gregtech.api.graphnet.predicate.IEdgePredicate; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import net.minecraft.nbt.NBTTagString; - -import org.jetbrains.annotations.NotNull; - -public final class ShutterPredicate implements IEdgePredicate { - - public static final ShutterPredicate INSTANCE = new ShutterPredicate(); - - private ShutterPredicate() {} - - @Override - @Deprecated - public ShutterPredicate getNew() { - return INSTANCE; - } - - @Override - public @NotNull String getName() { - return "Shuttered"; - } - - @Override - public NBTTagString serializeNBT() { - return new NBTTagString(); - } - - @Override - public void deserializeNBT(NBTTagString nbt) {} - - @Override - public boolean andy() { - return true; - } - - @Override - public boolean test(IPredicateTestObject object) { - return false; - } -} diff --git a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java new file mode 100644 index 00000000000..db7267691df --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java @@ -0,0 +1,63 @@ +package gregtech.api.graphnet.predicate; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import net.minecraft.nbt.NBTBase; +import net.minecraft.util.IStringSerializable; +import net.minecraftforge.common.util.INBTSerializable; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Note - all extenders of this class are suggested to be final, in order to avoid unexpected + * {@link #union(EdgePredicate)} behavior. + */ +public abstract class EdgePredicate, N extends NBTBase> + implements INBTSerializable, IStringSerializable { + + private final @NotNull String name; + + public EdgePredicate(@NotNull String name) { + this.name = name; + NetPredicateRegistry.register(this); + } + + @Override + public final @NotNull String getName() { + return name; + } + + public void deserializeNBTNaive(NBTBase nbt) { + deserializeNBT((N) nbt); + } + + /** + * Whether this predicate should behave in "and" fashion with other predicates.
+ *
+ * For example, if a predicate handler has 2 and-y predicates and 3 or-y predicates, + * the effective result of evaluation will be:
+ * (andy1) && (andy2) && (ory1 || ory2 || ory3) + */ + public abstract boolean andy(); + + @NotNull + public abstract T getNew(); + + public abstract boolean test(IPredicateTestObject object); + + /** + * Returns null if the operation is not supported. + */ + @Nullable + public T union(EdgePredicate other) { + return null; + } + + /** + * {@link Object#equals(Object)} should always have a good implementation for the sake of sameness checks. + */ + @Override + public abstract boolean equals(Object obj); +} diff --git a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java index 39fe69850f3..6a5f92257cd 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java +++ b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java @@ -1,7 +1,5 @@ package gregtech.api.graphnet.predicate; -import gregtech.api.graphnet.gather.GTGraphGatherables; -import gregtech.api.graphnet.gather.GatherPredicatesEvent; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTTagCompound; @@ -10,35 +8,29 @@ import net.minecraftforge.common.util.INBTSerializable; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.NotNull; import java.util.Map; import java.util.function.Predicate; -import java.util.function.Supplier; /** * Note - since the internal map representation encodes keys using {@link IStringSerializable#getName()} on predicates, - * making a predicate class return two different names is a valid way to register multiple instances.
- * Just make sure that a supplier is registered to {@link GatherPredicatesEvent} for all - * associated names, so that decoding from nbt and packets is possible. + * making a predicate class return two different names is a valid way to register multiple instances. */ public final class EdgePredicateHandler implements INBTSerializable, Predicate { - private final Map> predicateSet; + private final Map> predicateSet; public EdgePredicateHandler() { predicateSet = new Object2ObjectOpenHashMap<>(); } - private EdgePredicateHandler(Map> predicateSet) { - this.predicateSet = predicateSet; - } - /** - * If the {@link IEdgePredicate#union(IEdgePredicate)} operation is not supported for this predicate, + * If the {@link EdgePredicate#union(EdgePredicate)} operation is not supported for this predicate, * nothing happens if a predicate is already present. */ - public EdgePredicateHandler mergePredicate(IEdgePredicate predicate) { - IEdgePredicate current = predicateSet.get(predicate.getName()); + public EdgePredicateHandler mergePredicate(@NotNull EdgePredicate predicate) { + EdgePredicate current = predicateSet.get(predicate.getName()); if (current == null) return setPredicate(predicate); if (predicate.getClass().isInstance(current)) { @@ -48,13 +40,20 @@ public EdgePredicateHandler mergePredicate(IEdgePredicate predicate) { return setPredicate(predicate); } - public EdgePredicateHandler setPredicate(IEdgePredicate predicate) { + /** + * Do not modify the returned value + */ + public Map> getPredicateSet() { + return predicateSet; + } + + public EdgePredicateHandler setPredicate(@NotNull EdgePredicate predicate) { predicateSet.put(predicate.getName(), predicate); return this; } - public EdgePredicateHandler removePredicate(IEdgePredicate key) { - return removePredicate(key.getName()); + public EdgePredicateHandler removePredicate(@NotNull EdgePredicate predicate) { + return removePredicate(predicate.getName()); } public EdgePredicateHandler removePredicate(String key) { @@ -62,15 +61,28 @@ public EdgePredicateHandler removePredicate(String key) { return this; } + public boolean hasPredicate(@NotNull EdgePredicate predicate) { + return predicateSet.containsKey(predicate.getName()); + } + + public boolean hasPredicate(String key) { + return predicateSet.containsKey(key); + } + public void clearPredicates() { this.predicateSet.clear(); } + public boolean shouldIgnore() { + return predicateSet.isEmpty(); + } + @Override public boolean test(IPredicateTestObject iPredicateTestObject) { - // TODO predicate 'categories' or 'affinities' that determine order of operations with and-y and or-y behavior? + if (shouldIgnore()) return true; boolean result = false; - for (IEdgePredicate predicate : predicateSet.values()) { + for (EdgePredicate predicate : predicateSet.values()) { + // TODO predicate 'categories' or 'affinities' that determine order of operations with and-y and or-y behavior? boolean test = predicate.test(iPredicateTestObject); if (predicate.andy() && !test) return false; else result |= test; @@ -81,7 +93,7 @@ public boolean test(IPredicateTestObject iPredicateTestObject) { @Override public NBTTagList serializeNBT() { NBTTagList list = new NBTTagList(); - for (IEdgePredicate entry : predicateSet.values()) { + for (EdgePredicate entry : predicateSet.values()) { NBTTagCompound tag = new NBTTagCompound(); tag.setTag("Tag", entry.serializeNBT()); tag.setString("Name", entry.getName()); @@ -95,14 +107,10 @@ public void deserializeNBT(NBTTagList nbt) { for (int i = 0; i < nbt.tagCount(); i++) { NBTTagCompound tag = nbt.getCompoundTagAt(i); String key = tag.getString("Name"); - IEdgePredicate entry = this.predicateSet.get(key); - if (entry == null) entry = getSupplier(key).get(); + EdgePredicate entry = this.predicateSet.get(key); + if (entry == null) entry = NetPredicateRegistry.getSupplierNotNull(key).get(); if (entry == null) continue; entry.deserializeNBTNaive(tag.getTag("Tag")); } } - - private static Supplier> getSupplier(String identifier) { - return GTGraphGatherables.getPredicatesRegistry().getOrDefault(identifier, () -> null); - } } diff --git a/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java b/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java deleted file mode 100644 index db611221f29..00000000000 --- a/src/main/java/gregtech/api/graphnet/predicate/IEdgePredicate.java +++ /dev/null @@ -1,42 +0,0 @@ -package gregtech.api.graphnet.predicate; - -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import net.minecraft.nbt.NBTBase; -import net.minecraft.util.IStringSerializable; -import net.minecraftforge.common.util.INBTSerializable; - -import org.jetbrains.annotations.Nullable; - -/** - * Note - all implementers of this interface are suggested to be final, in order to avoid unexpected - * {@link #union(IEdgePredicate)} behavior. - */ -public interface IEdgePredicate, N extends NBTBase> - extends INBTSerializable, IStringSerializable { - - default void deserializeNBTNaive(NBTBase nbt) { - deserializeNBT((N) nbt); - } - - /** - * Whether this predicate should behave in "and" fashion with other predicates.
- *
- * For example, if a predicate handler has 2 and-y predicates and 3 or-y predicates, - * the effective result of evaluation will be:
- * (andy1) && (andy2) && (ory1 || ory2 || ory3) - */ - boolean andy(); - - T getNew(); - - boolean test(IPredicateTestObject object); - - /** - * Returns null if the operation is not supported. - */ - @Nullable - default T union(IEdgePredicate other) { - return null; - } -} diff --git a/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java new file mode 100644 index 00000000000..761274a2f66 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java @@ -0,0 +1,40 @@ +package gregtech.api.graphnet.predicate; + +import gregtech.api.graphnet.logic.NetLogicEntry; + +import gregtech.api.util.function.NullableSupplier; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.Supplier; + +public final class NetPredicateRegistry { + + private static final Map>> REGISTRY = new Object2ObjectOpenHashMap<>(); + + static void register(EdgePredicate predicate) { + REGISTRY.putIfAbsent(predicate.getName(), predicate::getNew); + } + + public static @Nullable Supplier> getSupplierNullable(String name) { + return REGISTRY.get(name); + } + + public static @NotNull NullableSupplier> getSupplierNotNull(String name) { + return REGISTRY.getOrDefault(name, () -> null); + } + + public static @NotNull Supplier> getSupplierErroring(String name) { + Supplier> supplier = REGISTRY.get(name); + if (supplier == null) throwNonexistenceError(); + return supplier; + } + + public static void throwNonexistenceError() { + throw new RuntimeException("Could not find a matching supplier for an encoded EdgePredicate. " + + "This suggests that the server and client have different GT versions or modifications."); + } +} diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java index 7880c75e928..a730f7d1397 100644 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java @@ -69,11 +69,9 @@ public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, boolean double weight = source.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue() + target.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue(); NetEdge edge = backer.addEdge(source, target, weight); - if (edge != null) initializeEdge(source, target, edge); if (bothWays) { if (this.getGraph().isDirected()) { - edge = backer.addEdge(target, source, weight); - if (edge != null) initializeEdge(target, source, edge); + backer.addEdge(target, source, weight); } return null; } else return edge; @@ -96,10 +94,6 @@ public void removeEdge(@NotNull NetNode source, @NotNull NetNode target, boolean } } - protected void initializeEdge(@NotNull NetNode source, @NotNull NetNode target, @NotNull NetEdge edge) { - edge.setData(NetLogicData.union(source.getData(), target.getData())); - } - @Override public void readFromNBT(@NotNull NBTTagCompound nbt) { backer.readFromNBT(nbt); diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java index 9edbdf108b7..2b0693f5531 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -30,9 +30,10 @@ public abstract class WorldNet extends WorldSavedData implements IGraphNet, Gene protected final GraphNetBacker backer; private World world; + private int fallbackDimensionID; @SafeVarargs - public WorldNet(String name, Function graphBuilder, + public WorldNet(String name, @NotNull Function graphBuilder, Function... algorithmBuilders) { super(name); this.backer = new GraphNetBacker(this, graphBuilder.apply(this), algorithmBuilders); @@ -97,11 +98,9 @@ public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, boolean double weight = source.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue() + target.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue(); NetEdge edge = backer.addEdge(source, target, weight); - if (edge != null) initializeEdge(source, target, edge); if (bothWays) { if (this.getGraph().isDirected()) { - edge = backer.addEdge(target, source, weight); - if (edge != null) initializeEdge(target, source, edge); + backer.addEdge(target, source, weight); } return null; } else return edge; @@ -124,21 +123,20 @@ public void removeEdge(@NotNull NetNode source, @NotNull NetNode target, boolean } } - protected void initializeEdge(@NotNull NetNode source, @NotNull NetNode target, @NotNull NetEdge edge) { - edge.setData(NetLogicData.union(source.getData(), target.getData())); - } - protected int getDimension() { - return world.provider.getDimension(); + if (world == null) return fallbackDimensionID; + else return world.provider.getDimension(); } @Override public void readFromNBT(@NotNull NBTTagCompound nbt) { + fallbackDimensionID = nbt.getInteger("Dimension"); backer.readFromNBT(nbt); } @Override public @NotNull NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { + compound.setInteger("Dimension", getDimension()); return backer.writeToNBT(compound); } diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index 541492e7123..aee6094333f 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -6,8 +6,13 @@ import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; + +import it.unimi.dsi.fastutil.objects.Object2ObjectRBTreeMap; + import net.minecraft.client.util.ITooltipFlag; import net.minecraft.item.ItemStack; +import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -17,12 +22,14 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.Map; public class PipeNetProperties implements IMaterialProperty, IPipeNetNodeHandler { - protected final Map, IPipeNetMaterialProperty> properties = new Object2ObjectOpenHashMap<>(); + protected final Map, IPipeNetMaterialProperty> properties = + new Object2ObjectRBTreeMap<>(Comparator.comparing(IPipeNetMaterialProperty.MaterialPropertyKey::getName)); public void setProperty(IPipeNetMaterialProperty property) { this.properties.put(property.getKey(), property); @@ -98,6 +105,14 @@ public void verifyProperty(MaterialProperties properties) { } } + protected final class MaterialPropertyComparator implements Comparator { + + @Override + public int compare(IPipeNetMaterialProperty o1, IPipeNetMaterialProperty o2) { + return 0; + } + } + public interface IPipeNetMaterialProperty extends IMaterialProperty { @Nullable @@ -119,7 +134,18 @@ void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List getKey(); - class MaterialPropertyKey { + class MaterialPropertyKey implements IStringSerializable { + + private final @NotNull String name; + + public MaterialPropertyKey(@NotNull String name) { + this.name = name; + } + + @Override + public @NotNull String getName() { + return name; + } T cast(IPipeNetMaterialProperty property) { return (T) property; diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index a0d98bc351b..817e8e748e2 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -976,4 +976,19 @@ public static BitSet setToMask(@NotNull EnumSet enumSet) { public static Set createWeakHashSet() { return Collections.newSetFromMap(new WeakHashMap<>()); } + + /** + * Forces the initialization of a class; this includes things like loading its static fields. + * This can be useful because a statement like {@code AClass.class} does not initialize a class. + *

+ * Does nothing if the class is already initialized. + * @param clazz the class object to initialize. + */ + public static void forceInitialization(Class clazz) { + try { + Class.forName(clazz.getName(), true, clazz.getClassLoader()); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); // Can't happen + } + } } diff --git a/src/main/java/gregtech/api/util/function/NullableSupplier.java b/src/main/java/gregtech/api/util/function/NullableSupplier.java new file mode 100644 index 00000000000..54f1f928418 --- /dev/null +++ b/src/main/java/gregtech/api/util/function/NullableSupplier.java @@ -0,0 +1,12 @@ +package gregtech.api.util.function; + +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +@FunctionalInterface +public interface NullableSupplier extends Supplier { + + @Override + @Nullable T get(); +} diff --git a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java index 77a8bc17f91..d8fe05f78ed 100644 --- a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java @@ -148,7 +148,7 @@ public boolean isAmbientOcclusion() { @Override public boolean isGui3d() { - return false; + return true; } @Override diff --git a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java index 2a7188b7b75..022077ba633 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java @@ -1,7 +1,7 @@ package gregtech.client.renderer.pipe; import gregtech.api.block.UnlistedBooleanProperty; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.unification.material.Material; import gregtech.api.util.GTUtility; @@ -125,7 +125,7 @@ public boolean allowActive() { @Override protected @Nullable PipeItemModel getItemModel(@NotNull ItemStack stack, World world, EntityLivingBase entity) { - WorldPipeBlock block = WorldPipeBlock.getBlockFromItem(stack); + PipeBlock block = PipeBlock.getBlockFromItem(stack); if (block == null) return null; return new PipeItemModel<>(this, new ActivableCacheKey(block.getStructure().getRenderThickness(), false), new ColorData(PipeTileEntity.DEFAULT_COLOR)); diff --git a/src/main/java/gregtech/client/renderer/pipe/CableModel.java b/src/main/java/gregtech/client/renderer/pipe/CableModel.java index f3b02aecfc9..38db2be690b 100644 --- a/src/main/java/gregtech/client/renderer/pipe/CableModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/CableModel.java @@ -1,7 +1,7 @@ package gregtech.client.renderer.pipe; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.unification.material.Material; import gregtech.api.util.GTUtility; @@ -112,7 +112,7 @@ protected StructureQuadCache constructForKey(CacheKey key) { @Override protected @Nullable PipeItemModel getItemModel(@NotNull ItemStack stack, World world, EntityLivingBase entity) { - WorldPipeBlock block = WorldPipeBlock.getBlockFromItem(stack); + PipeBlock block = PipeBlock.getBlockFromItem(stack); if (block == null) return null; Material mater = block instanceof PipeMaterialBlock mat ? mat.getMaterialForStack(stack) : null; return new PipeItemModel<>(this, new CacheKey(block.getStructure().getRenderThickness()), diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java index 3be48cce4b8..88d6ae9bbde 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java @@ -11,11 +11,14 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.model.TRSRTransformation; + import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import javax.vecmath.Matrix4f; +import javax.vecmath.Quat4f; import javax.vecmath.Vector3f; import java.util.EnumMap; import java.util.List; @@ -26,44 +29,26 @@ public class PipeItemModel implements IBakedModel { new EnumMap<>(ItemCameraTransforms.TransformType.class); static { - // TODO these transforms are atrocious - Matrix4f matrix4f = new Matrix4f(); - matrix4f.setIdentity(); - CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.NONE, matrix4f); - matrix4f = new Matrix4f(); - matrix4f.rotY((float) Math.toRadians(225)); - matrix4f.rotX((float) Math.toRadians(30)); - matrix4f.setScale(0.625f); - CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.GUI, matrix4f); - matrix4f = new Matrix4f(); - matrix4f.setTranslation(new Vector3f(0, 3, 0)); - matrix4f.setScale(0.25f); - CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.GROUND, matrix4f); - matrix4f = new Matrix4f(); - matrix4f.setScale(0.5f); - CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.FIXED, matrix4f); - matrix4f = new Matrix4f(); - matrix4f.rotY((float) Math.toRadians(45)); - matrix4f.rotX((float) Math.toRadians(75)); - matrix4f.setTranslation(new Vector3f(0, 2.5f, 0)); - matrix4f.setScale(0.375f); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.NONE, TRSRTransformation.mul(null, null, null, null)); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.GUI, TRSRTransformation.mul(null, rotDegrees(30, -45, 0), scale(0.625f), null)); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.GROUND, TRSRTransformation.mul(null, null, scale(0.25f), null)); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.FIXED, TRSRTransformation.mul(null, rotDegrees(0, 90, 0), scale(0.5f), null)); + Matrix4f matrix4f = TRSRTransformation.mul(null, rotDegrees(75, 45, 0), scale(0.375f), null); CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.THIRD_PERSON_RIGHT_HAND, matrix4f); - matrix4f = new Matrix4f(); - matrix4f.rotY((float) Math.toRadians(45)); - matrix4f.rotX((float) Math.toRadians(75)); - matrix4f.setTranslation(new Vector3f(0, 2.5f, 0)); - matrix4f.setScale(0.375f); CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.THIRD_PERSON_LEFT_HAND, matrix4f); - matrix4f = new Matrix4f(); - matrix4f.rotY((float) Math.toRadians(45)); - matrix4f.setScale(0.4f); + matrix4f = TRSRTransformation.mul(null, rotDegrees(0, 45, 0), scale(0.4f), null); CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.FIRST_PERSON_RIGHT_HAND, matrix4f); - matrix4f = new Matrix4f(); - matrix4f.rotY((float) Math.toRadians(225)); - matrix4f.setScale(0.4f); CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.FIRST_PERSON_LEFT_HAND, matrix4f); } + private static Vector3f scale(float scale) { + return new Vector3f(scale, scale, scale); + } + + private static Quat4f rotDegrees(float x, float y, float z) { + return TRSRTransformation.quatFromXYZDegrees(new Vector3f(x, y, z)); + } + private final AbstractPipeModel basis; private final K key; private final ColorData data; diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java index 1e0d48c87ba..da9650d732b 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java @@ -1,7 +1,7 @@ package gregtech.client.renderer.pipe; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.PropertyKey; @@ -72,7 +72,7 @@ public PipeModel(@NotNull PipeSpriteWoodClarifier inTex, @NotNull PipeSpriteWood public PipeModel(@NotNull PipeSpriteWoodClarifier inTex, @NotNull PipeSpriteWoodClarifier sideTex, boolean restrictive, String variant) { this(inTex, sideTex, restrictive ? wood -> Textures.RESTRICTIVE_OVERLAY.get() : null, - wood -> Textures.PIPE_BLOCKED_OVERLAY_UP.get(), variant); + wood -> Textures.PIPE_BLOCKED_OVERLAY.get(), variant); } public PipeModel(@NotNull PipeSpriteWoodClarifier inTex, boolean restrictive, String variant) { @@ -113,7 +113,7 @@ protected StructureQuadCache constructForKey(WoodCacheKey key) { @Override @Nullable protected PipeItemModel getItemModel(@NotNull ItemStack stack, World world, EntityLivingBase entity) { - WorldPipeBlock block = WorldPipeBlock.getBlockFromItem(stack); + PipeBlock block = PipeBlock.getBlockFromItem(stack); if (block == null) return null; Material mater = null; boolean wood = block instanceof PipeMaterialBlock mat && (mater = mat.getMaterialForStack(stack)) != null && diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java index fd38187e504..aced6d255f7 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java @@ -26,8 +26,8 @@ @SideOnly(Side.CLIENT) public class StructureQuadCache { - public static final float OVERLAY_DIST_1 = 0.001f; - public static final float OVERLAY_DIST_2 = 0.002f; + public static final float OVERLAY_DIST_1 = 0.003f; + public static final float OVERLAY_DIST_2 = 0.006f; protected final PipeQuadHelper helper; diff --git a/src/main/java/gregtech/client/renderer/texture/Textures.java b/src/main/java/gregtech/client/renderer/texture/Textures.java index 09e64603a00..94cc907b1aa 100644 --- a/src/main/java/gregtech/client/renderer/texture/Textures.java +++ b/src/main/java/gregtech/client/renderer/texture/Textures.java @@ -581,36 +581,8 @@ public class Textures { @SideOnly(Side.CLIENT) public static final SpriteInformationWrapper LASER_PIPE_OVERLAY_EMISSIVE = new SpriteInformationWrapper(); - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY; @SideOnly(Side.CLIENT) - public static final SpriteInformationWrapper PIPE_BLOCKED_OVERLAY_UP = new SpriteInformationWrapper(); - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DOWN; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_LEFT; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_RIGHT; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NU; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_ND; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NL; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_NR; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UD; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UL; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_UR; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DL; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_DR; - // @SideOnly(Side.CLIENT) - // public static TextureAtlasSprite PIPE_BLOCKED_OVERLAY_LR; + public static final SpriteInformationWrapper PIPE_BLOCKED_OVERLAY = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) public static ThreadLocal RENDER_STATE; @@ -638,7 +610,9 @@ public static void register(TextureMap textureMap) { INSULATION[i].accept(textureMap.registerSprite(gregtechId("blocks/cable/insulation_" + i)), 1); } + PIPE_BLOCKED_OVERLAY.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_blocked")), -1); RESTRICTIVE_OVERLAY.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_restrictive")), -1); + PIPE_TINY.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_tiny_in")), 0); PIPE_SMALL.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_small_in")), 0); PIPE_NORMAL.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_normal_in")), 0); @@ -652,23 +626,6 @@ public static void register(TextureMap textureMap) { PIPE_LARGE_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_large_in_wood")), 0); PIPE_SIDE_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_side_wood")), 0); - // Fluid Pipe Blocked overlay textures - // PIPE_BLOCKED_OVERLAY = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked")); - PIPE_BLOCKED_OVERLAY_UP.accept(textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_up")), - -1); - // PIPE_BLOCKED_OVERLAY_DOWN = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_down")); - // PIPE_BLOCKED_OVERLAY_LEFT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_left")); - // PIPE_BLOCKED_OVERLAY_RIGHT = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_right")); - // PIPE_BLOCKED_OVERLAY_NU = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nu")); - // PIPE_BLOCKED_OVERLAY_ND = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nd")); - // PIPE_BLOCKED_OVERLAY_NL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nl")); - // PIPE_BLOCKED_OVERLAY_NR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_nr")); - // PIPE_BLOCKED_OVERLAY_UD = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ud")); - // PIPE_BLOCKED_OVERLAY_UL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ul")); - // PIPE_BLOCKED_OVERLAY_UR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_ur")); - // PIPE_BLOCKED_OVERLAY_DL = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_dl")); - // PIPE_BLOCKED_OVERLAY_DR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_dr")); - // PIPE_BLOCKED_OVERLAY_LR = textureMap.registerSprite(gregtechId("blocks/pipe/blocked/pipe_blocked_lr")); OPTICAL_PIPE_IN.accept(textureMap .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_in")), -1); diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index 0947d00a0c4..fe49f7c1bde 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -13,11 +13,9 @@ import gregtech.api.recipes.ingredients.GTRecipeOreInput; import gregtech.api.recipes.recipeproperties.FusionEUToStartProperty; import gregtech.api.terminal.TerminalRegistry; -import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.info.MaterialFlags; import gregtech.api.unification.material.properties.DustProperty; -import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.unification.ore.OrePrefix; @@ -31,7 +29,7 @@ import gregtech.common.pipelike.block.cable.CableBlock; import gregtech.common.pipelike.block.laser.LaserPipeBlock; import gregtech.common.pipelike.block.optical.OpticalPipeBlock; -import gregtech.common.pipelike.block.pipe.PipeBlock; +import gregtech.common.pipelike.block.pipe.MaterialPipeBlock; import gregtech.integration.groovy.GroovyScriptModule; import gregtech.loaders.MaterialInfoLoader; import gregtech.loaders.OreDictionaryLoader; @@ -87,7 +85,7 @@ public static void registerBlocks(RegistryEvent.Register event) { } for (CableBlock cable : CABLES.get(materialRegistry.getModid())) registry.register(cable); - for (PipeBlock cable : MATERIAL_PIPES.get(materialRegistry.getModid())) registry.register(cable); + for (MaterialPipeBlock cable : MATERIAL_PIPES.get(materialRegistry.getModid())) registry.register(cable); } for (OpticalPipeBlock pipe : OPTICAL_PIPES) registry.register(pipe); for (LaserPipeBlock pipe : LASER_PIPES) registry.register(pipe); @@ -202,7 +200,7 @@ public static void registerItems(RegistryEvent.Register event) { for (MaterialRegistry materialRegistry : GregTechAPI.materialManager.getRegistries()) { for (CableBlock cable : CABLES.get(materialRegistry.getModid())) registry.register(createItemBlock(cable, ItemMaterialPipeBlock::new)); - for (PipeBlock cable : MATERIAL_PIPES.get(materialRegistry.getModid())) + for (MaterialPipeBlock cable : MATERIAL_PIPES.get(materialRegistry.getModid())) registry.register(createItemBlock(cable, ItemMaterialPipeBlock::new)); } for (OpticalPipeBlock pipe : OPTICAL_PIPES) registry.register(createItemBlock(pipe, ItemPipeBlock::new)); diff --git a/src/main/java/gregtech/common/ToolEventHandlers.java b/src/main/java/gregtech/common/ToolEventHandlers.java index 2f59d66db2f..8a9b771cd23 100644 --- a/src/main/java/gregtech/common/ToolEventHandlers.java +++ b/src/main/java/gregtech/common/ToolEventHandlers.java @@ -7,7 +7,7 @@ import gregtech.api.capability.impl.ElectricItem; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverHolder; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.toolitem.IGTTool; import gregtech.api.items.toolitem.ToolClasses; @@ -302,7 +302,7 @@ private static void postRenderDamagedBlocks() { @SideOnly(Side.CLIENT) private static boolean shouldRenderGridOverlays(@NotNull IBlockState state, @Nullable TileEntity tile, ItemStack mainHand, ItemStack offHand, boolean isSneaking) { - if (state.getBlock() instanceof WorldPipeBlock pipe) { + if (state.getBlock() instanceof PipeBlock pipe) { if (isSneaking && (mainHand.isEmpty() || mainHand.getItem().getClass() == Item.getItemFromBlock(pipe).getClass())) { return true; diff --git a/src/main/java/gregtech/common/blocks/BlockFrame.java b/src/main/java/gregtech/common/blocks/BlockFrame.java index 799d15a7cd3..192ef3f4bf2 100644 --- a/src/main/java/gregtech/common/blocks/BlockFrame.java +++ b/src/main/java/gregtech/common/blocks/BlockFrame.java @@ -1,7 +1,7 @@ package gregtech.common.blocks; import gregtech.api.graphnet.pipenet.physical.block.ItemPipeBlock; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; @@ -121,7 +121,7 @@ public boolean canCreatureSpawn(@NotNull IBlockState state, @NotNull IBlockAcces public boolean replaceWithFramedPipe(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, ItemStack stackInHand, EnumFacing facing) { - WorldPipeBlock block = WorldPipeBlock.getBlockFromItem(stackInHand); + PipeBlock block = PipeBlock.getBlockFromItem(stackInHand); if (block != null && block.getStructure().getRenderThickness() < 1) { ItemBlock itemBlock = (ItemBlock) stackInHand.getItem(); IBlockState pipeState = block.getDefaultState(); diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 64e78ef6f10..17804c23493 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -3,6 +3,7 @@ import gregtech.api.GTValues; import gregtech.api.GregTechAPI; import gregtech.api.block.machines.BlockMachine; +import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; @@ -44,8 +45,8 @@ import gregtech.common.pipelike.block.laser.LaserStructure; import gregtech.common.pipelike.block.optical.OpticalPipeBlock; import gregtech.common.pipelike.block.optical.OpticalStructure; -import gregtech.common.pipelike.block.pipe.PipeBlock; -import gregtech.common.pipelike.block.pipe.PipeStructure; +import gregtech.common.pipelike.block.pipe.MaterialPipeBlock; +import gregtech.common.pipelike.block.pipe.MaterialPipeStructure; import gregtech.common.pipelikeold.fluidpipe.longdistance.LDFluidPipeType; import gregtech.common.pipelikeold.itempipe.longdistance.LDItemPipeType; @@ -73,7 +74,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.model.ModelLoader; -import net.minecraftforge.client.model.ModelLoaderRegistry; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fluids.BlockFluidBase; import net.minecraftforge.fml.client.registry.ClientRegistry; @@ -109,7 +109,7 @@ private MetaBlocks() {} public static BlockMachine MACHINE; public static final Map CABLES = new Object2ObjectOpenHashMap<>(); - public static final Map MATERIAL_PIPES = new Object2ObjectOpenHashMap<>(); + public static final Map MATERIAL_PIPES = new Object2ObjectOpenHashMap<>(); public static OpticalPipeBlock[] OPTICAL_PIPES; public static LaserPipeBlock[] LASER_PIPES; public static BlockLongDistancePipe LD_ITEM_PIPE; @@ -186,7 +186,7 @@ public static void init() { for (MaterialRegistry registry : GregTechAPI.materialManager.getRegistries()) { String modid = registry.getModid(); - Set structuresCable = CableBlock.gatherStructures(); + Set structuresCable = PipeStructureRegistry.getStructures(CableStructure.class); CableBlock[] cables = new CableBlock[structuresCable.size()]; int i = 0; for (CableStructure struct : structuresCable) { @@ -197,11 +197,11 @@ public static void init() { } CABLES.put(modid, cables); - Set structuresPipe = PipeBlock.gatherStructures(); - PipeBlock[] pipes = new PipeBlock[structuresPipe.size()]; + Set structuresPipe = PipeStructureRegistry.getStructures(MaterialPipeStructure.class); + MaterialPipeBlock[] pipes = new MaterialPipeBlock[structuresPipe.size()]; i = 0; - for (PipeStructure struct : structuresPipe) { - PipeBlock block = new PipeBlock(struct, registry); + for (MaterialPipeStructure struct : structuresPipe) { + MaterialPipeBlock block = new MaterialPipeBlock(struct, registry); block.setRegistryName(modid, String.format(struct.getName())); pipes[i] = block; i++; @@ -209,7 +209,7 @@ public static void init() { MATERIAL_PIPES.put(modid, pipes); } - Set structuresOptical = OpticalPipeBlock.gatherStructures(); + Set structuresOptical = PipeStructureRegistry.getStructures(OpticalStructure.class); OPTICAL_PIPES = new OpticalPipeBlock[structuresOptical.size()]; int i = 0; for (OpticalStructure struct : structuresOptical) { @@ -218,7 +218,7 @@ public static void init() { OPTICAL_PIPES[i] = block; i++; } - Set structuresLaser = LaserPipeBlock.gatherStructures(); + Set structuresLaser = PipeStructureRegistry.getStructures(LaserStructure.class); LASER_PIPES = new LaserPipeBlock[structuresOptical.size()]; i = 0; for (LaserStructure struct : structuresLaser) { @@ -448,7 +448,7 @@ public static void registerItemModels() { ModelLoader.setCustomMeshDefinition(item, stack -> cable.getStructure().getModel().getLoc()); ModelBakery.registerItemVariants(item, decoy); } - for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) { + for (MaterialPipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) { Item item = Item.getItemFromBlock(pipe); ModelLoader.setCustomMeshDefinition(item, stack -> pipe.getStructure().getModel().getLoc()); ModelBakery.registerItemVariants(item, decoy); @@ -557,7 +557,7 @@ public static void registerStateMappers() { ModelLoader.setCustomStateMapper(cable, new SimpleStateMapper(cable.getStructure().getModel().getLoc())); } - for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) { + for (MaterialPipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) { ModelLoader.setCustomStateMapper(pipe, new SimpleStateMapper(pipe.getStructure().getModel().getLoc())); } } @@ -704,7 +704,7 @@ public static void registerOreDict() { OreDictUnifier.registerOre(itemStack, prefix, material); } } - for (PipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) { + for (MaterialPipeBlock pipe : MATERIAL_PIPES.get(registry.getModid())) { OrePrefix prefix = pipe.getStructure().getOrePrefix(); if (prefix.doGenerateItem(material) && properties.generatesStructure(pipe.getStructure())) { ItemStack itemStack = pipe.getItem(material); diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 182ad11b130..491665f55ae 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -8,6 +8,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; +import gregtech.api.cover.filter.CoverWithItemFilter; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; @@ -61,12 +63,13 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.Map; import java.util.Set; -public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, IControllable { +public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithItemFilter { public final int tier; public final int maxItemTransferRate; @@ -91,6 +94,21 @@ public CoverConveyor(@NotNull CoverDefinition definition, @NotNull CoverableView this.itemFilterContainer = new ItemFilterContainer(this); } + @Override + public @Nullable ItemFilterContainer getItemFilter() { + return itemFilterContainer; + } + + @Override + public ItemFilterMode getFilterMode() { + return ItemFilterMode.FILTER_BOTH; + } + + @Override + public ManualImportExportMode getManualMode() { + return this.manualImportExportMode; + } + public void setTransferRate(int transferRate) { this.transferRate = MathHelper.clamp(transferRate, 1, maxItemTransferRate); CoverableView coverable = getCoverableView(); diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index 45298e8371d..ed01a38daa7 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -3,6 +3,7 @@ import gregtech.api.capability.impl.FluidHandlerDelegate; import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; +import gregtech.api.cover.filter.CoverWithFluidFilter; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.mui.GTGuiTextures; @@ -46,7 +47,7 @@ import java.io.IOException; -public class CoverFluidFilter extends CoverBase implements CoverWithUI { +public class CoverFluidFilter extends CoverBase implements CoverWithUI, CoverWithFluidFilter { protected final String titleLocale; protected final SimpleOverlayRenderer texture; @@ -63,6 +64,16 @@ public CoverFluidFilter(@NotNull CoverDefinition definition, @NotNull CoverableV this.texture = texture; } + @Override + public @NotNull FluidFilterContainer getFluidFilter() { + return fluidFilterContainer; + } + + @Override + public ManualImportExportMode getManualMode() { + return ManualImportExportMode.FILTERED; + } + public void setFilterMode(FluidFilterMode filterMode) { this.filterMode = filterMode; this.getCoverableView().markDirty(); diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 0938de42de7..b1d48242c2c 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -5,6 +5,7 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; +import gregtech.api.cover.filter.CoverWithItemFilter; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; @@ -45,7 +46,7 @@ import java.io.IOException; -public class CoverItemFilter extends CoverBase implements CoverWithUI { +public class CoverItemFilter extends CoverBase implements CoverWithUI, CoverWithItemFilter { protected final String titleLocale; protected final SimpleOverlayRenderer texture; @@ -61,6 +62,16 @@ public CoverItemFilter(@NotNull CoverDefinition definition, @NotNull CoverableVi this.itemFilterContainer = new ItemFilterContainer(this); } + @Override + public @NotNull ItemFilterContainer getItemFilter() { + return itemFilterContainer; + } + + @Override + public ManualImportExportMode getManualMode() { + return ManualImportExportMode.FILTERED; + } + @Override public void onAttachment(@NotNull CoverableView coverableView, @NotNull EnumFacing side, @Nullable EntityPlayer player, @NotNull ItemStack itemStack) { diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index bc8e2de1811..1b1b1591bc9 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -8,6 +8,7 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; +import gregtech.api.cover.filter.CoverWithFluidFilter; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; @@ -57,7 +58,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable { +public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithFluidFilter { public final int tier; public final int maxFluidTransferRate; @@ -81,6 +82,21 @@ public CoverPump(@NotNull CoverDefinition definition, @NotNull CoverableView cov this.fluidFilterContainer = new FluidFilterContainer(this); } + @Override + public @Nullable FluidFilterContainer getFluidFilter() { + return this.fluidFilterContainer; + } + + @Override + public FluidFilterMode getFilterMode() { + return FluidFilterMode.FILTER_BOTH; + } + + @Override + public ManualImportExportMode getManualMode() { + return this.manualImportExportMode; + } + public void setStringTransferRate(String s) { this.fluidFilterContainer.setTransferSize( getBucketMode() == BucketMode.MILLI_BUCKET ? diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index 0bf807bba9b..bc0b9bf7fc4 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -1,25 +1,19 @@ package gregtech.common.pipelike.block.cable; -import gregtech.api.graphnet.gather.GatherStructuresEvent; import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.common.creativetab.GTCreativeTabs; import net.minecraft.block.state.IBlockState; -import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraftforge.common.MinecraftForge; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.jetbrains.annotations.NotNull; import java.util.Map; -import java.util.Set; public class CableBlock extends PipeMaterialBlock implements IBurnable { @@ -45,12 +39,6 @@ protected String getConnectLangKey() { return "gregtech.tool_action.wire_cutter.connect"; } - public static Set gatherStructures() { - GatherStructuresEvent event = new GatherStructuresEvent<>(CableStructure.class); - MinecraftForge.EVENT_BUS.post(event); - return event.getGathered(); - } - @Override public void partialBurn(IBlockState state, World world, BlockPos pos) { CableStructure structure = (CableStructure) getStructure(); diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java index 48ad1673d65..3c5b7bd78ed 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java @@ -2,6 +2,7 @@ import gregtech.api.graphnet.pipenet.physical.IInsulatable; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; +import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; import gregtech.api.unification.ore.OrePrefix; import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.client.renderer.pipe.CableModel; @@ -42,6 +43,20 @@ public record CableStructure(String name, int material, int costFactor, OrePrefi public static final CableStructure CABLE_HEX = new CableStructure("cable_hex", 16, 1, OrePrefix.cableGtHex, WIRE_HEX, INSULATION_BURN_TEMP, 1f, CableModel.INSULATED_INSTANCES[4]); + public CableStructure(String name, int material, int costFactor, OrePrefix ore, + @Nullable CableStructure partialBurnStructure, @Nullable Integer partialBurnThreshold, + float renderThickness, AbstractPipeModel model) { + this.name = name; + this.material = material; + this.costFactor = costFactor; + this.ore = ore; + this.partialBurnStructure = partialBurnStructure; + this.partialBurnThreshold = partialBurnThreshold; + this.renderThickness = renderThickness; + this.model = model; + PipeStructureRegistry.register(this); + } + @Override public @NotNull String getName() { return name; diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java index 18d4c1d8fd2..b2982c286e0 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java @@ -1,23 +1,17 @@ package gregtech.common.pipelike.block.laser; -import gregtech.api.graphnet.gather.GatherStructuresEvent; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.physical.block.PipeActivableBlock; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.items.toolitem.ToolHelper; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.pipelike.handlers.LaserNetHandler; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; -import net.minecraftforge.common.MinecraftForge; import org.jetbrains.annotations.NotNull; -import java.util.Set; - public class LaserPipeBlock extends PipeActivableBlock { public LaserPipeBlock(LaserStructure structure) { @@ -25,12 +19,6 @@ public LaserPipeBlock(LaserStructure structure) { setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); } - public static Set gatherStructures() { - GatherStructuresEvent event = new GatherStructuresEvent<>(LaserStructure.class); - MinecraftForge.EVENT_BUS.post(event); - return event.getGathered(); - } - @Override public String getToolClass() { return ToolClasses.WIRE_CUTTER; diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java index 64d653d6524..83293082727 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java @@ -1,6 +1,7 @@ package gregtech.common.pipelike.block.laser; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.client.renderer.pipe.ActivablePipeModel; @@ -17,6 +18,13 @@ public record LaserStructure(String name, float renderThickness, ActivablePipeMo public static final LaserStructure INSTANCE = new LaserStructure("laser_pipe_normal", 0.375f, ActivablePipeModel.LASER); + public LaserStructure(String name, float renderThickness, ActivablePipeModel model) { + this.name = name; + this.renderThickness = renderThickness; + this.model = model; + PipeStructureRegistry.register(this); + } + @Override public boolean canConnectTo(EnumFacing side, byte connectionMask) { for (EnumFacing facing : EnumFacing.VALUES) { diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java index e26555dc06c..8ce692697a2 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java @@ -1,23 +1,17 @@ package gregtech.common.pipelike.block.optical; -import gregtech.api.graphnet.gather.GatherStructuresEvent; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.physical.block.PipeActivableBlock; -import gregtech.api.graphnet.pipenet.physical.block.WorldPipeBlock; import gregtech.api.items.toolitem.ToolClasses; -import gregtech.api.items.toolitem.ToolHelper; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.pipelike.handlers.OpticalNetHandler; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; -import net.minecraftforge.common.MinecraftForge; import org.jetbrains.annotations.NotNull; -import java.util.Set; - public class OpticalPipeBlock extends PipeActivableBlock { public OpticalPipeBlock(OpticalStructure structure) { @@ -25,12 +19,6 @@ public OpticalPipeBlock(OpticalStructure structure) { setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); } - public static Set gatherStructures() { - GatherStructuresEvent event = new GatherStructuresEvent<>(OpticalStructure.class); - MinecraftForge.EVENT_BUS.post(event); - return event.getGathered(); - } - @Override public String getToolClass() { return ToolClasses.WIRE_CUTTER; diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java index 4416b5e9e4b..d561ad3adbd 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java @@ -1,6 +1,7 @@ package gregtech.common.pipelike.block.optical; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.client.renderer.pipe.ActivablePipeModel; @@ -18,6 +19,13 @@ public record OpticalStructure(String name, float renderThickness, ActivablePipe public static final OpticalStructure INSTANCE = new OpticalStructure("optical_pipe_normal", 0.375f, ActivablePipeModel.OPTICAL); + public OpticalStructure(String name, float renderThickness, ActivablePipeModel model) { + this.name = name; + this.renderThickness = renderThickness; + this.model = model; + PipeStructureRegistry.register(this); + } + @Override public boolean canConnectTo(EnumFacing side, byte connectionMask) { byte connectionCount = 0; diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java new file mode 100644 index 00000000000..9da4d3c226b --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java @@ -0,0 +1,16 @@ +package gregtech.common.pipelike.block.pipe; + +import gregtech.api.graphnet.pipenet.physical.IBurnable; +import gregtech.api.graphnet.pipenet.physical.IFreezable; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; +import gregtech.api.unification.material.registry.MaterialRegistry; + +import gregtech.common.creativetab.GTCreativeTabs; + +public class MaterialPipeBlock extends PipeMaterialBlock implements IBurnable, IFreezable { + + public MaterialPipeBlock(MaterialPipeStructure structure, MaterialRegistry registry) { + super(structure, registry); + setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java new file mode 100644 index 00000000000..50a25227f81 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java @@ -0,0 +1,110 @@ +package gregtech.common.pipelike.block.pipe; + +import gregtech.api.graphnet.pipenet.physical.IPipeChanneledStructure; +import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; +import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; +import gregtech.api.unification.ore.OrePrefix; +import gregtech.client.renderer.pipe.AbstractPipeModel; +import gregtech.client.renderer.pipe.PipeModel; + +import com.github.bsideup.jabel.Desugar; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Consumer; + +@Desugar +public record MaterialPipeStructure(String name, int material, int channelCount, boolean restrictive, OrePrefix ore, + float renderThickness, PipeModel model) + implements IPipeMaterialStructure, IPipeChanneledStructure { + + public static final MaterialPipeStructure TINY = new MaterialPipeStructure("pipe_tiny", 1, 1, false, OrePrefix.pipeTiny, 0.25f, + PipeModel.INSTANCES[0]); + public static final MaterialPipeStructure SMALL = new MaterialPipeStructure("pipe_small", 2, 1, false, OrePrefix.pipeSmall, 0.375f, + PipeModel.INSTANCES[1]); + public static final MaterialPipeStructure NORMAL = new MaterialPipeStructure("pipe_normal", 6, 1, false, OrePrefix.pipeNormal, 0.5f, + PipeModel.INSTANCES[2]); + public static final MaterialPipeStructure LARGE = new MaterialPipeStructure("pipe_large", 12, 1, false, OrePrefix.pipeLarge, 0.75f, + PipeModel.INSTANCES[3]); + public static final MaterialPipeStructure HUGE = new MaterialPipeStructure("pipe_huge", 24, 1, false, OrePrefix.pipeHuge, 0.875f, + PipeModel.INSTANCES[4]); + + public static final MaterialPipeStructure QUADRUPLE = new MaterialPipeStructure("pipe_quadruple", 8, 4, false, OrePrefix.pipeQuadruple, + 0.95f, PipeModel.INSTANCES[5]); + public static final MaterialPipeStructure NONUPLE = new MaterialPipeStructure("pipe_nonuple", 18, 9, false, OrePrefix.pipeNonuple, 0.95f, + PipeModel.INSTANCES[6]); + + public static final MaterialPipeStructure TINY_RESTRICTIVE = new MaterialPipeStructure("pipe_tiny_restrictive", 1, 1, true, + OrePrefix.pipeTinyRestrictive, 0.25f, PipeModel.RESTRICTIVE_INSTANCES[0]); + public static final MaterialPipeStructure SMALL_RESTRICTIVE = new MaterialPipeStructure("pipe_small_restrictive", 2, 1, true, + OrePrefix.pipeSmallRestrictive, 0.375f, PipeModel.RESTRICTIVE_INSTANCES[1]); + public static final MaterialPipeStructure NORMAL_RESTRICTIVE = new MaterialPipeStructure("pipe_normal_restrictive", 6, 1, true, + OrePrefix.pipeNormalRestrictive, 0.5f, PipeModel.RESTRICTIVE_INSTANCES[2]); + public static final MaterialPipeStructure LARGE_RESTRICTIVE = new MaterialPipeStructure("pipe_large_restrictive", 12, 1, true, + OrePrefix.pipeLargeRestrictive, 0.75f, PipeModel.RESTRICTIVE_INSTANCES[3]); + public static final MaterialPipeStructure HUGE_RESTRICTIVE = new MaterialPipeStructure("pipe_huge_restrictive", 24, 1, true, + OrePrefix.pipeHugeRestrictive, 0.875f, PipeModel.RESTRICTIVE_INSTANCES[4]); + + public static final MaterialPipeStructure QUADRUPLE_RESTRICTIVE = new MaterialPipeStructure("pipe_quadruple_restrictive", 8, 4, true, + OrePrefix.pipeQuadrupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[5]); + public static final MaterialPipeStructure NONUPLE_RESTRICTIVE = new MaterialPipeStructure("pipe_nonuple_restrictive", 18, 9, true, + OrePrefix.pipeNonupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[6]); + + public MaterialPipeStructure(String name, int material, int channelCount, boolean restrictive, OrePrefix ore, + float renderThickness, PipeModel model) { + this.name = name; + this.material = material; + this.channelCount = channelCount; + this.restrictive = restrictive; + this.ore = ore; + this.renderThickness = renderThickness; + this.model = model; + PipeStructureRegistry.register(this); + } + + @Override + public @NotNull String getName() { + return name; + } + + @Override + public OrePrefix getOrePrefix() { + return ore; + } + + @Override + public float getRenderThickness() { + return renderThickness; + } + + @Override + public int getChannelCount() { + return channelCount; + } + + @Override + public AbstractPipeModel getModel() { + return model; + } + + @Override + public boolean isPaintable() { + return true; + } + + public static void registerDefaultStructures(Consumer register) { + register.accept(TINY); + register.accept(SMALL); + register.accept(NORMAL); + register.accept(LARGE); + register.accept(HUGE); + register.accept(QUADRUPLE); + register.accept(NONUPLE); + register.accept(TINY_RESTRICTIVE); + register.accept(SMALL_RESTRICTIVE); + register.accept(NORMAL_RESTRICTIVE); + register.accept(LARGE_RESTRICTIVE); + register.accept(HUGE_RESTRICTIVE); + register.accept(QUADRUPLE_RESTRICTIVE); + register.accept(NONUPLE_RESTRICTIVE); + } +} diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java deleted file mode 100644 index 3423feaeaac..00000000000 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeBlock.java +++ /dev/null @@ -1,27 +0,0 @@ -package gregtech.common.pipelike.block.pipe; - -import gregtech.api.graphnet.gather.GatherStructuresEvent; -import gregtech.api.graphnet.pipenet.physical.IBurnable; -import gregtech.api.graphnet.pipenet.physical.IFreezable; -import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; -import gregtech.api.unification.material.registry.MaterialRegistry; - -import gregtech.common.creativetab.GTCreativeTabs; - -import net.minecraftforge.common.MinecraftForge; - -import java.util.Set; - -public class PipeBlock extends PipeMaterialBlock implements IBurnable, IFreezable { - - public PipeBlock(PipeStructure structure, MaterialRegistry registry) { - super(structure, registry); - setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); - } - - public static Set gatherStructures() { - GatherStructuresEvent event = new GatherStructuresEvent<>(PipeStructure.class); - MinecraftForge.EVENT_BUS.post(event); - return event.getGathered(); - } -} diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java b/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java deleted file mode 100644 index 9655da3f6f8..00000000000 --- a/src/main/java/gregtech/common/pipelike/block/pipe/PipeStructure.java +++ /dev/null @@ -1,97 +0,0 @@ -package gregtech.common.pipelike.block.pipe; - -import gregtech.api.graphnet.pipenet.physical.IPipeChanneledStructure; -import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; -import gregtech.api.unification.ore.OrePrefix; -import gregtech.client.renderer.pipe.AbstractPipeModel; -import gregtech.client.renderer.pipe.PipeModel; - -import com.github.bsideup.jabel.Desugar; -import org.jetbrains.annotations.NotNull; - -import java.util.function.Consumer; - -@Desugar -public record PipeStructure(String name, int material, int channelCount, boolean restrictive, OrePrefix ore, - float renderThickness, PipeModel model) - implements IPipeMaterialStructure, IPipeChanneledStructure { - - public static final PipeStructure TINY = new PipeStructure("pipe_tiny", 1, 1, false, OrePrefix.pipeTiny, 0.25f, - PipeModel.INSTANCES[0]); - public static final PipeStructure SMALL = new PipeStructure("pipe_small", 2, 1, false, OrePrefix.pipeSmall, 0.375f, - PipeModel.INSTANCES[1]); - public static final PipeStructure NORMAL = new PipeStructure("pipe_normal", 6, 1, false, OrePrefix.pipeNormal, 0.5f, - PipeModel.INSTANCES[2]); - public static final PipeStructure LARGE = new PipeStructure("pipe_large", 12, 1, false, OrePrefix.pipeLarge, 0.75f, - PipeModel.INSTANCES[3]); - public static final PipeStructure HUGE = new PipeStructure("pipe_huge", 24, 1, false, OrePrefix.pipeHuge, 0.875f, - PipeModel.INSTANCES[4]); - - public static final PipeStructure QUADRUPLE = new PipeStructure("pipe_quadruple", 8, 4, false, OrePrefix.pipeQuadruple, - 0.95f, PipeModel.INSTANCES[5]); - public static final PipeStructure NONUPLE = new PipeStructure("pipe_nonuple", 18, 9, false, OrePrefix.pipeNonuple, 0.95f, - PipeModel.INSTANCES[6]); - - public static final PipeStructure TINY_RESTRICTIVE = new PipeStructure("pipe_tiny_restrictive", 1, 1, true, - OrePrefix.pipeTinyRestrictive, 0.25f, PipeModel.RESTRICTIVE_INSTANCES[0]); - public static final PipeStructure SMALL_RESTRICTIVE = new PipeStructure("pipe_small_restrictive", 2, 1, true, - OrePrefix.pipeSmallRestrictive, 0.375f, PipeModel.RESTRICTIVE_INSTANCES[1]); - public static final PipeStructure NORMAL_RESTRICTIVE = new PipeStructure("pipe_normal_restrictive", 6, 1, true, - OrePrefix.pipeNormalRestrictive, 0.5f, PipeModel.RESTRICTIVE_INSTANCES[2]); - public static final PipeStructure LARGE_RESTRICTIVE = new PipeStructure("pipe_large_restrictive", 12, 1, true, - OrePrefix.pipeLargeRestrictive, 0.75f, PipeModel.RESTRICTIVE_INSTANCES[3]); - public static final PipeStructure HUGE_RESTRICTIVE = new PipeStructure("pipe_huge_restrictive", 24, 1, true, - OrePrefix.pipeHugeRestrictive, 0.875f, PipeModel.RESTRICTIVE_INSTANCES[4]); - - public static final PipeStructure QUADRUPLE_RESTRICTIVE = new PipeStructure("pipe_quadruple_restrictive", 8, 4, true, - OrePrefix.pipeQuadrupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[5]); - public static final PipeStructure NONUPLE_RESTRICTIVE = new PipeStructure("pipe_nonuple_restrictive", 18, 9, true, - OrePrefix.pipeNonupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[6]); - - @Override - public @NotNull String getName() { - return name; - } - - @Override - public OrePrefix getOrePrefix() { - return ore; - } - - @Override - public float getRenderThickness() { - return renderThickness; - } - - @Override - public int getChannelCount() { - return channelCount; - } - - @Override - public AbstractPipeModel getModel() { - return model; - } - - @Override - public boolean isPaintable() { - return true; - } - - public static void registerDefaultStructures(Consumer register) { - register.accept(TINY); - register.accept(SMALL); - register.accept(NORMAL); - register.accept(LARGE); - register.accept(HUGE); - register.accept(QUADRUPLE); - register.accept(NONUPLE); - register.accept(TINY_RESTRICTIVE); - register.accept(SMALL_RESTRICTIVE); - register.accept(NORMAL_RESTRICTIVE); - register.accept(LARGE_RESTRICTIVE); - register.accept(HUGE_RESTRICTIVE); - register.accept(QUADRUPLE_RESTRICTIVE); - register.accept(NONUPLE_RESTRICTIVE); - } -} diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 58274501404..7468d91c514 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -22,7 +22,7 @@ import gregtech.api.util.GTUtility; import gregtech.api.util.function.TriConsumer; import gregtech.common.pipelike.block.cable.CableStructure; -import gregtech.common.pipelike.block.pipe.PipeStructure; +import gregtech.common.pipelike.block.pipe.MaterialPipeStructure; import gregtech.common.pipelike.net.energy.VoltageLossLogic; import gregtech.common.pipelike.net.energy.SuperconductorLogic; import gregtech.common.pipelike.net.energy.VoltageLimitLogic; @@ -45,7 +45,7 @@ public final class MaterialEnergyProperties implements PipeNetProperties.IPipeNetMaterialProperty { - public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>(); + public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>("EnergyProperties"); private final long voltageLimit; private final long amperageLimit; @@ -160,7 +160,7 @@ public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStruc WorldPipeNetNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); mutateData(node.getData(), structure); return node; - } else if (structure instanceof PipeStructure pipe) { + } else if (structure instanceof MaterialPipeStructure pipe) { long amperage = amperageLimit * pipe.material() / 2; if (amperage == 0) return null; // skip pipes that are too small WorldPipeNetNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); @@ -188,7 +188,7 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { if (superconductorCriticalTemperature > 0) { data.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorCriticalTemperature)); } - } else if (structure instanceof PipeStructure pipe) { + } else if (structure instanceof MaterialPipeStructure pipe) { long amperage = getAmperage(structure); if (amperage == 0) return; // skip pipes that are too small long loss = getLoss(structure); @@ -209,7 +209,7 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { private long getLoss(IPipeStructure structure) { if (structure instanceof CableStructure cable) { return lossPerAmp * cable.costFactor(); - } else if (structure instanceof PipeStructure pipe) { + } else if (structure instanceof MaterialPipeStructure pipe) { return lossPerAmp * (pipe.material() > 6 ? 3 : 2); } else return lossPerAmp; } @@ -217,7 +217,7 @@ private long getLoss(IPipeStructure structure) { private long getAmperage(IPipeStructure structure) { if (structure instanceof CableStructure cable) { return amperageLimit * cable.material(); - } else if (structure instanceof PipeStructure pipe) { + } else if (structure instanceof MaterialPipeStructure pipe) { return amperageLimit * pipe.material() / 2; } else return amperageLimit; } @@ -225,14 +225,14 @@ private long getAmperage(IPipeStructure structure) { @Override @Nullable public WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { - if (structure instanceof CableStructure || structure instanceof PipeStructure) + if (structure instanceof CableStructure || structure instanceof MaterialPipeStructure) return WorldEnergyNet.getWorldNet(world).getNode(pos); else return null; } @Override public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { - if (structure instanceof CableStructure || structure instanceof PipeStructure) { + if (structure instanceof CableStructure || structure instanceof MaterialPipeStructure) { WorldEnergyNet net = WorldEnergyNet.getWorldNet(world); NetNode node = net.getNode(pos); if (node != null) net.removeNode(node); @@ -246,6 +246,6 @@ public boolean generatesStructure(IPipeStructure structure) { @Override public boolean supportsStructure(IPipeStructure structure) { - return structure instanceof CableStructure || structure instanceof PipeStructure; + return structure instanceof CableStructure || structure instanceof MaterialPipeStructure; } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index caf68afa959..f3e98237b5c 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -20,8 +20,7 @@ import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.util.TextFormattingUtil; -import gregtech.common.pipelike.block.cable.CableStructure; -import gregtech.common.pipelike.block.pipe.PipeStructure; +import gregtech.common.pipelike.block.pipe.MaterialPipeStructure; import gregtech.common.pipelike.net.fluid.FluidContainmentLogic; import gregtech.common.pipelike.net.fluid.WorldFluidNet; @@ -44,7 +43,7 @@ public final class MaterialFluidProperties implements PipeNetProperties.IPipeNetMaterialProperty, IPropertyFluidFilter { - public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>(); + public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>("FluidProperties"); private final Set containableAttributes = new ObjectOpenHashSet<>(); private final EnumSet containableStates = EnumSet.of(FluidState.LIQUID); @@ -183,7 +182,7 @@ public void verifyProperty(MaterialProperties properties) { @Override @Nullable public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure) { - if (structure instanceof PipeStructure) { + if (structure instanceof MaterialPipeStructure) { WorldPipeNetNode node = WorldFluidNet.getWorldNet(world).getOrCreateNode(pos); mutateData(node.getData(), structure); return node; @@ -193,7 +192,7 @@ public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStruc @Override public void mutateData(NetLogicData data, IPipeStructure structure) { - if (structure instanceof PipeStructure pipe) { + if (structure instanceof MaterialPipeStructure pipe) { long throughput = getThroughput(structure); float coolingFactor = (float) Math.sqrt((double) pipe.material() / (4 + pipe.channelCount())); data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(getFlowPriority(structure))) @@ -206,27 +205,27 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { } private long getThroughput(IPipeStructure structure) { - if (structure instanceof PipeStructure pipe) { + if (structure instanceof MaterialPipeStructure pipe) { return baseThroughput * pipe.material(); } else return baseThroughput; } private double getFlowPriority(IPipeStructure structure) { - if (structure instanceof PipeStructure pipe) { + if (structure instanceof MaterialPipeStructure pipe) { return priority * (pipe.restrictive() ? 100d : 1d) * pipe.channelCount() / pipe.material(); } else return priority; } @Override public @Nullable WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { - if (structure instanceof PipeStructure) + if (structure instanceof MaterialPipeStructure) return WorldFluidNet.getWorldNet(world).getNode(pos); else return null; } @Override public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { - if (structure instanceof PipeStructure) { + if (structure instanceof MaterialPipeStructure) { WorldFluidNet net = WorldFluidNet.getWorldNet(world); NetNode node = net.getNode(pos); if (node != null) net.removeNode(node); @@ -235,11 +234,11 @@ public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { @Override public boolean generatesStructure(IPipeStructure structure) { - return structure.getClass() == PipeStructure.class; + return structure.getClass() == MaterialPipeStructure.class; } @Override public boolean supportsStructure(IPipeStructure structure) { - return structure instanceof PipeStructure; + return structure instanceof MaterialPipeStructure; } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index 014d64fc000..0d005293fcf 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -11,7 +11,7 @@ import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.util.TextFormattingUtil; -import gregtech.common.pipelike.block.pipe.PipeStructure; +import gregtech.common.pipelike.block.pipe.MaterialPipeStructure; import gregtech.common.pipelike.net.item.WorldItemNet; import net.minecraft.client.resources.I18n; @@ -27,7 +27,7 @@ public final class MaterialItemProperties implements PipeNetProperties.IPipeNetMaterialProperty { - public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>(); + public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>("ItemProperties"); private final long baseItemsPer5Ticks; private final float priority; @@ -69,7 +69,7 @@ public void verifyProperty(MaterialProperties properties) { @Override @Nullable public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure) { - if (structure instanceof PipeStructure) { + if (structure instanceof MaterialPipeStructure) { WorldPipeNetNode node = WorldItemNet.getWorldNet(world).getOrCreateNode(pos); mutateData(node.getData(), structure); return node; @@ -79,7 +79,7 @@ public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStruc @Override public void mutateData(NetLogicData data, IPipeStructure structure) { - if (structure instanceof PipeStructure pipe) { + if (structure instanceof MaterialPipeStructure pipe) { long throughput = baseItemsPer5Ticks * pipe.material(); data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(getFlowPriority(structure))) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)); @@ -87,21 +87,21 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { } private double getFlowPriority(IPipeStructure structure) { - if (structure instanceof PipeStructure pipe) { + if (structure instanceof MaterialPipeStructure pipe) { return priority * (pipe.restrictive() ? 100d : 1d) * pipe.channelCount() / pipe.material(); } else return priority; } @Override public @Nullable WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { - if (structure instanceof PipeStructure) + if (structure instanceof MaterialPipeStructure) return WorldItemNet.getWorldNet(world).getNode(pos); else return null; } @Override public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { - if (structure instanceof PipeStructure) { + if (structure instanceof MaterialPipeStructure) { WorldItemNet net = WorldItemNet.getWorldNet(world); NetNode node = net.getNode(pos); if (node != null) net.removeNode(node); @@ -110,11 +110,11 @@ public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { @Override public boolean generatesStructure(IPipeStructure structure) { - return structure.getClass() == PipeStructure.class; + return structure.getClass() == MaterialPipeStructure.class; } @Override public boolean supportsStructure(IPipeStructure structure) { - return structure instanceof PipeStructure; + return structure instanceof MaterialPipeStructure; } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 56f67378d2b..acaf82ec2b6 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -71,7 +71,10 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage long availableAmperage = amperage; if (internalBuffer != null) { long limit = internalBuffer.getFlowLimit(IPredicateTestObject.INSTANCE, net, tick, simulator); - if (limit <= 0) return 0; + if (limit <= 0) { + this.transferring = false; + return 0; + } availableAmperage = Math.min(amperage, limit); } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java index 2832f6d32d4..368a8926a5b 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java @@ -4,21 +4,20 @@ import org.jetbrains.annotations.NotNull; -public class SuperconductorLogic extends AbstractIntLogicData { +public final class SuperconductorLogic extends AbstractIntLogicData { public static final SuperconductorLogic INSTANCE = new SuperconductorLogic().setValue(0); - public boolean canSuperconduct(int temp) { - return this.getValue() > temp; + public SuperconductorLogic() { + super("Superconductor"); } - @Override - public @NotNull String getName() { - return "Superconductor"; + public boolean canSuperconduct(int temp) { + return this.getValue() > temp; } @Override - public SuperconductorLogic getNew() { + public @NotNull SuperconductorLogic getNew() { return new SuperconductorLogic(); } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java index 9ff8103897b..e73944e7afa 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java @@ -1,7 +1,7 @@ package gregtech.common.pipelike.net.energy; import gregtech.api.graphnet.logic.AbstractLongLogicData; -import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.NetLogicEntry; import org.jetbrains.annotations.NotNull; @@ -9,18 +9,17 @@ public final class VoltageLimitLogic extends AbstractLongLogicData other) { + public VoltageLimitLogic union(NetLogicEntry other) { if (other instanceof VoltageLimitLogic l) { return this.getValue() < l.getValue() ? this : l; } else return this; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java index 5fd2ace2c21..d025b66be39 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java @@ -1,7 +1,7 @@ package gregtech.common.pipelike.net.energy; import gregtech.api.graphnet.logic.AbstractLongLogicData; -import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.NetLogicEntry; import org.jetbrains.annotations.NotNull; @@ -9,18 +9,17 @@ public final class VoltageLossLogic extends AbstractLongLogicData other) { + public VoltageLossLogic union(NetLogicEntry other) { if (other instanceof VoltageLossLogic l) { return this.getWith(this.getValue() + l.getValue()); } else return this; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index 6089faaf72c..118dd298e10 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -103,7 +103,10 @@ public int fill(FluidStack resource, boolean doFill, EnumFacing side) { long allowed = resource.amount; if (internalBuffer != null) { long limit = internalBuffer.getFlowLimit(testObject, net, tick, simulator); - if (limit <= 0) return 0; + if (limit <= 0) { + this.transferring = false; + return 0; + } allowed = Math.min(limit, allowed); } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java index e31d9a467ff..19a5fc561cb 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java @@ -2,7 +2,7 @@ import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.graphnet.logic.INetLogicEntry; +import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.util.GTUtility; import net.minecraft.nbt.NBTTagCompound; @@ -20,13 +20,17 @@ import java.util.EnumSet; import java.util.Set; -public class FluidContainmentLogic implements INetLogicEntry { +public final class FluidContainmentLogic extends NetLogicEntry { public static final FluidContainmentLogic INSTANCE = new FluidContainmentLogic().contain(FluidState.LIQUID); private final Set containableAttributes = new ObjectOpenHashSet<>(); private @NotNull EnumSet containableStates = EnumSet.noneOf(FluidState.class); + public FluidContainmentLogic() { + super("FluidContainment"); + } + public FluidContainmentLogic getWith(Collection states, Collection attributes) { FluidContainmentLogic logic = getNew(); logic.containableStates.addAll(states); @@ -36,8 +40,6 @@ public FluidContainmentLogic getWith(Collection states, Collection other) { + public @Nullable FluidContainmentLogic union(NetLogicEntry other) { if (other instanceof FluidContainmentLogic logic) { if (this.containableAttributes.equals(logic.containableAttributes) && this.containableStates.equals(logic.containableStates)) { @@ -111,7 +108,7 @@ public void deserializeNBT(NBTTagCompound nbt) { } @Override - public FluidContainmentLogic getNew() { + public @NotNull FluidContainmentLogic getNew() { return new FluidContainmentLogic(); } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index be0cce716e1..0ef64b8405f 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -1,14 +1,21 @@ package gregtech.common.pipelike.net.fluid; +import gregtech.api.cover.Cover; +import gregtech.api.cover.filter.CoverWithFluidFilter; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; +import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.predicate.FilterPredicate; +import gregtech.api.graphnet.pipenet.predicate.BlockedPredicate; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.common.covers.FluidFilterMode; +import gregtech.common.covers.ManualImportExportMode; import gregtech.common.pipelike.net.item.WorldItemNet; import net.minecraft.world.World; @@ -33,8 +40,8 @@ public class WorldFluidNet extends WorldPipeNet implements FlowWorldPipeNetPath. if (net == null) { net = new WorldFluidNet(DATA_ID); world.setData(DATA_ID, net); - net.setWorld(world); } + net.setWorld(world); return net; } @@ -42,6 +49,36 @@ public WorldFluidNet(String name) { super(name, false, DynamicWeightsShortestPathsAlgorithm::new); } + @Override + protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { + super.coverPredication(edge, a, b); + if (edge.getPredicateHandler().hasPredicate(BlockedPredicate.INSTANCE)) return; + FilterPredicate predicate = null; + if (a instanceof CoverWithFluidFilter filter) { + if (filter.getManualMode() == ManualImportExportMode.DISABLED) { + edge.getPredicateHandler().clearPredicates(); + edge.getPredicateHandler().setPredicate(BlockedPredicate.INSTANCE); + return; + } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && + filter.getFilterMode() != FluidFilterMode.FILTER_FILL) { + predicate = FilterPredicate.INSTANCE.getNew(); + predicate.setSourceFilter(filter.getFluidFilter()); + } + } + if (b instanceof CoverWithFluidFilter filter) { + if (filter.getManualMode() == ManualImportExportMode.DISABLED) { + edge.getPredicateHandler().clearPredicates(); + edge.getPredicateHandler().setPredicate(BlockedPredicate.INSTANCE); + return; + } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && + filter.getFilterMode() != FluidFilterMode.FILTER_DRAIN) { + if (predicate == null) predicate = FilterPredicate.INSTANCE.getNew(); + predicate.setTargetFilter(filter.getFluidFilter()); + } + } + if (predicate != null) edge.getPredicateHandler().setPredicate(predicate); + } + @Override public boolean usesDynamicWeights(int algorithmID) { return true; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index 572bd1359c0..f330419dd1e 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -92,7 +92,10 @@ public T getCapabilityForSide(Capability capability, @Nullable EnumFacing int available = stack.getCount(); if (internalBuffer != null) { long limit = internalBuffer.getFlowLimit(testObject, net, tick, simulator); - if (limit <= 0) return stack; + if (limit <= 0) { + this.transferring = false; + return stack; + } available = (int) Math.min(limit, available); } diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index eedb02d65f6..89bd6dd1618 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -1,14 +1,21 @@ package gregtech.common.pipelike.net.item; +import gregtech.api.cover.Cover; +import gregtech.api.cover.filter.CoverWithItemFilter; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; +import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.predicate.FilterPredicate; +import gregtech.api.graphnet.pipenet.predicate.BlockedPredicate; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.common.covers.ItemFilterMode; +import gregtech.common.covers.ManualImportExportMode; import gregtech.common.pipelike.net.fluid.WorldFluidNet; import net.minecraft.world.World; @@ -42,6 +49,36 @@ public WorldItemNet(String name) { super(name, false, DynamicWeightsShortestPathsAlgorithm::new); } + @Override + protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { + super.coverPredication(edge, a, b); + if (edge.getPredicateHandler().hasPredicate(BlockedPredicate.INSTANCE)) return; + FilterPredicate predicate = null; + if (a instanceof CoverWithItemFilter filter) { + if (filter.getManualMode() == ManualImportExportMode.DISABLED) { + edge.getPredicateHandler().clearPredicates(); + edge.getPredicateHandler().setPredicate(BlockedPredicate.INSTANCE); + return; + } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && + filter.getFilterMode() != ItemFilterMode.FILTER_INSERT) { + predicate = FilterPredicate.INSTANCE.getNew(); + predicate.setSourceFilter(filter.getItemFilter()); + } + } + if (b instanceof CoverWithItemFilter filter) { + if (filter.getManualMode() == ManualImportExportMode.DISABLED) { + edge.getPredicateHandler().clearPredicates(); + edge.getPredicateHandler().setPredicate(BlockedPredicate.INSTANCE); + return; + } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && + filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT) { + if (predicate == null) predicate = FilterPredicate.INSTANCE.getNew(); + predicate.setTargetFilter(filter.getItemFilter()); + } + } + if (predicate != null) edge.getPredicateHandler().setPredicate(predicate); + } + @Override public boolean usesDynamicWeights(int algorithmID) { return true; diff --git a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java index d9def3c0ce0..ac0e0c5ce84 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java @@ -47,8 +47,8 @@ private Iterator getPaths() { @Override public long receiveLaser(long laserVoltage, long laserAmperage) { - if (tile == null || transmitting) return 0; - transmitting = true; + if (tile == null || this.transmitting) return 0; + this.transmitting = true; long available = laserAmperage; for (Iterator it = getPaths(); it.hasNext();) { @@ -62,12 +62,15 @@ public long receiveLaser(long laserVoltage, long laserAmperage) { if (transmitted > 0) { SlowActiveWalker.dispatch(tile.getWorld(), path, 1, 2, 2); available -= transmitted; - if (available <= 0) return laserAmperage; + if (available <= 0) { + this.transmitting = false; + return laserAmperage; + } } } } } - transmitting = false; + this.transmitting = false; return laserAmperage - available; } diff --git a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java index cb61572b4e7..27d7cfc0287 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java @@ -35,7 +35,7 @@ public class WorldLaserNet extends WorldPipeNet implements BasicWorldPipeNetPath } public WorldLaserNet(String name) { - super(name, false, SinglePathAlgorithm::new); + super(name, false, graphNet -> new SinglePathAlgorithm(graphNet, false)); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java index 34bdbfe91f3..289d73551d4 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -36,7 +36,7 @@ public class WorldOpticalNet extends WorldPipeNet implements BasicWorldPipeNetPa } public WorldOpticalNet(String name) { - super(name, false, SinglePathAlgorithm::new); + super(name, false, graphNet -> new SinglePathAlgorithm(graphNet, false)); } @Override diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 8c37abd5075..381b50156e0 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -5562,7 +5562,7 @@ gregtech.cable.superconductor_loss=§cLoss is set to §f0§c under critical temp gregtech.cable.superconductor=§d%s Superconductor gregtech.fluid_pipe.max_temperature=§cTemperature Limit: §f%,d K -gregtech.fluid_pipe.min_temperature=§6Can handle fluids above §f%,d K +gregtech.fluid_pipe.min_temperature=§6Can handle fluids at or above §f%,d K gregtech.pipe.channels=§eChannels: §f%d gregtech.fluid_pipe.gas_proof=§6Can handle Gases gregtech.fluid_pipe.acid_proof=§6Can handle Acids diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_dl.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_dl.png deleted file mode 100644 index e07a3ff04d74e6b5a2cb83af6c277fcad0d63c3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!Yyx~jT!AzzE31^0l$@NLo}QkC zg@vuHt)HJ?OiWC1adBN;U44ChV`JmgsZ(dpoH={;?3F85u3EKf-MV#Kwru(H_ZrAx z#*!evUVmd3!_heTTC`85UYU zM2(lv+%x0B+ZFZKcWXaWZ8A8mek|X-o=V^1Iiw2HQ(|Ob0rQ!PC{xWt~$(69A1{ZNLBk diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_down.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_down.png deleted file mode 100644 index 5b77df828cbe0754ade62096d75a765f31f034cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!j01c^TqoGav$C>ENlD4c$?56o zSy))u+SuwQALtEn9ZH3s?Zu&R7!U7tG-B z>_!@p6YlBa7!q;#?d9Eq2Mjov17=#ZY25$2-1i}45qs*FDozas7cdB#HFG*wk4;_d z1uL;4=hr7+X8%w)e0=7eL(M8DU!S~ZApPm*&4824a$9XS-2e65Uw>W}Q!?A!DP2G- O7(8A5T-G@yGywqGuu{|j diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_dr.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_dr.png deleted file mode 100644 index 0bbdcfd783605d4a0ef4376850d13c980c4ed751..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 268 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!j01c^T)#g#!ph1jB_$;%C#R>U zXJKJsYik=56H{DVTvu0DUtizY*f?|M%-OSNuUxru)v8rnwro*;v{n_Uov|dyFPOpM z*^M+Hr`^-VF(l&f+bNbphaEUr7}tuKI352V|N21L8!fd>zRxdLi}ZM0Hu1guhr#Vx zX{n!ql1KC6oB-p^sf%(9_H@n_nG^o@>&%(a4A0NjDowwB@@cA!xnzopr0EF6Y`v3p{ diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_left.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_left.png deleted file mode 100644 index 5221719ca2f21070108fa48cdb68e8a8a9d9fdc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!%mREuTzCEd&&tXwB_*Y&r)Obd zVQXva=jRs_6H{DVTwh<`*w{FA>eQJtXU?8Id*#ZNt5&UAw{G2*EnA*WYY73Gz*rLG z7tG-B>_!@p6XEIN7!q;#?PY7R1_KV4z#e&zrp|Zun}c>RE&EvU>|4H;fTEJpuVqZ% zPG8$lColXuoBel|JLjx-@$;l2cx427TMH|9sP4V6(Kui;o8BB@8`tON!h#p&ZG0v& VIh{&WJqomg!PC{xWt~$(69BEBQo8^E diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_lr.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_lr.png deleted file mode 100644 index 2b304caed0ddfc2fe70d606a6e605ac8341bd390..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 281 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!Yyx~jT!AzzE31^0l$@NLo}QkC zg@vuHt)HJ?OiWC1adBN;U44ChV`JmgsZ(dpoH={;?3F85u3EKf-MV#Kwru(H_ZrAx z#*!evUO`J<^f>*3!0886DN{Q6nzaMmY$zpSa~iDR6Pw%?h`q#7?D5_%!{&HciYA7z8& z{HE?>nbYnz>4CWVnv>rgud>&wOl5g0@b{@!(zQ2^uk-zvdTwUF>>Rp$<%17jf##>2 ZVw)zw8vJyBha%8222WQ%mvv4FO#r8iZ;b!| diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_nd.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_nd.png deleted file mode 100644 index 4a9c81ee52d311ebe5dbf9b3ec58e03e41430b90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 331 zcmV-R0kr;!P)>%tP1IYRjB?+}(lJMy7PjEiZ0kK>X^(DlMnGlzH@5UjL z=rjI701#buo|WIi35%_d4B2_u`Y$uQGlbTY#h){4N*mMO{XehWK66YMG4@+g~n{@OQ dMNyP55{h+IE6uAj=zs@BJC z9{ICXS%j0{|2r2mW4x Rek%X~002ovPDHLkV1hughK&FK diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_nr.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_nr.png deleted file mode 100644 index 49ba54b4e664a6576c54d925697ab14f366dfc50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 322 zcmV-I0lof-P)bu_|Z7fG*=uXo@`imRq2N=Rs0ETe+^8{UEcOZ5@T8>b=Y``hC=ck}Rqn_~r z0Bh|%_Ic>Pq-=h#mCWzxoF6-#|C_3+rTt&!;$v|VAm%`vt>yE_oExHuxmS{Kbn+{< zvCTtIuFBbr8ZGU2Y|OwbeRSyRRsgqh5LpcXk*kA1$?2lg5V U`lo^QsQ>@~07*qoM6N<$g1SPDnE(I) diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_nu.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_nu.png deleted file mode 100644 index ff0957cd863680b97adc1b3b6aedd51d98492130..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 334 zcmV-U0kQsxP)*qTaRC6R_Vj2np_C0>0RNRIO2;Nkc;8Cc48?fY@>lq&t-gw&fhy zi&jlb3x=*f@muhU8C4n|=C1?z!e*t``0QIcv9hvCNlD4c$?56o zSy))u+SuwQALtEn9p##Lob=GnNGT1v5B2 zyO9Ruw0pWZhD02GJH=AyumcAR<61Ejr{n+QUmqxYqouaV_xa^&ksgoBCcc;dFt|M{ zE%h@{@@QV16JWeKby1GNp3b=Go)78&qol`;+09I>kp8x;= diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_right.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_right.png deleted file mode 100644 index 09307337abe5429a3555be76b8f394b0f8ce7137..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!j01c^Tql%VVP$2Nl9G~>lhf1F zv#_wRwY80ji775FuB)r7udi=xY@9iB=Iq(CSFT*SYSpSOTed`$HTM9uGnNGT1v5B2 zyO9RugnPO;hDb=hJ$O*CL4k+mfbybFLFK>U+VWBg^2c|^3J41RZB$tPrfW*pGLJy> zqqCF_m+hFH)cGStJgme2V?yh;hbG@&cm(wKwG_FyyY00ulIrN_*!Pn4NiI|J)}vQb QfL1Vgy85}Sb4q9e05;4}Qvd(} diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_ud.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_ud.png deleted file mode 100644 index d261c7db23d831732d46889f1339730965e26c0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!Yyx~jT!AzzE31^0l$@NLo}QkC zg@vuHt)HJ?OiWC1adBN;U44ChV`JmgsZ(dpoH={;?3F85u3EKf-MV#Kwru(H_ZrAx z#*!evUYXy6^8-I`}mt?m3+G8K^V6Xkx`K|i775FuCK3eY;2r5b?VHSGiT49y>jKsRjXF5Teoh@mMuL$m_>jlFqQ=Q z1v5B2yO9Ruw0XKXhD02GJH=3_Re{Gv@UI$o;Fo{XMct~?H(f3N)D`eH+rw<>gWgQF z&-S8v{040k(|OA8<)1hmC;B4Uc>cmITbPbl+)X*KBL7c=!eQJtXU?8Id*#ZNt5&UAw{G2*EnC*xaUKDhz*rLG z7tG-B>_!@p6XxmS7!q;#?PYJi1_c3@z$5%y`WAiPzeb2Z!DzGbSFsJRZV3b(nx4q> z?s-&FwPw(Z-yRR|{^qW<+NNcDJa6BjTbGpP{w+H_sde5*_Qs^LkMkLUhW@y7{V0=D TuH+|0Acw)z)z4*}Q$iB}v_V&P diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_ur.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked_ur.png deleted file mode 100644 index a72b0c98dcd1b5ceb2652a862a9ea519869bb487..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!Yyx~jTyu*9Sy@@7q@?8Jgww2>l+&zr%s(ZbLPz1vuCedxpLL2RqNKR+p=X#om=ez zpgD{sL4Lsu4$p3+0XdzXE{-7)hu=;;$k(F4+k2W7`&2>S6Gqeex~?C zQj6~IjYUn1yrfp`U%lCcEh(NuuSAh`_xd%_?lWtD?X%e7{^V2TqfaYya;`@C6brC8 behBc3_{bW(%HX>h&`}JYu6{1-oD!M<1}1Q7 diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/pipe_blocked.png similarity index 100% rename from src/main/resources/assets/gregtech/textures/blocks/pipe/blocked/pipe_blocked.png rename to src/main/resources/assets/gregtech/textures/blocks/pipe/pipe_blocked.png From 5a10bb377603c8c92e24dd2bb8a1fb1dd0d40c7a Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 3 Aug 2024 20:05:43 -0600 Subject: [PATCH 088/157] Cover rendering & misc other --- src/main/java/gregtech/api/cover/Cover.java | 10 +- .../java/gregtech/api/cover/CoverBase.java | 15 ++ .../gregtech/api/cover/CoverableView.java | 1 + .../api/graphnet/alg/SinglePathAlgorithm.java | 14 +- .../api/graphnet/path/AbstractNetPath.java | 15 ++ .../physical/block/PipeActivableBlock.java | 2 +- .../pipenet/physical/block/PipeBlock.java | 13 +- .../physical/block/PipeMaterialBlock.java | 6 +- .../tile/PipeActivableTileEntity.java | 3 + .../physical/tile/PipeCoverHolder.java | 45 +++-- .../physical/tile/PipeMaterialTileEntity.java | 11 ++ .../pipenet/physical/tile/PipeTileEntity.java | 24 ++- .../renderer/handler/FacadeRenderer.java | 35 ++++ .../renderer/pipe/AbstractPipeModel.java | 30 +++- .../renderer/pipe/ActivablePipeModel.java | 8 +- .../renderer/pipe/cache/ActivableSQC.java | 3 +- .../renderer/pipe/cache/BlockableSQC.java | 3 +- .../renderer/pipe/cache/ExtraCappedSQC.java | 3 +- .../renderer/pipe/cache/RestrictiveSQC.java | 5 +- .../pipe/cache/StructureQuadCache.java | 39 +---- .../renderer/pipe/cache/SubListAddress.java | 14 ++ .../renderer/pipe/cover/CoverRenderer.java | 17 ++ .../pipe/cover/CoverRendererBuilder.java | 156 ++++++++++++++++++ .../pipe/cover/CoverRendererPackage.java | 76 +++++++++ .../renderer/pipe/quad/PipeQuadHelper.java | 61 ++----- .../client/renderer/pipe/quad/QuadHelper.java | 96 +++++++++++ .../client/renderer/pipe/quad/UVMapper.java | 25 +++ .../texture/cube/SimpleOverlayRenderer.java | 8 + .../gregtech/common/covers/CoverConveyor.java | 26 ++- .../common/covers/CoverCraftingTable.java | 13 +- .../common/covers/CoverDigitalInterface.java | 14 +- .../common/covers/CoverEnderFluidLink.java | 7 + .../gregtech/common/covers/CoverFacade.java | 16 +- .../common/covers/CoverFluidFilter.java | 7 + .../common/covers/CoverFluidRegulator.java | 6 - .../common/covers/CoverFluidVoiding.java | 14 ++ .../covers/CoverFluidVoidingAdvanced.java | 7 + .../common/covers/CoverInfiniteWater.java | 7 + .../common/covers/CoverItemFilter.java | 7 + .../common/covers/CoverItemVoiding.java | 13 ++ .../covers/CoverItemVoidingAdvanced.java | 7 + .../common/covers/CoverMachineController.java | 7 + .../gregtech/common/covers/CoverPump.java | 23 +++ .../common/covers/CoverRoboticArm.java | 12 ++ .../gregtech/common/covers/CoverScreen.java | 9 +- .../gregtech/common/covers/CoverShutter.java | 9 +- .../common/covers/CoverSolarPanel.java | 7 + .../gregtech/common/covers/CoverStorage.java | 7 + .../detector/CoverDetectorActivity.java | 9 +- .../CoverDetectorActivityAdvanced.java | 7 + .../covers/detector/CoverDetectorEnergy.java | 9 +- .../detector/CoverDetectorEnergyAdvanced.java | 7 + .../covers/detector/CoverDetectorFluid.java | 7 + .../detector/CoverDetectorFluidAdvanced.java | 7 + .../covers/detector/CoverDetectorItem.java | 7 + .../detector/CoverDetectorItemAdvanced.java | 7 + .../detector/CoverDetectorMaintenance.java | 7 + .../common/pipelike/net/SlowActiveWalker.java | 21 ++- 58 files changed, 881 insertions(+), 163 deletions(-) create mode 100644 src/main/java/gregtech/client/renderer/pipe/cache/SubListAddress.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java diff --git a/src/main/java/gregtech/api/cover/Cover.java b/src/main/java/gregtech/api/cover/Cover.java index e4bc8d9b3c4..6b9194dafa3 100644 --- a/src/main/java/gregtech/api/cover/Cover.java +++ b/src/main/java/gregtech/api/cover/Cover.java @@ -1,7 +1,6 @@ package gregtech.api.cover; -import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.utils.BloomEffectUtil; import net.minecraft.entity.player.EntityPlayer; @@ -141,9 +140,9 @@ default boolean canInteractWithOutputSide() { } /** - * @return if the pipe this cover is placed on should render a connection to the cover + * @return if the pipe this cover is placed on should always render a connection to the cover */ - default boolean shouldAutoConnectToPipes() { + default boolean forcePipeRenderConnection() { return true; } @@ -250,6 +249,9 @@ void renderCoverPlate(@NotNull CCRenderState renderState, @NotNull Matrix4 trans @NotNull IVertexOperation[] pipeline, @NotNull Cuboid6 plateBox, @NotNull BlockRenderLayer layer); + @SideOnly(Side.CLIENT) + @NotNull CoverRenderer getRenderer(); + default boolean canRenderBackside() { return true; } diff --git a/src/main/java/gregtech/api/cover/CoverBase.java b/src/main/java/gregtech/api/cover/CoverBase.java index 49a3429f842..0fb02305c9d 100644 --- a/src/main/java/gregtech/api/cover/CoverBase.java +++ b/src/main/java/gregtech/api/cover/CoverBase.java @@ -2,6 +2,8 @@ import gregtech.api.GTValues; import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; @@ -20,6 +22,7 @@ import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public abstract class CoverBase implements Cover { @@ -27,6 +30,9 @@ public abstract class CoverBase implements Cover { private final CoverableView coverableView; private final EnumFacing attachedSide; + @SideOnly(Side.CLIENT) + protected @Nullable CoverRenderer renderer; + public CoverBase(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, @NotNull EnumFacing attachedSide) { this.definition = definition; @@ -77,6 +83,15 @@ public void renderCoverPlate(@NotNull CCRenderState renderState, @NotNull Matrix } } + @Override + @SideOnly(Side.CLIENT) + public @NotNull CoverRenderer getRenderer() { + if (renderer == null) renderer = buildRenderer(); + return renderer; + } + + protected abstract CoverRenderer buildRenderer(); + @SideOnly(Side.CLIENT) protected @NotNull TextureAtlasSprite getPlateSprite() { return Textures.VOLTAGE_CASINGS[GTValues.LV].getSpriteOnSide(SimpleSidedCubeRenderer.RenderSide.SIDE); diff --git a/src/main/java/gregtech/api/cover/CoverableView.java b/src/main/java/gregtech/api/cover/CoverableView.java index 8bebd97b26d..ed9a89f5f86 100644 --- a/src/main/java/gregtech/api/cover/CoverableView.java +++ b/src/main/java/gregtech/api/cover/CoverableView.java @@ -6,6 +6,7 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java index 0609e9265ba..0d5c7ba62a8 100644 --- a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java @@ -60,10 +60,16 @@ private Results compute(GraphVertex source, if (!i.hasNext()) break; // we've reached the end, exit the loop while still valid graphEdge = i.next(); // if we are directed, we know that the target is the target. - // if we aren't directed, we need to see if the graphEdge's source was secretly the target - boolean reversedEdge = !this.net.getGraph().isDirected() && graphEdge.getSource() == lastNode; - if (graphEdge.getTarget() == lastNode || reversedEdge) { - if (i.hasNext()) graphEdge = i.next(); + // if we aren't directed, we need to see if the graphEdge's target is secretly the source + boolean reversedEdge = !this.net.getGraph().isDirected() && graphEdge.getTarget() == node; + if ((!reversedEdge && graphEdge.getTarget() == lastNode) || + (reversedEdge && graphEdge.getSource() == lastNode)) { + // current edge points to a previous node, either get the other edge or exit safely. + if (i.hasNext()) { + graphEdge = i.next(); + reversedEdge = !this.net.getGraph().isDirected() && graphEdge.getTarget() == node; + // we know that the new edge cannot point to the previous node + } else break; // we've reached the end, exit the loop while still valid } else if (i.hasNext()) i.next(); if (i.hasNext()) valid = false; // third graphEdge detected - that's an invalid group diff --git a/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java b/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java index c2fd92c10a5..aaa8c5719ab 100644 --- a/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Objects; public abstract class AbstractNetPath implements INetPath { @@ -72,4 +73,18 @@ public NetLogicData getUnifiedEdgeData() { } return unifiedEdgeData; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AbstractNetPath that = (AbstractNetPath) o; + return Double.compare(that.weight, weight) == 0 && Objects.equals(nodes, that.nodes) && + Objects.equals(edges, that.edges); + } + + @Override + public int hashCode() { + return Objects.hash(nodes, edges, weight); + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java index c6123e0c347..4a908cebbb1 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java @@ -44,7 +44,7 @@ public Class getTileClass(@NotNull World worl } TileEntity tile = world.getTileEntity(pos); if (tile instanceof PipeActivableTileEntity pipe) { - lastTilePos.set(pos); + lastTilePos.set(pos.toImmutable()); lastTile.set(new WeakReference<>(pipe)); return pipe; } else return null; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 4e299d4761e..d7ef8250a43 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -18,6 +18,8 @@ import gregtech.api.util.EntityDamageUtil; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.AbstractPipeModel; +import gregtech.client.renderer.pipe.cover.CoverRendererPackage; +import gregtech.client.utils.BloomEffectUtil; import gregtech.client.utils.TooltipHelper; import gregtech.common.ConfigHolder; import gregtech.common.blocks.BlockFrame; @@ -185,6 +187,9 @@ else if (coverCheck(tile, other, facing)) { ToolHelper.damageItem(item, playerIn); ToolHelper.playToolSound(item, playerIn); connectTile(tile, other, facing); + } else { + // if the covers disallow the connection, simply try to render a connection. + connectTile(tile, null, facing); } } return true; @@ -404,7 +409,9 @@ public boolean recolorBlock(@NotNull World world, @NotNull BlockPos pos, @NotNul @Override public boolean canRenderInLayer(@NotNull IBlockState state, @NotNull BlockRenderLayer layer) { - return getStructure().getModel().canRenderInLayer(layer); + // guaranteed cutout & bloom for covers + return layer == BlockRenderLayer.CUTOUT_MIPPED || layer == BloomEffectUtil.getEffectiveBloomLayer() || + getStructure().getModel().canRenderInLayer(layer); } @Override @@ -562,7 +569,7 @@ public String getToolClass() { return builder.add(AbstractPipeModel.THICKNESS_PROPERTY).add(AbstractPipeModel.CONNECTION_MASK_PROPERTY) .add(AbstractPipeModel.CLOSED_MASK_PROPERTY).add(AbstractPipeModel.BLOCKED_MASK_PROPERTY) .add(AbstractPipeModel.COLOR_PROPERTY).add(AbstractPipeModel.FRAME_MATERIAL_PROPERTY) - .add(AbstractPipeModel.FRAME_MASK_PROPERTY); + .add(AbstractPipeModel.FRAME_MASK_PROPERTY).add(CoverRendererPackage.PROPERTY); } @Override @@ -588,7 +595,7 @@ public PipeTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockP } TileEntity tile = world.getTileEntity(pos); if (tile instanceof PipeTileEntity pipe) { - lastTilePos.set(pos); + lastTilePos.set(pos.toImmutable()); lastTile.set(new WeakReference<>(pipe)); return pipe; } else return null; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index 8415ec0c419..91cbf9e1847 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -82,8 +82,8 @@ public Material getMaterialForStack(@NotNull ItemStack stack) { @Override protected @NotNull IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos) { PipeMaterialTileEntity tile = getTileEntity(world, pos); - if (tile != null) tile.getMaterial().getProperty(PropertyKey.PIPENET_PROPERTIES); - return Materials.Aluminium.getProperty(PropertyKey.PIPENET_PROPERTIES); + if (tile != null) return tile.getMaterial().getProperty(PropertyKey.PIPENET_PROPERTIES); + else return Materials.Aluminium.getProperty(PropertyKey.PIPENET_PROPERTIES); } @Override @@ -120,7 +120,7 @@ protected BlockStateContainer.Builder constructState(BlockStateContainer.@NotNul } TileEntity tile = world.getTileEntity(pos); if (tile instanceof PipeMaterialTileEntity pipe) { - lastTilePos.set(pos); + lastTilePos.set(pos.toImmutable()); lastTile.set(new WeakReference<>(pipe)); return pipe; } else return null; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java index 91f69fe336d..9726edcd474 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java @@ -3,7 +3,10 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.client.renderer.pipe.ActivablePipeModel; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java index 5704cc71bcb..629c6ccf6c6 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java @@ -3,7 +3,9 @@ import gregtech.api.cover.Cover; import gregtech.api.cover.CoverHolder; import gregtech.api.cover.CoverSaveHandler; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.cover.CoverRendererPackage; import gregtech.common.ConfigHolder; import net.minecraft.item.ItemStack; @@ -39,13 +41,12 @@ public PipeCoverHolder(PipeTileEntity holder) { } protected final void addCoverSilent(@NotNull EnumFacing side, @NotNull Cover cover) { - if (cover instanceof ITickable && !holder.isTicking()) { - holder.addTicker(this); - tickingCovers.add(side); - return; - } // we checked before if the side already has a cover this.covers.put(side, cover); + if (cover instanceof ITickable) { + tickingCovers.add(side); + holder.addTicker(this); + } } @Override @@ -54,8 +55,8 @@ public final void addCover(@NotNull EnumFacing side, @NotNull Cover cover) { if (!getWorld().isRemote) { // do not sync or handle logic on client side CoverSaveHandler.writeCoverPlacement(this, COVER_ATTACHED_PIPE, side, cover); - if (cover.shouldAutoConnectToPipes()) { - if (holder.canConnectTo(side)) holder.setConnected(side, false); + if (holder.isConnected(side) && !cover.canPipePassThrough()) { + PipeBlock.disconnectTile(holder, holder.getPipeNeighbor(side, true), side); } } @@ -68,20 +69,11 @@ public final void removeCover(@NotNull EnumFacing side) { Cover cover = getCoverAtSide(side); if (cover == null) return; - if (cover instanceof ITickable) { - tickingCovers.remove(side); - if (tickingCovers.isEmpty()) holder.removeTicker(this); - } - dropCover(side); covers.remove(side); + tickingCovers.remove(side); + if (tickingCovers.isEmpty()) holder.removeTicker(this); writeCustomData(COVER_REMOVED_PIPE, buffer -> buffer.writeByte(side.getIndex())); - if (cover.shouldAutoConnectToPipes()) { - PipeTileEntity other; - if (holder.isConnected(side) && (other = holder.getPipeNeighbor(side, true)) != null && - !other.isConnected(side.getOpposite())) - holder.setDisconnected(side); - } holder.notifyBlockUpdate(); holder.markAsDirty(); } @@ -229,6 +221,8 @@ public void readCustomData(int dataId, PacketBuffer buf) { // cover removed event EnumFacing placementSide = EnumFacing.VALUES[buf.readByte()]; this.covers.remove(placementSide); + this.tickingCovers.remove(placementSide); + if (this.tickingCovers.isEmpty()) holder.removeTicker(this); holder.scheduleRenderUpdate(); } else if (dataId == UPDATE_COVER_DATA_PIPE) { // cover custom data received @@ -263,10 +257,6 @@ public BlockPos getPos() { return holder.getPos(); } - public TileEntity getTileEntityHere() { - return holder; - } - @Override public @Nullable TileEntity getNeighbor(@NotNull EnumFacing facing) { return holder.getNeighbor(facing); @@ -300,6 +290,15 @@ public boolean isValid() { @Override public T getCapability(@NotNull Capability capability, EnumFacing side) { - return holder.getCapability(capability, side); + return holder.getCapabilityCoverQuery(capability, side); + } + + public CoverRendererPackage createPackage() { + if (covers.isEmpty()) return CoverRendererPackage.EMPTY; + CoverRendererPackage rendererPackage = new CoverRendererPackage(shouldRenderCoverBackSides()); + for (var cover : covers.entrySet()) { + rendererPackage.addRenderer(cover.getValue().getRenderer(), cover.getKey()); + } + return rendererPackage; } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java index 7346f392cd3..6e7be13bbe9 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java @@ -12,6 +12,8 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; import org.jetbrains.annotations.NotNull; @@ -20,10 +22,19 @@ public class PipeMaterialTileEntity extends PipeTileEntity { private Material material; + @Override + protected void initialize() { + // prevent initialization when we don't know our material; + // this specifically happens right after we have been + // placed and placedBy() has yet to be called. + if (material != null) super.initialize(); + } + @Override public void placedBy(ItemStack stack, EntityPlayer player) { super.placedBy(stack, player); setMaterial(getBlockType().getMaterialForStack(stack)); + initialize(); } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index ab0c0455ee1..4855ead358d 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -19,6 +19,7 @@ import gregtech.api.util.GTUtility; import gregtech.client.particle.GTOverheatParticle; import gregtech.client.renderer.pipe.AbstractPipeModel; +import gregtech.client.renderer.pipe.cover.CoverRendererPackage; import gregtech.common.blocks.MetaBlocks; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; @@ -381,6 +382,12 @@ private void addCapabilities(IPipeCapabilityObject[] capabilities) { } } + public T getCapabilityCoverQuery(@NotNull Capability capability, @Nullable EnumFacing facing) { + // covers have access to the capability objects no matter the connection status + IPipeCapabilityObject object = capabilities.get(capability); + return object == null ? null : object.getCapabilityForSide(capability, facing); + } + @Override public boolean hasCapability(@NotNull Capability capability, EnumFacing facing) { return getCapability(capability, facing) != null; @@ -663,13 +670,6 @@ public void markDirty() { public void markAsDirty() { markDirty(); // this most notably gets called when the covers of a pipe get updated, aka the edge predicates need syncing. - for (EnumFacing facing : EnumFacing.VALUES) { - if (!GTUtility.evalMask(facing, connectionMask)) continue; - Cover cover = getCoverHolder().getCoverAtSide(facing); - if (cover != null && !cover.canPipePassThrough()) { - PipeBlock.disconnectTile(this, getPipeNeighbor(facing, true), facing); - } - } for (var node : this.netCapabilities.keySet()) { node.getNet().updatePredication(node, this); } @@ -689,8 +689,13 @@ public void markAsDirty() { */ public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { byte frameMask = 0; + byte connectionMask = this.connectionMask; for (EnumFacing facing : EnumFacing.VALUES) { - if (getCoverHolder().hasCover(facing)) frameMask |= 1 << facing.ordinal(); + Cover cover = getCoverHolder().getCoverAtSide(facing); + if (cover != null) { + frameMask |= 1 << facing.ordinal(); + if (cover.forcePipeRenderConnection()) connectionMask |= 1 << facing.ordinal(); + } } frameMask = (byte) ~frameMask; return state.withProperty(AbstractPipeModel.THICKNESS_PROPERTY, this.getStructure().getRenderThickness()) @@ -699,7 +704,8 @@ public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { .withProperty(AbstractPipeModel.BLOCKED_MASK_PROPERTY, blockedMask) .withProperty(AbstractPipeModel.COLOR_PROPERTY, getPaintingColor()) .withProperty(AbstractPipeModel.FRAME_MATERIAL_PROPERTY, frameMaterial) - .withProperty(AbstractPipeModel.FRAME_MASK_PROPERTY, frameMask); + .withProperty(AbstractPipeModel.FRAME_MASK_PROPERTY, frameMask) + .withProperty(CoverRendererPackage.PROPERTY, getCoverHolder().createPackage()); } public void dealAreaDamage(int size, Consumer damageFunction) { diff --git a/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java b/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java index 6db1848659a..d3d01127247 100644 --- a/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java +++ b/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java @@ -4,6 +4,8 @@ import gregtech.api.items.metaitem.MetaItem; import gregtech.client.model.pipeline.VertexLighterFlatSpecial; import gregtech.client.model.pipeline.VertexLighterSmoothAoSpecial; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.utils.AdvCCRSConsumer; import gregtech.client.utils.FacadeBlockAccess; import gregtech.client.utils.ItemRenderCompat; @@ -26,6 +28,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.IBlockAccess; @@ -50,8 +53,10 @@ import org.lwjgl.opengl.GL11; import java.util.ArrayList; +import java.util.EnumMap; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; /** * Mostly based on and (copied from) ThermalDynamics with minor tweaks @@ -147,6 +152,36 @@ public static boolean renderBlockCover(CCRenderState ccrs, Matrix4 translation, return false; } + public static CoverRenderer createRenderer(IBlockAccess world, BlockPos pos, IBlockState state) { + BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher(); + try { + state = state.getActualState(world, pos); + } catch (Exception ignored) {} + + IBakedModel model = dispatcher.getModelForState(state); + + try { + state = state.getBlock().getExtendedState(state, world, pos); + } catch (Exception ignored) {} + IBlockState finalState = state; + return (quads, facing, renderPlate, renderBackside, renderLayer, data) -> { + // since the block model may be sensitive to the current render layer, we have to recalculate + // every call. + long posRand = MathHelper.getPositionRandom(pos); + List modelQuads = new ArrayList<>(model.getQuads(finalState, null, posRand)); + for (EnumFacing face : EnumFacing.VALUES) { + modelQuads.addAll(model.getQuads(finalState, face, posRand)); + } + // is there anything that can be done to make this cheaper? + quads.addAll(remap(sliceQuads(fromArray(modelQuads), facing.getIndex(), + new Cuboid6(CoverRendererBuilder.PLATE_AABBS.get(facing))))); + }; + } + + private static List remap(List quads) { + return quads.stream().map(CCQuad::bake).collect(Collectors.toList()); + } + public static void renderItemCover(CCRenderState ccrs, int side, ItemStack renderStack, Cuboid6 bounds) { Minecraft minecraft = Minecraft.getMinecraft(); RenderItem renderItem = minecraft.getRenderItem(); diff --git a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java index d8fe05f78ed..1dd92b20555 100644 --- a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java @@ -9,6 +9,7 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.cache.ColorQuadCache; import gregtech.client.renderer.pipe.cache.StructureQuadCache; +import gregtech.client.renderer.pipe.cover.CoverRendererPackage; import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.util.CacheKey; @@ -76,14 +77,35 @@ public AbstractPipeModel(ModelResourceLocation loc) { @Override public @NotNull List getQuads(IBlockState state, EnumFacing side, long rand) { if (side == null && state instanceof IExtendedBlockState ext) { - return getQuads(toKey(ext), safeByte(ext.getValue(CONNECTION_MASK_PROPERTY)), - safeByte(ext.getValue(CLOSED_MASK_PROPERTY)), safeByte(ext.getValue(BLOCKED_MASK_PROPERTY)), - computeColorData(ext), ext.getValue(FRAME_MATERIAL_PROPERTY), - safeByte(ext.getValue(FRAME_MASK_PROPERTY))); + List quads; + ColorData data = computeColorData(ext); + if (canRenderInLayer(getCurrentRenderLayer())) { + quads = getQuads(toKey(ext), safeByte(ext.getValue(CONNECTION_MASK_PROPERTY)), + safeByte(ext.getValue(CLOSED_MASK_PROPERTY)), safeByte(ext.getValue(BLOCKED_MASK_PROPERTY)), + data, ext.getValue(FRAME_MATERIAL_PROPERTY), + safeByte(ext.getValue(FRAME_MASK_PROPERTY))); + } else quads = new ObjectArrayList<>(); + CoverRendererPackage rendererPackage = ext.getValue(CoverRendererPackage.PROPERTY); + if (rendererPackage != null) renderCovers(quads, rendererPackage, ext); + return quads; } return Collections.emptyList(); } + protected void renderCovers(List quads, @NotNull CoverRendererPackage rendererPackage, IExtendedBlockState ext) { + if (!ext.getUnlistedProperties().containsKey(AbstractPipeModel.MATERIAL_PROPERTY)) return; + Material material = ext.getValue(AbstractPipeModel.MATERIAL_PROPERTY); + int color = safeInt(ext.getValue(COLOR_PROPERTY)); + if (material != null) { + int matColor = GTUtility.convertRGBtoARGB(material.getMaterialRGB()); + if (color == 0 || color == matColor) { + // unpainted + color = 0xFFFFFFFF; + } + } + rendererPackage.addQuads(quads, getCurrentRenderLayer(), new ColorData(color)); + } + protected ColorData computeColorData(IExtendedBlockState ext) { return new ColorData(safeInt(ext.getValue(COLOR_PROPERTY))); } diff --git a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java index 022077ba633..42fcd5b00f1 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java @@ -77,16 +77,16 @@ public ActivablePipeModel(@NotNull Supplier inTex, @NotNull S List quads = bloomLayer ? new ObjectArrayList<>() : super.getQuads(key, connectionMask, closedMask, blockedMask, data, frameMaterial, frameMask); - if (!bloomLayer && (!key.isActive() || !allowActive())) { - ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, data, false); - } else { + if (key.isActive() && allowActive()) { if (emissiveActive && bloomLayer) { ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, data, true); // TODO bake this into the original quads quads = quads.stream().map(RenderUtil::makeEmissive).collect(Collectors.toList()); - } else if (!emissiveActive && getCurrentRenderLayer() == BlockRenderLayer.CUTOUT_MIPPED) { + } else if (!emissiveActive && !bloomLayer) { ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, data, true); } + } else if (!bloomLayer) { + ((ActivableSQC) pipeCache.get(key)).addOverlay(quads, connectionMask, data, false); } return quads; } diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java index 32539f51f54..5b868652e7d 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java @@ -3,6 +3,7 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; +import gregtech.client.renderer.pipe.quad.QuadHelper; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -33,7 +34,7 @@ protected ActivableSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteIn public static @NotNull ActivableSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation overlayTex, SpriteInformation overlayActiveTex) { - helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> StructureQuadCache.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); ActivableSQC cache = new ActivableSQC(helper, endTex, sideTex, overlayTex, overlayActiveTex); cache.buildPrototype(); return cache; diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java index e1b5393a1c5..b733f93ef9b 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java @@ -3,6 +3,7 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; +import gregtech.client.renderer.pipe.quad.QuadHelper; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -32,7 +33,7 @@ protected BlockableSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteIn public static @NotNull BlockableSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation blockedTex) { - helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> StructureQuadCache.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); BlockableSQC cache = new BlockableSQC(helper, endTex, sideTex, blockedTex); cache.buildPrototype(); return cache; diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java index 5a766238f28..075ea5f5898 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java @@ -3,6 +3,7 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; +import gregtech.client.renderer.pipe.quad.QuadHelper; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -32,7 +33,7 @@ protected ExtraCappedSQC(PipeQuadHelper helper, SpriteInformation endTex, Sprite public static @NotNull ExtraCappedSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation extraEndTex) { - helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> StructureQuadCache.capOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.capOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); ExtraCappedSQC cache = new ExtraCappedSQC(helper, endTex, sideTex, extraEndTex); cache.buildPrototype(); return cache; diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java index ebabb9c985b..4acfd74220e 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java @@ -3,6 +3,7 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; +import gregtech.client.renderer.pipe.quad.QuadHelper; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -33,8 +34,8 @@ protected RestrictiveSQC(PipeQuadHelper helper, SpriteInformation endTex, Sprite public static @NotNull RestrictiveSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation blockedTex, SpriteInformation restrictiveTex) { - helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> StructureQuadCache.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_2), - (facing, x1, y1, z1, x2, y2, z2) -> StructureQuadCache.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_2), + (facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); RestrictiveSQC sqc = new RestrictiveSQC(helper, endTex, sideTex, blockedTex, restrictiveTex); sqc.buildPrototype(); return sqc; diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java index aced6d255f7..f561c4b5873 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java @@ -1,10 +1,7 @@ package gregtech.client.renderer.pipe.cache; import gregtech.api.util.GTUtility; -import gregtech.client.renderer.pipe.quad.ColorData; -import gregtech.client.renderer.pipe.quad.OverlayLayerDefinition; -import gregtech.client.renderer.pipe.quad.PipeQuadHelper; -import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; +import gregtech.client.renderer.pipe.quad.*; import gregtech.client.renderer.pipe.util.SpriteInformation; import net.minecraft.client.renderer.block.model.BakedQuad; @@ -12,13 +9,8 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import com.github.bsideup.jabel.Desugar; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.lwjgl.util.vector.Vector3f; import java.util.EnumMap; import java.util.List; @@ -121,33 +113,4 @@ public void addToList(List list, byte connectionMask, byte closedMask } } - @Desugar - protected record SubListAddress(int startInclusive, int endExclusive) { - - public @NotNull List getSublist(@NotNull List list) { - return list.subList(startInclusive, endExclusive); - } - } - - public static ImmutablePair capOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { - if (facing == null) return PipeQuadHelper.pair(x1 - g, y1 - g, z1 - g, x2 + g, y2 + g, z2 + g); - return switch (facing.getAxis()) { - case X -> PipeQuadHelper.pair(x1 - g, y1, z1, x2 + g, y2, z2); - case Y -> PipeQuadHelper.pair(x1, y1 - g, z1, x2, y2 + g, z2); - case Z -> PipeQuadHelper.pair(x1, y1, z1 - g, x2, y2, z2 + g); - }; - } - - public static ImmutablePair tubeOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { - if (facing == null) return PipeQuadHelper.pair(x1, y1, z1, x2, y2, z2); - return switch (facing.getAxis()) { - case X -> PipeQuadHelper.pair(x1, y1 - g, z1 - g, x2, y2 + g, z2 + g); - case Y -> PipeQuadHelper.pair(x1 - g, y1, z1 - g, x2 + g, y2, z2 + g); - case Z -> PipeQuadHelper.pair(x1 - g, y1 - g, z1, x2 + g, y2 + g, z2); - }; - } - - public static ImmutablePair fullOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { - return PipeQuadHelper.pair(x1 - g, y1 - g, z1 - g, x2 + g, y2 + g, z2 + g); - } } diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/SubListAddress.java b/src/main/java/gregtech/client/renderer/pipe/cache/SubListAddress.java new file mode 100644 index 00000000000..23453222ce8 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/cache/SubListAddress.java @@ -0,0 +1,14 @@ +package gregtech.client.renderer.pipe.cache; + +import com.github.bsideup.jabel.Desugar; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +@Desugar +public record SubListAddress(int startInclusive, int endExclusive) { + + public @NotNull List getSublist(@NotNull List list) { + return list.subList(startInclusive, endExclusive); + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java new file mode 100644 index 00000000000..49472431824 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java @@ -0,0 +1,17 @@ +package gregtech.client.renderer.pipe.cover; + +import gregtech.client.renderer.pipe.quad.ColorData; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumFacing; + +import java.util.EnumSet; +import java.util.List; + +@FunctionalInterface +public interface CoverRenderer { + + void addQuads(List quads, EnumFacing facing, EnumSet renderPlate, boolean renderBackside, + BlockRenderLayer renderLayer, ColorData data); +} diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java new file mode 100644 index 00000000000..f39ecf4988f --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java @@ -0,0 +1,156 @@ +package gregtech.client.renderer.pipe.cover; + +import gregtech.api.GTValues; +import gregtech.api.cover.CoverUtil; +import gregtech.client.renderer.pipe.cache.ColorQuadCache; +import gregtech.client.renderer.pipe.cache.SubListAddress; +import gregtech.client.renderer.pipe.quad.ColorData; +import gregtech.client.renderer.pipe.quad.QuadHelper; +import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; +import gregtech.client.renderer.pipe.quad.UVMapper; +import gregtech.client.renderer.pipe.util.SpriteInformation; +import gregtech.client.renderer.texture.Textures; +import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; + +import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; + +import gregtech.client.utils.BloomEffectUtil; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; + +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumFacing; + +import net.minecraft.util.math.AxisAlignedBB; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.util.vector.Vector3f; + +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.List; + +public class CoverRendererBuilder { + + private static final float OVERLAY_DIST_1 = 0.003f; + private static final float OVERLAY_DIST_2 = 0.006f; + + private static final ColorQuadCache PLATE_QUADS; + private static final EnumMap PLATE_COORDS = new EnumMap<>(EnumFacing.class); + + public static final EnumMap PLATE_AABBS = new EnumMap<>(EnumFacing.class); + private static final EnumMap> PLATE_BOXES = new EnumMap<>(EnumFacing.class); + private static final EnumMap> OVERLAY_BOXES_1 = new EnumMap<>(EnumFacing.class); + private static final EnumMap> OVERLAY_BOXES_2 = new EnumMap<>(EnumFacing.class); + + private static final UVMapper defaultMapper = UVMapper.standard(0); + + static { + for (EnumFacing facing : EnumFacing.VALUES) { + PLATE_AABBS.put(facing, CoverUtil.getCoverPlateBox(facing, 1d / 16).aabb()); + } + for (var value : PLATE_AABBS.entrySet()) { + // make sure that plates render slightly below any normal block quad + PLATE_BOXES.put(value.getKey(), QuadHelper.fullOverlay(value.getKey(), value.getValue(), -OVERLAY_DIST_1)); + OVERLAY_BOXES_1.put(value.getKey(), QuadHelper.fullOverlay(value.getKey(), value.getValue(), OVERLAY_DIST_1)); + OVERLAY_BOXES_2.put(value.getKey(), QuadHelper.fullOverlay(value.getKey(), value.getValue(), OVERLAY_DIST_2)); + } + PLATE_QUADS = buildPlates(new SpriteInformation(defaultPlateSprite(), 0)); + } + + private static @NotNull TextureAtlasSprite defaultPlateSprite() { + return Textures.VOLTAGE_CASINGS[GTValues.LV].getSpriteOnSide(SimpleSidedCubeRenderer.RenderSide.SIDE); + } + + public static ColorQuadCache buildPlates(SpriteInformation sprite) { + List quads = new ObjectArrayList<>(); + UVMapper mapper = UVMapper.standard(0); + for (EnumFacing facing : EnumFacing.VALUES) { + PLATE_COORDS.put(facing, buildPlates(quads, facing, mapper, sprite)); + } + return new ColorQuadCache(quads); + } + + protected static SubListAddress buildPlates(List quads, EnumFacing facing, + UVMapper mapper, SpriteInformation sprite) { + int start = quads.size(); + Pair box = PLATE_BOXES.get(facing); + for (EnumFacing dir : EnumFacing.values()) { + quads.add(QuadHelper.buildQuad(dir, box, mapper, sprite)); + } + return new SubListAddress(start, quads.size()); + } + + protected static void addPlates(List quads, List plateQuads, EnumSet plates) { + for (EnumFacing facing : plates) { + quads.add(plateQuads.get(facing.ordinal())); + } + } + + protected final TextureAtlasSprite sprite; + protected final TextureAtlasSprite spriteEmissive; + + protected UVMapper mapper = defaultMapper; + protected UVMapper mapperEmissive = defaultMapper; + + protected ColorQuadCache plateQuads = PLATE_QUADS; + + public CoverRendererBuilder(@NotNull SimpleOverlayRenderer overlay) { + this(overlay.getSprite(), overlay.getSpriteEmissive()); + } + + public CoverRendererBuilder(@NotNull TextureAtlasSprite sprite, @Nullable TextureAtlasSprite spriteEmissive) { + this.sprite = sprite; + this.spriteEmissive = spriteEmissive; + } + + public CoverRendererBuilder setMapper(@NotNull UVMapper mapper) { + this.mapper = mapper; + return this; + } + + public CoverRendererBuilder setMapperEmissive(@NotNull UVMapper mapperEmissive) { + this.mapperEmissive = mapperEmissive; + return this; + } + + public CoverRendererBuilder setPlateQuads(ColorQuadCache cache) { + this.plateQuads = cache; + return this; + } + + protected static List getPlates(EnumFacing facing, ColorData data, ColorQuadCache plateQuads) { + return PLATE_COORDS.get(facing).getSublist(plateQuads.getQuads(data)); + } + + public CoverRenderer build() { + EnumMap> spriteQuads = new EnumMap<>(EnumFacing.class); + EnumMap> spriteEmissiveQuads = spriteEmissive != null ? new EnumMap<>(EnumFacing.class) : null; + for (EnumFacing facing : EnumFacing.VALUES) { + spriteQuads.put(facing, ImmutablePair.of( + QuadHelper.buildQuad(facing, OVERLAY_BOXES_1.get(facing), mapper, sprite), + QuadHelper.buildQuad(facing.getOpposite(), OVERLAY_BOXES_1.get(facing), mapper, sprite))); + if (spriteEmissive != null) spriteEmissiveQuads.put(facing, ImmutablePair.of( + QuadHelper.buildQuad(facing, OVERLAY_BOXES_2.get(facing), mapperEmissive, spriteEmissive), + QuadHelper.buildQuad(facing.getOpposite(), OVERLAY_BOXES_2.get(facing), mapperEmissive, spriteEmissive))); + } + + return (quads, facing, renderPlate, renderBackside, renderLayer, data) -> { + if (renderLayer == BlockRenderLayer.CUTOUT_MIPPED) { + addPlates(quads, getPlates(facing, data, plateQuads), renderPlate); + quads.add(spriteQuads.get(facing).getLeft()); + if (renderBackside) quads.add(spriteQuads.get(facing).getRight()); + } + if (spriteEmissiveQuads != null && renderLayer == BloomEffectUtil.getEffectiveBloomLayer()) { + quads.add(spriteEmissiveQuads.get(facing).getLeft()); + if (renderBackside) quads.add(spriteEmissiveQuads.get(facing).getRight()); + } + }; + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java new file mode 100644 index 00000000000..9e72373290c --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java @@ -0,0 +1,76 @@ +package gregtech.client.renderer.pipe.cover; + +import gregtech.client.renderer.pipe.quad.ColorData; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.EnumFacing; + +import net.minecraftforge.common.property.IUnlistedProperty; + +import org.jetbrains.annotations.NotNull; + +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.List; + +public final class CoverRendererPackage { + + public static final UnlistedCRPProperty PROPERTY = new UnlistedCRPProperty("CRP"); + + public static final CoverRendererPackage EMPTY = new CoverRendererPackage(false); + + private final EnumMap renderers = new EnumMap<>(EnumFacing.class); + private final EnumSet plates = EnumSet.allOf(EnumFacing.class); + + private final boolean renderBackside; + + public CoverRendererPackage(boolean renderBackside) { + this.renderBackside = renderBackside; + } + + public void addRenderer(CoverRenderer renderer, @NotNull EnumFacing facing) { + renderers.put(facing, renderer); + plates.remove(facing); + } + + public void addQuads(List quads, BlockRenderLayer renderLayer, ColorData data) { + for (var renderer : renderers.entrySet()) { + EnumSet plates = EnumSet.copyOf(this.plates); + // force front and back plates to render + plates.add(renderer.getKey()); + plates.add(renderer.getKey().getOpposite()); + renderer.getValue().addQuads(quads, renderer.getKey(), plates, renderBackside, renderLayer, data); + } + } + + public static class UnlistedCRPProperty implements IUnlistedProperty { + + private final String name; + + public UnlistedCRPProperty(@NotNull String name) { + this.name = name; + } + + @NotNull + @Override + public String getName() { + return name; + } + + @Override + public boolean isValid(CoverRendererPackage value) { + return true; + } + + @Override + public Class getType() { + return CoverRendererPackage.class; + } + + @Override + public String valueToString(CoverRendererPackage value) { + return value.toString(); + } + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java index f3c7494d307..d215ad8010e 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -2,18 +2,12 @@ import gregtech.client.renderer.pipe.util.SpriteInformation; -import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.block.model.BlockFaceUV; -import net.minecraft.client.renderer.block.model.BlockPartFace; -import net.minecraft.client.renderer.block.model.FaceBakery; -import net.minecraft.client.renderer.block.model.ModelRotation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.EnumFacing; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.Contract; import org.lwjgl.util.vector.Vector3f; @@ -24,7 +18,6 @@ @SideOnly(Side.CLIENT) public final class PipeQuadHelper { - private static final FaceBakery BAKERY = new FaceBakery(); private SpriteInformation targetSprite; @@ -33,10 +26,6 @@ public final class PipeQuadHelper { private float[] definition; - public static ImmutablePair pair(float x1, float y1, float z1, float x2, float y2, float z2) { - return ImmutablePair.of(new Vector3f(x1, y1, z1), new Vector3f(x2, y2, z2)); - } - public PipeQuadHelper(float x, float y, float z, float small, float large) { float xS = (x + small) * 16; float xL = (x + large) * 16; @@ -58,7 +47,7 @@ public PipeQuadHelper initialize(OverlayLayerDefinition... overlayLayers) { float zL = definition[5]; definition = null; generateBox(xS, xL, yS, yL, zS, zL, (facing, x1, y1, z1, x2, y2, z2) -> - ImmutablePair.of(new Vector3f(x1, y1, z1), new Vector3f(x2, y2, z2))); + QuadHelper.toPair(x1, y1, z1, x2, y2, z2)); for (OverlayLayerDefinition definition : overlayLayers) { generateBox(xS, xL, yS, yL, zS, zL, definition); } @@ -101,7 +90,7 @@ public RecolorableBakedQuad visitCore(EnumFacing facing) { } public RecolorableBakedQuad visitCore(EnumFacing facing, int overlayLayer) { - return visitQuad(facing, coreBoxList.get(overlayLayer), uvMapper(0)); + return visitQuad(facing, coreBoxList.get(overlayLayer), UVMapper.standard(0)); } public List visitTube(EnumFacing facing) { @@ -113,24 +102,24 @@ public List visitTube(EnumFacing facing, int overlayLayer) Pair box = sideBoxesList.get(overlayLayer).get(facing); switch (facing.getAxis()) { case X -> { - UVMapper mapper = uvMapper(0); + UVMapper mapper = UVMapper.standard(0); list.add(visitQuad(EnumFacing.UP, box, mapper)); list.add(visitQuad(EnumFacing.DOWN, box, mapper)); list.add(visitQuad(EnumFacing.SOUTH, box, mapper)); - list.add(visitQuad(EnumFacing.NORTH, box, uvMapper(180))); + list.add(visitQuad(EnumFacing.NORTH, box, UVMapper.standard(180))); } case Y -> { - UVMapper mapper = uvMapper(0); - list.add(visitQuad(EnumFacing.EAST, box, uvMapper(270))); - list.add(visitQuad(EnumFacing.WEST, box, uvMapper(270))); + UVMapper mapper = UVMapper.standard(0); + list.add(visitQuad(EnumFacing.EAST, box, UVMapper.standard(270))); + list.add(visitQuad(EnumFacing.WEST, box, UVMapper.standard(270))); list.add(visitQuad(EnumFacing.SOUTH, box, mapper)); list.add(visitQuad(EnumFacing.NORTH, box, mapper)); } case Z -> { - list.add(visitQuad(EnumFacing.UP, box, uvMapper(180))); - list.add(visitQuad(EnumFacing.DOWN, box, uvMapper(0))); - list.add(visitQuad(EnumFacing.EAST, box, uvMapper(270))); - list.add(visitQuad(EnumFacing.WEST, box, uvMapper(90))); + list.add(visitQuad(EnumFacing.UP, box, UVMapper.standard(180))); + list.add(visitQuad(EnumFacing.DOWN, box, UVMapper.standard(0))); + list.add(visitQuad(EnumFacing.EAST, box, UVMapper.standard(270))); + list.add(visitQuad(EnumFacing.WEST, box, UVMapper.standard(90))); } } return list; @@ -141,30 +130,11 @@ public RecolorableBakedQuad visitCapper(EnumFacing facing) { } public RecolorableBakedQuad visitCapper(EnumFacing facing, int overlayLayer) { - return visitQuad(facing, sideBoxesList.get(overlayLayer).get(facing), uvMapper(0)); + return visitQuad(facing, sideBoxesList.get(overlayLayer).get(facing), UVMapper.standard(0)); } public RecolorableBakedQuad visitQuad(EnumFacing normal, Pair box, UVMapper uv) { - BlockPartFace face = new BlockPartFace(null, -1, targetSprite.sprite().getIconName(), uv.map(normal, box)); - BakedQuad quad = BAKERY.makeBakedQuad(box.getLeft(), box.getRight(), face, targetSprite.sprite(), normal, ModelRotation.X0_Y0, null, false, true); - RecolorableBakedQuad.Builder builder = new RecolorableBakedQuad.Builder(quad.getFormat()); - builder.setTexture(targetSprite); - quad.pipe(builder); - return builder.build(); - } - - private static UVMapper uvMapper(int rot) { - return (normal, box) -> uv(normal, box, rot); - } - - private static BlockFaceUV uv(EnumFacing normal, Pair box, int rot) { - Vector3f small = box.getLeft(); - Vector3f large = box.getRight(); - return switch (normal.getAxis()) { - case X -> new BlockFaceUV(new float[] {small.y, large.z, large.y, small.z}, rot); - case Y -> new BlockFaceUV(new float[] {small.x, large.z, large.x, small.z}, rot); - case Z -> new BlockFaceUV(new float[] {small.x, large.y, large.x, small.y}, rot); - }; + return QuadHelper.buildQuad(normal, box, uv, targetSprite); } public static List createFrame(TextureAtlasSprite sprite) { @@ -177,9 +147,4 @@ public static List createFrame(TextureAtlasSprite sprite) return list; } - @FunctionalInterface - public interface UVMapper { - - BlockFaceUV map(EnumFacing normal, Pair box); - } } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java new file mode 100644 index 00000000000..671054017c8 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java @@ -0,0 +1,96 @@ +package gregtech.client.renderer.pipe.quad; + +import gregtech.client.renderer.pipe.util.SpriteInformation; + +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.BlockPartFace; +import net.minecraft.client.renderer.block.model.FaceBakery; +import net.minecraft.client.renderer.block.model.ModelRotation; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.util.EnumFacing; + +import net.minecraft.util.math.AxisAlignedBB; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.util.vector.Vector3f; + +public final class QuadHelper { + + private static final FaceBakery BAKERY = new FaceBakery(); + + private QuadHelper() {} + + public static RecolorableBakedQuad buildQuad(EnumFacing normal, Pair box, + UVMapper uv, SpriteInformation targetSprite) { + BlockPartFace face = new BlockPartFace(null, -1, targetSprite.sprite().getIconName(), uv.map(normal, box)); + BakedQuad quad = BAKERY.makeBakedQuad(box.getLeft(), box.getRight(), face, targetSprite.sprite(), normal, ModelRotation.X0_Y0, null, false, true); + RecolorableBakedQuad.Builder builder = new RecolorableBakedQuad.Builder(quad.getFormat()); + builder.setTexture(targetSprite); + quad.pipe(builder); + return builder.build(); + } + + public static BakedQuad buildQuad(EnumFacing normal, Pair box, + UVMapper uv, TextureAtlasSprite targetSprite) { + BlockPartFace face = new BlockPartFace(null, -1, targetSprite.getIconName(), uv.map(normal, box)); + return BAKERY.makeBakedQuad(box.getLeft(), box.getRight(), face, targetSprite, normal, ModelRotation.X0_Y0, null, false, true); + } + + @Contract("_ -> new") + public static @NotNull ImmutablePair toPair(@NotNull AxisAlignedBB bb) { + return ImmutablePair.of(new Vector3f((float) bb.minX * 16, (float) bb.minY * 16, (float) bb.minZ * 16), + new Vector3f((float) bb.maxX * 16, (float) bb.maxY * 16, (float) bb.maxZ * 16)); + } + + @Contract("_, _, _, _, _, _ -> new") + public static @NotNull ImmutablePair toPair(float x1, float y1, float z1, float x2, float y2, float z2) { + return ImmutablePair.of(new Vector3f(x1, y1, z1), new Vector3f(x2, y2, z2)); + } + + @Contract("_, _, _ -> new") + public static @NotNull ImmutablePair capOverlay(@Nullable EnumFacing facing, @NotNull AxisAlignedBB bb, float g) { + return capOverlay(facing, (float) bb.minX * 16, (float) bb.minY * 16, (float) bb.minZ * 16, (float) bb.maxX * 16, (float) bb.maxY * 16, + (float) bb.maxZ * 16, g); + } + + @Contract("_, _, _, _, _, _, _, _ -> new") + public static @NotNull ImmutablePair capOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { + if (facing == null) return toPair(x1 - g, y1 - g, z1 - g, x2 + g, y2 + g, z2 + g); + return switch (facing.getAxis()) { + case X -> toPair(x1 - g, y1, z1, x2 + g, y2, z2); + case Y -> toPair(x1, y1 - g, z1, x2, y2 + g, z2); + case Z -> toPair(x1, y1, z1 - g, x2, y2, z2 + g); + }; + } + + @Contract("_, _, _ -> new") + public static @NotNull ImmutablePair tubeOverlay(@Nullable EnumFacing facing, @NotNull AxisAlignedBB bb, float g) { + return tubeOverlay(facing, (float) bb.minX * 16, (float) bb.minY * 16, (float) bb.minZ * 16, (float) bb.maxX * 16, (float) bb.maxY * 16, + (float) bb.maxZ * 16, g); + } + + @Contract("_, _, _, _, _, _, _, _ -> new") + public static @NotNull ImmutablePair tubeOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { + if (facing == null) return toPair(x1, y1, z1, x2, y2, z2); + return switch (facing.getAxis()) { + case X -> toPair(x1, y1 - g, z1 - g, x2, y2 + g, z2 + g); + case Y -> toPair(x1 - g, y1, z1 - g, x2 + g, y2, z2 + g); + case Z -> toPair(x1 - g, y1 - g, z1, x2 + g, y2 + g, z2); + }; + } + + @Contract("_, _, _ -> new") + public static @NotNull ImmutablePair fullOverlay(@Nullable EnumFacing facing, @NotNull AxisAlignedBB bb, float g) { + return fullOverlay(facing, (float) bb.minX * 16, (float) bb.minY * 16, (float) bb.minZ * 16, (float) bb.maxX * 16, (float) bb.maxY * 16, + (float) bb.maxZ * 16, g); + } + + @Contract("_, _, _, _, _, _, _, _ -> new") + public static @NotNull ImmutablePair fullOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { + return toPair(x1 - g, y1 - g, z1 - g, x2 + g, y2 + g, z2 + g); + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java new file mode 100644 index 00000000000..7b84209727b --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java @@ -0,0 +1,25 @@ +package gregtech.client.renderer.pipe.quad; + +import net.minecraft.client.renderer.block.model.BlockFaceUV; +import net.minecraft.util.EnumFacing; + +import org.apache.commons.lang3.tuple.Pair; +import org.lwjgl.util.vector.Vector3f; + +@FunctionalInterface +public interface UVMapper { + + static UVMapper standard(int rot) { + return (normal, box) -> { + Vector3f small = box.getLeft(); + Vector3f large = box.getRight(); + return switch (normal.getAxis()) { + case X -> new BlockFaceUV(new float[] {small.y, large.z, large.y, small.z}, rot); + case Y -> new BlockFaceUV(new float[] {small.x, large.z, large.x, small.z}, rot); + case Z -> new BlockFaceUV(new float[] {small.x, large.y, large.x, small.y}, rot); + }; + }; + } + + BlockFaceUV map(EnumFacing normal, Pair box); +} diff --git a/src/main/java/gregtech/client/renderer/texture/cube/SimpleOverlayRenderer.java b/src/main/java/gregtech/client/renderer/texture/cube/SimpleOverlayRenderer.java index 768933b0da9..bfcaad3fb0b 100644 --- a/src/main/java/gregtech/client/renderer/texture/cube/SimpleOverlayRenderer.java +++ b/src/main/java/gregtech/client/renderer/texture/cube/SimpleOverlayRenderer.java @@ -79,4 +79,12 @@ public void renderOrientedState(CCRenderState renderState, Matrix4 translation, public TextureAtlasSprite getParticleSprite() { return sprite; } + + public TextureAtlasSprite getSprite() { + return sprite; + } + + public @Nullable TextureAtlasSprite getSpriteEmissive() { + return spriteEmissive; + } } diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 491665f55ae..8cc1c66690f 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -9,11 +9,12 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; -import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.ItemStackHashStrategy; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; import gregtech.common.covers.filter.ItemFilterContainer; @@ -82,6 +83,8 @@ public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, private CoverableItemHandlerWrapper itemHandlerWrapper; protected boolean isWorkingAllowed = true; + protected @Nullable CoverRenderer rendererInverted; + public CoverConveyor(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, @NotNull EnumFacing attachedSide, int tier, int itemsPerSecond) { super(definition, coverableView, attachedSide); @@ -454,7 +457,7 @@ protected Map countInventoryItemsByMatchSlot(@NotNull II @Override public boolean canAttach(@NotNull CoverableView coverable, @NotNull EnumFacing side) { - return coverable.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, getAttachedSide()) != null; + return coverable.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, getAttachedSide()); } @Override @@ -686,6 +689,25 @@ public void readFromNBT(@NotNull NBTTagCompound tagCompound) { this.itemFilterContainer.handleLegacyNBT(tagCompound.getCompoundTag("Filter")); } + @Override + public @NotNull CoverRenderer getRenderer() { + if (conveyorMode == ConveyorMode.EXPORT) { + if (renderer == null) renderer = buildRenderer(); + return renderer; + } else { + if (rendererInverted == null) rendererInverted = buildRendererInverted(); + return rendererInverted; + } + } + + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.CONVEYOR_OVERLAY).build(); + } + protected CoverRenderer buildRendererInverted() { + return new CoverRendererBuilder(Textures.CONVEYOR_OVERLAY_INVERTED).build(); + } + @Override @SideOnly(Side.CLIENT) protected @NotNull TextureAtlasSprite getPlateSprite() { diff --git a/src/main/java/gregtech/common/covers/CoverCraftingTable.java b/src/main/java/gregtech/common/covers/CoverCraftingTable.java index 902873c7ffa..e2a5fc3b45c 100644 --- a/src/main/java/gregtech/common/covers/CoverCraftingTable.java +++ b/src/main/java/gregtech/common/covers/CoverCraftingTable.java @@ -4,6 +4,7 @@ import gregtech.api.cover.*; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.common.inventory.handlers.ToolItemStackHandler; import net.minecraft.item.ItemStack; @@ -51,7 +52,7 @@ public boolean canAttach(@NotNull CoverableView coverable, @NotNull EnumFacing s } @Override - public boolean shouldAutoConnectToPipes() { + public boolean forcePipeRenderConnection() { return false; } @@ -59,6 +60,16 @@ public boolean shouldAutoConnectToPipes() { public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 translation, IVertexOperation[] pipeline, @NotNull Cuboid6 plateBox, @NotNull BlockRenderLayer layer) {} + @Override + public @NotNull CoverRenderer getRenderer() { + return (quads, facing, renderPlate, renderBackside, renderLayer, data) -> {}; + } + + @Override + protected CoverRenderer buildRenderer() { + return null; + } + @Override public void update() { if (getWorld().isRemote) { diff --git a/src/main/java/gregtech/common/covers/CoverDigitalInterface.java b/src/main/java/gregtech/common/covers/CoverDigitalInterface.java index d8797b4af8c..cd2c854601a 100644 --- a/src/main/java/gregtech/common/covers/CoverDigitalInterface.java +++ b/src/main/java/gregtech/common/covers/CoverDigitalInterface.java @@ -6,6 +6,7 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCoverHolder; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.*; @@ -17,6 +18,7 @@ import gregtech.api.util.GTLog; import gregtech.api.util.Position; import gregtech.api.util.TextFormattingUtil; +import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.client.utils.RenderUtil; import gregtech.common.metatileentities.multi.electric.MetaTileEntityPowerSubstation; @@ -891,7 +893,7 @@ public void readCustomData(int id, @NotNull PacketBuffer packetBuffer) { @Override public boolean canAttach(@NotNull CoverableView coverable, @NotNull EnumFacing side) { - return canCapabilityAttach(); + return !(coverable instanceof PipeCoverHolder) && canCapabilityAttach(); } public boolean canCapabilityAttach() { @@ -953,6 +955,16 @@ public void renderCover(CCRenderState ccRenderState, Matrix4 translation, IVerte } } + @Override + public @NotNull CoverRenderer getRenderer() { + return (quads, facing, renderPlate, renderBackside, renderLayer, data) -> {}; + } + + @Override + protected CoverRenderer buildRenderer() { + return null; + } + @SideOnly(Side.CLIENT) @Override public void renderMetaTileEntityFast(CCRenderState renderState, Matrix4 translation, float partialTicks) {} diff --git a/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java b/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java index a1aae68ace1..6f51ba3cef5 100644 --- a/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java +++ b/src/main/java/gregtech/common/covers/CoverEnderFluidLink.java @@ -11,6 +11,8 @@ import gregtech.api.util.FluidTankSwitchShim; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.VirtualTankRegistry; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.FluidFilterContainer; @@ -105,6 +107,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.ENDER_FLUID_LINK.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.ENDER_FLUID_LINK).build(); + } + @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, @NotNull RayTraceResult hitResult) { diff --git a/src/main/java/gregtech/common/covers/CoverFacade.java b/src/main/java/gregtech/common/covers/CoverFacade.java index 9f458f8cec2..7eb14607f7f 100644 --- a/src/main/java/gregtech/common/covers/CoverFacade.java +++ b/src/main/java/gregtech/common/covers/CoverFacade.java @@ -7,10 +7,13 @@ import gregtech.api.cover.IFacadeCover; import gregtech.api.util.GTLog; import gregtech.client.renderer.handler.FacadeRenderer; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.common.covers.facade.FacadeHelper; import gregtech.common.items.behaviors.FacadeItem; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.Items; @@ -27,6 +30,10 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; + +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -72,6 +79,12 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra ForgeHooksClient.setRenderLayer(oldLayer); } + @Override + @SideOnly(Side.CLIENT) + protected CoverRenderer buildRenderer() { + return FacadeRenderer.createRenderer(getWorld(), getPos(), facadeState); + } + @Override public boolean canRenderInLayer(@NotNull BlockRenderLayer renderLayer) { return true; @@ -140,6 +153,7 @@ public boolean canPipePassThrough() { private void updateFacadeState() { this.facadeState = FacadeHelper.lookupBlockForItem(facadeStack); + this.renderer = null; // called during world load, where world can be null if (getWorld() != null && !getWorld().isRemote) { scheduleRenderUpdate(); @@ -147,7 +161,7 @@ private void updateFacadeState() { } @Override - public boolean shouldAutoConnectToPipes() { + public boolean forcePipeRenderConnection() { return false; } diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index ed01a38daa7..8845c358a86 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -9,6 +9,8 @@ import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; import gregtech.client.utils.TooltipHelper; import gregtech.common.covers.filter.BaseFilter; @@ -182,6 +184,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra this.texture.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(this.texture).build(); + } + @Override public T getCapability(@NotNull Capability capability, @Nullable T defaultValue) { if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index dc55702148d..979206b0e0e 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -317,10 +317,4 @@ public void readFromNBT(@NotNull NBTTagCompound tagCompound) { } } } - - @Override - @SideOnly(Side.CLIENT) - protected @NotNull TextureAtlasSprite getPlateSprite() { - return Textures.VOLTAGE_CASINGS[this.tier].getSpriteOnSide(SimpleSidedCubeRenderer.RenderSide.SIDE); - } } diff --git a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java index 4807811357f..6629083c616 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java +++ b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java @@ -1,9 +1,12 @@ package gregtech.common.covers; import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; import gregtech.api.util.GTTransferUtils; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.FluidFilterContainer; @@ -70,6 +73,17 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.FLUID_VOIDING.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + public @NotNull CoverRenderer getRenderer() { + if (renderer == null) renderer = buildRenderer(); + return renderer; + } + + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.FLUID_VOIDING).build(); + } + @Override public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { return super.buildUI(guiData, guiSyncManager).height(192 - 22); diff --git a/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java b/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java index 3af29c03b3b..b15ec2cc8a9 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java +++ b/src/main/java/gregtech/common/covers/CoverFluidVoidingAdvanced.java @@ -4,6 +4,8 @@ import gregtech.api.cover.CoverableView; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTTransferUtils; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.nbt.NBTTagCompound; @@ -147,6 +149,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.FLUID_VOIDING_ADVANCED.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.FLUID_VOIDING_ADVANCED).build(); + } + @Override public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { super.readInitialSyncData(packetBuffer); diff --git a/src/main/java/gregtech/common/covers/CoverInfiniteWater.java b/src/main/java/gregtech/common/covers/CoverInfiniteWater.java index 808308ecabb..8966e361ecb 100644 --- a/src/main/java/gregtech/common/covers/CoverInfiniteWater.java +++ b/src/main/java/gregtech/common/covers/CoverInfiniteWater.java @@ -3,6 +3,8 @@ import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.util.BlockRenderLayer; @@ -38,6 +40,11 @@ public void renderCover(@NotNull CCRenderState ccRenderState, @NotNull Matrix4 m Textures.INFINITE_WATER.renderSided(getAttachedSide(), cuboid6, ccRenderState, iVertexOperations, matrix4); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.INFINITE_WATER).build(); + } + @Override public void update() { if (!getWorld().isRemote && getOffsetTimer() % 20 == 0) { diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index b1d48242c2c..4f7b5d774cd 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -9,6 +9,8 @@ import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; import gregtech.client.utils.TooltipHelper; import gregtech.common.covers.filter.BaseFilter; @@ -184,6 +186,11 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO this.texture.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(this.texture).build(); + } + @Override public void writeToNBT(@NotNull NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); diff --git a/src/main/java/gregtech/common/covers/CoverItemVoiding.java b/src/main/java/gregtech/common/covers/CoverItemVoiding.java index 950761911e8..b600e7a81d9 100644 --- a/src/main/java/gregtech/common/covers/CoverItemVoiding.java +++ b/src/main/java/gregtech/common/covers/CoverItemVoiding.java @@ -3,6 +3,8 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.entity.player.EntityPlayer; @@ -115,6 +117,17 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO Textures.ITEM_VOIDING.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + public @NotNull CoverRenderer getRenderer() { + if (renderer == null) renderer = buildRenderer(); + return renderer; + } + + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.ITEM_VOIDING).build(); + } + @Override public @NotNull EnumActionResult onSoftMalletClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, @NotNull RayTraceResult hitResult) { diff --git a/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java b/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java index fe7a52f64e5..1e1bf644666 100644 --- a/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java +++ b/src/main/java/gregtech/common/covers/CoverItemVoidingAdvanced.java @@ -3,6 +3,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; import gregtech.api.mui.GTGuiTextures; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.item.ItemStack; @@ -132,6 +134,11 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO Textures.ITEM_VOIDING_ADVANCED.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.ITEM_VOIDING_ADVANCED).build(); + } + public void setVoidingMode(VoidingMode voidingMode) { this.voidingMode = voidingMode; this.itemFilterContainer.setMaxTransferSize(getMaxStackSize()); diff --git a/src/main/java/gregtech/common/covers/CoverMachineController.java b/src/main/java/gregtech/common/covers/CoverMachineController.java index ca4b16f4968..c0ba3b8f68c 100644 --- a/src/main/java/gregtech/common/covers/CoverMachineController.java +++ b/src/main/java/gregtech/common/covers/CoverMachineController.java @@ -5,6 +5,8 @@ import gregtech.api.cover.*; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.entity.player.EntityPlayer; @@ -234,6 +236,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.MACHINE_CONTROLLER_OVERLAY).build(); + } + @Override public boolean canConnectRedstone() { return true; diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index 1b1b1591bc9..097d0c029cc 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -12,6 +12,8 @@ import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; import gregtech.common.covers.filter.FluidFilterContainer; @@ -72,6 +74,8 @@ public class CoverPump extends CoverBase implements CoverWithUI, ITickable, ICon protected FluidFilterContainer fluidFilterContainer; protected BucketMode bucketMode = BucketMode.MILLI_BUCKET; + protected @Nullable CoverRenderer rendererInverted; + public CoverPump(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, @NotNull EnumFacing attachedSide, int tier, int mbPerTick) { super(definition, coverableView, attachedSide); @@ -363,6 +367,25 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra } } + @Override + public @NotNull CoverRenderer getRenderer() { + if (pumpMode == PumpMode.EXPORT) { + if (renderer == null) renderer = buildRenderer(); + return renderer; + } else { + if (rendererInverted == null) rendererInverted = buildRendererInverted(); + return rendererInverted; + } + } + + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.PUMP_OVERLAY).build(); + } + protected CoverRenderer buildRendererInverted() { + return new CoverRendererBuilder(Textures.PUMP_OVERLAY_INVERTED).build(); + } + @Override public T getCapability(@NotNull Capability capability, T defaultValue) { if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index a999c19f8d2..0da47e4051f 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -4,6 +4,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; import gregtech.api.mui.GTGuiTextures; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.SmartItemFilter; @@ -55,6 +57,16 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO } } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.ARM_OVERLAY).build(); + } + + @Override + protected CoverRenderer buildRendererInverted() { + return new CoverRendererBuilder(Textures.ARM_OVERLAY_INVERTED).build(); + } + @Override protected int doTransferItems(IItemHandler itemHandler, IItemHandler myItemHandler, int maxTransferAmount) { // if (conveyorMode == ConveyorMode.EXPORT && itemHandler instanceof ItemNetHandler && diff --git a/src/main/java/gregtech/common/covers/CoverScreen.java b/src/main/java/gregtech/common/covers/CoverScreen.java index 723741b006f..22eb9e402cf 100644 --- a/src/main/java/gregtech/common/covers/CoverScreen.java +++ b/src/main/java/gregtech/common/covers/CoverScreen.java @@ -3,6 +3,8 @@ import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.util.BlockRenderLayer; @@ -33,7 +35,12 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra } @Override - public boolean shouldAutoConnectToPipes() { + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.DISPLAY).build(); + } + + @Override + public boolean forcePipeRenderConnection() { return false; } } diff --git a/src/main/java/gregtech/common/covers/CoverShutter.java b/src/main/java/gregtech/common/covers/CoverShutter.java index 0431f1b4408..1ee0ebb208d 100644 --- a/src/main/java/gregtech/common/covers/CoverShutter.java +++ b/src/main/java/gregtech/common/covers/CoverShutter.java @@ -5,6 +5,8 @@ import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.entity.player.EntityPlayer; @@ -38,6 +40,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.SHUTTER.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.SHUTTER).build(); + } + @Override public boolean canAttach(@NotNull CoverableView coverable, @NotNull EnumFacing side) { return true; @@ -64,7 +71,7 @@ public T getCapability(@NotNull Capability capability, T defaultValue) { } @Override - public boolean shouldAutoConnectToPipes() { + public boolean forcePipeRenderConnection() { return false; } diff --git a/src/main/java/gregtech/common/covers/CoverSolarPanel.java b/src/main/java/gregtech/common/covers/CoverSolarPanel.java index e972ef560ad..419212d89cc 100644 --- a/src/main/java/gregtech/common/covers/CoverSolarPanel.java +++ b/src/main/java/gregtech/common/covers/CoverSolarPanel.java @@ -6,6 +6,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; @@ -45,6 +47,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.SOLAR_PANEL.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.SOLAR_PANEL).build(); + } + @Override public void update() { CoverableView coverable = getCoverableView(); diff --git a/src/main/java/gregtech/common/covers/CoverStorage.java b/src/main/java/gregtech/common/covers/CoverStorage.java index 0d8b7e3cf6a..3554739aae1 100644 --- a/src/main/java/gregtech/common/covers/CoverStorage.java +++ b/src/main/java/gregtech/common/covers/CoverStorage.java @@ -5,6 +5,8 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.mui.GTGuis; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.entity.player.EntityPlayer; @@ -59,6 +61,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.STORAGE.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.STORAGE).build(); + } + @Override public void onRemoval() { dropInventoryContents(storageHandler); diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorActivity.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorActivity.java index f4f6eb25a7b..26e306f2212 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorActivity.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorActivity.java @@ -4,6 +4,8 @@ import gregtech.api.capability.IWorkable; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.util.BlockRenderLayer; @@ -25,7 +27,7 @@ public CoverDetectorActivity(@NotNull CoverDefinition definition, @NotNull Cover @Override public boolean canAttach(@NotNull CoverableView coverable, @NotNull EnumFacing side) { - return coverable.getCapability(GregtechTileCapabilities.CAPABILITY_WORKABLE, null) != null; + return coverable.hasCapability(GregtechTileCapabilities.CAPABILITY_WORKABLE, null); } @Override @@ -34,6 +36,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.DETECTOR_ACTIVITY.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.DETECTOR_ACTIVITY).build(); + } + @Override public void update() { if (getOffsetTimer() % 20 != 0) return; diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorActivityAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorActivityAdvanced.java index cd13c60c0c6..84b738c9515 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorActivityAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorActivityAdvanced.java @@ -5,6 +5,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; import gregtech.api.util.RedstoneUtil; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.util.BlockRenderLayer; @@ -30,6 +32,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.DETECTOR_ACTIVITY_ADVANCED).build(); + } + @Override public void update() { if (getOffsetTimer() % 20 != 0) return; diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergy.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergy.java index 5363b7a48ca..3d0dc83d7ba 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergy.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergy.java @@ -5,6 +5,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; import gregtech.api.util.RedstoneUtil; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.common.metatileentities.multi.electric.MetaTileEntityPowerSubstation; @@ -27,7 +29,7 @@ public CoverDetectorEnergy(@NotNull CoverDefinition definition, @NotNull Coverab @Override public boolean canAttach(@NotNull CoverableView coverable, @NotNull EnumFacing side) { - return coverable.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, null) != null || + return coverable.hasCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, null) || coverable instanceof MetaTileEntityPowerSubstation; // todo check this } @@ -59,6 +61,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.DETECTOR_ENERGY.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.DETECTOR_ENERGY).build(); + } + @Override public void update() { if (getOffsetTimer() % 20 != 0) return; diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java index 91ada6c3e9f..55015bb194d 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java @@ -8,6 +8,8 @@ import gregtech.api.gui.Widget; import gregtech.api.gui.widgets.*; import gregtech.api.util.RedstoneUtil; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.entity.player.EntityPlayer; @@ -52,6 +54,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.DETECTOR_ENERGY_ADVANCED.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.DETECTOR_ENERGY_ADVANCED).build(); + } + @Override public @NotNull EnumActionResult onScrewdriverClick(@NotNull EntityPlayer playerIn, @NotNull EnumHand hand, @NotNull RayTraceResult hitResult) { diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorFluid.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorFluid.java index e3b0a26db68..725a6fa957d 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorFluid.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorFluid.java @@ -3,6 +3,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; import gregtech.api.util.RedstoneUtil; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.util.BlockRenderLayer; @@ -37,6 +39,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.DETECTOR_FLUID.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.DETECTOR_FLUID).build(); + } + @Override public void update() { if (getOffsetTimer() % 20 != 0) return; diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java index 869656a0fc9..f11b6897d40 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorFluidAdvanced.java @@ -7,6 +7,8 @@ import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.*; import gregtech.api.util.RedstoneUtil; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.FluidFilterContainer; @@ -64,6 +66,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.DETECTOR_FLUID_ADVANCED.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.DETECTOR_FLUID_ADVANCED).build(); + } + @Override public ModularUI createUI(EntityPlayer player) { WidgetGroup group = new WidgetGroup(); diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorItem.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorItem.java index 00df1e03792..07dce97bcbc 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorItem.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorItem.java @@ -3,6 +3,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; import gregtech.api.util.RedstoneUtil; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import net.minecraft.util.BlockRenderLayer; @@ -35,6 +37,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.DETECTOR_ITEM.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.DETECTOR_ITEM).build(); + } + @Override public void update() { if (getOffsetTimer() % 20 != 0) return; diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java index 1cf4c875038..4b431e3b859 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorItemAdvanced.java @@ -7,6 +7,8 @@ import gregtech.api.gui.ModularUI; import gregtech.api.gui.widgets.*; import gregtech.api.util.RedstoneUtil; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.ItemFilterContainer; @@ -52,6 +54,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.DETECTOR_ITEM_ADVANCED.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.DETECTOR_ITEM_ADVANCED).build(); + } + @Override public ModularUI createUI(EntityPlayer player) { WidgetGroup group = new WidgetGroup(); diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorMaintenance.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorMaintenance.java index 85bb2b17dce..22c09478ddd 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorMaintenance.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorMaintenance.java @@ -3,6 +3,8 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; import gregtech.api.metatileentity.multiblock.IMaintenance; +import gregtech.client.renderer.pipe.cover.CoverRenderer; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.common.ConfigHolder; @@ -35,6 +37,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra Textures.DETECTOR_MAINTENANCE.renderSided(getAttachedSide(), plateBox, renderState, pipeline, translation); } + @Override + protected CoverRenderer buildRenderer() { + return new CoverRendererBuilder(Textures.DETECTOR_MAINTENANCE).build(); + } + @Override public void update() { if (getOffsetTimer() % 20 != 0) { diff --git a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java index 81cda089f63..190869084b5 100644 --- a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java +++ b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java @@ -1,11 +1,17 @@ package gregtech.common.pipelike.net; +import com.google.common.collect.BiMap; + +import com.google.common.collect.HashBiMap; + import gregtech.api.graphnet.path.AbstractNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.util.TaskScheduler; import gregtech.api.util.function.Task; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; @@ -15,13 +21,20 @@ public class SlowActiveWalker implements Task { + private static final int RECENT_WALKER_CUTOFF = 5; + + private static final BiMap, SlowActiveWalker> RECENT_WALKERS = HashBiMap.create(); + public static void dispatch(World world, AbstractNetPath path, int delay) { dispatch(world, path, delay, 1, 1); } public static void dispatch(World world, AbstractNetPath path, int delay, int stepSize, int activeLength) { - TaskScheduler.scheduleTask(world, new SlowActiveWalker(path, delay, stepSize, activeLength)); + if (RECENT_WALKERS.containsKey(path)) return; // do not dispatch a walker to a path recently walked + SlowActiveWalker walker = new SlowActiveWalker(path, delay, stepSize, activeLength); + RECENT_WALKERS.put(path, walker); + TaskScheduler.scheduleTask(world, walker); } private final List path; @@ -46,12 +59,16 @@ protected SlowActiveWalker(AbstractNetPath path, @Override public boolean run() { counter++; + if (counter > RECENT_WALKER_CUTOFF) RECENT_WALKERS.inverse().remove(this); if (counter >= delay) { counter = 0; for (int i = 0; i < stepSize; i++) { index++; this.step(getSafe(index - activeLength), getSafe(index)); - if (index >= lastStep) return false; + if (index >= lastStep) { + if (counter <= RECENT_WALKER_CUTOFF) RECENT_WALKERS.inverse().remove(this); + return false; + } } } return true; From d2402689433b08d25064fbe993d17c29f0db0473 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 7 Aug 2024 12:24:42 -0600 Subject: [PATCH 089/157] misc improvements --- .../impl/LaserContainerHandler.java | 5 ++ .../gregtech/api/graphnet/GraphNetBacker.java | 9 ++- .../java/gregtech/api/graphnet/IGraphNet.java | 9 +++ .../api/graphnet/alg/AlgorithmBuilder.java | 11 +++ .../DynamicWeightsShortestPathsAlgorithm.java | 23 ++---- .../api/graphnet/alg/NetAlgorithmWrapper.java | 14 +++- .../graphnet/alg/ShortestPathsAlgorithm.java | 24 ++++-- .../api/graphnet/alg/SinglePathAlgorithm.java | 10 +-- .../api/graphnet/pipenet/WorldPipeNet.java | 20 +++-- .../pipenet/insertion/TransferControl.java | 28 +++++++ .../insertion/TransferControlProvider.java | 8 ++ .../pipenet/physical/IPipeStructure.java | 10 ++- .../pipenet/physical/block/PipeBlock.java | 42 ++++++++-- .../physical/tile/PipeCapabilityWrapper.java | 18 +++-- .../pipenet/physical/tile/PipeTileEntity.java | 28 ++++++- .../pipenet/predicate/FilterPredicate.java | 7 +- .../predicate/test/FluidTestObject.java | 21 ++++- .../predicate/test/IPredicateTestObject.java | 7 ++ .../predicate/test/ItemTestObject.java | 23 +++++- .../api/graphnet/servernet/ServerNet.java | 7 +- .../api/graphnet/traverse/ITraverseData.java | 7 +- .../api/graphnet/worldnet/WorldNet.java | 9 +-- .../renderer/handler/FacadeRenderer.java | 1 + .../renderer/pipe/AbstractPipeModel.java | 35 ++++---- .../renderer/pipe/ActivablePipeModel.java | 4 +- .../client/renderer/pipe/CableModel.java | 2 +- .../client/renderer/pipe/PipeItemModel.java | 3 +- .../renderer/pipe/cache/BlockableSQC.java | 12 +-- .../renderer/pipe/cache/ExtraCappedSQC.java | 14 ++-- .../renderer/pipe/cache/RestrictiveSQC.java | 12 +-- .../pipe/cache/StructureQuadCache.java | 13 +-- .../pipe/cover/CoverRendererPackage.java | 8 ++ .../renderer/pipe/quad/PipeQuadHelper.java | 3 +- .../gregtech/common/covers/CoverConveyor.java | 42 +++++++++- .../common/covers/CoverFluidFilter.java | 39 ++++++++- .../common/covers/CoverFluidRegulator.java | 16 ++++ .../common/covers/CoverItemFilter.java | 36 ++++++++- .../gregtech/common/covers/CoverPump.java | 45 ++++++++++- .../common/covers/CoverRoboticArm.java | 15 ++++ .../gregtech/common/covers/CoverShutter.java | 12 ++- .../pipelike/block/cable/CableBlock.java | 63 +++++++++++++++ .../properties/MaterialEnergyProperties.java | 2 +- .../common/pipelike/net/SlowActiveWalker.java | 16 ++++ .../pipelike/net/energy/EnergyFlowData.java | 11 +++ .../pipelike/net/energy/EnergyFlowLogic.java | 76 ++++++++++++++++++ .../net/energy/EnergyTraverseData.java | 20 ++++- .../net/energy/IEnergyTransferController.java | 47 +++++++++++ .../pipelike/net/fluid/FluidTraverseData.java | 9 ++- .../net/fluid/IFluidTransferController.java | 74 +++++++++++++++++ .../pipelike/net/fluid/WorldFluidNet.java | 5 ++ .../net/item/IItemTransferController.java | 80 +++++++++++++++++++ .../pipelike/net/item/ItemTraverseData.java | 10 +-- .../pipelike/net/item/WorldItemNet.java | 5 ++ .../net/laser/ILaserTransferController.java | 43 ++++++++++ .../net/laser/LaserCapabilityObject.java | 3 +- .../pipelike/net/laser/WorldLaserNet.java | 2 +- .../net/optical/DataCapabilityObject.java | 3 +- .../optical/IOpticalTransferController.java | 44 ++++++++++ .../pipelike/net/optical/WorldOpticalNet.java | 2 +- 59 files changed, 1015 insertions(+), 152 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControl.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControlProvider.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowData.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java create mode 100644 src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java create mode 100644 src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java create mode 100644 src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java diff --git a/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java b/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java index 8604f6a0902..06097aa38c6 100644 --- a/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java +++ b/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java @@ -5,6 +5,8 @@ import gregtech.api.capability.ILaserRelay; import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.util.GTUtility; + import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; @@ -28,8 +30,11 @@ public static LaserContainerHandler receiverContainer(MetaTileEntity tileEntity, @Override public long receiveLaser(long laserVoltage, long laserAmperage) { + long allowedAmps = getEnergyCanBeInserted() / laserVoltage; addEnergy(laserVoltage * allowedAmps); + // over voltage explosion + if (laserVoltage > getInputVoltage()) getMetaTileEntity().doExplosion(GTUtility.getExplosionPower(laserVoltage)); return allowedAmps; } diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index cca5d2bb0ae..8f166887bfb 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -1,5 +1,6 @@ package gregtech.api.graphnet; +import gregtech.api.graphnet.alg.AlgorithmBuilder; import gregtech.api.graphnet.alg.INetAlgorithm; import gregtech.api.graphnet.alg.NetAlgorithmWrapper; import gregtech.api.graphnet.alg.NetPathMapper; @@ -37,14 +38,13 @@ public final class GraphNetBacker { private final Object2ObjectOpenHashMap vertexMap; private final NetAlgorithmWrapper[] netAlgorithms; - @SafeVarargs public GraphNetBacker(IGraphNet backedNet, INetGraph graph, - Function... algorithmBuilders) { + AlgorithmBuilder @NotNull ... algorithmBuilders) { this.backedNet = backedNet; this.pipeGraph = graph; this.netAlgorithms = new NetAlgorithmWrapper[algorithmBuilders.length]; for (int i = 0; i < algorithmBuilders.length; i++) { - this.netAlgorithms[i] = new NetAlgorithmWrapper(backedNet, algorithmBuilders[i]); + this.netAlgorithms[i] = new NetAlgorithmWrapper(backedNet, algorithmBuilders[i], backedNet.supportsPredication()); } this.vertexMap = new Object2ObjectOpenHashMap<>(); } @@ -145,7 +145,8 @@ public boolean removeEdge(GraphEdge edge) { Iterator> cache = node.getPathCache(testObject, simulator, queryTick); if (cache != null) return (Iterator) cache; - IteratorFactory factory = this.netAlgorithms[algorithmID].getPathsIterator(node.wrapper, remapper); + IteratorFactory factory = this.netAlgorithms[algorithmID] + .getPathsIterator(node.wrapper, remapper, testObject, simulator, queryTick); if (factory.cacheable()) { return (Iterator) (node.setPathCache(factory).getPathCache(testObject, simulator, queryTick)); } else return factory.newIterator(getGraph(), testObject, simulator, queryTick); diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index 8a81ee72c29..546d421ff56 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -25,6 +25,15 @@ default boolean usesDynamicWeights(int algorithmID) { return false; } + /** + * Controls whether predication of edges is allowed for this net. When false, path caching is improved by + * skipping the recomputation required in order to compensate for predication. + * @return whether predication should be allowed for this net. + */ + default boolean supportsPredication() { + return false; + } + /** * Adds a node to the graphnet. * diff --git a/src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java b/src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java new file mode 100644 index 00000000000..55d009e77ae --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java @@ -0,0 +1,11 @@ +package gregtech.api.graphnet.alg; + +import gregtech.api.graphnet.IGraphNet; + +import org.jetbrains.annotations.NotNull; + +@FunctionalInterface +public interface AlgorithmBuilder { + + @NotNull INetAlgorithm build(@NotNull IGraphNet net, boolean recomputeEveryCall); +} diff --git a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java index 725982bf4c4..17b502d51ca 100644 --- a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java @@ -3,14 +3,10 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.alg.iter.IteratorFactory; -import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.path.INetPath; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.Nullable; import org.jgrapht.alg.shortestpath.DefaultManyToManyShortestPaths; @@ -27,8 +23,11 @@ public class DynamicWeightsShortestPathsAlgorithm extends DefaultManyToManyShortestPaths implements INetAlgorithm { - public DynamicWeightsShortestPathsAlgorithm(IGraphNet net) { + private final boolean recomputeEveryCall; + + public DynamicWeightsShortestPathsAlgorithm(IGraphNet net, boolean recomputeEveryCall) { super(net.getGraph()); + this.recomputeEveryCall = recomputeEveryCall; } @Override @@ -37,8 +36,8 @@ public DynamicWeightsShortestPathsAlgorithm(IGraphNet net) { Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream().filter(NetNode::isActive) .map(n -> n.wrapper).filter(node -> !source.equals(node)).collect(Collectors.toSet()); return (graph, testObject, simulator, queryTick) -> { - IteratorFactory.defaultPrepareRun(graph, testObject, simulator, queryTick); - return new LimitedIterator<>(source, searchSpace, remapper, testObject, simulator, queryTick); + if (recomputeEveryCall) graph.prepareForAlgorithmRun(testObject, simulator, queryTick); + return new LimitedIterator<>(source, searchSpace, remapper); }; } @@ -46,10 +45,6 @@ protected class LimitedIterator> implements Iterator private static final int MAX_ITERATIONS = 100; - private final IPredicateTestObject testObject; - private final SimulatorKey simulator; - private final long queryTick; - private final GraphVertex source; private final Set searchSpace; private final NetPathMapper remapper; @@ -58,14 +53,10 @@ protected class LimitedIterator> implements Iterator private final ObjectArrayList visited = new ObjectArrayList<>(); private @Nullable Path next; - public LimitedIterator(GraphVertex source, Set searchSpace, NetPathMapper remapper, - IPredicateTestObject testObject, SimulatorKey simulator, long queryTick) { + public LimitedIterator(GraphVertex source, Set searchSpace, NetPathMapper remapper) { this.source = source; this.searchSpace = searchSpace; this.remapper = remapper; - this.testObject = testObject; - this.simulator = simulator; - this.queryTick = queryTick; } @Override diff --git a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java index dd85c752f6b..6567f97afd4 100644 --- a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java +++ b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java @@ -16,14 +16,16 @@ public class NetAlgorithmWrapper { private final IGraphNet net; + private final boolean recomputeEveryCall; @Nullable private INetAlgorithm alg; - private final Function builder; + private final AlgorithmBuilder builder; - public NetAlgorithmWrapper(IGraphNet net, @NotNull Function builder) { + public NetAlgorithmWrapper(IGraphNet net, @NotNull AlgorithmBuilder builder, boolean recomputeEveryCall) { this.net = net; this.builder = builder; + this.recomputeEveryCall = recomputeEveryCall; } public IGraphNet getNet() { @@ -35,8 +37,12 @@ public void invalidate() { } public > IteratorFactory getPathsIterator(GraphVertex source, - NetPathMapper remapper) { - if (alg == null) alg = builder.apply(net); + NetPathMapper remapper, + IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, + long queryTick) { + if (!recomputeEveryCall) net.getGraph().prepareForAlgorithmRun(testObject, simulator, queryTick); + if (alg == null) alg = builder.build(net, recomputeEveryCall); return alg.getPathsIteratorFactory(source, remapper); } } diff --git a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java index 096605f280c..ea64027bca3 100644 --- a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java @@ -19,8 +19,11 @@ public final class ShortestPathsAlgorithm extends CHManyToManyShortestPaths implements INetAlgorithm { - public ShortestPathsAlgorithm(IGraphNet net) { + private final boolean recomputeEveryCall; + + public ShortestPathsAlgorithm(IGraphNet net, boolean recomputeEveryCall) { super(net.getGraph()); + this.recomputeEveryCall = recomputeEveryCall; } @Override @@ -38,12 +41,21 @@ public ShortestPathsAlgorithm(IGraphNet net) { Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream() .filter(NetNode::isActive).map(n -> n.wrapper).collect(Collectors.toSet()); Set singleton = Collections.singleton(source); - return (graph1, testObject, simulator, queryTick) -> { - IteratorFactory.defaultPrepareRun(graph1, testObject, simulator, queryTick); + if (recomputeEveryCall) { + return (graph1, testObject, simulator, queryTick) -> { + graph1.prepareForAlgorithmRun(testObject, simulator, queryTick); + ManyToManyShortestPaths manyToManyPaths = getManyToManyPaths(singleton, + searchSpace); + return searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)) + .map(remapper::map).sorted(Comparator.comparingDouble(INetPath::getWeight)).iterator(); + }; + } else { ManyToManyShortestPaths manyToManyPaths = getManyToManyPaths(singleton, searchSpace); - return searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)) - .map(remapper::map).sorted(Comparator.comparingDouble(INetPath::getWeight)).iterator(); - }; + return SimpleIteratorFactories.fromIterable(searchSpace.stream() + .map(node -> manyToManyPaths.getPath(source, node)) + .map(remapper::map).sorted(Comparator.comparingDouble(INetPath::getWeight)) + .collect(Collectors.toList())); + } } } diff --git a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java index 0d5c7ba62a8..81a5c244ee2 100644 --- a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java @@ -17,19 +17,19 @@ public final class SinglePathAlgorithm implements INetAlgorithm { private final IGraphNet net; - private final boolean needsRecalculation; + private final boolean recomputeEveryCall; - public SinglePathAlgorithm(IGraphNet pipenet, boolean needsRecalculation) { + public SinglePathAlgorithm(IGraphNet pipenet, boolean recomputeEveryCall) { this.net = pipenet; - this.needsRecalculation = needsRecalculation; + this.recomputeEveryCall = recomputeEveryCall; } @Override public > IteratorFactory getPathsIteratorFactory(GraphVertex source, NetPathMapper remapper) { - if (needsRecalculation) { + if (recomputeEveryCall) { return (graph, testObject, simulator, queryTick) -> { - IteratorFactory.defaultPrepareRun(graph, testObject, simulator, queryTick); + graph.prepareForAlgorithmRun(testObject, simulator, queryTick); List graphEdges = new ObjectArrayList<>(); List nodes = new ObjectArrayList<>(); Results results = compute(source, nodes, graphEdges); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 7f25a8a7274..af826deea2a 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -4,6 +4,7 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.MultiNodeHelper; import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.alg.AlgorithmBuilder; import gregtech.api.graphnet.alg.INetAlgorithm; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; @@ -39,14 +40,12 @@ public abstract class WorldPipeNet extends WorldNet { private static final Object2ObjectOpenHashMap> dimensionNets = new Object2ObjectOpenHashMap<>(); - @SafeVarargs public WorldPipeNet(String name, Function graphBuilder, - Function... algorithmBuilders) { + AlgorithmBuilder... algorithmBuilders) { super(name, graphBuilder, algorithmBuilders); } - @SafeVarargs - public WorldPipeNet(String name, boolean directed, Function... algorithmBuilders) { + public WorldPipeNet(String name, boolean directed, AlgorithmBuilder... algorithmBuilders) { super(name, directed, algorithmBuilders); } @@ -61,6 +60,11 @@ public void setWorld(World world) { }); } + public final void updatePredication(@NotNull WorldPipeNetNode node, @NotNull PipeTileEntity tile) { + if (supportsPredication()) updatePredicationInternal(node, tile); + } + + /** * Called when a PipeTileEntity is marked dirty through {@link IDirtyNotifiable#markAsDirty()}, which is generally * when the state of its covers is changed. @@ -68,7 +72,7 @@ public void setWorld(World world) { * @param tile the tile marked dirty. * @param node the associated node. */ - public void updatePredication(@NotNull WorldPipeNetNode node, @NotNull PipeTileEntity tile) { + protected void updatePredicationInternal(@NotNull WorldPipeNetNode node, @NotNull PipeTileEntity tile) { boolean dirty = false; for (EnumFacing facing : EnumFacing.VALUES) { PipeTileEntity neighbor = tile.getPipeNeighbor(facing, false); @@ -84,7 +88,7 @@ public void updatePredication(@NotNull WorldPipeNetNode node, @NotNull PipeTileE } /** - * Preferred method to override if your net has custom predication rules. If the net is directed, + * Preferred method to override if your net has complex custom predication rules. If the net is directed, * this method will not be called twice, so special handling for directedness is needed. * * @param source the source of the edge. @@ -93,7 +97,7 @@ public void updatePredication(@NotNull WorldPipeNetNode node, @NotNull PipeTileE * @param coverTarget the cover on the target facing the source. * @return whether the predication state has changed and this net needs to be marked dirty. */ - public boolean predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode source, @Nullable Cover coverSource, + protected boolean predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode source, @Nullable Cover coverSource, @NotNull WorldPipeNetNode target, @Nullable Cover coverTarget) { Map> prevValue = new Object2ObjectOpenHashMap<>(edge.getPredicateHandler().getPredicateSet()); @@ -118,7 +122,7 @@ public boolean predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode so /** * Preferred method to override if your net has custom predication rules that only depend on covers. - * If the net is directed, this method will be called twice, so special handling for directedness is not needed. + * If the net is directed, this method will be called twice, so no special handling for directedness is needed. * * @param edge the edge to predicate * @param a the cover on the source of the edge diff --git a/src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControl.java b/src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControl.java new file mode 100644 index 00000000000..7b5d1eee34c --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControl.java @@ -0,0 +1,28 @@ +package gregtech.api.graphnet.pipenet.insertion; + +import net.minecraft.util.IStringSerializable; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class TransferControl implements IStringSerializable { + + private final String name; + + public TransferControl(@NotNull String name) { + this.name = name; + } + + @Override + public @NotNull String getName() { + return name; + } + + public abstract @NotNull T get(@Nullable Object potentialHolder); + + public abstract @NotNull T getNoPassage(); + + public T cast(Object o) { + return (T) o; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControlProvider.java b/src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControlProvider.java new file mode 100644 index 00000000000..802acb4493c --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControlProvider.java @@ -0,0 +1,8 @@ +package gregtech.api.graphnet.pipenet.insertion; + +import org.jetbrains.annotations.Nullable; + +public interface TransferControlProvider { + + @Nullable T getControllerForControl(TransferControl control); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java index f47fe5dfd11..14072b3f2c7 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java @@ -3,10 +3,15 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.client.renderer.pipe.AbstractPipeModel; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + import net.minecraft.util.EnumFacing; import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.AxisAlignedBB; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import java.util.List; @@ -31,8 +36,9 @@ default boolean canConnectTo(EnumFacing side, byte connectionMask) { return true; } - default List getPipeBoxes(PipeTileEntity tileContext) { - List pipeBoxes = new ArrayList<>(); + @Contract("_ -> new") + default List getPipeBoxes(@NotNull PipeTileEntity tileContext) { + List pipeBoxes = new ObjectArrayList<>(); float thickness = getRenderThickness(); if ((tileContext.getConnectionMask() & 63) < 63) { pipeBoxes.add(getSideBox(null, thickness)); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index d7ef8250a43..19796bbc410 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -15,15 +15,19 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; +import gregtech.api.unification.material.Material; import gregtech.api.util.EntityDamageUtil; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.AbstractPipeModel; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.pipe.cover.CoverRendererPackage; import gregtech.client.utils.BloomEffectUtil; import gregtech.client.utils.TooltipHelper; import gregtech.common.ConfigHolder; import gregtech.common.blocks.BlockFrame; +import gregtech.common.blocks.MetaBlocks; + import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.block.Block; @@ -47,6 +51,7 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.NonNullList; +import net.minecraft.util.SoundCategory; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; @@ -124,6 +129,20 @@ public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @ ItemStack item = playerIn.getHeldItem(hand); PipeTileEntity tile = getTileEntity(worldIn, pos); if (tile != null) { + if (tile.getFrameMaterial() == null) { + BlockFrame frame = BlockFrame.getFrameBlockFromItem(item); + if (frame != null) { + tile.setFrameMaterial(frame.getGtMaterial(item)); + SoundType type = frame.getSoundType(item); + worldIn.playSound(playerIn, pos, type.getPlaceSound(), SoundCategory.BLOCKS, + (type.getVolume() + 1.0F) / 2.0F, type.getPitch() * 0.8F); + if (!playerIn.capabilities.isCreativeMode) { + item.shrink(1); + } + return true; + } + } + RayTraceAABB trace = collisionRayTrace(playerIn, worldIn, pos); if (trace == null) return super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ); @@ -169,6 +188,16 @@ public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @ if (result == EnumActionResult.FAIL) return false; } + // frame removal + Material frame = tile.getFrameMaterial(); + if (frame != null && ToolHelper.isTool(item, ToolClasses.CROWBAR)) { + tile.setFrameMaterial(null); + spawnAsEntity(worldIn, pos, MetaBlocks.FRAMES.get(frame).getItem(frame)); + ToolHelper.damageItem(item, playerIn); + ToolHelper.playToolSound(item, playerIn); + return true; + } + // pipe modification if (isPipeTool(item)) { PipeTileEntity other = tile.getPipeNeighbor(facing, true); @@ -443,11 +472,7 @@ public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World wor if (hasPipeCollisionChangingItem(worldIn, pos, entityIn)) { addCollisionBoxToList(pos, entityBox, collidingBoxes, FULL_BLOCK_AABB); } else { - List covers = new ObjectArrayList<>(); - tile.getCoverHolder().addCoverCollisionBoundingBox(covers); - for (IndexedCuboid6 cuboid6 : covers) { - addCollisionBoxToList(pos, entityBox, collidingBoxes, cuboid6.aabb()); - } + tile.getCoverBoxes(bb -> addCollisionBoxToList(pos, entityBox, collidingBoxes, bb)); } if (tile.getFrameMaterial() != null) { addCollisionBoxToList(pos, entityBox, collidingBoxes, BlockFrame.COLLISION_BOX); @@ -487,7 +512,12 @@ public RayTraceResult collisionRayTrace(@NotNull IBlockState blockState, @NotNul RayTraceResult min = null; AxisAlignedBB minbb = null; double minDistSqrd = Double.MAX_VALUE; - for (AxisAlignedBB aabb : getStructure().getPipeBoxes(tile)) { + List bbs = getStructure().getPipeBoxes(tile); + tile.getCoverBoxes(bbs::add); + if (tile.getFrameMaterial() != null) { + bbs.add(FULL_BLOCK_AABB); + } + for (AxisAlignedBB aabb : bbs) { RayTraceResult result = rayTrace(pos, start, end, aabb); if (result == null) continue; double distSqrd = start.squareDistanceTo(result.hitVec); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java index 55d8dcdad1c..f7dd0cff3f9 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java @@ -10,22 +10,30 @@ public class PipeCapabilityWrapper { private byte activeMask; + private final PipeTileEntity owner; private final WorldPipeNetNode node; public final Capability[] capabilities; - public PipeCapabilityWrapper(WorldPipeNetNode node) { + public PipeCapabilityWrapper(PipeTileEntity owner, WorldPipeNetNode node) { + this.owner = owner; this.node = node; this.capabilities = node.getNet().getTargetCapabilities(); } public void setActive(@NotNull EnumFacing facing) { - this.activeMask |= 1 << facing.ordinal(); - this.node.setActive(this.activeMask > 0); + if (!isActive(facing)) { + this.activeMask |= 1 << facing.ordinal(); + this.node.setActive(this.activeMask > 0); + this.owner.notifyBlockUpdate(); + } } public void setIdle(@NotNull EnumFacing facing) { - this.activeMask &= ~(1 << facing.ordinal()); - this.node.setActive(this.activeMask > 0); + if (isActive(facing)) { + this.activeMask &= ~(1 << facing.ordinal()); + this.node.setActive(this.activeMask > 0); + this.owner.notifyBlockUpdate(); + } } public boolean isActive(@NotNull EnumFacing facing) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 4855ead358d..d495a88f338 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -19,6 +19,7 @@ import gregtech.api.util.GTUtility; import gregtech.client.particle.GTOverheatParticle; import gregtech.client.renderer.pipe.AbstractPipeModel; +import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.pipe.cover.CoverRendererPackage; import gregtech.common.blocks.MetaBlocks; @@ -51,6 +52,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -178,6 +180,12 @@ public boolean isConnected(EnumFacing facing) { return (this.connectionMask & 1 << facing.ordinal()) > 0; } + public boolean isConnectedCoverAdjusted(EnumFacing facing) { + Cover cover; + return ((this.connectionMask & 1 << facing.ordinal()) > 0) || + (cover = getCoverHolder().getCoverAtSide(facing)) != null && cover.forcePipeRenderConnection(); + } + public boolean renderClosed(EnumFacing facing) { return (this.renderMask & 1 << facing.ordinal()) > 0; } @@ -320,7 +328,7 @@ public EnumMap getTargetsWithCapabilities(WorldPipeNetNo for (EnumFacing facing : EnumFacing.VALUES) { if (wrapper.isActive(facing)) { TileEntity tile = getNeighbor(facing); - if (tile == null || tile instanceof PipeTileEntity) updateActiveStatus(facing, false); + if (tile == null) updateActiveStatus(facing, false); else caps.put(facing, tile); } } @@ -341,7 +349,7 @@ public void updateActiveStatus(@Nullable EnumFacing facing, boolean canOpenConne } return; } - if (!this.isConnected(facing) && !(canOpenConnection && canConnectTo(facing))) { + if (!this.isConnectedCoverAdjusted(facing) && !(canOpenConnection && canConnectTo(facing))) { setAllIdle(facing); return; } @@ -413,7 +421,7 @@ public T getCapability(@NotNull Capability capability, @Nullable EnumFaci T coverCapability = cover.getCapability(capability, pipeCapability); if (coverCapability == pipeCapability) { - if (isConnected(facing)) { + if (isConnectedCoverAdjusted(facing)) { return pipeCapability; } return null; @@ -448,7 +456,7 @@ protected void initialize() { boolean firstNode = true; for (WorldPipeNetNode node : PipeBlock.getNodesForTile(this)) { this.addCapabilities(node.getNet().getNewCapabilityObjects(node)); - this.netCapabilities.put(node, new PipeCapabilityWrapper(node)); + this.netCapabilities.put(node, new PipeCapabilityWrapper(this, node)); String netName = node.getNet().mapName; netLogicDatas.put(netName, node.getData()); var listener = node.getData().createListener( @@ -467,6 +475,9 @@ protected void initialize() { firstNode = false; this.temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); } + // TODO + // this and updateActiveStatus() theoretically only need to be called when loading old world data; + // is there a way to detect that and skip if so? node.getNet().updatePredication(node, this); } this.netLogicDatas.trim(); @@ -687,6 +698,7 @@ public void markAsDirty() { /** * Note - the block corresponding to this tile entity must register any new unlisted properties to the default state. */ + @MustBeInvokedByOverriders public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { byte frameMask = 0; byte connectionMask = this.connectionMask; @@ -708,6 +720,14 @@ public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { .withProperty(CoverRendererPackage.PROPERTY, getCoverHolder().createPackage()); } + public void getCoverBoxes(Consumer consumer) { + for (EnumFacing facing : EnumFacing.VALUES) { + if (getCoverHolder().hasCover(facing)) { + consumer.accept(CoverRendererBuilder.PLATE_AABBS.get(facing)); + } + } + } + public void dealAreaDamage(int size, Consumer damageFunction) { long timer = getOffsetTimer(); if (timer >= this.nextDamageTime) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java b/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java index 877588e5a8b..921de9b56d9 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java @@ -68,10 +68,9 @@ public boolean andy() { @Override public boolean test(IPredicateTestObject object) { - if (!(object instanceof FluidTestObject fluid)) return false; - FluidStack stack = fluid.recombine(); - if (sourceFilter != null && !sourceFilter.test(stack)) return false; - return targetFilter == null || targetFilter.test(stack); + Object test = object.recombine(); + if (sourceFilter != null && !sourceFilter.test(test)) return false; + return targetFilter == null || targetFilter.test(test); } private static class GenericFilterContainer extends BaseFilterContainer { diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java index 16b44dea78e..842f106d9d4 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java @@ -4,26 +4,39 @@ import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.Objects; +import java.util.function.Predicate; -public final class FluidTestObject implements IPredicateTestObject { +public final class FluidTestObject implements IPredicateTestObject, Predicate { public final Fluid fluid; public final NBTTagCompound tag; - public FluidTestObject(FluidStack stack) { + public FluidTestObject(@NotNull FluidStack stack) { this.fluid = stack.getFluid(); this.tag = stack.tag; } - public FluidStack recombine() { + @Override + @Contract(" -> new") + public @NotNull FluidStack recombine() { return new FluidStack(fluid, 1, tag); } - public FluidStack recombine(int amount) { + @Contract("_ -> new") + public @NotNull FluidStack recombine(int amount) { return new FluidStack(fluid, amount, tag); } + @Override + public boolean test(@Nullable FluidStack stack) { + return stack != null && stack.getFluid() == fluid && Objects.equals(tag, stack.tag); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java index f08ee1b4018..86ca341a19a 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/IPredicateTestObject.java @@ -1,6 +1,13 @@ package gregtech.api.graphnet.predicate.test; +import org.jetbrains.annotations.UnknownNullability; + public interface IPredicateTestObject { IPredicateTestObject INSTANCE = new IPredicateTestObject() {}; + + @UnknownNullability + default Object recombine() { + return null; + } } diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java index 9f0bed3a897..8c20cbcbfba 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java @@ -4,9 +4,13 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + import java.util.Objects; +import java.util.function.Predicate; -public class ItemTestObject implements IPredicateTestObject { +public class ItemTestObject implements IPredicateTestObject, Predicate { public final Item item; public final int meta; @@ -14,22 +18,35 @@ public class ItemTestObject implements IPredicateTestObject { public final int stackLimit; - public ItemTestObject(ItemStack stack) { + public ItemTestObject(@NotNull ItemStack stack) { item = stack.getItem(); meta = stack.getMetadata(); tag = stack.getTagCompound(); stackLimit = stack.getMaxStackSize(); } + @Override + @Contract(" -> new") public ItemStack recombine() { return new ItemStack(item, 1, meta, tag); } + @Contract("_ -> new") public ItemStack recombine(int amount) { - assert amount < getStackLimit() && amount > 0; + assert amount <= getStackLimit() && amount > 0; return new ItemStack(item, amount, meta, tag); } + @Override + public boolean test(@NotNull ItemStack stack) { + if (this.stackLimit == stack.getMaxStackSize() && this.item == stack.getItem() && + this.meta == stack.getMetadata()) { + NBTTagCompound other = stack.getTagCompound(); + return Objects.equals(this.tag, other); + } + return false; + } + public int getStackLimit() { return stackLimit; } diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java index a730f7d1397..d2ead1561d5 100644 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java @@ -3,6 +3,7 @@ import gregtech.api.graphnet.GraphNetBacker; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.alg.AlgorithmBuilder; import gregtech.api.graphnet.alg.INetAlgorithm; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; @@ -28,15 +29,13 @@ public abstract class ServerNet extends WorldSavedData implements IGraphNet { protected final GraphNetBacker backer; - @SafeVarargs public ServerNet(String name, Function graphBuilder, - Function... algorithmBuilders) { + AlgorithmBuilder... algorithmBuilders) { super(name); this.backer = new GraphNetBacker(this, graphBuilder.apply(this), algorithmBuilders); } - @SafeVarargs - public ServerNet(String name, boolean directed, Function... algorithmBuilders) { + public ServerNet(String name, boolean directed, AlgorithmBuilder... algorithmBuilders) { this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), algorithmBuilders); } diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java index 54223357ac0..f0b4a7f2c11 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java @@ -8,6 +8,8 @@ import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; +import org.jetbrains.annotations.MustBeInvokedByOverriders; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface ITraverseData> { @@ -55,7 +57,7 @@ public interface ITraverseData> { * @param edge the edge to get capacity for. * @return a non-negative capacity that is less than or equal to the true capacity of the edge. */ - default long getFlowLimit(AbstractNetFlowEdge edge) { + default long getFlowLimit(@NotNull AbstractNetFlowEdge edge) { return edge.getFlowLimit(this.getTestObject(), this.getGraphNet(), this.getQueryTick(), this.getSimulatorKey()); } @@ -67,7 +69,8 @@ default long getFlowLimit(AbstractNetFlowEdge edge) { * @param targetNode the target node of the edge. * @param consumption the amount to consume from the edge's flow limit. */ - default void consumeFlowLimit(AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { + @MustBeInvokedByOverriders + default void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { edge.consumeFlowLimit(this.getTestObject(), this.getGraphNet(), consumption, this.getQueryTick(), this.getSimulatorKey()); } diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java index 2b0693f5531..a6c50e8d128 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -3,13 +3,13 @@ import gregtech.api.graphnet.GraphNetBacker; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.alg.AlgorithmBuilder; import gregtech.api.graphnet.alg.INetAlgorithm; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.graph.NetDirectedGraph; import gregtech.api.graphnet.graph.NetUndirectedGraph; -import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.path.GenericGraphNetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; @@ -19,7 +19,6 @@ import net.minecraft.world.World; import net.minecraft.world.storage.WorldSavedData; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,15 +31,13 @@ public abstract class WorldNet extends WorldSavedData implements IGraphNet, Gene private World world; private int fallbackDimensionID; - @SafeVarargs public WorldNet(String name, @NotNull Function graphBuilder, - Function... algorithmBuilders) { + AlgorithmBuilder... algorithmBuilders) { super(name); this.backer = new GraphNetBacker(this, graphBuilder.apply(this), algorithmBuilders); } - @SafeVarargs - public WorldNet(String name, boolean directed, Function... algorithmBuilders) { + public WorldNet(String name, boolean directed, AlgorithmBuilder... algorithmBuilders) { this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), algorithmBuilders); } diff --git a/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java b/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java index d3d01127247..47c1986c551 100644 --- a/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java +++ b/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java @@ -165,6 +165,7 @@ public static CoverRenderer createRenderer(IBlockAccess world, BlockPos pos, IBl } catch (Exception ignored) {} IBlockState finalState = state; return (quads, facing, renderPlate, renderBackside, renderLayer, data) -> { + if (renderLayer != BlockRenderLayer.CUTOUT_MIPPED) return; // since the block model may be sensitive to the current render layer, we have to recalculate // every call. long posRand = MathHelper.getPositionRandom(pos); diff --git a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java index 1dd92b20555..8e0e6d790ea 100644 --- a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java @@ -20,7 +20,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.IBakedModel; -import net.minecraft.client.renderer.block.model.ItemCameraTransforms; import net.minecraft.client.renderer.block.model.ItemOverrideList; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -42,13 +41,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.vecmath.Matrix4f; -import javax.vecmath.Vector3f; -import java.util.ArrayList; import java.util.Collections; -import java.util.EnumMap; import java.util.List; -import java.util.stream.Collectors; @SideOnly(Side.CLIENT) public abstract class AbstractPipeModel implements IBakedModel { @@ -79,34 +73,37 @@ public AbstractPipeModel(ModelResourceLocation loc) { if (side == null && state instanceof IExtendedBlockState ext) { List quads; ColorData data = computeColorData(ext); + CoverRendererPackage rendererPackage = ext.getValue(CoverRendererPackage.PROPERTY); + byte coverMask = rendererPackage == null ? 0 : rendererPackage.getMask(); if (canRenderInLayer(getCurrentRenderLayer())) { quads = getQuads(toKey(ext), safeByte(ext.getValue(CONNECTION_MASK_PROPERTY)), safeByte(ext.getValue(CLOSED_MASK_PROPERTY)), safeByte(ext.getValue(BLOCKED_MASK_PROPERTY)), data, ext.getValue(FRAME_MATERIAL_PROPERTY), - safeByte(ext.getValue(FRAME_MASK_PROPERTY))); + safeByte(ext.getValue(FRAME_MASK_PROPERTY)), coverMask); } else quads = new ObjectArrayList<>(); - CoverRendererPackage rendererPackage = ext.getValue(CoverRendererPackage.PROPERTY); if (rendererPackage != null) renderCovers(quads, rendererPackage, ext); return quads; } return Collections.emptyList(); } - protected void renderCovers(List quads, @NotNull CoverRendererPackage rendererPackage, IExtendedBlockState ext) { - if (!ext.getUnlistedProperties().containsKey(AbstractPipeModel.MATERIAL_PROPERTY)) return; - Material material = ext.getValue(AbstractPipeModel.MATERIAL_PROPERTY); + protected void renderCovers(List quads, @NotNull CoverRendererPackage rendererPackage, + @NotNull IExtendedBlockState ext) { int color = safeInt(ext.getValue(COLOR_PROPERTY)); - if (material != null) { - int matColor = GTUtility.convertRGBtoARGB(material.getMaterialRGB()); - if (color == 0 || color == matColor) { - // unpainted - color = 0xFFFFFFFF; + if (ext.getUnlistedProperties().containsKey(AbstractPipeModel.MATERIAL_PROPERTY)) { + Material material = ext.getValue(AbstractPipeModel.MATERIAL_PROPERTY); + if (material != null) { + int matColor = GTUtility.convertRGBtoARGB(material.getMaterialRGB()); + if (color == 0 || color == matColor) { + // unpainted + color = 0xFFFFFFFF; + } } } rendererPackage.addQuads(quads, getCurrentRenderLayer(), new ColorData(color)); } - protected ColorData computeColorData(IExtendedBlockState ext) { + protected ColorData computeColorData(@NotNull IExtendedBlockState ext) { return new ColorData(safeInt(ext.getValue(COLOR_PROPERTY))); } @@ -119,7 +116,7 @@ protected static int safeInt(@Nullable Integer integer) { } public @NotNull List getQuads(K key, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, - @Nullable Material frameMaterial, byte frameMask) { + @Nullable Material frameMaterial, byte frameMask, byte coverMask) { List quads = new ObjectArrayList<>(); StructureQuadCache cache = pipeCache.get(key); @@ -128,7 +125,7 @@ protected static int safeInt(@Nullable Integer integer) { pipeCache.put(key, cache); } cache.addToList(quads, connectionMask, closedMask, - blockedMask, data); + blockedMask, data, coverMask); if (frameMaterial != null) { ResourceLocation rl = MaterialIconType.frameGt.getBlockTexturePath(frameMaterial.getMaterialIconSet()); diff --git a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java index 42fcd5b00f1..41e0feab4bc 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java @@ -71,11 +71,11 @@ public ActivablePipeModel(@NotNull Supplier inTex, @NotNull S @Override public @NotNull List getQuads(ActivableCacheKey key, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, @Nullable Material frameMaterial, - byte frameMask) { + byte frameMask, byte coverMask) { boolean bloomLayer = getCurrentRenderLayer() == BloomEffectUtil.getEffectiveBloomLayer(); // don't render the main shape to the bloom layer List quads = bloomLayer ? new ObjectArrayList<>() : - super.getQuads(key, connectionMask, closedMask, blockedMask, data, frameMaterial, frameMask); + super.getQuads(key, connectionMask, closedMask, blockedMask, data, frameMaterial, frameMask, coverMask); if (key.isActive() && allowActive()) { if (emissiveActive && bloomLayer) { diff --git a/src/main/java/gregtech/client/renderer/pipe/CableModel.java b/src/main/java/gregtech/client/renderer/pipe/CableModel.java index 38db2be690b..9bf1e8ad453 100644 --- a/src/main/java/gregtech/client/renderer/pipe/CableModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/CableModel.java @@ -68,7 +68,7 @@ public CableModel(String variant) { } @Override - protected ColorData computeColorData(IExtendedBlockState ext) { + protected ColorData computeColorData(@NotNull IExtendedBlockState ext) { if (insulationTex == null) return super.computeColorData(ext); Material material = ext.getValue(AbstractPipeModel.MATERIAL_PROPERTY); int insulationColor = safeInt(ext.getValue(COLOR_PROPERTY)); diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java index 88d6ae9bbde..0bd73563993 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java @@ -61,7 +61,8 @@ public PipeItemModel(AbstractPipeModel basis, K key, ColorData data) { @Override public @NotNull List getQuads(IBlockState state, EnumFacing side, long rand) { - return basis.getQuads(key, (byte) 0b1100, (byte) 0b0, (byte) 0b0, data, null, (byte) 0b0); + byte z = 0; + return basis.getQuads(key, (byte) 0b1100, z, z, data, null, z, z); } @Override diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java index b733f93ef9b..d20f20838ba 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java @@ -56,15 +56,17 @@ protected void buildBlocked(List list) { } @Override - public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data) { + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, byte coverMask) { List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, connectionMask)) { list.addAll(tubeCoords.get(facing).getSublist(quads)); - if (GTUtility.evalMask(facing, closedMask)) { - list.addAll(capperClosedCoords.get(facing).getSublist(quads)); - } else { - list.addAll(capperCoords.get(facing).getSublist(quads)); + if (!GTUtility.evalMask(facing, coverMask)) { + if (GTUtility.evalMask(facing, closedMask)) { + list.addAll(capperClosedCoords.get(facing).getSublist(quads)); + } else { + list.addAll(capperCoords.get(facing).getSublist(quads)); + } } if (GTUtility.evalMask(facing, blockedMask)) { list.addAll(blockedCoords.get(facing).getSublist(quads)); diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java index 075ea5f5898..72876c1e827 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java @@ -56,16 +56,18 @@ protected void buildExtraCapper(List list) { } @Override - public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data) { + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, byte coverMask) { List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, connectionMask)) { list.addAll(tubeCoords.get(facing).getSublist(quads)); - if (GTUtility.evalMask(facing, closedMask)) { - list.addAll(capperClosedCoords.get(facing).getSublist(quads)); - } else { - list.addAll(capperCoords.get(facing).getSublist(quads)); - list.addAll(extraCapperCoords.get(facing).getSublist(quads)); + if (!GTUtility.evalMask(facing, coverMask)) { + if (GTUtility.evalMask(facing, closedMask)) { + list.addAll(capperClosedCoords.get(facing).getSublist(quads)); + } else { + list.addAll(capperCoords.get(facing).getSublist(quads)); + list.addAll(extraCapperCoords.get(facing).getSublist(quads)); + } } } else { list.addAll(coreCoords.get(facing).getSublist(quads)); diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java index 4acfd74220e..aff38ae1792 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java @@ -58,16 +58,18 @@ protected void buildRestrictive(List list) { } @Override - public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data) { + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, byte coverMask) { List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, connectionMask)) { list.addAll(tubeCoords.get(facing).getSublist(quads)); list.addAll(restrictiveCoords.get(facing).getSublist(quads)); - if (GTUtility.evalMask(facing, closedMask)) { - list.addAll(capperClosedCoords.get(facing).getSublist(quads)); - } else { - list.addAll(capperCoords.get(facing).getSublist(quads)); + if (!GTUtility.evalMask(facing, coverMask)) { + if (GTUtility.evalMask(facing, closedMask)) { + list.addAll(capperClosedCoords.get(facing).getSublist(quads)); + } else { + list.addAll(capperCoords.get(facing).getSublist(quads)); + } } if (GTUtility.evalMask(facing, blockedMask)) { list.addAll(blockedCoords.get(facing).getSublist(quads)); diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java index f561c4b5873..73f38248ae3 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java @@ -97,15 +97,18 @@ protected void buildCapperClosed(List list) { } } - public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data) { + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, + byte coverMask) { List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, connectionMask)) { list.addAll(tubeCoords.get(facing).getSublist(quads)); - if (GTUtility.evalMask(facing, closedMask)) { - list.addAll(capperClosedCoords.get(facing).getSublist(quads)); - } else { - list.addAll(capperCoords.get(facing).getSublist(quads)); + if (!GTUtility.evalMask(facing, coverMask)) { + if (GTUtility.evalMask(facing, closedMask)) { + list.addAll(capperClosedCoords.get(facing).getSublist(quads)); + } else { + list.addAll(capperCoords.get(facing).getSublist(quads)); + } } } else { list.addAll(coreCoords.get(facing).getSublist(quads)); diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java index 9e72373290c..3dcd7485e16 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java @@ -44,6 +44,14 @@ public void addQuads(List quads, BlockRenderLayer renderLayer, ColorD } } + public byte getMask() { + byte mask = 0; + for (EnumFacing facing : renderers.keySet()) { + mask |= 1 << facing.ordinal(); + } + return mask; + } + public static class UnlistedCRPProperty implements IUnlistedProperty { private final String name; diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java index d215ad8010e..6661c54a38d 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -18,7 +18,6 @@ @SideOnly(Side.CLIENT) public final class PipeQuadHelper { - private SpriteInformation targetSprite; private final List> coreBoxList = new ObjectArrayList<>(); @@ -138,7 +137,7 @@ public RecolorableBakedQuad visitQuad(EnumFacing normal, Pair createFrame(TextureAtlasSprite sprite) { - PipeQuadHelper helper = PipeQuadHelper.create(0.998f); + PipeQuadHelper helper = PipeQuadHelper.create(0.998f).initialize(); helper.setTargetSprite(new SpriteInformation(sprite, 0)); List list = new ObjectArrayList<>(); for (EnumFacing facing : EnumFacing.VALUES) { diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 8cc1c66690f..7f44ba9fb40 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -9,6 +9,9 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; +import gregtech.api.graphnet.pipenet.insertion.TransferControl; +import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; @@ -19,6 +22,8 @@ import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; import gregtech.common.covers.filter.ItemFilterContainer; +import gregtech.common.pipelike.net.item.IItemTransferController; + import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -70,7 +75,8 @@ import java.util.Map; import java.util.Set; -public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithItemFilter { +public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithItemFilter, + TransferControlProvider, IItemTransferController { public final int tier; public final int maxItemTransferRate; @@ -370,6 +376,40 @@ protected int moveInventoryItems(IItemHandler sourceInventory, IItemHandler targ return maxTransferAmount - itemsLeftToTransfer; } + @Override + public @Nullable T getControllerForControl(TransferControl control) { + if (control == IItemTransferController.CONTROL) { + return control.cast(this); + } + return null; + } + + @Override + public int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, + boolean simulate) { + if (getManualImportExportMode() == ManualImportExportMode.DISABLED) return amount; + if (getManualImportExportMode() == ManualImportExportMode.UNFILTERED || + getFilterMode() == ItemFilterMode.FILTER_INSERT) // insert to handler is an extract from us + return IItemTransferController.super.insertToHandler(testObject, amount, destHandler, simulate); + ItemFilterContainer filter = getItemFilter(); + if (filter == null || filter.test(testObject.recombine())) { + return IItemTransferController.super.insertToHandler(testObject, amount, destHandler, simulate); + } else return amount; + } + + @Override + public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler sourceHandler, + boolean simulate) { + if (getManualImportExportMode() == ManualImportExportMode.DISABLED) return 0; + if (getManualImportExportMode() == ManualImportExportMode.UNFILTERED || + getFilterMode() == ItemFilterMode.FILTER_EXTRACT) // extract from handler is an insert to us + return IItemTransferController.super.extractFromHandler(testObject, amount, sourceHandler, simulate); + ItemFilterContainer filter = getItemFilter(); + if (filter == null || filter.test(testObject.recombine())) { + return IItemTransferController.super.extractFromHandler(testObject, amount, sourceHandler, simulate); + } else return 0; + } + protected static class TypeItemInfo { public final ItemStack itemStack; diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index 8845c358a86..dadda370dc6 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -6,6 +6,9 @@ import gregtech.api.cover.filter.CoverWithFluidFilter; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; +import gregtech.api.graphnet.pipenet.insertion.TransferControl; +import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; @@ -17,6 +20,10 @@ import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.FluidFilterContainer; +import gregtech.common.pipelike.net.fluid.IFluidTransferController; + +import gregtech.common.pipelike.net.item.IItemTransferController; + import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; @@ -49,7 +56,8 @@ import java.io.IOException; -public class CoverFluidFilter extends CoverBase implements CoverWithUI, CoverWithFluidFilter { +public class CoverFluidFilter extends CoverBase implements CoverWithUI, CoverWithFluidFilter, TransferControlProvider, + IFluidTransferController { protected final String titleLocale; protected final SimpleOverlayRenderer texture; @@ -224,6 +232,35 @@ public void readFromNBT(@NotNull NBTTagCompound tagCompound) { this.fluidFilterContainer.handleLegacyNBT(tagCompound); } + @Override + public @Nullable T getControllerForControl(TransferControl control) { + if (control == IFluidTransferController.CONTROL) { + return control.cast(this); + } + return null; + } + + @Override + public int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, + boolean doFill) { + if (getFilterMode() == FluidFilterMode.FILTER_FILL) // insert to handler is a drain for us + return IFluidTransferController.super.insertToHandler(testObject, amount, destHandler, doFill); + if (getFluidFilter().test(testObject.recombine())) { + return IFluidTransferController.super.insertToHandler(testObject, amount, destHandler, doFill); + } else return 0; + } + + @Override + public @Nullable FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, + IFluidHandler sourceHandler, boolean doDrain) { + if (testObject == null || + getFilterMode() == FluidFilterMode.FILTER_DRAIN) // extract from handler is an insert to us + return IFluidTransferController.super.extractFromHandler(testObject, amount, sourceHandler, doDrain); + if (getFluidFilter().test(testObject.recombine())) { + return IFluidTransferController.super.extractFromHandler(testObject, amount, sourceHandler, doDrain); + } else return null; + } + private class FluidHandlerFiltered extends FluidHandlerDelegate { public FluidHandlerFiltered(@NotNull IFluidHandler delegate) { diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 979206b0e0e..099847d4189 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -2,6 +2,7 @@ import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; +import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTTransferUtils; import gregtech.client.renderer.texture.Textures; @@ -31,6 +32,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.apache.logging.log4j.message.FormattedMessage; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.Map; @@ -276,6 +278,20 @@ protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncMa .setTextColor(Color.WHITE.darker(1)))); } + @Override + public int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, + boolean doFill) { + // TODO + return super.insertToHandler(testObject, amount, destHandler, doFill); + } + + @Override + public @Nullable FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, + IFluidHandler sourceHandler, boolean doDrain) { + // TODO + return super.extractFromHandler(testObject, amount, sourceHandler, doDrain); + } + @Override public int getMaxTransferRate() { return switch (this.transferMode) { diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 4f7b5d774cd..745105a5a77 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -6,6 +6,9 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; +import gregtech.api.graphnet.pipenet.insertion.TransferControl; +import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; @@ -17,6 +20,8 @@ import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.ItemFilterContainer; +import gregtech.common.pipelike.net.item.IItemTransferController; + import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; @@ -48,7 +53,8 @@ import java.io.IOException; -public class CoverItemFilter extends CoverBase implements CoverWithUI, CoverWithItemFilter { +public class CoverItemFilter extends CoverBase implements CoverWithUI, CoverWithItemFilter, TransferControlProvider, + IItemTransferController { protected final String titleLocale; protected final SimpleOverlayRenderer texture; @@ -226,6 +232,34 @@ public T getCapability(@NotNull Capability capability, T defaultValue) { return defaultValue; } + @Override + public @Nullable T getControllerForControl(TransferControl control) { + if (control == IItemTransferController.CONTROL) { + return control.cast(this); + } + return null; + } + + @Override + public int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, + boolean simulate) { + if (getFilterMode() == ItemFilterMode.FILTER_INSERT) // insert to handler is an extract from us + return IItemTransferController.super.insertToHandler(testObject, amount, destHandler, simulate); + if (getItemFilter().test(testObject.recombine())) { + return IItemTransferController.super.insertToHandler(testObject, amount, destHandler, simulate); + } else return amount; + } + + @Override + public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler sourceHandler, + boolean simulate) { + if (getFilterMode() == ItemFilterMode.FILTER_EXTRACT) // extract from handler is an insert to us + return IItemTransferController.super.extractFromHandler(testObject, amount, sourceHandler, simulate); + if (getItemFilter().test(testObject.recombine())) { + return IItemTransferController.super.extractFromHandler(testObject, amount, sourceHandler, simulate); + } else return 0; + } + private class ItemHandlerFiltered extends ItemHandlerDelegate { public ItemHandlerFiltered(IItemHandler delegate) { diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index 097d0c029cc..1239be6f302 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -9,6 +9,9 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithFluidFilter; +import gregtech.api.graphnet.pipenet.insertion.TransferControl; +import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; @@ -18,6 +21,11 @@ import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; import gregtech.common.covers.filter.FluidFilterContainer; +import gregtech.common.covers.filter.ItemFilterContainer; +import gregtech.common.pipelike.net.fluid.IFluidTransferController; + +import gregtech.common.pipelike.net.item.IItemTransferController; + import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -60,7 +68,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithFluidFilter { +public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithFluidFilter, + TransferControlProvider, IFluidTransferController { public final int tier; public final int maxFluidTransferRate; @@ -445,6 +454,40 @@ public void readFromNBT(@NotNull NBTTagCompound tagCompound) { return Textures.VOLTAGE_CASINGS[this.tier].getSpriteOnSide(SimpleSidedCubeRenderer.RenderSide.SIDE); } + @Override + public @Nullable T getControllerForControl(TransferControl control) { + if (control == IFluidTransferController.CONTROL) { + return control.cast(this); + } + return null; + } + + @Override + public int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, + boolean doFill) { + if (getManualImportExportMode() == ManualImportExportMode.DISABLED) return 0; + if (getManualImportExportMode() == ManualImportExportMode.UNFILTERED || + getFilterMode() == FluidFilterMode.FILTER_FILL) // insert to handler is a drain for us + return IFluidTransferController.super.insertToHandler(testObject, amount, destHandler, doFill); + FluidFilterContainer filter = getFluidFilter(); + if (filter == null || filter.test(testObject.recombine())) { + return IFluidTransferController.super.insertToHandler(testObject, amount, destHandler, doFill); + } else return 0; + } + + @Override + public @Nullable FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, + IFluidHandler sourceHandler, boolean doDrain) { + if (getManualImportExportMode() == ManualImportExportMode.DISABLED) return null; + if (testObject == null || getManualImportExportMode() == ManualImportExportMode.UNFILTERED || + getFilterMode() == FluidFilterMode.FILTER_DRAIN) // extract from handler is an insert to us + return IFluidTransferController.super.extractFromHandler(testObject, amount, sourceHandler, doDrain); + FluidFilterContainer filter = getFluidFilter(); + if (filter == null || filter.test(testObject.recombine())) { + return IFluidTransferController.super.extractFromHandler(testObject, amount, sourceHandler, doDrain); + } else return null; + } + public enum PumpMode implements IStringSerializable, IIOMode { IMPORT("cover.pump.mode.import"), diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 0da47e4051f..c385bfda6e4 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -3,6 +3,7 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; +import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; @@ -232,6 +233,20 @@ protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager g .setTextColor(Color.WHITE.darker(1)))); } + @Override + public int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, + boolean simulate) { + // TODO + return super.insertToHandler(testObject, amount, destHandler, simulate); + } + + @Override + public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler sourceHandler, + boolean simulate) { + // TODO + return super.extractFromHandler(testObject, amount, sourceHandler, simulate); + } + @Override protected int getMaxStackSize() { return getTransferMode().maxStackSize; diff --git a/src/main/java/gregtech/common/covers/CoverShutter.java b/src/main/java/gregtech/common/covers/CoverShutter.java index 1ee0ebb208d..bd0b05b4a20 100644 --- a/src/main/java/gregtech/common/covers/CoverShutter.java +++ b/src/main/java/gregtech/common/covers/CoverShutter.java @@ -5,6 +5,8 @@ import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; +import gregtech.api.graphnet.pipenet.insertion.TransferControl; +import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; @@ -23,9 +25,11 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; + import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -public class CoverShutter extends CoverBase implements IControllable { +public class CoverShutter extends CoverBase implements IControllable, TransferControlProvider { private boolean isWorkingAllowed = true; @@ -115,4 +119,10 @@ public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); isWorkingAllowed = tagCompound.getBoolean("WorkingAllowed"); } + + @Override + public @Nullable T getControllerForControl(TransferControl control) { + if (!isWorkingEnabled()) return null; + else return control.getNoPassage(); + } } diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index bc0b9bf7fc4..864a9b88e29 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -1,18 +1,48 @@ package gregtech.common.pipelike.block.cable; +import gregtech.api.damagesources.DamageSources; +import gregtech.api.graphnet.AbstractGroupData; +import gregtech.api.graphnet.NetGroup; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.IBurnable; +import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.unification.material.registry.MaterialRegistry; +import gregtech.api.util.EntityDamageUtil; +import gregtech.api.util.GTUtility; import gregtech.common.creativetab.GTCreativeTabs; +import gregtech.common.pipelike.net.energy.EnergyFlowData; +import gregtech.common.pipelike.net.energy.EnergyFlowLogic; +import gregtech.common.pipelike.net.energy.SuperconductorLogic; +import gregtech.common.pipelike.net.energy.WorldEnergyNet; + +import gregtech.common.pipelikeold.cable.net.EnergyGroupData; + +import gregtech.core.advancement.AdvancementTriggers; + import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraftforge.fml.common.FMLCommonHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.WeakReference; import java.util.Map; public class CableBlock extends PipeMaterialBlock implements IBurnable { @@ -29,6 +59,11 @@ public CableBlock(CableStructure structure, MaterialRegistry registry) { setCreativeTab(GTCreativeTabs.TAB_GREGTECH_CABLES); } + @Override + public CableStructure getStructure() { + return (CableStructure) super.getStructure(); + } + @Override public String getToolClass() { return ToolClasses.WIRE_CUTTER; @@ -48,4 +83,32 @@ public void partialBurn(IBlockState state, World world, BlockPos pos) { world.setBlockState(pos, newBlock.getStateFromMeta(this.getMetaFromState(state))); } } + + @Override + public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, + @NotNull Entity entityIn) { + super.onEntityCollision(worldIn, pos, state, entityIn); + if (worldIn.isRemote || getStructure().isInsulated() || !(entityIn instanceof EntityLivingBase living)) return; + PipeTileEntity tile = getTileEntity(worldIn, pos); + if (tile != null && tile.getFrameMaterial() == null && tile.getOffsetTimer() % 10 == 0) { + WorldPipeNetNode node = WorldEnergyNet.getWorldNet(worldIn).getNode(pos); + if (node != null) { + if (node.getData().getLogicEntryNullable(SuperconductorLogic.INSTANCE) != null) return; + EnergyFlowLogic logic = node.getData().getLogicEntryNullable(EnergyFlowLogic.INSTANCE); + if (logic != null) { + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + long cumulativeDamage = 0; + for (EnergyFlowData data : logic.getFlow(tick)) { + cumulativeDamage += (GTUtility.getTierByVoltage(data.voltage()) + 1) * data.amperage() * 4; + } + if (cumulativeDamage != 0) { + living.attackEntityFrom(DamageSources.getElectricDamage(), cumulativeDamage); + if (living instanceof EntityPlayerMP playerMP) { + AdvancementTriggers.ELECTROCUTION_DEATH.trigger(playerMP); + } + } + } + } + } + } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 7468d91c514..b11d249b673 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -241,7 +241,7 @@ public void removeFromNet(World world, BlockPos pos, IPipeStructure structure) { @Override public boolean generatesStructure(IPipeStructure structure) { - return structure.getClass() == CableStructure.class; + return structure instanceof CableStructure cable && (!isSuperconductor() || !cable.isInsulated()); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java index 190869084b5..722146c443b 100644 --- a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java +++ b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java @@ -25,10 +25,26 @@ public class SlowActiveWalker implements Task { private static final BiMap, SlowActiveWalker> RECENT_WALKERS = HashBiMap.create(); + /** + * Dispatches a slow walker along a path with default parameters. + * @param world the world to schedule the task in. When this world is unloaded, the task will die no matter + * its state, so be careful! + * @param path the path to walk. + * @param delay the ticks between steps of the walker + */ public static void dispatch(World world, AbstractNetPath path, int delay) { dispatch(world, path, delay, 1, 1); } + /** + * Dispatches a slow walker along a path. + * @param world the world to schedule the task in. When this world is unloaded, the task will die no matter + * its state, so be careful! + * @param path the path to walk. + * @param delay the ticks between steps of the walker + * @param stepSize the number of nodes within the path that the walker progresses every step + * @param activeLength the number of tiles that will be left active behind a progressing walker + */ public static void dispatch(World world, AbstractNetPath path, int delay, int stepSize, int activeLength) { if (RECENT_WALKERS.containsKey(path)) return; // do not dispatch a walker to a path recently walked diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowData.java new file mode 100644 index 00000000000..558cc379961 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowData.java @@ -0,0 +1,11 @@ +package gregtech.common.pipelike.net.energy; + +import com.github.bsideup.jabel.Desugar; + +@Desugar +public record EnergyFlowData(long amperage, long voltage) { + + public long getEU() { + return amperage * voltage; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java new file mode 100644 index 00000000000..e106b9e2e93 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java @@ -0,0 +1,76 @@ +package gregtech.common.pipelike.net.energy; + +import gregtech.api.graphnet.logic.NetLogicEntry; + +import it.unimi.dsi.fastutil.longs.Long2LongLinkedOpenHashMap; + +import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; + +import it.unimi.dsi.fastutil.longs.Long2ObjectRBTreeMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectIterator; + +import net.minecraft.nbt.NBTTagByte; +import net.minecraft.network.PacketBuffer; + +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class EnergyFlowLogic extends NetLogicEntry { + + public static final EnergyFlowLogic INSTANCE = new EnergyFlowLogic(); + + private static final int MEMORY_TICKS = 10; + + private final Long2ObjectOpenHashMap> memory = new Long2ObjectOpenHashMap<>(); + + protected EnergyFlowLogic() { + super("EnergyFlow"); + } + + public @NotNull List getFlow(long tick) { + return memory.getOrDefault(tick, Collections.emptyList()); + } + + public void recordFlow(long tick, EnergyFlowData flow) { + updateMemory(tick); + memory.compute(tick, (k, v) -> { + if (v == null) v = new ObjectArrayList<>(); + v.add(flow); + return v; + }); + } + + private void updateMemory(long tick) { + var iter = memory.long2ObjectEntrySet().fastIterator(); + while (iter.hasNext()) { + Long2ObjectMap.Entry> entry = iter.next(); + if (entry.getLongKey() + MEMORY_TICKS < tick) { + iter.remove(); + } + } + } + + @Override + public NBTTagByte serializeNBT() { + return new NBTTagByte((byte) 0); + } + + @Override + public void deserializeNBT(NBTTagByte nbt) {} + + @Override + public @NotNull EnergyFlowLogic getNew() { + return new EnergyFlowLogic(); + } + + @Override + public void encode(PacketBuffer buf, boolean fullChange) {} + + @Override + public void decode(PacketBuffer buf, boolean fullChange) {} +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index 55ae45826c5..1e8c5b40f15 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -3,12 +3,15 @@ import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IEnergyContainer; import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.NodeLossCache; import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.AbstractTraverseData; import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; @@ -19,6 +22,7 @@ import net.minecraft.util.math.BlockPos; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.NotNull; import java.util.function.Supplier; @@ -102,8 +106,9 @@ public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachin IEnergyContainer container = capability.getValue() .getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, capability.getKey().getOpposite()); if (container != null) { - availableFlow -= container.acceptEnergyFromNetwork(capability.getKey(), pathVoltage, availableFlow, - getSimulatorKey() != null); + availableFlow -= IEnergyTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(pathVoltage, availableFlow, container, + capability.getKey(), getSimulatorKey() != null); } } long accepted = flowReachingDestination - availableFlow; @@ -114,6 +119,17 @@ public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachin return accepted; } + @Override + public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { + super.consumeFlowLimit(edge, targetNode, consumption); + EnergyFlowLogic logic = targetNode.getData().getLogicEntryNullable(EnergyFlowLogic.INSTANCE); + if (logic == null) { + logic = EnergyFlowLogic.INSTANCE.getNew(); + targetNode.getData().setLogicEntry(logic); + } + logic.recordFlow(getQueryTick(), new EnergyFlowData(consumption, pathVoltage)); + } + private static int calculateHeatV(long amperage, long voltage, long maxVoltage) { return (int) (amperage * (Math.log1p(Math.log((double) voltage / maxVoltage)) * 45 + 36.5)); } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java b/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java new file mode 100644 index 00000000000..f23a6d67bea --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java @@ -0,0 +1,47 @@ +package gregtech.common.pipelike.net.energy; + +import gregtech.api.capability.IEnergyContainer; +import gregtech.api.graphnet.pipenet.insertion.TransferControl; +import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; + +import net.minecraft.util.EnumFacing; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface IEnergyTransferController { + + TransferControl CONTROL = new TransferControl<>("Energy") { + + @Override + public @NotNull IEnergyTransferController get(@Nullable Object potentialHolder) { + if (!(potentialHolder instanceof TransferControlProvider holder)) return DEFAULT; + IEnergyTransferController found = holder.getControllerForControl(CONTROL); + return found == null ? DEFAULT : found; + } + + @Override + public @NotNull IEnergyTransferController getNoPassage() { + return NO_PASSAGE; + } + }; + + IEnergyTransferController DEFAULT = new IEnergyTransferController() {}; + + IEnergyTransferController NO_PASSAGE = new IEnergyTransferController() { + + @Override + public long insertToHandler(long voltage, long amperage, @NotNull IEnergyContainer destHandler, + EnumFacing side, boolean simulate) { + return 0; + } + }; + + /** + * @return inserted amperes + */ + default long insertToHandler(long voltage, long amperage, @NotNull IEnergyContainer destHandler, EnumFacing side, + boolean simulate) { + return destHandler.acceptEnergyFromNetwork(side, voltage, amperage, simulate); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index eb91ccbc422..70dec1cbab5 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -29,6 +29,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.NotNull; import java.util.function.LongConsumer; @@ -151,16 +152,16 @@ public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachin IFluidHandler container = capability.getValue() .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); if (container != null) { - availableFlow -= container.fill( - getTestObject().recombine((int) Math.min(Integer.MAX_VALUE, availableFlow)), - getSimulatorKey() == null); + availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + (int) Math.min(Integer.MAX_VALUE, availableFlow), container, getSimulatorKey() == null); } } return flowReachingDestination - availableFlow; } @Override - public void consumeFlowLimit(AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { + public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { super.consumeFlowLimit(edge, targetNode, consumption); temperatureUpdates.getOrDefault(targetNode, l -> {}).accept(consumption); } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java new file mode 100644 index 00000000000..cc5451a97fc --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java @@ -0,0 +1,74 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.graphnet.pipenet.insertion.TransferControl; + +import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.predicate.test.FluidTestObject; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface IFluidTransferController { + + TransferControl CONTROL = new TransferControl<>("Fluid") { + + @Override + public @NotNull IFluidTransferController get(@Nullable Object potentialHolder) { + if (!(potentialHolder instanceof TransferControlProvider holder)) return DEFAULT; + IFluidTransferController found = holder.getControllerForControl(CONTROL); + return found == null ? DEFAULT : found; + } + + @Override + public @NotNull IFluidTransferController getNoPassage() { + return NO_PASSAGE; + } + }; + + IFluidTransferController DEFAULT = new IFluidTransferController() {}; + + IFluidTransferController NO_PASSAGE = new IFluidTransferController() { + + @Override + public int insertToHandler(@NotNull FluidTestObject testObject, int amount, + @NotNull IFluidHandler destHandler, boolean doFill) { + return 0; + } + + @Override + public @Nullable FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, + IFluidHandler sourceHandler, boolean doDrain) { + return null; + } + }; + + /** + * @return the amount filled. + */ + default int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, boolean doFill) { + return destHandler.fill(testObject.recombine(amount), doFill); + } + + /** + * @return the fluidstack drained. + */ + @Nullable + default FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, IFluidHandler sourceHandler, + boolean doDrain) { + if (testObject == null) return sourceHandler.drain(amount, doDrain); + else { + FluidStack recombined = testObject.recombine(); + FluidStack drained = sourceHandler.drain(recombined, false); + if (testObject.test(drained)) { + if (doDrain) { + return sourceHandler.drain(recombined, true); + } else { + return drained; + } + } else return null; + } + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 0ef64b8405f..98f17f61ade 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -49,6 +49,11 @@ public WorldFluidNet(String name) { super(name, false, DynamicWeightsShortestPathsAlgorithm::new); } + @Override + public boolean supportsPredication() { + return true; + } + @Override protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { super.coverPredication(edge, a, b); diff --git a/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java b/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java new file mode 100644 index 00000000000..cafa0e779c7 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java @@ -0,0 +1,80 @@ +package gregtech.common.pipelike.net.item; + +import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.pipenet.insertion.TransferControl; + +import gregtech.api.graphnet.predicate.test.ItemTestObject; + +import net.minecraft.item.ItemStack; + +import net.minecraftforge.items.IItemHandler; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface IItemTransferController { + + TransferControl CONTROL = new TransferControl<>("Item") { + + @Override + public @NotNull IItemTransferController get(@Nullable Object potentialHolder) { + if (!(potentialHolder instanceof TransferControlProvider holder)) return DEFAULT; + IItemTransferController found = holder.getControllerForControl(CONTROL); + return found == null ? DEFAULT : found; + } + + @Override + public @NotNull IItemTransferController getNoPassage() { + return NO_PASSAGE; + } + }; + + IItemTransferController DEFAULT = new IItemTransferController() {}; + + IItemTransferController NO_PASSAGE = new IItemTransferController() { + + @Override + public int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, + boolean simulate) { + return amount; + } + + @Override + public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, + @NotNull IItemHandler sourceHandler, boolean simulate) { + return 0; + } + }; + + /** + * @return the amount left uninserted; aka the remainder + */ + default int insertToHandler(@NotNull ItemTestObject testObject, int amount, + @NotNull IItemHandler destHandler, boolean simulate) { + for (int i = 0; i < destHandler.getSlots(); i++) { + int allowed = Math.min(amount, Math.min(destHandler.getSlotLimit(i), testObject.getStackLimit())); + amount = destHandler.insertItem(i, testObject.recombine(allowed), simulate).getCount(); + } + return amount; + } + + /** + * @return the amount extracted + */ + default int extractFromHandler(@NotNull ItemTestObject testObject, int amount, + @NotNull IItemHandler sourceHandler, boolean simulate) { + int extracted = 0; + for (int i = 0; i < sourceHandler.getSlots(); i++) { + ItemStack stack = sourceHandler.extractItem(i, amount - extracted, true); + if (testObject.test(stack)) { + if (simulate) { + extracted += stack.getCount(); + } else { + extracted += sourceHandler.extractItem(i, amount - extracted, false).getCount(); + } + + } + } + return extracted; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java index dcb8f304faf..19c773820f3 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java @@ -52,13 +52,9 @@ public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachin IItemHandler container = capability.getValue() .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); if (container != null) { - for (int i = 0; i < container.getSlots(); i++) { - int toInsert = (int) Math.min(Math.min(getTestObject().getStackLimit(), container.getSlotLimit(i)), - availableFlow); - availableFlow -= toInsert - container.insertItem(i, getTestObject().recombine(toInsert), - getSimulatorKey() != null).getCount(); - - } + availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + (int) Math.min(Integer.MAX_VALUE, availableFlow), container, getSimulatorKey() != null); } } return flowReachingDestination - availableFlow; diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 89bd6dd1618..a6e0e5c9146 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -49,6 +49,11 @@ public WorldItemNet(String name) { super(name, false, DynamicWeightsShortestPathsAlgorithm::new); } + @Override + public boolean supportsPredication() { + return true; + } + @Override protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { super.coverPredication(edge, a, b); diff --git a/src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java b/src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java new file mode 100644 index 00000000000..5376b172f16 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java @@ -0,0 +1,43 @@ +package gregtech.common.pipelike.net.laser; + +import gregtech.api.capability.ILaserRelay; +import gregtech.api.graphnet.pipenet.insertion.TransferControl; +import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface ILaserTransferController { + + TransferControl CONTROL = new TransferControl<>("Laser") { + + @Override + public @NotNull ILaserTransferController get(@Nullable Object potentialHolder) { + if (!(potentialHolder instanceof TransferControlProvider holder)) return DEFAULT; + ILaserTransferController found = holder.getControllerForControl(CONTROL); + return found == null ? DEFAULT : found; + } + + @Override + public @NotNull ILaserTransferController getNoPassage() { + return NO_PASSAGE; + } + }; + + ILaserTransferController DEFAULT = new ILaserTransferController() {}; + + ILaserTransferController NO_PASSAGE = new ILaserTransferController() { + + @Override + public long insertToHandler(long voltage, long amperage, @NotNull ILaserRelay destHandler) { + return 0; + } + }; + + /** + * @return inserted amperes + */ + default long insertToHandler(long voltage, long amperage, @NotNull ILaserRelay destHandler) { + return destHandler.receiveLaser(voltage, amperage); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java index ac0e0c5ce84..b7b114732a4 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java @@ -58,7 +58,8 @@ public long receiveLaser(long laserVoltage, long laserAmperage) { ILaserRelay laser = capability.getValue() .getCapability(GregtechTileCapabilities.CAPABILITY_LASER, capability.getKey().getOpposite()); if (laser != null) { - long transmitted = laser.receiveLaser(laserVoltage, laserAmperage); + long transmitted = ILaserTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(laserVoltage, laserAmperage, laser); if (transmitted > 0) { SlowActiveWalker.dispatch(tile.getWorld(), path, 1, 2, 2); available -= transmitted; diff --git a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java index 27d7cfc0287..cb61572b4e7 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java @@ -35,7 +35,7 @@ public class WorldLaserNet extends WorldPipeNet implements BasicWorldPipeNetPath } public WorldLaserNet(String name) { - super(name, false, graphNet -> new SinglePathAlgorithm(graphNet, false)); + super(name, false, SinglePathAlgorithm::new); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index 4e0ffb919e9..c997af781a5 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -59,7 +59,8 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { capability.getKey().getOpposite()); if (access != null) { queryObject.setShouldTriggerWalker(false); - boolean cancelled = access.accessData(queryObject); + boolean cancelled = IOpticalTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).queryHandler(queryObject, access); if (queryObject.shouldTriggerWalker()) { SlowActiveWalker.dispatch(tile.getWorld(), path, 1); } diff --git a/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java b/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java new file mode 100644 index 00000000000..c5fc7a3c878 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java @@ -0,0 +1,44 @@ +package gregtech.common.pipelike.net.optical; + +import gregtech.api.capability.data.IDataAccess; +import gregtech.api.capability.data.query.DataQueryObject; +import gregtech.api.graphnet.pipenet.insertion.TransferControl; +import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface IOpticalTransferController { + + TransferControl CONTROL = new TransferControl<>("Laser") { + + @Override + public @NotNull IOpticalTransferController get(@Nullable Object potentialHolder) { + if (!(potentialHolder instanceof TransferControlProvider holder)) return DEFAULT; + IOpticalTransferController found = holder.getControllerForControl(CONTROL); + return found == null ? DEFAULT : found; + } + + @Override + public @NotNull IOpticalTransferController getNoPassage() { + return NO_PASSAGE; + } + }; + + IOpticalTransferController DEFAULT = new IOpticalTransferController() {}; + + IOpticalTransferController NO_PASSAGE = new IOpticalTransferController() { + + @Override + public boolean queryHandler(DataQueryObject query, IDataAccess handler) { + return false; + } + }; + + /** + * @return whether the request should be cancelled + */ + default boolean queryHandler(DataQueryObject query, IDataAccess handler) { + return handler.accessData(query); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java index 289d73551d4..34bdbfe91f3 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -36,7 +36,7 @@ public class WorldOpticalNet extends WorldPipeNet implements BasicWorldPipeNetPa } public WorldOpticalNet(String name) { - super(name, false, graphNet -> new SinglePathAlgorithm(graphNet, false)); + super(name, false, SinglePathAlgorithm::new); } @Override From 6febda587ed4421da042724cb23010b6df72ea97 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 10 Aug 2024 21:11:24 -0600 Subject: [PATCH 090/157] Cover-controlled traversal --- .../gregtech/api/graphnet/GraphNetBacker.java | 7 + .../api/graphnet/edge/NetFlowEdge.java | 5 +- .../api/graphnet/edge/NetFlowSharedEdge.java | 25 +- .../gregtech/api/graphnet/path/INetPath.java | 8 +- .../graphnet/pipenet/WorldPipeNetNode.java | 14 +- .../pipenet/physical/tile/PipeTileEntity.java | 2 +- .../TransferControl.java | 2 +- .../TransferControlProvider.java | 2 +- .../traverse/IEqualizableTraverseData.java | 8 +- .../traverse/IRoundRobinTraverseData.java | 7 +- .../api/graphnet/traverse/ITraverseData.java | 6 +- .../traverse/ITraverseGuideProvider.java | 17 + .../traverse/TraverseDataProvider.java | 15 + .../api/graphnet/traverse/TraverseGuide.java | 46 ++ .../graphnet/traverse/TraverseHelpers.java | 61 ++- .../properties/PipeNetProperties.java | 2 +- .../api/util/function/BiIntConsumer.java | 6 + .../gregtech/common/covers/CoverConveyor.java | 398 ++++++++-------- .../common/covers/CoverFluidFilter.java | 6 +- .../common/covers/CoverFluidRegulator.java | 432 ++++++++++-------- .../common/covers/CoverFluidVoiding.java | 5 + .../common/covers/CoverItemFilter.java | 4 +- .../gregtech/common/covers/CoverPump.java | 223 ++++++++- .../common/covers/CoverRoboticArm.java | 334 +++++++++----- .../gregtech/common/covers/CoverShutter.java | 4 +- .../common/covers/DistributionMode.java | 6 +- .../gregtech/common/covers/TransferMode.java | 10 +- .../common/covers/filter/MergabilityInfo.java | 66 +++ .../net/energy/EnergyTraverseData.java | 6 +- .../net/energy/IEnergyTransferController.java | 4 +- .../net/fluid/FluidCapabilityObject.java | 74 ++- .../net/fluid/FluidEQTraverseData.java | 66 +++ .../net/fluid/FluidRRTraverseData.java | 36 ++ .../pipelike/net/fluid/FluidTraverseData.java | 12 +- .../net/fluid/IFluidTransferController.java | 4 +- .../fluid/IFluidTraverseGuideProvider.java | 20 + .../net/item/IItemTransferController.java | 11 +- .../net/item/IItemTraverseGuideProvider.java | 19 + .../net/item/ItemCapabilityObject.java | 77 +++- .../pipelike/net/item/ItemEQTraverseData.java | 66 +++ .../pipelike/net/item/ItemRRTraverseData.java | 36 ++ .../pipelike/net/item/ItemTraverseData.java | 12 +- .../pipelike/net/item/WorldItemNet.java | 1 + .../net/laser/ILaserTransferController.java | 4 +- .../optical/IOpticalTransferController.java | 4 +- .../resources/assets/gregtech/lang/en_us.lang | 9 +- .../covers/CoverFluidRegulatorTest.java | 430 ++++++++--------- 47 files changed, 1742 insertions(+), 870 deletions(-) rename src/main/java/gregtech/api/graphnet/pipenet/{insertion => transfer}/TransferControl.java (92%) rename src/main/java/gregtech/api/graphnet/pipenet/{insertion => transfer}/TransferControlProvider.java (76%) create mode 100644 src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/TraverseDataProvider.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java create mode 100644 src/main/java/gregtech/api/util/function/BiIntConsumer.java create mode 100644 src/main/java/gregtech/common/covers/filter/MergabilityInfo.java create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java create mode 100644 src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java create mode 100644 src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java create mode 100644 src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index 8f166887bfb..572281a50d2 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -68,6 +68,13 @@ public NetNode getNode(Object equivalencyData) { public boolean removeNode(@Nullable NetNode node) { if (node != null) { + if (!this.getGraph().containsVertex(node.wrapper)) { + // edge case -- the node's group most likely still has this node registered, + // but the node doesn't actually exist in the graph. + // no idea what causes this, but it happens. + NetGroup group = node.getGroupUnsafe(); + if (group != null) group.removeNode(node); + } if (this.getGraph().edgesOf(node.wrapper).size() != 0) this.invalidateAlgs(); NetGroup group = node.getGroupUnsafe(); if (group != null) { diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java index 8824ce8fac1..46964945f72 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java @@ -31,9 +31,8 @@ public NetFlowEdge(int flowBufferTicks) { * NetEdge that provides standard flow behavior handling * * @param flowBufferMult Determines maximum mult of 'buffer' flow capacity that can be built up along edges. - * Allows - * for once-an-interval push/pull operations instead of needing them every unit of time - * for maximum throughput. + * Allows for once-an-interval push/pull operations instead of needing them every unit of + * time for maximum throughput. * @param regenerationTime Ticks required for flow to regenerate once. Allows slowing down the rate of regeneration. */ public NetFlowEdge(int flowBufferMult, int regenerationTime) { diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java index 6df5ce5d1c0..ac126e05f94 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java @@ -15,6 +15,8 @@ public class NetFlowSharedEdge extends AbstractNetFlowEdge { private final int flowBufferTicks; + private final int regenerationTime; + /** * NetEdge that provides flow behavior where the capacity along an edge is shared by all channels. @@ -25,6 +27,21 @@ public class NetFlowSharedEdge extends AbstractNetFlowEdge { */ public NetFlowSharedEdge(int flowBufferTicks) { this.flowBufferTicks = Math.max(flowBufferTicks, 1); + this.regenerationTime = 1; + } + + + /** + * NetEdge that provides flow behavior where the capacity along an edge is shared by all channels. + * + * @param flowBufferTicks Determines how many ticks of 'buffer' flow capacity can be built up along edges. Allows + * for once-an-interval push/pull operations instead of needing them every tick for maximum + * throughput. + * @param regenerationTime Ticks required for flow to regenerate once. Allows slowing down the rate of regeneration. + */ + public NetFlowSharedEdge(int flowBufferTicks, int regenerationTime) { + this.flowBufferTicks = Math.max(flowBufferTicks, 1); + this.regenerationTime = Math.max(regenerationTime, 1); } @Override @@ -121,12 +138,12 @@ public void recalculateFlowLimits(long queryTick) { this.maxCapacity = getThroughput() * flowBufferTicks; this.init = true; } - int time = (int) (queryTick - this.lastQueryTick); - if (time < 0) { + int regenerationUnits = (int) (queryTick - this.lastQueryTick) / regenerationTime; + if (regenerationUnits < 0) { this.map.clear(); } else { List toRemove = new ObjectArrayList<>(); - long regenerationPer = MathHelper.ceil((double) time * getThroughput() / map.size()); + long regenerationPer = MathHelper.ceil((double) regenerationUnits * getThroughput() / map.size()); map.replaceAll((k, v) -> { v -= regenerationPer; if (v <= 0) toRemove.add(k); @@ -135,8 +152,8 @@ public void recalculateFlowLimits(long queryTick) { sharedCapacity += regenerationPer * map.size(); boundCapacity(); toRemove.forEach(map::removeLong); + this.lastQueryTick += (long) regenerationUnits * regenerationTime; } - this.lastQueryTick = queryTick; } private void boundCapacity() { diff --git a/src/main/java/gregtech/api/graphnet/path/INetPath.java b/src/main/java/gregtech/api/graphnet/path/INetPath.java index 50d0f5fe55c..3c0da1e701a 100644 --- a/src/main/java/gregtech/api/graphnet/path/INetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/INetPath.java @@ -4,12 +4,16 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.logic.NetLogicData; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jgrapht.alg.util.ToleranceDoubleComparator; import java.util.List; public interface INetPath { + ToleranceDoubleComparator WEIGHT_COMPARATOR = new ToleranceDoubleComparator(); + List getOrderedNodes(); default N getSourceNode() { @@ -25,8 +29,8 @@ default N getTargetNode() { double getWeight(); - default boolean matches(INetPath other) { - return getWeight() == other.getWeight() && + default boolean matches(@NotNull INetPath other) { + return WEIGHT_COMPARATOR.compare(getWeight(), other.getWeight()) == 0 && getOrderedNodes().equals(other.getOrderedNodes()) && getOrderedEdges().equals(other.getOrderedEdges()); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java index 4f8da146a5c..56fd5599760 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java @@ -1,9 +1,11 @@ package gregtech.api.graphnet.pipenet; import gregtech.api.graphnet.MultiNodeHelper; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.worldnet.WorldNetNode; +import net.minecraft.block.Block; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -15,6 +17,8 @@ public final class WorldPipeNetNode extends WorldNetNode { + private static final PipeTileEntity FALLBACK = new PipeTileEntity(); + @Nullable MultiNodeHelper overlapHelper; @@ -24,8 +28,14 @@ public WorldPipeNetNode(WorldPipeNet net) { super(net); } - public PipeTileEntity getTileEntity() { - return getTileEntity(true); + public @NotNull PipeTileEntity getTileEntity() { + PipeTileEntity tile = getTileEntity(true); + if (tile == null) { + // something went very wrong, return the fallback to prevent NPEs and remove us from the net. + getNet().removeNode(this); + tile = FALLBACK; + } + return tile; } @Nullable diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index d495a88f338..9fd456b5dab 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -320,7 +320,7 @@ public void onNeighborChanged(@NotNull EnumFacing facing) { * @param node the node for this tile entity. Used to identify the capabilities to match. * @return a map of facings to tile entities. */ - public EnumMap getTargetsWithCapabilities(WorldPipeNetNode node) { + public @NotNull EnumMap getTargetsWithCapabilities(WorldPipeNetNode node) { PipeCapabilityWrapper wrapper = netCapabilities.get(node); EnumMap caps = new EnumMap<>(EnumFacing.class); if (wrapper == null) return caps; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControl.java b/src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControl.java similarity index 92% rename from src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControl.java rename to src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControl.java index 7b5d1eee34c..4eeb4b51f3e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControl.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControl.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.pipenet.insertion; +package gregtech.api.graphnet.pipenet.transfer; import net.minecraft.util.IStringSerializable; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControlProvider.java b/src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControlProvider.java similarity index 76% rename from src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControlProvider.java rename to src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControlProvider.java index 802acb4493c..3f013370f3d 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/insertion/TransferControlProvider.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControlProvider.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.pipenet.insertion; +package gregtech.api.graphnet.pipenet.transfer; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java index 6ec10b99fb1..67e8e57d558 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java @@ -3,19 +3,21 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.path.INetPath; +import org.jetbrains.annotations.NotNull; + public interface IEqualizableTraverseData> { - int getDestinationsAtNode(N node); + int getDestinationsAtNode(@NotNull N node); /** * Whether a path should be skipped before running the collection process on it. * The return of {@link ITraverseData#prepareForPathWalk(INetPath, long)} will be ignored during traversal. */ - boolean shouldSkipPath(P path); + boolean shouldSkipPath(@NotNull P path); /** * Should return how much flow the destination with the smallest maximum allowed flow among destinations at * this node requires. */ - long getMaxFlowToLeastDestination(N node); + long getMaxFlowToLeastDestination(@NotNull N destination); } diff --git a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java index 2609fdf6063..d17553b70c1 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java @@ -12,11 +12,14 @@ public interface IRoundRobinTraverseDatamodification during simulation must not be reflected on the cache used for nonsimulation. + * The easiest way to accomplish this is to provide a cloned {@link ArrayDeque} during simulated transfers. + * * @return the traversal cache. */ @NotNull - ArrayDeque getTraversalCache(); + ArrayDeque getTraversalCache(); /** * Whether a path should be skipped before checking it against the round robin cache. diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java index f0b4a7f2c11..bd1f6b08665 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java @@ -30,7 +30,7 @@ public interface ITraverseData> { * @param flow how much flow can be provided to the path. * @return whether the path should be skipped */ - boolean prepareForPathWalk(P path, long flow); + boolean prepareForPathWalk(@NotNull P path, long flow); /** * Reports that the traverse is traversing to a node, for additional logic to be run. @@ -39,7 +39,7 @@ public interface ITraverseData> { * @param flowReachingNode the flow that has reached this node. * @return the loss operator for the node. */ - ReversibleLossOperator traverseToNode(N node, long flowReachingNode); + ReversibleLossOperator traverseToNode(@NotNull N node, long flowReachingNode); /** * Reports that the traverse has finished a path walk, for finalization. @@ -48,7 +48,7 @@ public interface ITraverseData> { * @param flowReachingDestination the flow that reached the destination * @return the amount of flow that should be consumed, before walking the next path. */ - long finalizeAtDestination(N destination, long flowReachingDestination); + long finalizeAtDestination(@NotNull N destination, long flowReachingDestination); /** * Allows for reporting a smaller capacity along an edge than it actually has. Do not report a larger capacity diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java b/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java new file mode 100644 index 00000000000..0d2e8b58195 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java @@ -0,0 +1,17 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.predicate.test.ItemTestObject; + +import org.jetbrains.annotations.Nullable; + +public interface ITraverseGuideProvider, T extends IPredicateTestObject> { + + @Nullable + > TraverseGuide getGuide( + TraverseDataProvider provider, T testObject, long flow, boolean simulate); +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseDataProvider.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseDataProvider.java new file mode 100644 index 00000000000..98ec3348ac6 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseDataProvider.java @@ -0,0 +1,15 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +@FunctionalInterface +public interface TraverseDataProvider, T extends IPredicateTestObject> { + + D of(IGraphNet net, T testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing); +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java new file mode 100644 index 00000000000..ac498f6f0de --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java @@ -0,0 +1,46 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.path.INetPath; + +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; +import java.util.function.LongConsumer; +import java.util.function.Supplier; + +public class TraverseGuide, T extends ITraverseData> { + + private final T data; + private final Supplier> pathsSupplier; + private final long flow; + private final LongConsumer consumptionReport; + + public TraverseGuide(T data, Supplier> pathsSupplier, long flow, @Nullable LongConsumer consumptionReport) { + this.data = data; + this.pathsSupplier = pathsSupplier; + this.flow = flow; + this.consumptionReport = consumptionReport; + } + + public void reportConsumedFlow(long consumedFlow) { + if (consumptionReport != null) consumptionReport.accept(consumedFlow); + } + + public T getData() { + return data; + } + + public Supplier> getPathsSupplier() { + return pathsSupplier; + } + + public Iterator

getPaths() { + return pathsSupplier.get(); + } + + public long getFlow() { + return flow; + } + +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index 54466af03ba..9a4bc76a489 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -20,6 +20,8 @@ import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.function.Supplier; public final class TraverseHelpers { @@ -233,6 +235,7 @@ D extends ITraverseData & IEqualizableTraverseData> long traverseEqu }); } } + if (totalDesired == 0) return 0; maxMult = Math.min(maxMult, flowIn / totalDesired); // scaling long mult = GTUtility.binarySearch(0, maxMult, l -> { @@ -342,27 +345,51 @@ D extends ITraverseData & IRoundRobinTraverseData> long traverseRoun long flowIn, boolean strict) { long availableFlow = flowIn; - ArrayDeque cache = data.getTraversalCache(); + ArrayDeque cache = data.getTraversalCache(); + Predicate invalidityCheck = null; - Map skippedPaths = new Object2ObjectOpenHashMap<>(); + Map skippedPaths = new Object2ObjectOpenHashMap<>(); while (paths.hasNext()) { P path = paths.next(); - N destinationNode = path.getTargetNode(); if (data.shouldSkipPath(path)) continue; - - N nextUp = cache.peekFirst(); - if (destinationNode.equals(nextUp)) { + N destinationNode = path.getTargetNode(); + if (invalidityCheck == null) { + invalidityCheck = d -> { + if (d == null) return false; + NetNode node = destinationNode.getNet().getNode(d); + return node == null || !node.isActive(); + }; + } + Object destIdentifier = destinationNode.getEquivalencyData(); + Object nextUp = cache.peekFirst(); + // filter out invalid equivalency data + while (invalidityCheck.test(nextUp)) { + cache.removeFirst(); + nextUp = cache.peekFirst(); + } + if (destIdentifier.equals(nextUp)) { + // keep iterating over paths in order to collect destinations into the cache + if (availableFlow <= 0) continue; // path is next up in the ordering, we can traverse. cache.removeFirst(); - cache.addLast(destinationNode); + cache.addLast(destIdentifier); long accepted = rrTraverse(data, path, availableFlow, strict); if (accepted == -1) return flowIn - availableFlow; else availableFlow -= accepted; } else { // this path isn't the next one up, skip it unless it's a completely new destination. - if (cache.contains(destinationNode)) skippedPaths.put(destinationNode, path); + if (cache.contains(destIdentifier)) { + // keep iterating over paths in order to collect destinations into the cache + if (availableFlow <= 0) continue; + skippedPaths.put(destIdentifier, path); + } else { - cache.addLast(destinationNode); + // keep iterating over paths in order to collect destinations into the cache + if (availableFlow <= 0) { + cache.addFirst(destIdentifier); + continue; + } + cache.addLast(destIdentifier); long accepted = rrTraverse(data, path, availableFlow, strict); if (accepted == -1) return flowIn - availableFlow; else availableFlow -= accepted; @@ -370,12 +397,18 @@ D extends ITraverseData & IRoundRobinTraverseData> long traverseRoun } } // finally, try and work through skipped paths - while (true) { - P path = skippedPaths.get(cache.peekFirst()); + while (availableFlow > 0) { + Object nextUp = cache.peekFirst(); + if (nextUp == null) break; + P path = skippedPaths.get(nextUp); if (path == null) break; - N dest = cache.removeFirst(); - skippedPaths.remove(dest); - cache.addLast(dest); + assert invalidityCheck != null; // skipped paths would be empty if invalidity check is null + if (invalidityCheck.test(nextUp)) { + cache.removeFirst(); + continue; + } + cache.removeFirst(); + cache.addLast(nextUp); long accepted = rrTraverse(data, path, availableFlow, strict); if (accepted == -1) return flowIn - availableFlow; else availableFlow -= accepted; diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index aee6094333f..f31ab9ec6ce 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -105,7 +105,7 @@ public void verifyProperty(MaterialProperties properties) { } } - protected final class MaterialPropertyComparator implements Comparator { + protected static final class MaterialPropertyComparator implements Comparator { @Override public int compare(IPipeNetMaterialProperty o1, IPipeNetMaterialProperty o2) { diff --git a/src/main/java/gregtech/api/util/function/BiIntConsumer.java b/src/main/java/gregtech/api/util/function/BiIntConsumer.java new file mode 100644 index 00000000000..e6ace74a5a2 --- /dev/null +++ b/src/main/java/gregtech/api/util/function/BiIntConsumer.java @@ -0,0 +1,6 @@ +package gregtech.api.util.function; + +public interface BiIntConsumer { + + void accept(int a, int b); +} diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 7f44ba9fb40..dda0abd477c 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -9,21 +9,40 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; -import gregtech.api.graphnet.pipenet.insertion.TransferControl; -import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.transfer.TransferControl; +import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.graphnet.traverse.TraverseGuide; +import gregtech.api.graphnet.traverse.TraverseHelpers; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.ItemStackHashStrategy; +import gregtech.api.util.function.BiIntConsumer; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; import gregtech.common.covers.filter.ItemFilterContainer; +import gregtech.common.covers.filter.MatchResult; +import gregtech.common.covers.filter.MergabilityInfo; import gregtech.common.pipelike.net.item.IItemTransferController; +import gregtech.common.pipelike.net.item.IItemTraverseGuideProvider; + +import gregtech.common.pipelike.net.item.ItemEQTraverseData; +import gregtech.common.pipelike.net.item.ItemRRTraverseData; +import gregtech.common.pipelike.net.item.ItemTraverseData; + +import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; + +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; + import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -37,6 +56,7 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.IStringSerializable; import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.common.capabilities.Capability; @@ -63,17 +83,18 @@ import com.cleanroommc.modularui.widgets.layout.Column; import com.cleanroommc.modularui.widgets.layout.Row; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; -import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collections; +import java.util.ArrayDeque; import java.util.Map; +import java.util.Objects; import java.util.Set; +import java.util.function.IntUnaryOperator; public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithItemFilter, TransferControlProvider, IItemTransferController { @@ -83,12 +104,15 @@ public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, private int transferRate; protected ConveyorMode conveyorMode; protected DistributionMode distributionMode; + protected boolean transferByFilterGroups; protected ManualImportExportMode manualImportExportMode = ManualImportExportMode.DISABLED; protected final ItemFilterContainer itemFilterContainer; protected int itemsLeftToTransferLastSecond; private CoverableItemHandlerWrapper itemHandlerWrapper; protected boolean isWorkingAllowed = true; + protected final ArrayDeque roundRobinCache = new ArrayDeque<>(); + protected @Nullable CoverRenderer rendererInverted; public CoverConveyor(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, @@ -99,7 +123,8 @@ public CoverConveyor(@NotNull CoverDefinition definition, @NotNull CoverableView this.transferRate = maxItemTransferRate; this.itemsLeftToTransferLastSecond = transferRate; this.conveyorMode = ConveyorMode.EXPORT; - this.distributionMode = DistributionMode.INSERT_FIRST; + this.distributionMode = DistributionMode.FLOOD; + this.transferByFilterGroups = false; this.itemFilterContainer = new ItemFilterContainer(this); } @@ -173,207 +198,192 @@ public ItemFilterContainer getItemFilterContainer() { public void update() { CoverableView coverable = getCoverableView(); long timer = coverable.getOffsetTimer(); - if (timer % 5 == 0 && isWorkingAllowed && itemsLeftToTransferLastSecond > 0) { + if (timer % 5 == 0 && isWorkingAllowed && getItemsLeftToTransfer() > 0) { EnumFacing side = getAttachedSide(); TileEntity tileEntity = coverable.getNeighbor(side); IItemHandler itemHandler = tileEntity == null ? null : tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side.getOpposite()); IItemHandler myItemHandler = coverable.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side); if (itemHandler != null && myItemHandler != null) { - int totalTransferred = doTransferItems(itemHandler, myItemHandler, itemsLeftToTransferLastSecond); - this.itemsLeftToTransferLastSecond -= totalTransferred; + if (conveyorMode == ConveyorMode.EXPORT) { + performTransferOnUpdate(myItemHandler, itemHandler); + } else { + performTransferOnUpdate(itemHandler, myItemHandler); + } } } if (timer % 20 == 0) { - this.itemsLeftToTransferLastSecond = transferRate; - } - } - - protected int doTransferItems(IItemHandler itemHandler, IItemHandler myItemHandler, int maxTransferAmount) { - return doTransferItemsAny(itemHandler, myItemHandler, maxTransferAmount); - } - - protected int doTransferItemsAny(IItemHandler itemHandler, IItemHandler myItemHandler, int maxTransferAmount) { - if (conveyorMode == ConveyorMode.IMPORT) { - return moveInventoryItems(itemHandler, myItemHandler, maxTransferAmount); - } else if (conveyorMode == ConveyorMode.EXPORT) { - return moveInventoryItems(myItemHandler, itemHandler, maxTransferAmount); + refreshBuffer(transferRate); } - return 0; } - protected int doTransferItemsByGroup(IItemHandler itemHandler, IItemHandler myItemHandler, - Map itemInfos, int maxTransferAmount) { - if (conveyorMode == ConveyorMode.IMPORT) { - return moveInventoryItems(itemHandler, myItemHandler, itemInfos, maxTransferAmount); - } else if (conveyorMode == ConveyorMode.EXPORT) { - return moveInventoryItems(myItemHandler, itemHandler, itemInfos, maxTransferAmount); - } - return 0; + protected int getItemsLeftToTransfer() { + return itemsLeftToTransferLastSecond; } - protected Map doCountDestinationInventoryItemsByMatchIndex(IItemHandler itemHandler, - IItemHandler myItemHandler) { - if (conveyorMode == ConveyorMode.IMPORT) { - return countInventoryItemsByMatchSlot(myItemHandler); - } else if (conveyorMode == ConveyorMode.EXPORT) { - return countInventoryItemsByMatchSlot(itemHandler); - } - return Collections.emptyMap(); + protected void reportItemsTransfer(int transferred) { + this.itemsLeftToTransferLastSecond -= transferred; } - protected Map doCountSourceInventoryItemsByType(IItemHandler itemHandler, - IItemHandler myItemHandler) { - if (conveyorMode == ConveyorMode.IMPORT) { - return countInventoryItemsByType(itemHandler); - } else if (conveyorMode == ConveyorMode.EXPORT) { - return countInventoryItemsByType(myItemHandler); - } - return Collections.emptyMap(); + protected void refreshBuffer(int transferRate) { + this.itemsLeftToTransferLastSecond = transferRate; } - protected boolean doTransferItemsExact(IItemHandler itemHandler, IItemHandler myItemHandler, - TypeItemInfo itemInfo) { - if (conveyorMode == ConveyorMode.IMPORT) { - return moveInventoryItemsExact(itemHandler, myItemHandler, itemInfo); - } else if (conveyorMode == ConveyorMode.EXPORT) { - return moveInventoryItemsExact(myItemHandler, itemHandler, itemInfo); - } - return false; - } - - protected static boolean moveInventoryItemsExact(IItemHandler sourceInventory, IItemHandler targetInventory, - TypeItemInfo itemInfo) { - // first, compute how much can we extract in reality from the machine, - // because totalCount is based on what getStackInSlot returns, which may differ from what - // extractItem() will return - ItemStack resultStack = itemInfo.itemStack.copy(); - int totalExtractedCount = 0; - int itemsLeftToExtract = itemInfo.totalCount; - - for (int i = 0; i < itemInfo.slots.size(); i++) { - int slotIndex = itemInfo.slots.get(i); - ItemStack extractedStack = sourceInventory.extractItem(slotIndex, itemsLeftToExtract, true); - if (!extractedStack.isEmpty() && - ItemStack.areItemsEqual(resultStack, extractedStack) && - ItemStack.areItemStackTagsEqual(resultStack, extractedStack)) { - totalExtractedCount += extractedStack.getCount(); - itemsLeftToExtract -= extractedStack.getCount(); - } - if (itemsLeftToExtract == 0) { - break; + protected void performTransferOnUpdate(@NotNull IItemHandler sourceHandler, @NotNull IItemHandler destHandler) { + reportItemsTransfer(performTransfer(sourceHandler, destHandler, false, i -> 0, + i -> getItemsLeftToTransfer(), null)); + } + + /** + * Performs transfer + * + * @param sourceHandler the handler to pull from + * @param destHandler the handler to push to + * @param byFilterSlot whether to perform the transfer by filter slot. + * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. + * Each filter slot will report its transfer before the next slot is calculated. + * @return how much was transferred in total. + */ + protected int performTransfer(@NotNull IItemHandler sourceHandler, @NotNull IItemHandler destHandler, + boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, + @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { + ItemFilterContainer filter = this.getItemFilter(); + byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter + Int2IntArrayMap extractableByFilterSlot = new Int2IntArrayMap(); + Int2ObjectArrayMap> filterSlotToMergability = new Int2ObjectArrayMap<>(); + for (int i = 0; i < sourceHandler.getSlots(); i++) { + ItemStack stack = sourceHandler.extractItem(i, Integer.MAX_VALUE, true); + int extracted = stack.getCount(); + if (extracted == 0) continue; + MatchResult match = null; + if (filter == null || (match = filter.match(stack)).isMatched()) { + int filterSlot = -1; + if (byFilterSlot) { + filterSlot = match.getFilterIndex(); + } + extractableByFilterSlot.merge(filterSlot, extracted, Integer::sum); + final int handlerSlot = i; + filterSlotToMergability.compute(filterSlot, (k, v) -> { + if (v == null) v = new MergabilityInfo<>(); + v.add(handlerSlot, new ItemTestObject(stack), extracted); + return v; + }); } } - // if amount of items extracted is not equal to the amount of items we - // wanted to extract, abort item extraction - if (totalExtractedCount != itemInfo.totalCount) { - return false; - } - // adjust size of the result stack accordingly - resultStack.setCount(totalExtractedCount); - - // now, see how much we can insert into destination inventory - // if we can't insert as much as itemInfo requires, and remainder is empty, abort, abort - ItemStack remainder = GTTransferUtils.insertItem(targetInventory, resultStack, true); - if (!remainder.isEmpty()) { - return false; - } - - // otherwise, perform real insertion and then remove items from the source inventory - GTTransferUtils.insertItem(targetInventory, resultStack, false); - - // perform real extraction of the items from the source inventory now - itemsLeftToExtract = itemInfo.totalCount; - for (int i = 0; i < itemInfo.slots.size(); i++) { - int slotIndex = itemInfo.slots.get(i); - ItemStack extractedStack = sourceInventory.extractItem(slotIndex, itemsLeftToExtract, false); - if (!extractedStack.isEmpty() && - ItemStack.areItemsEqual(resultStack, extractedStack) && - ItemStack.areItemStackTagsEqual(resultStack, extractedStack)) { - itemsLeftToExtract -= extractedStack.getCount(); - } - if (itemsLeftToExtract == 0) { - break; + var iter = extractableByFilterSlot.int2IntEntrySet().fastIterator(); + int totalTransfer = 0; + while (iter.hasNext()) { + var next = iter.next(); + int filterSlot = next.getIntKey(); + int min = minTransfer.applyAsInt(filterSlot); + int max = maxTransfer.applyAsInt(filterSlot); + if (max < min || max <= 0) continue; + int slotTransfer = 0; + if (next.getIntValue() >= min) { + MergabilityInfo mergabilityInfo = filterSlotToMergability.get(filterSlot); + MergabilityInfo.Merge merge = mergabilityInfo.getLargestMerge(); + if (merge.getCount() >= min) { + int transfer = Math.min(merge.getCount(), max); + transfer = insertToHandler(destHandler, merge.getTestObject(), transfer, true); + // since we can't guarantee the insertability of multiple stack types while just simulating, + // if the largest merge is not large enough we have to give up. + if (transfer < min) continue; + int toExtract = transfer; + for (int handlerSlot : merge.getHandlerSlots()) { + toExtract -= sourceHandler.extractItem(handlerSlot, toExtract, false).getCount(); + if (toExtract == 0) break; + } + insertToHandler(destHandler, merge.getTestObject(), transfer - toExtract, false); + int remaining = max - transfer + toExtract; + slotTransfer += transfer; + if (remaining <= 0) continue; + for (MergabilityInfo.Merge otherMerge : mergabilityInfo.getNonLargestMerges(merge)) { + transfer = Math.min(otherMerge.getCount(), remaining); + transfer = insertToHandler(destHandler, merge.getTestObject(), transfer, true); + toExtract = transfer; + for (int handlerSlot :otherMerge.getHandlerSlots()) { + toExtract -= sourceHandler.extractItem(handlerSlot, toExtract, false).getCount(); + if (toExtract == 0) break; + } + insertToHandler(destHandler, otherMerge.getTestObject(), transfer - toExtract, false); + remaining -= transfer; + slotTransfer += transfer; + if (remaining <= 0) break; + } + } } + if (transferReport != null) transferReport.accept(filterSlot, slotTransfer); + totalTransfer += slotTransfer; } - return true; + return totalTransfer; } - protected int moveInventoryItems(IItemHandler sourceInventory, IItemHandler targetInventory, - Map itemInfos, int maxTransferAmount) { - int itemsLeftToTransfer = maxTransferAmount; - for (int i = 0; i < sourceInventory.getSlots(); i++) { - ItemStack itemStack = sourceInventory.getStackInSlot(i); - if (itemStack.isEmpty()) { - continue; + protected int insertToHandler(@NotNull IItemHandler destHandler, ItemTestObject testObject, int count, + boolean simulate) { + if (!(destHandler instanceof IItemTraverseGuideProvider provider)) { + return simpleInsert(destHandler, testObject, count, simulate); + } + switch (distributionMode) { + case FLOOD -> { + var guide = provider.getGuide(this::getTD, testObject, count, simulate); + if (guide == null) return 0; + int consumed = (int) TraverseHelpers.traverseFlood(guide.getData(), guide.getPaths(), guide.getFlow()); + guide.reportConsumedFlow(consumed); + return consumed; } - - var matchResult = itemFilterContainer.match(itemStack); - int matchSlotIndex = matchResult.getFilterIndex(); - if (!matchResult.isMatched() || !itemInfos.containsKey(matchSlotIndex)) { - continue; + case EQUALIZED -> { + var guide = provider.getGuide(this::getEQTD, testObject, count, simulate); + if (guide == null) return 0; + int consumed = (int) TraverseHelpers.traverseEqualDistribution(guide.getData(), guide.getPathsSupplier(), guide.getFlow(), true); + guide.reportConsumedFlow(consumed); + return consumed; } - - GroupItemInfo itemInfo = itemInfos.get(matchSlotIndex); - - ItemStack extractedStack = sourceInventory.extractItem(i, - Math.min(itemInfo.totalCount, itemsLeftToTransfer), true); - - ItemStack remainderStack = GTTransferUtils.insertItem(targetInventory, extractedStack, true); - int amountToInsert = extractedStack.getCount() - remainderStack.getCount(); - - if (amountToInsert > 0) { - extractedStack = sourceInventory.extractItem(i, amountToInsert, false); - - if (!extractedStack.isEmpty()) { - - GTTransferUtils.insertItem(targetInventory, extractedStack, false); - itemsLeftToTransfer -= extractedStack.getCount(); - itemInfo.totalCount -= extractedStack.getCount(); - - if (itemInfo.totalCount == 0) { - itemInfos.remove(matchSlotIndex); - if (itemInfos.isEmpty()) { - break; - } - } - if (itemsLeftToTransfer == 0) { - break; - } - } + case ROUND_ROBIN -> { + var guide = provider.getGuide((net, testObject1, simulator, queryTick, sourcePos, inputFacing) -> + getRRTD(net, testObject1, simulator, queryTick, sourcePos, inputFacing, simulate), testObject, count, simulate); + if (guide == null) return 0; + int consumed = (int) TraverseHelpers.traverseRoundRobin(guide.getData(), guide.getPaths(), guide.getFlow(), true); + guide.reportConsumedFlow(consumed); + return consumed; } } - return maxTransferAmount - itemsLeftToTransfer; + return 0; } - protected int moveInventoryItems(IItemHandler sourceInventory, IItemHandler targetInventory, - int maxTransferAmount) { - int itemsLeftToTransfer = maxTransferAmount; - for (int srcIndex = 0; srcIndex < sourceInventory.getSlots(); srcIndex++) { - ItemStack sourceStack = sourceInventory.extractItem(srcIndex, itemsLeftToTransfer, true); - if (sourceStack.isEmpty()) { - continue; - } + @Contract("_, _, _, _, _, _ -> new") + protected @NotNull ItemTraverseData getTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { + return new ItemTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } - var result = itemFilterContainer.match(sourceStack); - if (!result.isMatched()) continue; + @Contract("_, _, _, _, _, _ -> new") + protected @NotNull ItemEQTraverseData getEQTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { + return new ItemEQTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } - ItemStack remainder = GTTransferUtils.insertItem(targetInventory, sourceStack, true); - int amountToInsert = sourceStack.getCount() - remainder.getCount(); + @Contract("_, _, _, _, _, _, _ -> new") + protected @NotNull ItemRRTraverseData getRRTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing, boolean simulate) { + return new ItemRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, getRoundRobinCache(simulate)); + } - if (amountToInsert > 0) { - sourceStack = sourceInventory.extractItem(srcIndex, amountToInsert, false); - if (!sourceStack.isEmpty()) { - GTTransferUtils.insertItem(targetInventory, sourceStack, false); - itemsLeftToTransfer -= sourceStack.getCount(); + protected ArrayDeque getRoundRobinCache(boolean simulate) { + return simulate ? roundRobinCache.clone() : roundRobinCache; + } - if (itemsLeftToTransfer == 0) { - break; - } - } - } + protected int simpleInsert(@NotNull IItemHandler destHandler, ItemTestObject testObject, int count, boolean simulate) { + int available = count; + for (int i = 0; i < destHandler.getSlots(); i++) { + ItemStack toInsert = testObject.recombine(Math.min(available, destHandler.getSlotLimit(i))); + available -= toInsert.getCount() - destHandler.insertItem(i, toInsert, simulate).getCount(); + if (available == 0) return count; } - return maxTransferAmount - itemsLeftToTransfer; + return count - available; } @Override @@ -425,19 +435,6 @@ public TypeItemInfo(ItemStack itemStack, int filterSlot, IntList slots, int tota } } - protected static class GroupItemInfo { - - public final int filterSlot; - public final Set itemStackTypes; - public int totalCount; - - public GroupItemInfo(int filterSlot, Set itemStackTypes, int totalCount) { - this.filterSlot = filterSlot; - this.itemStackTypes = itemStackTypes; - this.totalCount = totalCount; - } - } - @NotNull protected Map countInventoryItemsByType(@NotNull IItemHandler inventory) { Map result = new Object2ObjectOpenCustomHashMap<>( @@ -466,35 +463,6 @@ protected Map countInventoryItemsByType(@NotNull IItemH return result; } - @NotNull - protected Map countInventoryItemsByMatchSlot(@NotNull IItemHandler inventory) { - Map result = new Int2ObjectOpenHashMap<>(); - for (int srcIndex = 0; srcIndex < inventory.getSlots(); srcIndex++) { - ItemStack itemStack = inventory.getStackInSlot(srcIndex); - if (itemStack.isEmpty()) { - continue; - } - - var matchResult = itemFilterContainer.match(itemStack); - if (!matchResult.isMatched()) continue; - int matchedSlot = matchResult.getFilterIndex(); - - if (!result.containsKey(matchedSlot)) { - GroupItemInfo itemInfo = new GroupItemInfo(matchedSlot, - new ObjectOpenCustomHashSet<>(ItemStackHashStrategy.comparingAllButCount()), 0); - itemInfo.itemStackTypes.add(itemStack.copy()); - itemInfo.totalCount += itemStack.getCount(); - result.put(matchedSlot, itemInfo); - } else { - GroupItemInfo itemInfo = result.get(matchedSlot); - itemInfo.itemStackTypes.add(itemStack.copy()); - itemInfo.totalCount += itemStack.getCount(); - } - - } - return result; - } - @Override public boolean canAttach(@NotNull CoverableView coverable, @NotNull EnumFacing side) { return coverable.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, getAttachedSide()); @@ -637,7 +605,7 @@ protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager g column.child(new EnumRowBuilder<>(DistributionMode.class) .value(distributionMode) .overlay(16, GTGuiTextures.DISTRIBUTION_MODE_OVERLAY) - .lang("cover.conveyor.distribution.name") + .lang("cover.generic.distribution.name") .build()); return column; diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index dadda370dc6..1bad8e9eba7 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -6,8 +6,8 @@ import gregtech.api.cover.filter.CoverWithFluidFilter; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.pipenet.insertion.TransferControl; -import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.pipenet.transfer.TransferControl; +import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTLog; @@ -22,8 +22,6 @@ import gregtech.common.pipelike.net.fluid.IFluidTransferController; -import gregtech.common.pipelike.net.item.IItemTransferController; - import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 099847d4189..8912cd60731 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -1,24 +1,30 @@ package gregtech.common.covers; +import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.mui.GTGuiTextures; -import gregtech.api.util.GTTransferUtils; -import gregtech.client.renderer.texture.Textures; -import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; +import gregtech.api.util.GTUtility; import gregtech.common.covers.filter.FluidFilterContainer; import gregtech.common.covers.filter.SimpleFluidFilter; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import gregtech.common.pipelike.net.fluid.FluidEQTraverseData; +import gregtech.common.pipelike.net.fluid.FluidRRTraverseData; +import gregtech.common.pipelike.net.fluid.FluidTraverseData; +import gregtech.common.pipelike.net.fluid.IFluidTransferController; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidTankProperties; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; import com.cleanroommc.modularui.api.drawable.IKey; import com.cleanroommc.modularui.factory.SidedPosGuiData; @@ -29,206 +35,112 @@ import com.cleanroommc.modularui.value.sync.StringSyncValue; import com.cleanroommc.modularui.widget.ParentWidget; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import org.apache.logging.log4j.message.FormattedMessage; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; -import java.util.function.Predicate; +import java.util.ArrayDeque; +import java.util.function.IntUnaryOperator; public class CoverFluidRegulator extends CoverPump { protected TransferMode transferMode = TransferMode.TRANSFER_ANY; + protected boolean noTransferDueToMinimum = false; public CoverFluidRegulator(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, @NotNull EnumFacing attachedSide, int tier, int mbPerTick) { super(definition, coverableView, attachedSide, tier, mbPerTick); this.fluidFilterContainer = new FluidFilterContainer(this); + this.fluidFilterContainer.setMaxTransferSize(1); } @Override - protected int doTransferFluidsInternal(IFluidHandler myFluidHandler, IFluidHandler fluidHandler, - int transferLimit) { - IFluidHandler sourceHandler; - IFluidHandler destHandler; - - if (pumpMode == PumpMode.IMPORT) { - sourceHandler = fluidHandler; - destHandler = myFluidHandler; - } else if (pumpMode == PumpMode.EXPORT) { - sourceHandler = myFluidHandler; - destHandler = fluidHandler; - } else { - return 0; + protected void refreshBuffer(int transferRate) { + if (this.transferMode == TransferMode.TRANSFER_EXACT && noTransferDueToMinimum) { + FluidFilterContainer filter = this.getFluidFilter(); + if (filter != null) { + this.noTransferDueToMinimum = false; + this.fluidLeftToTransferLastSecond += transferRate; + int max = filter.getTransferSize(); + if (this.fluidLeftToTransferLastSecond > max) { + this.fluidLeftToTransferLastSecond = max; + } + return; + } } - return switch (transferMode) { - case TRANSFER_ANY -> GTTransferUtils.transferFluids(sourceHandler, destHandler, transferLimit, - fluidFilterContainer::test); - case KEEP_EXACT -> doKeepExact(transferLimit, sourceHandler, destHandler, - fluidFilterContainer::test, - this.fluidFilterContainer.getTransferSize()); - case TRANSFER_EXACT -> doTransferExact(transferLimit, sourceHandler, destHandler, - fluidFilterContainer::test, this.fluidFilterContainer.getTransferSize()); - }; + super.refreshBuffer(transferRate); } - protected int doTransferExact(int transferLimit, IFluidHandler sourceHandler, IFluidHandler destHandler, - Predicate fluidFilter, int supplyAmount) { - int fluidLeftToTransfer = transferLimit; - for (IFluidTankProperties tankProperties : sourceHandler.getTankProperties()) { - FluidStack sourceFluid = tankProperties.getContents(); - if (this.fluidFilterContainer.hasFilter()) { - supplyAmount = this.fluidFilterContainer.getFilter().getTransferLimit(sourceFluid, supplyAmount); - } - if (fluidLeftToTransfer < supplyAmount) - break; - if (sourceFluid == null || sourceFluid.amount == 0 || !fluidFilter.test(sourceFluid)) continue; - sourceFluid.amount = supplyAmount; - if (GTTransferUtils.transferExactFluidStack(sourceHandler, destHandler, sourceFluid.copy())) { - fluidLeftToTransfer -= sourceFluid.amount; - } - if (fluidLeftToTransfer == 0) break; + @Override + protected void performTransferOnUpdate(@NotNull IFluidHandler sourceHandler, @NotNull IFluidHandler destHandler) { + if (transferMode == TransferMode.TRANSFER_ANY) { + super.performTransferOnUpdate(sourceHandler, destHandler); + return; + } + FluidFilterContainer filter = this.getFluidFilter(); + if (filter == null) return; + if (transferMode == TransferMode.KEEP_EXACT) { + IntUnaryOperator maxflow = s -> Math.min(filter.getTransferLimit(s), getFluidsLeftToTransfer()); + reportFluidsTransfer(performTransfer(sourceHandler, destHandler, true, s -> 0, maxflow, null)); + } else if (transferMode == TransferMode.TRANSFER_EXACT) { + IntUnaryOperator maxflow = s -> { + int limit = filter.getTransferLimit(s); + if (getFluidsLeftToTransfer() < limit) { + noTransferDueToMinimum = true; + return 0; + } + else return limit; + }; + performTransfer(sourceHandler, destHandler, true, maxflow, maxflow, (a, b) -> reportFluidsTransfer(b)); } - return transferLimit - fluidLeftToTransfer; } - /** - * Performs one tick worth of Keep Exact behavior. - * - * @param transferLimit the maximum amount in milliBuckets that may be transferred in one tick - * @param sourceHandler source(s) to move fluids from - * @param destHandler destination(s) to move fluids to - * @param fluidFilter a predicate which determines what fluids may be moved - * @param keepAmount the desired amount in milliBuckets of a particular fluid in the destination - * @return the total amount in milliBuckets of all fluids transferred from source to dest by this method - */ - protected int doKeepExact(final int transferLimit, - final IFluidHandler sourceHandler, - final IFluidHandler destHandler, - final Predicate fluidFilter, - int keepAmount) { - if (sourceHandler == null || destHandler == null || fluidFilter == null) - return 0; - - final Map sourceFluids = collectDistinctFluids(sourceHandler, - IFluidTankProperties::canDrain, fluidFilter); - final Map destFluids = collectDistinctFluids(destHandler, IFluidTankProperties::canFill, - fluidFilter); - - int transferred = 0; - for (FluidStack fluidStack : sourceFluids.keySet()) { - if (transferred >= transferLimit) - break; - - if (this.fluidFilterContainer.hasFilter()) { - keepAmount = this.fluidFilterContainer.getFilter().getTransferLimit(fluidStack, keepAmount); - } - - // if fluid needs to be moved to meet the Keep Exact value - int amountInDest; - if ((amountInDest = destFluids.getOrDefault(fluidStack, 0)) < keepAmount) { - - // move the lesser of the remaining transfer limit and the difference in actual vs keep exact amount - int amountToMove = Math.min(transferLimit - transferred, - keepAmount - amountInDest); - - // Nothing to do here, try the next fluid. - if (amountToMove <= 0) - continue; - - // Simulate a drain of this fluid from the source tanks - FluidStack drainedResult = sourceHandler.drain(copyFluidStackWithAmount(fluidStack, amountToMove), - false); - - // Can't drain this fluid. Try the next one. - if (drainedResult == null || drainedResult.amount <= 0 || !fluidStack.equals(drainedResult)) - continue; - - // account for the possibility that the drain might give us less than requested - final int drainable = Math.min(amountToMove, drainedResult.amount); - - // Simulate a fill of the drained amount - int fillResult = destHandler.fill(copyFluidStackWithAmount(fluidStack, drainable), false); - - // Can't fill, try the next fluid. - if (fillResult <= 0) - continue; - - // This Fluid can be drained and filled, so let's move the most that will actually work. - int fluidToMove = Math.min(drainable, fillResult); - FluidStack drainedActual = sourceHandler.drain(copyFluidStackWithAmount(fluidStack, fluidToMove), true); - - // Account for potential error states from the drain - if (drainedActual == null) - throw new RuntimeException( - "Misbehaving fluid container: drain produced null after simulation succeeded"); - - if (!fluidStack.equals(drainedActual)) - throw new RuntimeException( - "Misbehaving fluid container: drain produced a different fluid than the simulation"); - - if (drainedActual.amount != fluidToMove) - throw new RuntimeException(new FormattedMessage( - "Misbehaving fluid container: drain expected: {}, actual: {}", - fluidToMove, - drainedActual.amount).getFormattedMessage()); - - // Perform Fill - int filledActual = destHandler.fill(copyFluidStackWithAmount(fluidStack, fluidToMove), true); - - // Account for potential error states from the fill - if (filledActual != fluidToMove) - throw new RuntimeException(new FormattedMessage( - "Misbehaving fluid container: fill expected: {}, actual: {}", - fluidToMove, - filledActual).getFormattedMessage()); - - // update the transferred amount - transferred += fluidToMove; - } + @Override + protected @NotNull FluidTraverseData getTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { + if (transferMode == TransferMode.KEEP_EXACT) { + return new KeepFluidTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); } + return super.getTD(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } - return transferred; + @Override + protected @NotNull FluidEQTraverseData getEQTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { + if (transferMode == TransferMode.KEEP_EXACT) { + return new KeepFluidEQTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } + return super.getEQTD(net, testObject, simulator, queryTick, sourcePos, inputFacing); } - /** - * Copies a FluidStack and sets its amount to the specified value. - * - * @param fs the original fluid stack to copy - * @param amount the amount to set the copied FluidStack to - * @return the copied FluidStack with the specified amount - */ - private static FluidStack copyFluidStackWithAmount(FluidStack fs, int amount) { - FluidStack fs2 = fs.copy(); - fs2.amount = amount; - return fs2; + @Override + protected @NotNull FluidRRTraverseData getRRTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing, + boolean simulate) { + if (transferMode == TransferMode.KEEP_EXACT) { + return new KeepFluidRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, getRoundRobinCache(simulate)); + } + return super.getRRTD(net, testObject, simulator, queryTick, sourcePos, inputFacing, simulate); } - private static Map collectDistinctFluids(IFluidHandler handler, - Predicate tankTypeFilter, - Predicate fluidTypeFilter) { - final Map summedFluids = new Object2IntOpenHashMap<>(); - Arrays.stream(handler.getTankProperties()) - .filter(tankTypeFilter) - .map(IFluidTankProperties::getContents) - .filter(Objects::nonNull) - .filter(fluidTypeFilter) - .forEach(fs -> { - summedFluids.putIfAbsent(fs, 0); - summedFluids.computeIfPresent(fs, (k, v) -> v + fs.amount); - }); - - return summedFluids; + @Override + protected int simpleInsert(@NotNull IFluidHandler destHandler, FluidTestObject testObject, int count, + boolean simulate) { + if (transferMode == TransferMode.KEEP_EXACT) { + assert getFluidFilter() != null; + int kept = getFluidFilter().getTransferLimit(testObject.recombine()); + count = Math.min(count, kept - computeContained(destHandler, testObject)); + } + return super.simpleInsert(destHandler, testObject, count, simulate); } public void setTransferMode(TransferMode transferMode) { if (this.transferMode != transferMode) { this.transferMode = transferMode; + this.getCoverableView().markDirty(); this.fluidFilterContainer.setMaxTransferSize(getMaxTransferRate()); - this.markDirty(); + writeCustomData(GregtechDataCodes.UPDATE_TRANSFER_MODE, + buffer -> buffer.writeByte(this.transferMode.ordinal())); } } @@ -245,7 +157,7 @@ private boolean shouldDisplayAmountSlider() { @Override public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { - return super.buildUI(guiData, guiSyncManager).height(192 + 36); + return super.buildUI(guiData, guiSyncManager).height(192 + 36 + 18 + 2); } @Override @@ -281,24 +193,42 @@ protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncMa @Override public int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, boolean doFill) { - // TODO + if (pumpMode == PumpMode.EXPORT) { + if (transferMode == TransferMode.KEEP_EXACT) { + int contained = computeContained(destHandler, testObject); + assert getFluidFilter() != null; + int keep = getFluidFilter().getTransferLimit(testObject.recombine()); + if (contained >= keep) return 0; + return super.insertToHandler(testObject, Math.min(keep - contained, amount), destHandler, doFill); + } else if (transferMode == TransferMode.TRANSFER_EXACT) { + assert getFluidFilter() != null; + int required = getFluidFilter().getTransferLimit(testObject.recombine()); + if (amount < required) return 0; + return super.insertToHandler(testObject, required, destHandler, doFill); + } + } return super.insertToHandler(testObject, amount, destHandler, doFill); } @Override public @Nullable FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, IFluidHandler sourceHandler, boolean doDrain) { - // TODO + if (pumpMode == PumpMode.IMPORT) { + // TODO should extraction instead be ignored for transfer exact? + if (transferMode == TransferMode.TRANSFER_EXACT) { + assert getFluidFilter() != null; + int required = testObject == null ? getFluidFilter().getTransferSize() : + getFluidFilter().getTransferLimit(testObject.recombine()); + if (amount < required) return null; + else amount = required; + } + } return super.extractFromHandler(testObject, amount, sourceHandler, doDrain); } @Override public int getMaxTransferRate() { - return switch (this.transferMode) { - case TRANSFER_ANY -> 1; - case TRANSFER_EXACT -> maxFluidTransferRate; - case KEEP_EXACT -> Integer.MAX_VALUE; - }; + return this.transferMode.maxFluidStackSize; } @Override @@ -311,6 +241,16 @@ public void writeInitialSyncData(@NotNull PacketBuffer packetBuffer) { public void readInitialSyncData(@NotNull PacketBuffer packetBuffer) { super.readInitialSyncData(packetBuffer); this.transferMode = TransferMode.VALUES[packetBuffer.readByte()]; + this.fluidFilterContainer.setMaxTransferSize(this.transferMode.maxStackSize); + } + + @Override + public void readCustomData(int discriminator, @NotNull PacketBuffer buf) { + super.readCustomData(discriminator, buf); + if (discriminator == GregtechDataCodes.UPDATE_TRANSFER_MODE) { + this.transferMode = TransferMode.VALUES[buf.readByte()]; + this.fluidFilterContainer.setMaxTransferSize(this.transferMode.maxStackSize); + } } @Override @@ -333,4 +273,134 @@ public void readFromNBT(@NotNull NBTTagCompound tagCompound) { } } } + + protected int computeContained(@NotNull IFluidHandler handler, @NotNull FluidTestObject testObject) { + int found = 0; + for (IFluidTankProperties tank : handler.getTankProperties()) { + FluidStack contained = tank.getContents(); + if (testObject.test(contained)) { + found += contained.amount; + } + } + return found; + } + + protected class KeepFluidTraverseData extends FluidTraverseData { + + public KeepFluidTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing) { + super(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } + + @Override + public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { + long availableFlow = flowReachingDestination; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IFluidHandler container = capability.getValue() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + int contained = computeContained(container, getTestObject()); + assert getFluidFilter() != null; + int kept = getFluidFilter().getTransferLimit(getTestObject().recombine()); + if (contained >= kept) continue; + availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() == null); + } + } + return flowReachingDestination - availableFlow; + } + } + + protected class KeepFluidEQTraverseData extends FluidEQTraverseData { + + public KeepFluidEQTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing) { + super(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } + + @Override + protected void compute(@NotNull WorldPipeNetNode destination) { + this.destCount = 0; + this.maxMinFlow = 0; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IFluidHandler container = capability.getValue() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + int contained = computeContained(container, getTestObject()); + assert getFluidFilter() != null; + int kept = getFluidFilter().getTransferLimit(getTestObject().recombine()); + if (contained >= kept) continue; + if (destCount == 0) maxMinFlow = Integer.MAX_VALUE; + destCount += 1; + maxMinFlow = Math.min(maxMinFlow, + IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), kept - contained, + container, false)); + } + } + } + + @Override + public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { + long availableFlow = flowReachingDestination; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IFluidHandler container = capability.getValue() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + int contained = computeContained(container, getTestObject()); + assert getFluidFilter() != null; + int kept = getFluidFilter().getTransferLimit(getTestObject().recombine()); + if (contained >= kept) continue; + availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() == null); + } + } + return flowReachingDestination - availableFlow; + } + } + + protected class KeepFluidRRTraverseData extends FluidRRTraverseData { + + public KeepFluidRRTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing, ArrayDeque cache) { + super(net, testObject, simulator, queryTick, sourcePos, inputFacing, cache); + } + + @Override + public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { + long availableFlow = flowReachingDestination; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IFluidHandler container = capability.getValue() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + int contained = computeContained(container, getTestObject()); + assert getFluidFilter() != null; + int kept = getFluidFilter().getTransferLimit(getTestObject().recombine()); + if (contained >= kept) continue; + availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() == null); + } + } + return flowReachingDestination - availableFlow; + } + } } diff --git a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java index 6629083c616..969545e3c22 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java +++ b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java @@ -111,6 +111,11 @@ protected boolean createPumpModeRow() { return false; } + @Override + protected boolean createDistributionModeRow() { + return false; + } + @Override protected boolean createThroughputRow() { return false; diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 745105a5a77..16df0cf8a4b 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -6,8 +6,8 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; -import gregtech.api.graphnet.pipenet.insertion.TransferControl; -import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.pipenet.transfer.TransferControl; +import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTLog; diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index 1239be6f302..d739bad9793 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -9,12 +9,17 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithFluidFilter; -import gregtech.api.graphnet.pipenet.insertion.TransferControl; -import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.transfer.TransferControl; +import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.graphnet.traverse.TraverseHelpers; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; import gregtech.api.util.GTTransferUtils; +import gregtech.api.util.function.BiIntConsumer; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; @@ -22,13 +27,27 @@ import gregtech.common.covers.filter.FluidFilterContainer; import gregtech.common.covers.filter.ItemFilterContainer; +import gregtech.common.covers.filter.MatchResult; +import gregtech.common.pipelike.net.fluid.FluidEQTraverseData; +import gregtech.common.pipelike.net.fluid.FluidRRTraverseData; +import gregtech.common.pipelike.net.fluid.FluidTraverseData; import gregtech.common.pipelike.net.fluid.IFluidTransferController; -import gregtech.common.pipelike.net.item.IItemTransferController; +import gregtech.common.pipelike.net.fluid.IFluidTraverseGuideProvider; +import gregtech.common.pipelike.net.item.IItemTraverseGuideProvider; +import gregtech.common.pipelike.net.item.ItemEQTraverseData; +import gregtech.common.pipelike.net.item.ItemRRTraverseData; +import gregtech.common.pipelike.net.item.ItemTraverseData; + +import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; + +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; @@ -38,12 +57,14 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.IStringSerializable; import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -65,9 +86,17 @@ import com.cleanroommc.modularui.widgets.layout.Column; import com.cleanroommc.modularui.widgets.layout.Row; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; + +import net.minecraftforge.items.IItemHandler; + +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayDeque; +import java.util.Set; +import java.util.function.IntUnaryOperator; + public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithFluidFilter, TransferControlProvider, IFluidTransferController { @@ -76,13 +105,15 @@ public class CoverPump extends CoverBase implements CoverWithUI, ITickable, ICon protected int transferRate; protected PumpMode pumpMode = PumpMode.EXPORT; protected ManualImportExportMode manualImportExportMode = ManualImportExportMode.DISABLED; - protected DistributionMode distributionMode = DistributionMode.INSERT_FIRST; + protected DistributionMode distributionMode = DistributionMode.FLOOD; protected int fluidLeftToTransferLastSecond; private CoverableFluidHandlerWrapper fluidHandlerWrapper; protected boolean isWorkingAllowed = true; protected FluidFilterContainer fluidFilterContainer; protected BucketMode bucketMode = BucketMode.MILLI_BUCKET; + protected final ArrayDeque roundRobinCache = new ArrayDeque<>(); + protected @Nullable CoverRenderer rendererInverted; public CoverPump(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, @@ -148,6 +179,14 @@ public PumpMode getPumpMode() { return pumpMode; } + public DistributionMode getDistributionMode() { + return distributionMode; + } + + public void setDistributionMode(DistributionMode distributionMode) { + this.distributionMode = distributionMode; + } + public void setBucketMode(BucketMode bucketMode) { this.bucketMode = bucketMode; if (this.bucketMode == BucketMode.BUCKET) @@ -175,38 +214,157 @@ public FluidFilterContainer getFluidFilterContainer() { @Override public void update() { long timer = getOffsetTimer(); - if (isWorkingAllowed && fluidLeftToTransferLastSecond > 0) { - this.fluidLeftToTransferLastSecond -= doTransferFluids(fluidLeftToTransferLastSecond); + if (isWorkingAllowed && getFluidsLeftToTransfer() > 0) { + TileEntity tileEntity = getNeighbor(getAttachedSide()); + IFluidHandler fluidHandler = tileEntity == null ? null : tileEntity + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, getAttachedSide().getOpposite()); + IFluidHandler myFluidHandler = getCoverableView().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + getAttachedSide()); + if (myFluidHandler != null && fluidHandler != null) { + if (pumpMode == PumpMode.EXPORT) { + performTransferOnUpdate(myFluidHandler, fluidHandler); + } else { + performTransferOnUpdate(fluidHandler, myFluidHandler); + } + } } if (timer % 20 == 0) { - this.fluidLeftToTransferLastSecond = transferRate; + refreshBuffer(transferRate); } } - protected int doTransferFluids(int transferLimit) { - TileEntity tileEntity = getNeighbor(getAttachedSide()); - IFluidHandler fluidHandler = tileEntity == null ? null : tileEntity - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, getAttachedSide().getOpposite()); - IFluidHandler myFluidHandler = getCoverableView().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - getAttachedSide()); - if (fluidHandler == null || myFluidHandler == null) { - return 0; + public int getFluidsLeftToTransfer() { + return fluidLeftToTransferLastSecond; + } + + public void reportFluidsTransfer(int transferred) { + fluidLeftToTransferLastSecond -= transferred; + } + + protected void refreshBuffer(int transferRate) { + this.fluidLeftToTransferLastSecond = transferRate; + } + + protected void performTransferOnUpdate(@NotNull IFluidHandler sourceHandler, @NotNull IFluidHandler destHandler) { + reportFluidsTransfer(performTransfer(sourceHandler, destHandler, false, i -> 0, + i -> getFluidsLeftToTransfer(), null)); + } + + /** + * Performs transfer + * + * @param sourceHandler the handler to pull from + * @param destHandler the handler to push to + * @param byFilterSlot whether to perform the transfer by filter slot. + * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. + * Each filter slot will report its transfer before the next slot is calculated. + * @return how much was transferred in total. + */ + protected int performTransfer(@NotNull IFluidHandler sourceHandler, @NotNull IFluidHandler destHandler, + boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, + @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { + FluidFilterContainer filter = this.getFluidFilter(); + byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter + Object2IntOpenHashMap contained = new Object2IntOpenHashMap<>(); + var tanks = sourceHandler.getTankProperties(); + for (IFluidTankProperties tank : tanks) { + FluidStack contents = tank.getContents(); + if (contents != null) contained.merge(new FluidTestObject(contents), contents.amount, Integer::sum); + } + var iter = contained.object2IntEntrySet().fastIterator(); + int totalTransfer = 0; + while (iter.hasNext()) { + var content = iter.next(); + FluidStack contents = content.getKey().recombine(content.getIntValue()); + MatchResult match = null; + if (filter == null || (match = filter.match(contents)).isMatched()) { + int filterSlot = -1; + if (byFilterSlot) { + assert filter != null; // we know it is not null, because if it were byFilterSlot would be false. + filterSlot = match.getFilterIndex(); + } + int min = minTransfer.applyAsInt(filterSlot); + int max = maxTransfer.applyAsInt(filterSlot); + if (max < min || max <= 0) continue; + + if (contents.amount < min) continue; + int transfer = Math.min(contents.amount, max); + FluidStack extracted = sourceHandler.drain(content.getKey().recombine(transfer), false); + if (extracted == null || extracted.amount < min) continue; + transfer = insertToHandler(destHandler, content.getKey(), extracted.amount, true); + if (transfer <= 0 || transfer < min) continue; + extracted = sourceHandler.drain(content.getKey().recombine(transfer), true); + if (extracted == null) continue; + transfer = insertToHandler(destHandler, content.getKey(), extracted.amount, false); + if (transferReport != null) transferReport.accept(filterSlot, transfer); + totalTransfer += transfer; + } } - return doTransferFluidsInternal(myFluidHandler, fluidHandler, transferLimit); + return totalTransfer; } - protected int doTransferFluidsInternal(IFluidHandler myFluidHandler, IFluidHandler fluidHandler, - int transferLimit) { - if (pumpMode == PumpMode.IMPORT) { - return GTTransferUtils.transferFluids(fluidHandler, myFluidHandler, transferLimit, - fluidFilterContainer::test); - } else if (pumpMode == PumpMode.EXPORT) { - return GTTransferUtils.transferFluids(myFluidHandler, fluidHandler, transferLimit, - fluidFilterContainer::test); + protected int insertToHandler(@NotNull IFluidHandler destHandler, FluidTestObject testObject, int count, + boolean simulate) { + if (!(destHandler instanceof IFluidTraverseGuideProvider provider)) { + return simpleInsert(destHandler, testObject, count, simulate); + } + switch (distributionMode) { + case FLOOD -> { + var guide = provider.getGuide(this::getTD, testObject, count, simulate); + if (guide == null) return 0; + int consumed = (int) TraverseHelpers.traverseFlood(guide.getData(), guide.getPaths(), guide.getFlow()); + guide.reportConsumedFlow(consumed); + return consumed; + } + case EQUALIZED -> { + var guide = provider.getGuide(this::getEQTD, testObject, count, simulate); + if (guide == null) return 0; + int consumed = (int) TraverseHelpers.traverseEqualDistribution(guide.getData(), guide.getPathsSupplier(), guide.getFlow(), true); + guide.reportConsumedFlow(consumed); + return consumed; + } + case ROUND_ROBIN -> { + var guide = provider.getGuide((net, testObject1, simulator, queryTick, sourcePos, inputFacing) -> + getRRTD(net, testObject1, simulator, queryTick, sourcePos, inputFacing, simulate), testObject, count, simulate); + if (guide == null) return 0; + int consumed = (int) TraverseHelpers.traverseRoundRobin(guide.getData(), guide.getPaths(), guide.getFlow(), true); + guide.reportConsumedFlow(consumed); + return consumed; + } } return 0; } + @Contract("_, _, _, _, _, _ -> new") + protected @NotNull FluidTraverseData getTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { + return new FluidTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } + + @Contract("_, _, _, _, _, _ -> new") + protected @NotNull FluidEQTraverseData getEQTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { + return new FluidEQTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } + + @Contract("_, _, _, _, _, _, _ -> new") + protected @NotNull FluidRRTraverseData getRRTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing, boolean simulate) { + return new FluidRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, getRoundRobinCache(simulate)); + } + + protected ArrayDeque getRoundRobinCache(boolean simulate) { + return simulate ? roundRobinCache.clone() : roundRobinCache; + } + + protected int simpleInsert(@NotNull IFluidHandler destHandler, FluidTestObject testObject, int count, boolean simulate) { + return count - destHandler.fill(testObject.recombine(count), !simulate); + } + protected boolean checkInputFluid(FluidStack fluidStack) { return fluidFilterContainer.test(fluidStack); } @@ -218,7 +376,7 @@ public boolean usesMui2() { @Override public ModularPanel buildUI(SidedPosGuiData guiData, GuiSyncManager guiSyncManager) { - var panel = GTGuis.createPanel(this, 176, 192); + var panel = GTGuis.createPanel(this, 176, 192 + 18); getFluidFilterContainer().setMaxTransferSize(getMaxTransferRate()); @@ -243,8 +401,12 @@ protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncMa var pumpMode = new EnumSyncValue<>(PumpMode.class, this::getPumpMode, this::setPumpMode); pumpMode.updateCacheFromSource(true); + EnumSyncValue distributionMode = new EnumSyncValue<>(DistributionMode.class, + this::getDistributionMode, this::setDistributionMode); + syncManager.syncValue("manual_io", manualIOmode); syncManager.syncValue("pump_mode", pumpMode); + syncManager.syncValue("distribution_mode", distributionMode); syncManager.syncValue("throughput", throughput); var column = new Column().top(24).margin(7, 0) @@ -296,6 +458,13 @@ protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager syncMa .overlay(GTGuiTextures.CONVEYOR_MODE_OVERLAY) // todo pump mode overlays .build()); + if (createDistributionModeRow()) + column.child(new EnumRowBuilder<>(DistributionMode.class) + .value(distributionMode) + .overlay(16, GTGuiTextures.DISTRIBUTION_MODE_OVERLAY) + .lang("cover.generic.distribution.name") + .build()); + return column; } @@ -315,6 +484,10 @@ protected boolean createPumpModeRow() { return true; } + protected boolean createDistributionModeRow() { + return true; + } + protected int getMaxTransferRate() { return 1; } diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index c385bfda6e4..f43fed636eb 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -3,18 +3,30 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.mui.GTGuiTextures; +import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; -import gregtech.common.covers.filter.SmartItemFilter; +import gregtech.common.covers.filter.FluidFilterContainer; +import gregtech.common.covers.filter.ItemFilterContainer; + +import gregtech.common.pipelike.net.item.IItemTransferController; +import gregtech.common.pipelike.net.item.ItemEQTraverseData; +import gregtech.common.pipelike.net.item.ItemRRTraverseData; +import gregtech.common.pipelike.net.item.ItemTraverseData; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import codechicken.lib.render.CCRenderState; @@ -33,13 +45,13 @@ import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; -import java.util.Iterator; -import java.util.Map; +import java.util.ArrayDeque; +import java.util.function.IntUnaryOperator; public class CoverRoboticArm extends CoverConveyor { protected TransferMode transferMode; - protected int itemsTransferBuffered; + protected boolean noTransferDueToMinimum = false; public CoverRoboticArm(@NotNull CoverDefinition definition, @NotNull CoverableView coverableView, @NotNull EnumFacing attachedSide, int tier, int itemsPerSecond) { @@ -69,117 +81,82 @@ protected CoverRenderer buildRendererInverted() { } @Override - protected int doTransferItems(IItemHandler itemHandler, IItemHandler myItemHandler, int maxTransferAmount) { - // if (conveyorMode == ConveyorMode.EXPORT && itemHandler instanceof ItemNetHandler && - // transferMode == TransferMode.KEEP_EXACT) { - // return 0; - // } - // if (conveyorMode == ConveyorMode.IMPORT && myItemHandler instanceof ItemNetHandler && - // transferMode == TransferMode.KEEP_EXACT) { - // return 0; - // } - return switch (transferMode) { - case TRANSFER_ANY -> doTransferItemsAny(itemHandler, myItemHandler, maxTransferAmount); - case TRANSFER_EXACT -> doTransferExact(itemHandler, myItemHandler, maxTransferAmount); - case KEEP_EXACT -> doKeepExact(itemHandler, myItemHandler, maxTransferAmount); - }; - } - - protected int doTransferExact(IItemHandler itemHandler, IItemHandler myItemHandler, int maxTransferAmount) { - Map sourceItemAmount = doCountSourceInventoryItemsByType(itemHandler, myItemHandler); - Iterator iterator = sourceItemAmount.keySet().iterator(); - while (iterator.hasNext()) { - TypeItemInfo sourceInfo = sourceItemAmount.get(iterator.next()); - int itemAmount = sourceInfo.totalCount; - int itemToMoveAmount = itemFilterContainer.getTransferLimit(sourceInfo.itemStack); - - // if smart item filter and whitelist - if (itemFilterContainer.getFilter() instanceof SmartItemFilter && - !itemFilterContainer.isBlacklistFilter()) { - if (itemFilterContainer.getTransferSize() > 1 && itemToMoveAmount * 2 <= itemAmount) { - // get the max we can extract from the item filter variable - int maxMultiplier = Math.floorDiv(maxTransferAmount, itemToMoveAmount); - - // multiply up to the total count of all the items - itemToMoveAmount *= Math.min(itemFilterContainer.getTransferSize(), maxMultiplier); + protected void refreshBuffer(int transferRate) { + if (this.transferMode == TransferMode.TRANSFER_EXACT && noTransferDueToMinimum) { + ItemFilterContainer filter = this.getItemFilter(); + if (filter != null) { + this.noTransferDueToMinimum = false; + this.itemsLeftToTransferLastSecond += transferRate; + int max = filter.getTransferSize(); + if (this.itemsLeftToTransferLastSecond > max) { + this.itemsLeftToTransferLastSecond = max; } - } - - if (itemAmount >= itemToMoveAmount) { - sourceInfo.totalCount = itemToMoveAmount; - } else { - iterator.remove(); + return; } } + super.refreshBuffer(transferRate); + } - int itemsTransferred = 0; - int maxTotalTransferAmount = maxTransferAmount + itemsTransferBuffered; - boolean notEnoughTransferRate = false; - for (TypeItemInfo itemInfo : sourceItemAmount.values()) { - if (maxTotalTransferAmount >= itemInfo.totalCount) { - boolean result = doTransferItemsExact(itemHandler, myItemHandler, itemInfo); - itemsTransferred += result ? itemInfo.totalCount : 0; - maxTotalTransferAmount -= result ? itemInfo.totalCount : 0; - } else { - notEnoughTransferRate = true; - } + @Override + protected void performTransferOnUpdate(@NotNull IItemHandler sourceHandler, @NotNull IItemHandler destHandler) { + if (transferMode == TransferMode.TRANSFER_ANY) { + super.performTransferOnUpdate(sourceHandler, destHandler); + return; } - // if we didn't transfer anything because of too small transfer rate, buffer it - if (itemsTransferred == 0 && notEnoughTransferRate) { - itemsTransferBuffered += maxTransferAmount; - } else { - // otherwise, if transfer succeed, empty transfer buffer value - itemsTransferBuffered = 0; + ItemFilterContainer filter = this.getItemFilter(); + if (filter == null) return; + if (transferMode == TransferMode.KEEP_EXACT) { + IntUnaryOperator maxflow = s -> Math.min(filter.getTransferLimit(s), getItemsLeftToTransfer()); + reportItemsTransfer(performTransfer(sourceHandler, destHandler, true, s -> 0, maxflow, null)); + } else if (transferMode == TransferMode.TRANSFER_EXACT) { + IntUnaryOperator maxflow = s -> { + int limit = filter.getTransferLimit(s); + if (getItemsLeftToTransfer() < limit) { + noTransferDueToMinimum = true; + return 0; + } + else return limit; + }; + performTransfer(sourceHandler, destHandler, true, maxflow, maxflow, (a, b) -> reportItemsTransfer(b)); } - return Math.min(itemsTransferred, maxTransferAmount); } - protected int doKeepExact(IItemHandler itemHandler, IItemHandler myItemHandler, int maxTransferAmount) { - Map currentItemAmount = doCountDestinationInventoryItemsByMatchIndex(itemHandler, - myItemHandler); - Map sourceItemAmounts = doCountDestinationInventoryItemsByMatchIndex(myItemHandler, - itemHandler); - Iterator iterator = sourceItemAmounts.keySet().iterator(); - while (iterator.hasNext()) { - int filterSlotIndex = iterator.next(); - GroupItemInfo sourceInfo = sourceItemAmounts.get(filterSlotIndex); - int itemToKeepAmount = itemFilterContainer.getTransferLimit(sourceInfo.filterSlot); - - // only run multiplier for smart item - if (itemFilterContainer.getFilter() instanceof SmartItemFilter) { - if (itemFilterContainer.getTransferSize() > 1 && itemToKeepAmount * 2 <= sourceInfo.totalCount) { - // get the max we can keep from the item filter variable - int maxMultiplier = Math.floorDiv(sourceInfo.totalCount, itemToKeepAmount); - - // multiply up to the total count of all the items - itemToKeepAmount *= Math.min(itemFilterContainer.getTransferSize(), maxMultiplier); - } - } - - int itemAmount = 0; - if (currentItemAmount.containsKey(filterSlotIndex)) { - GroupItemInfo destItemInfo = currentItemAmount.get(filterSlotIndex); - itemAmount = destItemInfo.totalCount; - } - if (itemAmount < itemToKeepAmount) { - sourceInfo.totalCount = itemToKeepAmount - itemAmount; - } else { - iterator.remove(); - } + @Override + protected @NotNull ItemTraverseData getTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { + if (transferMode == TransferMode.KEEP_EXACT) { + return new KeepItemTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); } - return doTransferItemsByGroup(itemHandler, myItemHandler, sourceItemAmounts, maxTransferAmount); + return super.getTD(net, testObject, simulator, queryTick, sourcePos, inputFacing); } - public int getBuffer() { - return itemsTransferBuffered; + @Override + protected @NotNull ItemEQTraverseData getEQTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { + if (transferMode == TransferMode.KEEP_EXACT) { + return new KeepItemEQTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } + return super.getEQTD(net, testObject, simulator, queryTick, sourcePos, inputFacing); } - public void buffer(int amount) { - itemsTransferBuffered += amount; + @Override + protected @NotNull ItemRRTraverseData getRRTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing, boolean simulate) { + if (transferMode == TransferMode.KEEP_EXACT) { + return new KeepItemRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, getRoundRobinCache(simulate)); + } + return super.getRRTD(net, testObject, simulator, queryTick, sourcePos, inputFacing, simulate); } - public void clearBuffer() { - itemsTransferBuffered = 0; + @Override + protected int simpleInsert(@NotNull IItemHandler destHandler, ItemTestObject testObject, int count, + boolean simulate) { + if (transferMode == TransferMode.KEEP_EXACT) { + assert getItemFilter() != null; + int kept = getItemFilter().getTransferLimit(testObject.recombine()); + count = Math.min(count, kept - computeContained(destHandler, testObject)); + } + return super.simpleInsert(destHandler, testObject, count, simulate); } public void setTransferMode(TransferMode transferMode) { @@ -236,14 +213,36 @@ protected ParentWidget createUI(ModularPanel mainPanel, GuiSyncManager g @Override public int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, boolean simulate) { - // TODO + if (conveyorMode == ConveyorMode.EXPORT) { + if (transferMode == TransferMode.KEEP_EXACT) { + int contained = computeContained(destHandler, testObject); + assert getItemFilter() != null; + int keep = getItemFilter().getTransferLimit(testObject.recombine()); + if (contained >= keep) return amount; + int allowed = Math.min(keep - contained, amount); + return (amount - allowed) + super.insertToHandler(testObject, allowed, destHandler, simulate); + } else if (transferMode == TransferMode.TRANSFER_EXACT) { + assert getItemFilter() != null; + int required = getItemFilter().getTransferLimit(testObject.recombine()); + if (amount < required) return amount; + return (amount - required) + super.insertToHandler(testObject, required, destHandler, simulate); + } + } return super.insertToHandler(testObject, amount, destHandler, simulate); } @Override public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler sourceHandler, boolean simulate) { - // TODO + if (conveyorMode == ConveyorMode.IMPORT) { + // TODO should extraction instead be ignored for transfer exact? + if (transferMode == TransferMode.TRANSFER_EXACT) { + assert getItemFilter() != null; + int required = getItemFilter().getTransferLimit(testObject.recombine()); + if (amount < required) return 0; + else amount = required; + } + } return super.extractFromHandler(testObject, amount, sourceHandler, simulate); } @@ -286,4 +285,135 @@ public void readFromNBT(NBTTagCompound tagCompound) { this.itemFilterContainer.setMaxTransferSize(this.transferMode.maxStackSize); super.readFromNBT(tagCompound); } + + protected int computeContained(@NotNull IItemHandler handler, @NotNull ItemTestObject testObject) { + int found = 0; + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack contained = handler.getStackInSlot(i); + if (testObject.test(contained)) { + found += contained.getCount(); + } + } + return found; + } + + protected class KeepItemTraverseData extends ItemTraverseData { + + public KeepItemTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing) { + super(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } + + @Override + public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { + long availableFlow = flowReachingDestination; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IItemHandler container = capability.getValue() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + int contained = computeContained(container, getTestObject()); + assert getItemFilter() != null; + int kept = getItemFilter().getTransferLimit(getTestObject().recombine()); + if (contained >= kept) continue; + availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() != null); + } + } + return flowReachingDestination - availableFlow; + } + } + + protected class KeepItemEQTraverseData extends ItemEQTraverseData { + + public KeepItemEQTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing) { + super(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } + + @Override + protected void compute(@NotNull WorldPipeNetNode destination) { + this.destCount = 0; + this.maxMinFlow = 0; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IItemHandler container = capability.getValue() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + int contained = computeContained(container, getTestObject()); + assert getItemFilter() != null; + int kept = getItemFilter().getTransferLimit(getTestObject().recombine()); + if (contained >= kept) continue; + if (destCount == 0) maxMinFlow = Integer.MAX_VALUE; + destCount += 1; + int test = kept - contained; + maxMinFlow = Math.min(maxMinFlow, test - + IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), test, + container, true)); + } + } + } + + @Override + public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { + long availableFlow = flowReachingDestination; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IItemHandler container = capability.getValue() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + int contained = computeContained(container, getTestObject()); + assert getItemFilter() != null; + int kept = getItemFilter().getTransferLimit(getTestObject().recombine()); + if (contained >= kept) continue; + availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() != null); + } + } + return flowReachingDestination - availableFlow; + } + } + + protected class KeepItemRRTraverseData extends ItemRRTraverseData { + + public KeepItemRRTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing, ArrayDeque cache) { + super(net, testObject, simulator, queryTick, sourcePos, inputFacing, cache); + } + + @Override + public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { + long availableFlow = flowReachingDestination; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IItemHandler container = capability.getValue() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + int contained = computeContained(container, getTestObject()); + assert getItemFilter() != null; + int kept = getItemFilter().getTransferLimit(getTestObject().recombine()); + if (contained >= kept) continue; + availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() != null); + } + } + return flowReachingDestination - availableFlow; + } + } } diff --git a/src/main/java/gregtech/common/covers/CoverShutter.java b/src/main/java/gregtech/common/covers/CoverShutter.java index bd0b05b4a20..70b3eaf577e 100644 --- a/src/main/java/gregtech/common/covers/CoverShutter.java +++ b/src/main/java/gregtech/common/covers/CoverShutter.java @@ -5,8 +5,8 @@ import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.pipenet.insertion.TransferControl; -import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.pipenet.transfer.TransferControl; +import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; diff --git a/src/main/java/gregtech/common/covers/DistributionMode.java b/src/main/java/gregtech/common/covers/DistributionMode.java index c704d045b18..4a19270323f 100644 --- a/src/main/java/gregtech/common/covers/DistributionMode.java +++ b/src/main/java/gregtech/common/covers/DistributionMode.java @@ -6,9 +6,9 @@ public enum DistributionMode implements IStringSerializable { - ROUND_ROBIN_GLOBAL("cover.conveyor.distribution.round_robin_enhanced"), - ROUND_ROBIN_PRIO("cover.conveyor.distribution.round_robin"), - INSERT_FIRST("cover.conveyor.distribution.first_insert"); + EQUALIZED("cover.generic.distribution.equalized"), + ROUND_ROBIN("cover.generic.distribution.round_robin"), + FLOOD("cover.generic.distribution.flood"); public static final DistributionMode[] VALUES = values(); public final String localeName; diff --git a/src/main/java/gregtech/common/covers/TransferMode.java b/src/main/java/gregtech/common/covers/TransferMode.java index 2f278c88ce4..e02d7ade929 100644 --- a/src/main/java/gregtech/common/covers/TransferMode.java +++ b/src/main/java/gregtech/common/covers/TransferMode.java @@ -6,17 +6,19 @@ public enum TransferMode implements IStringSerializable { - TRANSFER_ANY("cover.robotic_arm.transfer_mode.transfer_any", 1), - TRANSFER_EXACT("cover.robotic_arm.transfer_mode.transfer_exact", 1024), - KEEP_EXACT("cover.robotic_arm.transfer_mode.keep_exact", Integer.MAX_VALUE); + TRANSFER_ANY("cover.robotic_arm.transfer_mode.transfer_any", 1, 1), + TRANSFER_EXACT("cover.robotic_arm.transfer_mode.transfer_exact", 1024, 163840), + KEEP_EXACT("cover.robotic_arm.transfer_mode.keep_exact", Integer.MAX_VALUE, Integer.MAX_VALUE); public static final TransferMode[] VALUES = values(); public final String localeName; public final int maxStackSize; + public final int maxFluidStackSize; - TransferMode(String localeName, int maxStackSize) { + TransferMode(String localeName, int maxStackSize, int maxFluidStackSize) { this.localeName = localeName; this.maxStackSize = maxStackSize; + this.maxFluidStackSize = maxFluidStackSize; } @NotNull diff --git a/src/main/java/gregtech/common/covers/filter/MergabilityInfo.java b/src/main/java/gregtech/common/covers/filter/MergabilityInfo.java new file mode 100644 index 00000000000..16f6343196a --- /dev/null +++ b/src/main/java/gregtech/common/covers/filter/MergabilityInfo.java @@ -0,0 +1,66 @@ +package gregtech.common.covers.filter; + +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +import net.minecraft.item.ItemStack; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.alg.util.Pair; + +import java.util.Comparator; +import java.util.List; + +public final class MergabilityInfo { + + private final Object2ObjectOpenHashMap mergeMap = new Object2ObjectOpenHashMap<>(); + + public void add(int handlerSlot, T testObject, int count) { + mergeMap.compute(testObject, (k , v) -> { + if (v == null) v = new Merge(k); + v.count += count; + v.handlerSlots.add(handlerSlot); + return v; + }); + } + + public Merge getLargestMerge() { + return mergeMap.values().stream().max(Comparator.comparingInt(Merge::getCount)).orElse(null); + } + + public @NotNull List getNonLargestMerges(@Nullable Merge largestMerge) { + List merges = new ObjectArrayList<>(mergeMap.values()); + merges.remove(largestMerge == null ? getLargestMerge() : largestMerge); + return merges; + } + + public final class Merge { + private final T testObject; + + private int count = 0; + private final IntList handlerSlots = new IntArrayList(); + + public Merge(T testObject) { + this.testObject = testObject; + } + + public int getCount() { + return count; + } + + public T getTestObject() { + return testObject; + } + + public IntList getHandlerSlots() { + return handlerSlots; + } + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index 1e8c5b40f15..a431be17c72 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -46,7 +46,7 @@ public EnergyTraverseData(IGraphNet net, IPredicateTestObject testObject, Simula } @Override - public boolean prepareForPathWalk(FlowWorldPipeNetPath path, long flow) { + public boolean prepareForPathWalk(@NotNull FlowWorldPipeNetPath path, long flow) { if (flow <= 0) return true; this.pathVoltage = startVoltage; this.overVoltageInformation.clear(); @@ -55,7 +55,7 @@ public boolean prepareForPathWalk(FlowWorldPipeNetPath path, long flow) { } @Override - public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowReachingNode) { + public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, long flowReachingNode) { VoltageLimitLogic limitLogic = node.getData().getLogicEntryNullable(VoltageLimitLogic.INSTANCE); if (limitLogic != null) { long voltage = limitLogic.getValue(); @@ -92,7 +92,7 @@ public void handleOverflow(WorldPipeNetNode node, long overflow) { } @Override - public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachingDestination) { + public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { this.pathVoltage = (long) GTUtility.geometricMean(pathVoltage, overVoltageInformation.values().stream().filter(o -> o.voltageCap < this.pathVoltage) .mapToDouble(o -> (double) o.voltageCap).toArray()); diff --git a/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java b/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java index f23a6d67bea..628c5c3eec9 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java @@ -1,8 +1,8 @@ package gregtech.common.pipelike.net.energy; import gregtech.api.capability.IEnergyContainer; -import gregtech.api.graphnet.pipenet.insertion.TransferControl; -import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.pipenet.transfer.TransferControl; +import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index 118dd298e10..ad029234483 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -10,9 +10,14 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.graphnet.traverse.ITraverseData; +import gregtech.api.graphnet.traverse.TraverseDataProvider; +import gregtech.api.graphnet.traverse.TraverseGuide; import gregtech.api.graphnet.traverse.TraverseHelpers; import gregtech.common.pipelike.net.energy.WorldEnergyNet; +import gregtech.common.pipelike.net.item.ItemCapabilityObject; + import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.FluidStack; @@ -27,8 +32,9 @@ import java.util.Arrays; import java.util.EnumMap; import java.util.Iterator; +import java.util.function.LongConsumer; -public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler, IFluidTankProperties { +public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler, IFluidTankProperties, IFluidTraverseGuideProvider { private final WorldPipeNet net; private @Nullable PipeTileEntity tile; @@ -60,7 +66,7 @@ private boolean inputDisallowed(EnumFacing side) { else return tile.isBlocked(side); } - private Iterator getPaths(FluidTraverseData data) { + private Iterator getPaths(@NotNull ITraverseData data) { assert tile != null; return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), data.getQueryTick()); @@ -90,32 +96,47 @@ public int fill(FluidStack resource, boolean doFill) { } public int fill(FluidStack resource, boolean doFill, EnumFacing side) { - if (tile == null || this.transferring || inputDisallowed(side)) return 0; + if (this.transferring) return 0; this.transferring = true; - SimulatorKey simulator = null; - if (!doFill) simulator = SimulatorKey.getNewSimulatorInstance(); - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + var guide = getGuide(FluidTraverseData::new, new FluidTestObject(resource), resource.amount, !doFill, side); + if (guide == null) return 0; + int accepted = (int) TraverseHelpers.traverseFlood(guide.getData(), guide.getPaths(), guide.getFlow()); - FluidTestObject testObject = new FluidTestObject(resource); + this.transferring = false; + return accepted; + } - AbstractNetFlowEdge internalBuffer = this.wrappers.get(side).getBuffer(); - long allowed = resource.amount; - if (internalBuffer != null) { - long limit = internalBuffer.getFlowLimit(testObject, net, tick, simulator); - if (limit <= 0) { - this.transferring = false; - return 0; - } - allowed = Math.min(limit, allowed); - } + @Override + public @Nullable > TraverseGuide getGuide( + TraverseDataProvider provider, FluidTestObject testObject, long flow, + boolean simulate) { + return getGuide(provider, testObject, flow, simulate, null); + } - FluidTraverseData data = new FluidTraverseData(net, testObject, simulator, tick, tile.getPos(), side); - long accepted = TraverseHelpers.traverseFlood(data, getPaths(data), allowed); + public @Nullable > TraverseGuide getGuide( + TraverseDataProvider provider, FluidTestObject testObject, long flow, + boolean simulate, EnumFacing side) { + if (tile == null || inputDisallowed(side)) return null; + SimulatorKey simulator = simulate ? SimulatorKey.getNewSimulatorInstance() : null; + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - if (internalBuffer != null) internalBuffer.consumeFlowLimit(testObject, net, accepted, tick, simulator); - this.transferring = false; - return (int) accepted; + LongConsumer flowReport = null; + Wrapper wrapper = this.wrappers.get(side); + if (wrapper != null) { + AbstractNetFlowEdge internalBuffer = wrapper.getBuffer(); + if (internalBuffer != null) { + long limit = internalBuffer.getFlowLimit(testObject, net, tick, simulator); + if (limit <= 0) { + this.transferring = false; + return null; + } + flow = Math.min(limit, flow); + flowReport = l -> internalBuffer.consumeFlowLimit(testObject, net, l, tick, simulator); + } + } + D data = provider.of(net, testObject, simulator, tick, tile.getPos(), side); + return new TraverseGuide<>(data, () -> getPaths(data), flow, flowReport); } @Override @@ -163,7 +184,7 @@ public boolean canDrainFluidType(FluidStack fluidStack) { return false; } - protected class Wrapper implements IFluidHandler, IFluidTankProperties { + protected class Wrapper implements IFluidHandler, IFluidTankProperties, IFluidTraverseGuideProvider { private final EnumFacing facing; private final AbstractNetFlowEdge buffer; @@ -176,6 +197,13 @@ public Wrapper(EnumFacing facing, AbstractNetFlowEdge buffer) { Arrays.fill(properties, this); } + @Override + public @Nullable > TraverseGuide getGuide( + TraverseDataProvider provider, FluidTestObject testObject, long flow, + boolean simulate) { + return FluidCapabilityObject.this.getGuide(provider, testObject, flow, simulate, facing); + } + public AbstractNetFlowEdge getBuffer() { return buffer; } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java new file mode 100644 index 00000000000..59880946aa7 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java @@ -0,0 +1,66 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.graphnet.traverse.IEqualizableTraverseData; + +import gregtech.api.util.GTUtility; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; + +import org.jetbrains.annotations.NotNull; + +public class FluidEQTraverseData extends FluidTraverseData implements IEqualizableTraverseData { + + protected int destCount; + protected int maxMinFlow; + + public FluidEQTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing) { + super(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } + + protected void compute(@NotNull WorldPipeNetNode destination) { + this.destCount = 0; + this.maxMinFlow = 0; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IFluidHandler container = capability.getValue() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + if (destCount == 0) maxMinFlow = Integer.MAX_VALUE; + destCount += 1; + maxMinFlow = Math.min(maxMinFlow, + IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), Integer.MAX_VALUE, + container, false)); + } + } + } + + @Override + public int getDestinationsAtNode(@NotNull WorldPipeNetNode node) { + return destCount; + } + + @Override + public boolean shouldSkipPath(@NotNull FlowWorldPipeNetPath path) { + compute(path.getTargetNode()); + return maxMinFlow == 0; + } + + @Override + public long getMaxFlowToLeastDestination(@NotNull WorldPipeNetNode destination) { + return maxMinFlow; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java new file mode 100644 index 00000000000..6f862e6d29c --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java @@ -0,0 +1,36 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.graphnet.traverse.IRoundRobinTraverseData; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayDeque; + +public class FluidRRTraverseData extends FluidTraverseData implements IRoundRobinTraverseData { + + private final ArrayDeque cache; + + public FluidRRTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing, @NotNull ArrayDeque cache) { + super(net, testObject, simulator, queryTick, sourcePos, inputFacing); + this.cache = cache; + } + + @Override + public @NotNull ArrayDeque getTraversalCache() { + return cache; + } + + @Override + public boolean shouldSkipPath(FlowWorldPipeNetPath path) { + return false; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index 70dec1cbab5..aabbc6bdf61 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -41,10 +41,10 @@ public class FluidTraverseData extends AbstractTraverseData temperatureUpdates = new Object2ObjectOpenHashMap<>(); + protected final Object2ObjectOpenHashMap temperatureUpdates = new Object2ObjectOpenHashMap<>(); public FluidTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { @@ -59,7 +59,7 @@ public FluidTestObject getTestObject() { } @Override - public boolean prepareForPathWalk(FlowWorldPipeNetPath path, long flow) { + public boolean prepareForPathWalk(@NotNull FlowWorldPipeNetPath path, long flow) { if (flow <= 0) return true; temperatureUpdates.clear(); temperatureUpdates.trim(16); @@ -67,7 +67,7 @@ public boolean prepareForPathWalk(FlowWorldPipeNetPath path, long flow) { } @Override - public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowReachingNode) { + public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, long flowReachingNode) { NodeLossCache.Key key = NodeLossCache.key(node, this); NodeLossResult result = NodeLossCache.getLossResult(key); if (result != null) { @@ -142,7 +142,7 @@ public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowRea } @Override - public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachingDestination) { + public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { long availableFlow = flowReachingDestination; for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java index cc5451a97fc..e5e1e1f3ed6 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java @@ -1,8 +1,8 @@ package gregtech.common.pipelike.net.fluid; -import gregtech.api.graphnet.pipenet.insertion.TransferControl; +import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.predicate.test.FluidTestObject; import net.minecraftforge.fluids.FluidStack; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java new file mode 100644 index 00000000000..89e08a61e4a --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java @@ -0,0 +1,20 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.graphnet.traverse.ITraverseData; +import gregtech.api.graphnet.traverse.ITraverseGuideProvider; +import gregtech.api.graphnet.traverse.TraverseDataProvider; +import gregtech.api.graphnet.traverse.TraverseGuide; + +import org.jetbrains.annotations.Nullable; + +public interface IFluidTraverseGuideProvider extends ITraverseGuideProvider { + + @Nullable + @Override + > TraverseGuide getGuide( + TraverseDataProvider provider, FluidTestObject testObject, long flow, boolean simulate); +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java b/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java index cafa0e779c7..462437b570f 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java +++ b/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java @@ -1,7 +1,7 @@ package gregtech.common.pipelike.net.item; -import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; -import gregtech.api.graphnet.pipenet.insertion.TransferControl; +import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; +import gregtech.api.graphnet.pipenet.transfer.TransferControl; import gregtech.api.graphnet.predicate.test.ItemTestObject; @@ -51,11 +51,12 @@ public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, */ default int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, boolean simulate) { + int available = amount; for (int i = 0; i < destHandler.getSlots(); i++) { - int allowed = Math.min(amount, Math.min(destHandler.getSlotLimit(i), testObject.getStackLimit())); - amount = destHandler.insertItem(i, testObject.recombine(allowed), simulate).getCount(); + int allowed = Math.min(available, Math.min(destHandler.getSlotLimit(i), testObject.getStackLimit())); + available -= allowed - destHandler.insertItem(i, testObject.recombine(allowed), simulate).getCount(); } - return amount; + return available; } /** diff --git a/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java b/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java new file mode 100644 index 00000000000..a955651d7e4 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java @@ -0,0 +1,19 @@ +package gregtech.common.pipelike.net.item; + +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.graphnet.traverse.ITraverseData; +import gregtech.api.graphnet.traverse.ITraverseGuideProvider; +import gregtech.api.graphnet.traverse.TraverseDataProvider; +import gregtech.api.graphnet.traverse.TraverseGuide; + +import org.jetbrains.annotations.Nullable; + +public interface IItemTraverseGuideProvider extends ITraverseGuideProvider { + + @Nullable + @Override + > TraverseGuide getGuide( + TraverseDataProvider provider, ItemTestObject testObject, long flow, boolean simulate); +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index f330419dd1e..c93539952c6 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -9,8 +9,10 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.graphnet.traverse.ITraverseData; +import gregtech.api.graphnet.traverse.TraverseDataProvider; +import gregtech.api.graphnet.traverse.TraverseGuide; import gregtech.api.graphnet.traverse.TraverseHelpers; -import gregtech.common.pipelike.net.energy.WorldEnergyNet; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; @@ -24,8 +26,9 @@ import java.util.EnumMap; import java.util.Iterator; +import java.util.function.LongConsumer; -public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler { +public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler, IItemTraverseGuideProvider { private final WorldPipeNet net; private @Nullable PipeTileEntity tile; @@ -54,7 +57,7 @@ private boolean inputDisallowed(EnumFacing side) { else return tile.isBlocked(side); } - private Iterator getPaths(ItemTraverseData data) { + private Iterator getPaths(@NotNull ITraverseData data) { assert tile != null; return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), data.getQueryTick()); @@ -79,33 +82,49 @@ public T getCapabilityForSide(Capability capability, @Nullable EnumFacing } public @NotNull ItemStack insertItem(@NotNull ItemStack stack, boolean simulate, EnumFacing side) { - if (tile == null || this.transferring || inputDisallowed(side)) return stack; + if (this.transferring) return stack; this.transferring = true; - SimulatorKey simulator = null; - if (simulate) simulator = SimulatorKey.getNewSimulatorInstance(); - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + var guide = getGuide(ItemTraverseData::new, new ItemTestObject(stack), stack.getCount(), simulate, side); + if (guide == null) return stack; + int consumed = (int) TraverseHelpers.traverseFlood(guide.getData(), guide.getPaths(), guide.getFlow()); + guide.reportConsumedFlow(consumed); - ItemTestObject testObject = new ItemTestObject(stack); + this.transferring = false; + return guide.getData().getTestObject().recombine(stack.getCount() - consumed); + } - AbstractNetFlowEdge internalBuffer = this.wrappers.get(side).getBuffer(); - int available = stack.getCount(); - if (internalBuffer != null) { - long limit = internalBuffer.getFlowLimit(testObject, net, tick, simulator); - if (limit <= 0) { - this.transferring = false; - return stack; - } - available = (int) Math.min(limit, available); - } + @Nullable + @Override + public > TraverseGuide getGuide( + TraverseDataProvider provider, ItemTestObject testObject, long flow, boolean simulate) { + return getGuide(provider, testObject, flow, simulate, null); + } - ItemTraverseData data = new ItemTraverseData(net, testObject, simulator, tick, tile.getPos(), side); - available = (int) TraverseHelpers.traverseFlood(data, getPaths(data), available); + @Nullable + protected > TraverseGuide getGuide( + TraverseDataProvider provider, ItemTestObject testObject, long flow, boolean simulate, EnumFacing side) { + if (tile == null || inputDisallowed(side)) return null; - if (internalBuffer != null) - internalBuffer.consumeFlowLimit(testObject, net, stack.getCount() - available, tick, simulator); - this.transferring = false; - return testObject.recombine(available); + SimulatorKey simulator = simulate ? SimulatorKey.getNewSimulatorInstance() : null; + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + + LongConsumer flowReport = null; + Wrapper wrapper = this.wrappers.get(side); + if (wrapper != null) { + AbstractNetFlowEdge internalBuffer = wrapper.getBuffer(); + if (internalBuffer != null) { + long limit = internalBuffer.getFlowLimit(testObject, net, tick, simulator); + if (limit <= 0) { + this.transferring = false; + return null; + } + flow = Math.min(limit, flow); + flowReport = l -> internalBuffer.consumeFlowLimit(testObject, net, l, tick, simulator); + } + } + D data = provider.of(net, testObject, simulator, tick, tile.getPos(), side); + return new TraverseGuide<>(data, () -> getPaths(data), flow, flowReport); } @Override @@ -133,7 +152,7 @@ public int getSlotLimit(int slot) { return 64; } - protected class Wrapper implements IItemHandler { + protected class Wrapper implements IItemHandler, IItemTraverseGuideProvider { private final EnumFacing facing; private final AbstractNetFlowEdge buffer; @@ -143,6 +162,14 @@ public Wrapper(EnumFacing facing, AbstractNetFlowEdge buffer) { this.buffer = buffer; } + @Nullable + @Override + public > TraverseGuide getGuide( + TraverseDataProvider provider, ItemTestObject testObject, long flow, + boolean simulate) { + return ItemCapabilityObject.this.getGuide(provider, testObject, flow, simulate, facing); + } + public AbstractNetFlowEdge getBuffer() { return buffer; } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java new file mode 100644 index 00000000000..94e9794ad76 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java @@ -0,0 +1,66 @@ +package gregtech.common.pipelike.net.item; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.graphnet.traverse.IEqualizableTraverseData; + +import gregtech.api.util.GTUtility; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; + +import org.jetbrains.annotations.NotNull; + +public class ItemEQTraverseData extends ItemTraverseData implements IEqualizableTraverseData { + + protected int destCount; + protected int maxMinFlow; + + public ItemEQTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing) { + super(net, testObject, simulator, queryTick, sourcePos, inputFacing); + } + + protected void compute(@NotNull WorldPipeNetNode destination) { + this.destCount = 0; + this.maxMinFlow = 0; + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IItemHandler container = capability.getValue() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + if (destCount == 0) maxMinFlow = Integer.MAX_VALUE; + destCount += 1; + int test = Integer.MAX_VALUE; + maxMinFlow = Math.min(maxMinFlow, test - + IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), test, + container, true)); + } + } + } + + @Override + public int getDestinationsAtNode(@NotNull WorldPipeNetNode node) { + return destCount; + } + + @Override + public boolean shouldSkipPath(@NotNull FlowWorldPipeNetPath path) { + compute(path.getTargetNode()); + return maxMinFlow == 0; + } + + @Override + public long getMaxFlowToLeastDestination(@NotNull WorldPipeNetNode destination) { + return maxMinFlow; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java new file mode 100644 index 00000000000..2b7b1db92c2 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java @@ -0,0 +1,36 @@ +package gregtech.common.pipelike.net.item; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.graphnet.traverse.IRoundRobinTraverseData; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayDeque; + +public class ItemRRTraverseData extends ItemTraverseData implements IRoundRobinTraverseData { + + private final ArrayDeque cache; + + public ItemRRTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, + BlockPos sourcePos, EnumFacing inputFacing, @NotNull ArrayDeque cache) { + super(net, testObject, simulator, queryTick, sourcePos, inputFacing); + this.cache = cache; + } + + @Override + public @NotNull ArrayDeque getTraversalCache() { + return cache; + } + + @Override + public boolean shouldSkipPath(FlowWorldPipeNetPath path) { + return false; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java index 19c773820f3..05676341359 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java @@ -14,10 +14,12 @@ import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; +import org.jetbrains.annotations.NotNull; + public class ItemTraverseData extends AbstractTraverseData { - private final BlockPos sourcePos; - private final EnumFacing inputFacing; + protected final BlockPos sourcePos; + protected final EnumFacing inputFacing; public ItemTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { @@ -32,17 +34,17 @@ public ItemTestObject getTestObject() { } @Override - public boolean prepareForPathWalk(FlowWorldPipeNetPath path, long flow) { + public boolean prepareForPathWalk(@NotNull FlowWorldPipeNetPath path, long flow) { return flow <= 0; } @Override - public ReversibleLossOperator traverseToNode(WorldPipeNetNode node, long flowReachingNode) { + public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, long flowReachingNode) { return ReversibleLossOperator.IDENTITY; } @Override - public long finalizeAtDestination(WorldPipeNetNode destination, long flowReachingDestination) { + public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { long availableFlow = flowReachingDestination; for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index a6e0e5c9146..50ab0def139 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -6,6 +6,7 @@ import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.edge.NetFlowSharedEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNet; diff --git a/src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java b/src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java index 5376b172f16..4ef8b2b87ab 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java @@ -1,8 +1,8 @@ package gregtech.common.pipelike.net.laser; import gregtech.api.capability.ILaserRelay; -import gregtech.api.graphnet.pipenet.insertion.TransferControl; -import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.pipenet.transfer.TransferControl; +import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java b/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java index c5fc7a3c878..d44f58cbd00 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java @@ -2,8 +2,8 @@ import gregtech.api.capability.data.IDataAccess; import gregtech.api.capability.data.query.DataQueryObject; -import gregtech.api.graphnet.pipenet.insertion.TransferControl; -import gregtech.api.graphnet.pipenet.insertion.TransferControlProvider; +import gregtech.api.graphnet.pipenet.transfer.TransferControl; +import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 381b50156e0..fe7740b558e 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -1297,15 +1297,15 @@ cover.smart_item_filter.filtering_mode.description=Select Machine this Smart Fil cover.generic.transfer_mode=Transfer Mode cover.generic.manual_io=Manual IO Mode cover.generic.io=IO Mode +cover.generic.distribution.name=Distribution Mode +cover.generic.distribution.equalized=§bEqual Distribution§r\n§7Fills all destinations by the same amount per operation. +cover.generic.distribution.round_robin=§bRound Robin§r\n§7Fills destinations in a fixed order, but performs no further equalization. +cover.generic.distribution.flood=§bFlood Insert§r\n§7Fills destinations based on their priorities, performing no further equalization. cover.pump.mode=Pump Mode cover.conveyor.title=Conveyor Cover Settings (%s) cover.conveyor.transfer_rate=§7items/sec cover.conveyor.mode.export=Mode: Export cover.conveyor.mode.import=Mode: Import -cover.conveyor.distribution.name=Distribution Mode -cover.conveyor.distribution.round_robin_enhanced=§bEnhanced Round Robin§r\n§7Splits items equally to all inventories -cover.conveyor.distribution.round_robin=§bRound Robin§r with Priority\n§7Tries to split items equally to inventories -cover.conveyor.distribution.first_insert=§bFirst Insert§r\n§7Will insert into the first inventory it finds cover.conveyor.blocks_input.enabled=If enabled, items will not be inserted when cover is set to pull items from the inventory into pipe./n§aEnabled cover.conveyor.blocks_input.disabled=If enabled, items will not be inserted when cover is set to pull items from the inventory into pipe./n§cDisabled cover.universal.manual_import_export.mode.disabled=Manual I/O: Disabled @@ -1334,7 +1334,6 @@ cover.bucket.mode.bucket_exact=kL cover.bucket.mode.milli_bucket_rate=L/s cover.bucket.mode.milli_bucket_exact=L cover.fluid_regulator.title=Fluid Regulator Settings (%s) -cover.fluid_regulator.transfer_mode.description=§eTransfer Any§r - in this mode, cover will transfer as many fluids matching its filter as possible./n§eSupply Exact§r - in this mode, cover will supply fluids in portions specified in the window underneath this button. If amount of fluids is less than portion size, fluids won't be moved./n§eKeep Exact§r - in this mode, cover will keep specified amount of fluids in the destination inventory, supplying additional amount of fluids if required./n§7Tip: shift click will multiply increase/decrease amounts by 10 and ctrl click will multiply by 100. cover.fluid_regulator.supply_exact=Supply Exact: %s cover.fluid_regulator.keep_exact=Keep Exact: %s diff --git a/src/test/java/gregtech/common/covers/CoverFluidRegulatorTest.java b/src/test/java/gregtech/common/covers/CoverFluidRegulatorTest.java index b5402ff0afa..291b241e02d 100644 --- a/src/test/java/gregtech/common/covers/CoverFluidRegulatorTest.java +++ b/src/test/java/gregtech/common/covers/CoverFluidRegulatorTest.java @@ -32,219 +32,219 @@ public static void bootstrap() { Bootstrap.perform(); } - @Test - public void doKeepExact_does_nothing_if_no_destination_tank_exists() { - // Create a regulator for testing with, and set it to "Keep Exact" mode - CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); - cfr.transferMode = TransferMode.KEEP_EXACT; - - FluidStack water = new FluidStack(FluidRegistry.WATER, 1234); - - // Source consists of only an output tank containing a bit of water - IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), - new FluidTankList(false, new FluidTank(water.copy(), 64000))); - - // Tell it to keep exact from a machine with an empty fluid tank and null target fluid tank - int amountTransferred = cfr.doKeepExact(1000, source, null, isWater, 1000); - - MatcherAssert.assertThat("Unexpectedly moved fluids, nothing is supposed to happen", amountTransferred, is(0)); - } - - @Test - public void doKeepExact_moves_one_fluid_into_an_empty_tank() { - // Create a regulator for testing with, and set it to "Keep Exact" mode - CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); - cfr.transferMode = TransferMode.KEEP_EXACT; - - FluidStack water = new FluidStack(FluidRegistry.WATER, 1234); - - IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), - new FluidTankList(false, new FluidTank(water.copy(), 64000))); - - // Dest consists of one empty input tank - IFluidHandler dest = new FluidHandlerProxy(new FluidTankList(false, new FluidTank(64000)), - new FluidTankList(false)); - - // Tell it to keep exact from a machine with an empty fluid tank and no target fluid tank - int amountTransferred = cfr.doKeepExact(1000, source, dest, isWater, 1000); - - MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(1000)); - } - - @Test - public void doKeepExact_moves_only_as_much_fluid_as_exists_in_the_source() { - // Create a regulator for testing with, and set it to "Keep Exact" mode - CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); - cfr.transferMode = TransferMode.KEEP_EXACT; - - IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 1234), 64000))); - - IFluidHandler dest = new FluidHandlerProxy(new FluidTankList(false, new FluidTank(64000)), - new FluidTankList(false)); - - int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 10000); - - MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(1234)); - } - - @Test - public void doKeepExact_moves_only_the_fluid_required_if_more_could_be_moved() { - CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); - cfr.transferMode = TransferMode.KEEP_EXACT; - - IFluidHandler source = new FluidHandlerProxy( - new FluidTankList(false), - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000))); - - IFluidHandler dest = new FluidHandlerProxy( - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000)), - new FluidTankList(false)); - - int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 144); - - MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(44)); - } - - @Test - public void doKeepExact_moves_multiple_valid_fluids() { - // Create a regulator for testing with, and set it to "Keep Exact" mode - CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); - cfr.transferMode = TransferMode.KEEP_EXACT; - - IFluidHandler source = new FluidHandlerProxy( - new FluidTankList(false), - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), - new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); - - // One tank with 100mB water, another with nothing - IFluidHandler dest = new FluidHandlerProxy( - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000), - new FluidTank(64000)), - new FluidTankList(false)); - - // accept any fluid this time - int amountTransferred = cfr.doKeepExact(10000, source, dest, fs -> true, 144); - - // expect that 44mB of water and 144mB of lava will be moved - MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(44 + 144)); - - // verify final fluid quantities - MatcherAssert.assertThat(dest.getTankProperties().length, is(2)); - IFluidTankProperties tank1 = dest.getTankProperties()[0]; - IFluidTankProperties tank2 = dest.getTankProperties()[1]; - MatcherAssert.assertThat(tank1.getContents(), notNullValue()); - MatcherAssert.assertThat(tank2.getContents(), notNullValue()); - MatcherAssert.assertThat(tank1.getContents().isFluidStackIdentical(new FluidStack(FluidRegistry.WATER, 144)), - is(true)); - MatcherAssert.assertThat(tank2.getContents().isFluidStackIdentical(new FluidStack(FluidRegistry.LAVA, 144)), - is(true)); - } - - @Test - public void doKeepExact_respects_transfer_limit_with_one_fluid() { - // Create a regulator for testing with, and set it to "Keep Exact" mode - CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); - cfr.transferMode = TransferMode.KEEP_EXACT; - - // One output tank full of water - IFluidHandler source = new FluidHandlerProxy( - new FluidTankList(false), - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000))); - - // One input tank with nothing in it - IFluidHandler dest = new FluidHandlerProxy( - new FluidTankList(false, new FluidTank(64000)), - new FluidTankList(false)); - - // accept any fluid this time - int amountTransferred = cfr.doKeepExact(100, source, dest, fs -> true, 144); - - // expect that at most 100mB of fluids total will be moved this tick, as if possible it would do 144mB - MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(100)); - } - - @Test - public void doKeepExact_respects_transfer_limit_with_multiple_fluids() { - // Create a regulator for testing with, and set it to "Keep Exact" mode - CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); - cfr.transferMode = TransferMode.KEEP_EXACT; - - IFluidHandler source = new FluidHandlerProxy( - new FluidTankList(false), - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), - new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); - - // One tank with 100mB water, another with nothing - IFluidHandler dest = new FluidHandlerProxy( - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000), - new FluidTank(64000)), - new FluidTankList(false)); - - // accept any fluid this time - int amountTransferred = cfr.doKeepExact(100, source, dest, fs -> true, 144); - - // expect that at most 100mB of fluids total will be moved this tick, as if possible it would do 188mB - MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(100)); - } - - @Test - public void doKeepExact_does_nothing_if_levels_are_already_correct_in_dest() { - // Create a regulator for testing with, and set it to "Keep Exact" mode - CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); - cfr.transferMode = TransferMode.KEEP_EXACT; - - IFluidHandler source = new FluidHandlerProxy( - new FluidTankList(false), - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), - new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); - - // One tank with 144mB water, another with 144mB lava - IFluidHandler dest = new FluidHandlerProxy( - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 144), 64000), - new FluidTank(new FluidStack(FluidRegistry.LAVA, 144), 64000)), - new FluidTankList(false)); - - // accept any fluid this time - int amountTransferred = cfr.doKeepExact(10000, source, dest, fs -> true, 144); - - // expect that no fluids are moved because Keep Exact levels are already met - MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(0)); - } - - @Test - public void doKeepExact_ignores_fluids_not_in_filter() { - // Create a regulator for testing with, and set it to "Keep Exact" mode - CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); - cfr.transferMode = TransferMode.KEEP_EXACT; - - IFluidHandler source = new FluidHandlerProxy( - new FluidTankList(false), - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), - new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); - - // One tank with 144mB water, another with 100mB lava - IFluidHandler dest = new FluidHandlerProxy( - new FluidTankList(false, - new FluidTank(new FluidStack(FluidRegistry.WATER, 144), 64000), - new FluidTank(new FluidStack(FluidRegistry.LAVA, 100), 64000)), - new FluidTankList(false)); - - // accept any fluid this time - int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 144); - - // expect that no fluids are moved because already have enough water and lava isn't in the filter - MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(0)); - } +// @Test +// public void doKeepExact_does_nothing_if_no_destination_tank_exists() { +// // Create a regulator for testing with, and set it to "Keep Exact" mode +// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); +// cfr.transferMode = TransferMode.KEEP_EXACT; +// +// FluidStack water = new FluidStack(FluidRegistry.WATER, 1234); +// +// // Source consists of only an output tank containing a bit of water +// IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), +// new FluidTankList(false, new FluidTank(water.copy(), 64000))); +// +// // Tell it to keep exact from a machine with an empty fluid tank and null target fluid tank +// int amountTransferred = cfr.doKeepExact(1000, source, null, isWater, 1000); +// +// MatcherAssert.assertThat("Unexpectedly moved fluids, nothing is supposed to happen", amountTransferred, is(0)); +// } +// +// @Test +// public void doKeepExact_moves_one_fluid_into_an_empty_tank() { +// // Create a regulator for testing with, and set it to "Keep Exact" mode +// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); +// cfr.transferMode = TransferMode.KEEP_EXACT; +// +// FluidStack water = new FluidStack(FluidRegistry.WATER, 1234); +// +// IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), +// new FluidTankList(false, new FluidTank(water.copy(), 64000))); +// +// // Dest consists of one empty input tank +// IFluidHandler dest = new FluidHandlerProxy(new FluidTankList(false, new FluidTank(64000)), +// new FluidTankList(false)); +// +// // Tell it to keep exact from a machine with an empty fluid tank and no target fluid tank +// int amountTransferred = cfr.doKeepExact(1000, source, dest, isWater, 1000); +// +// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(1000)); +// } +// +// @Test +// public void doKeepExact_moves_only_as_much_fluid_as_exists_in_the_source() { +// // Create a regulator for testing with, and set it to "Keep Exact" mode +// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); +// cfr.transferMode = TransferMode.KEEP_EXACT; +// +// IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 1234), 64000))); +// +// IFluidHandler dest = new FluidHandlerProxy(new FluidTankList(false, new FluidTank(64000)), +// new FluidTankList(false)); +// +// int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 10000); +// +// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(1234)); +// } +// +// @Test +// public void doKeepExact_moves_only_the_fluid_required_if_more_could_be_moved() { +// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); +// cfr.transferMode = TransferMode.KEEP_EXACT; +// +// IFluidHandler source = new FluidHandlerProxy( +// new FluidTankList(false), +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000))); +// +// IFluidHandler dest = new FluidHandlerProxy( +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000)), +// new FluidTankList(false)); +// +// int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 144); +// +// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(44)); +// } +// +// @Test +// public void doKeepExact_moves_multiple_valid_fluids() { +// // Create a regulator for testing with, and set it to "Keep Exact" mode +// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); +// cfr.transferMode = TransferMode.KEEP_EXACT; +// +// IFluidHandler source = new FluidHandlerProxy( +// new FluidTankList(false), +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), +// new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); +// +// // One tank with 100mB water, another with nothing +// IFluidHandler dest = new FluidHandlerProxy( +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000), +// new FluidTank(64000)), +// new FluidTankList(false)); +// +// // accept any fluid this time +// int amountTransferred = cfr.doKeepExact(10000, source, dest, fs -> true, 144); +// +// // expect that 44mB of water and 144mB of lava will be moved +// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(44 + 144)); +// +// // verify final fluid quantities +// MatcherAssert.assertThat(dest.getTankProperties().length, is(2)); +// IFluidTankProperties tank1 = dest.getTankProperties()[0]; +// IFluidTankProperties tank2 = dest.getTankProperties()[1]; +// MatcherAssert.assertThat(tank1.getContents(), notNullValue()); +// MatcherAssert.assertThat(tank2.getContents(), notNullValue()); +// MatcherAssert.assertThat(tank1.getContents().isFluidStackIdentical(new FluidStack(FluidRegistry.WATER, 144)), +// is(true)); +// MatcherAssert.assertThat(tank2.getContents().isFluidStackIdentical(new FluidStack(FluidRegistry.LAVA, 144)), +// is(true)); +// } +// +// @Test +// public void doKeepExact_respects_transfer_limit_with_one_fluid() { +// // Create a regulator for testing with, and set it to "Keep Exact" mode +// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); +// cfr.transferMode = TransferMode.KEEP_EXACT; +// +// // One output tank full of water +// IFluidHandler source = new FluidHandlerProxy( +// new FluidTankList(false), +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000))); +// +// // One input tank with nothing in it +// IFluidHandler dest = new FluidHandlerProxy( +// new FluidTankList(false, new FluidTank(64000)), +// new FluidTankList(false)); +// +// // accept any fluid this time +// int amountTransferred = cfr.doKeepExact(100, source, dest, fs -> true, 144); +// +// // expect that at most 100mB of fluids total will be moved this tick, as if possible it would do 144mB +// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(100)); +// } +// +// @Test +// public void doKeepExact_respects_transfer_limit_with_multiple_fluids() { +// // Create a regulator for testing with, and set it to "Keep Exact" mode +// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); +// cfr.transferMode = TransferMode.KEEP_EXACT; +// +// IFluidHandler source = new FluidHandlerProxy( +// new FluidTankList(false), +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), +// new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); +// +// // One tank with 100mB water, another with nothing +// IFluidHandler dest = new FluidHandlerProxy( +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000), +// new FluidTank(64000)), +// new FluidTankList(false)); +// +// // accept any fluid this time +// int amountTransferred = cfr.doKeepExact(100, source, dest, fs -> true, 144); +// +// // expect that at most 100mB of fluids total will be moved this tick, as if possible it would do 188mB +// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(100)); +// } +// +// @Test +// public void doKeepExact_does_nothing_if_levels_are_already_correct_in_dest() { +// // Create a regulator for testing with, and set it to "Keep Exact" mode +// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); +// cfr.transferMode = TransferMode.KEEP_EXACT; +// +// IFluidHandler source = new FluidHandlerProxy( +// new FluidTankList(false), +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), +// new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); +// +// // One tank with 144mB water, another with 144mB lava +// IFluidHandler dest = new FluidHandlerProxy( +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 144), 64000), +// new FluidTank(new FluidStack(FluidRegistry.LAVA, 144), 64000)), +// new FluidTankList(false)); +// +// // accept any fluid this time +// int amountTransferred = cfr.doKeepExact(10000, source, dest, fs -> true, 144); +// +// // expect that no fluids are moved because Keep Exact levels are already met +// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(0)); +// } +// +// @Test +// public void doKeepExact_ignores_fluids_not_in_filter() { +// // Create a regulator for testing with, and set it to "Keep Exact" mode +// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); +// cfr.transferMode = TransferMode.KEEP_EXACT; +// +// IFluidHandler source = new FluidHandlerProxy( +// new FluidTankList(false), +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), +// new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); +// +// // One tank with 144mB water, another with 100mB lava +// IFluidHandler dest = new FluidHandlerProxy( +// new FluidTankList(false, +// new FluidTank(new FluidStack(FluidRegistry.WATER, 144), 64000), +// new FluidTank(new FluidStack(FluidRegistry.LAVA, 100), 64000)), +// new FluidTankList(false)); +// +// // accept any fluid this time +// int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 144); +// +// // expect that no fluids are moved because already have enough water and lava isn't in the filter +// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(0)); +// } } From 695a1ab6ea833bd4d4ef03d2ab9554ffc1857087 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 10 Aug 2024 21:12:12 -0600 Subject: [PATCH 091/157] Spotless --- .../data/query/DataAccessFormat.java | 12 +- .../impl/LaserContainerHandler.java | 5 +- src/main/java/gregtech/api/cover/Cover.java | 3 +- .../java/gregtech/api/cover/CoverBase.java | 1 - .../gregtech/api/cover/CoverableView.java | 1 - .../cover/filter/CoverWithFluidFilter.java | 4 +- .../api/cover/filter/CoverWithItemFilter.java | 5 +- .../gregtech/api/graphnet/GraphNetBacker.java | 7 +- .../java/gregtech/api/graphnet/IGraphNet.java | 1 + .../api/graphnet/MultiNodeHelper.java | 2 +- .../java/gregtech/api/graphnet/NetGroup.java | 2 - .../java/gregtech/api/graphnet/NetNode.java | 1 - .../api/graphnet/alg/AlgorithmBuilder.java | 3 +- .../api/graphnet/alg/INetAlgorithm.java | 3 +- .../api/graphnet/alg/NetAlgorithmWrapper.java | 3 - .../graphnet/alg/ShortestPathsAlgorithm.java | 1 - .../api/graphnet/alg/SinglePathAlgorithm.java | 8 +- .../graphnet/alg/iter/IteratorFactory.java | 7 +- .../alg/iter/SimpleIteratorFactories.java | 9 +- .../api/graphnet/edge/NetFlowSharedEdge.java | 8 +- .../api/graphnet/graph/GraphEdge.java | 1 + .../logic/AbstractDoubleLogicData.java | 2 +- .../api/graphnet/logic/NetLogicData.java | 3 +- .../api/graphnet/logic/NetLogicEntry.java | 3 +- .../api/graphnet/logic/NetLogicRegistry.java | 2 +- .../graphnet/pipenet/IPipeNetNodeHandler.java | 3 +- .../api/graphnet/pipenet/WorldPipeNet.java | 26 +- .../graphnet/pipenet/WorldPipeNetNode.java | 2 - .../pipenet/logic/TemperatureLogic.java | 2 +- .../pipenet/physical/IPipeStructure.java | 4 +- .../physical/block/PipeActivableBlock.java | 2 - .../pipenet/physical/block/PipeBlock.java | 50 +- .../physical/block/PipeMaterialBlock.java | 2 - .../tile/PipeActivableTileEntity.java | 3 - .../physical/tile/PipeMaterialTileEntity.java | 2 - .../pipenet/physical/tile/PipeTileEntity.java | 12 +- .../pipenet/predicate/BlockedPredicate.java | 1 - .../pipenet/predicate/FilterPredicate.java | 5 - .../api/graphnet/predicate/EdgePredicate.java | 3 +- .../predicate/EdgePredicateHandler.java | 3 +- .../predicate/NetPredicateRegistry.java | 4 +- .../api/graphnet/servernet/ServerNet.java | 2 - .../traverse/ITraverseGuideProvider.java | 6 +- .../api/graphnet/traverse/TraverseGuide.java | 4 +- .../graphnet/traverse/TraverseHelpers.java | 4 +- .../api/graphnet/worldnet/WorldNet.java | 1 - .../properties/PipeNetProperties.java | 13 +- .../material/properties/WoodProperty.java | 2 - .../java/gregtech/api/util/GTUtility.java | 4 +- .../api/util/function/NullableSupplier.java | 3 +- .../renderer/handler/FacadeRenderer.java | 2 - .../renderer/pipe/AbstractPipeModel.java | 9 +- .../client/renderer/pipe/CableModel.java | 2 +- .../client/renderer/pipe/PipeItemModel.java | 21 +- .../client/renderer/pipe/PipeModel.java | 2 +- .../renderer/pipe/cache/ActivableSQC.java | 6 +- .../renderer/pipe/cache/BlockableSQC.java | 9 +- .../renderer/pipe/cache/ColorQuadCache.java | 4 +- .../renderer/pipe/cache/ExtraCappedSQC.java | 9 +- .../renderer/pipe/cache/RestrictiveSQC.java | 13 +- .../pipe/cache/StructureQuadCache.java | 4 +- .../renderer/pipe/cover/CoverRenderer.java | 4 +- .../pipe/cover/CoverRendererBuilder.java | 27 +- .../pipe/cover/CoverRendererPackage.java | 1 - .../pipe/quad/OverlayLayerDefinition.java | 3 +- .../renderer/pipe/quad/PipeQuadHelper.java | 10 +- .../client/renderer/pipe/quad/QuadHelper.java | 40 +- .../client/renderer/pipe/quad/UVMapper.java | 6 +- .../renderer/pipe/util/SpriteInformation.java | 1 + .../renderer/pipe/util/WoodCacheKey.java | 3 +- .../client/renderer/texture/Textures.java | 1 - .../gregtech/common/blocks/MetaBlocks.java | 3 +- .../gregtech/common/covers/CoverConveyor.java | 63 ++- .../covers/CoverDigitalInterfaceWireless.java | 2 +- .../gregtech/common/covers/CoverFacade.java | 8 +- .../common/covers/CoverFluidFilter.java | 5 +- .../common/covers/CoverFluidRegulator.java | 42 +- .../common/covers/CoverFluidVoiding.java | 1 - .../common/covers/CoverItemFilter.java | 3 +- .../gregtech/common/covers/CoverPump.java | 62 ++- .../common/covers/CoverRoboticArm.java | 34 +- .../gregtech/common/covers/CoverShutter.java | 1 - .../detector/CoverDetectorEnergyAdvanced.java | 4 +- .../common/covers/filter/MergabilityInfo.java | 9 +- .../pipelike/block/cable/CableBlock.java | 19 +- .../pipelike/block/laser/LaserStructure.java | 3 +- .../block/pipe/MaterialPipeBlock.java | 1 - .../block/pipe/MaterialPipeStructure.java | 42 +- .../pipelike/handlers/LaserNetHandler.java | 3 +- .../pipelike/handlers/OpticalNetHandler.java | 3 +- .../properties/MaterialEnergyProperties.java | 6 +- .../properties/MaterialFluidProperties.java | 3 +- .../properties/MaterialItemProperties.java | 5 +- .../common/pipelike/net/SlowActiveWalker.java | 25 +- .../pipelike/net/energy/EnergyFlowLogic.java | 11 +- .../net/energy/EnergyTraverseData.java | 3 +- .../net/energy/IEnergyTransferController.java | 2 +- .../net/fluid/FluidCapabilityObject.java | 37 +- .../net/fluid/FluidEQTraverseData.java | 10 +- .../net/fluid/FluidRRTraverseData.java | 3 +- .../pipelike/net/fluid/FluidTraverseData.java | 2 +- .../net/fluid/IFluidTransferController.java | 6 +- .../fluid/IFluidTraverseGuideProvider.java | 9 +- .../pipelike/net/fluid/WorldFluidNet.java | 14 +- .../net/item/IItemTransferController.java | 8 +- .../net/item/IItemTraverseGuideProvider.java | 8 +- .../net/item/ItemCapabilityObject.java | 20 +- .../pipelike/net/item/ItemEQTraverseData.java | 6 +- .../pipelike/net/item/ItemRRTraverseData.java | 3 +- .../pipelike/net/item/ItemTraverseData.java | 4 +- .../pipelike/net/item/WorldItemNet.java | 15 +- .../net/optical/DataCapabilityObject.java | 6 +- .../covers/CoverFluidRegulatorTest.java | 441 +++++++++--------- 113 files changed, 689 insertions(+), 703 deletions(-) diff --git a/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java b/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java index 4eef544d137..2232a15b1cb 100644 --- a/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java +++ b/src/main/java/gregtech/api/capability/data/query/DataAccessFormat.java @@ -1,9 +1,8 @@ package gregtech.api.capability.data.query; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraft.util.IStringSerializable; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -11,10 +10,13 @@ public final class DataAccessFormat implements IStringSerializable { - public static final DataAccessFormat STANDARD = create("gregtech.data_format.access.standard", DataQueryFormat.RECIPE); - public static final DataAccessFormat COMPUTATION = create("gregtech.data_format.access.computation", DataQueryFormat.COMPUTATION); + public static final DataAccessFormat STANDARD = create("gregtech.data_format.access.standard", + DataQueryFormat.RECIPE); + public static final DataAccessFormat COMPUTATION = create("gregtech.data_format.access.computation", + DataQueryFormat.COMPUTATION); - public static final DataAccessFormat UNIVERSAL = new DataAccessFormat("gregtech.data_format.access.universal", null); + public static final DataAccessFormat UNIVERSAL = new DataAccessFormat("gregtech.data_format.access.universal", + null); private final Set supportedFormats; diff --git a/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java b/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java index 06097aa38c6..a66aeb7d8e0 100644 --- a/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java +++ b/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java @@ -4,7 +4,6 @@ import gregtech.api.capability.ILaserContainer; import gregtech.api.capability.ILaserRelay; import gregtech.api.metatileentity.MetaTileEntity; - import gregtech.api.util.GTUtility; import net.minecraft.tileentity.TileEntity; @@ -30,11 +29,11 @@ public static LaserContainerHandler receiverContainer(MetaTileEntity tileEntity, @Override public long receiveLaser(long laserVoltage, long laserAmperage) { - long allowedAmps = getEnergyCanBeInserted() / laserVoltage; addEnergy(laserVoltage * allowedAmps); // over voltage explosion - if (laserVoltage > getInputVoltage()) getMetaTileEntity().doExplosion(GTUtility.getExplosionPower(laserVoltage)); + if (laserVoltage > getInputVoltage()) + getMetaTileEntity().doExplosion(GTUtility.getExplosionPower(laserVoltage)); return allowedAmps; } diff --git a/src/main/java/gregtech/api/cover/Cover.java b/src/main/java/gregtech/api/cover/Cover.java index 6b9194dafa3..bd21ef27753 100644 --- a/src/main/java/gregtech/api/cover/Cover.java +++ b/src/main/java/gregtech/api/cover/Cover.java @@ -250,7 +250,8 @@ void renderCoverPlate(@NotNull CCRenderState renderState, @NotNull Matrix4 trans @NotNull Cuboid6 plateBox, @NotNull BlockRenderLayer layer); @SideOnly(Side.CLIENT) - @NotNull CoverRenderer getRenderer(); + @NotNull + CoverRenderer getRenderer(); default boolean canRenderBackside() { return true; diff --git a/src/main/java/gregtech/api/cover/CoverBase.java b/src/main/java/gregtech/api/cover/CoverBase.java index 0fb02305c9d..dc2985c16f9 100644 --- a/src/main/java/gregtech/api/cover/CoverBase.java +++ b/src/main/java/gregtech/api/cover/CoverBase.java @@ -3,7 +3,6 @@ import gregtech.api.GTValues; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.client.renderer.pipe.cover.CoverRenderer; -import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; diff --git a/src/main/java/gregtech/api/cover/CoverableView.java b/src/main/java/gregtech/api/cover/CoverableView.java index ed9a89f5f86..8bebd97b26d 100644 --- a/src/main/java/gregtech/api/cover/CoverableView.java +++ b/src/main/java/gregtech/api/cover/CoverableView.java @@ -6,7 +6,6 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/cover/filter/CoverWithFluidFilter.java b/src/main/java/gregtech/api/cover/filter/CoverWithFluidFilter.java index 85737dbdc81..82d1057a1d3 100644 --- a/src/main/java/gregtech/api/cover/filter/CoverWithFluidFilter.java +++ b/src/main/java/gregtech/api/cover/filter/CoverWithFluidFilter.java @@ -5,12 +5,12 @@ import gregtech.common.covers.ManualImportExportMode; import gregtech.common.covers.filter.FluidFilterContainer; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface CoverWithFluidFilter extends Cover { - @Nullable FluidFilterContainer getFluidFilter(); + @Nullable + FluidFilterContainer getFluidFilter(); FluidFilterMode getFilterMode(); diff --git a/src/main/java/gregtech/api/cover/filter/CoverWithItemFilter.java b/src/main/java/gregtech/api/cover/filter/CoverWithItemFilter.java index f1b2b75f672..912947aa13e 100644 --- a/src/main/java/gregtech/api/cover/filter/CoverWithItemFilter.java +++ b/src/main/java/gregtech/api/cover/filter/CoverWithItemFilter.java @@ -1,17 +1,16 @@ package gregtech.api.cover.filter; import gregtech.api.cover.Cover; -import gregtech.common.covers.FluidFilterMode; import gregtech.common.covers.ItemFilterMode; import gregtech.common.covers.ManualImportExportMode; import gregtech.common.covers.filter.ItemFilterContainer; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface CoverWithItemFilter extends Cover { - @Nullable ItemFilterContainer getItemFilter(); + @Nullable + ItemFilterContainer getItemFilter(); ItemFilterMode getFilterMode(); diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index 572281a50d2..c17632193c1 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -1,7 +1,6 @@ package gregtech.api.graphnet; import gregtech.api.graphnet.alg.AlgorithmBuilder; -import gregtech.api.graphnet.alg.INetAlgorithm; import gregtech.api.graphnet.alg.NetAlgorithmWrapper; import gregtech.api.graphnet.alg.NetPathMapper; import gregtech.api.graphnet.alg.iter.IteratorFactory; @@ -24,7 +23,6 @@ import java.util.Collections; import java.util.Iterator; -import java.util.function.Function; /** * The bridge between JGraphT graphs and graphnet abstractions. @@ -39,12 +37,13 @@ public final class GraphNetBacker { private final NetAlgorithmWrapper[] netAlgorithms; public GraphNetBacker(IGraphNet backedNet, INetGraph graph, - AlgorithmBuilder @NotNull ... algorithmBuilders) { + AlgorithmBuilder @NotNull... algorithmBuilders) { this.backedNet = backedNet; this.pipeGraph = graph; this.netAlgorithms = new NetAlgorithmWrapper[algorithmBuilders.length]; for (int i = 0; i < algorithmBuilders.length; i++) { - this.netAlgorithms[i] = new NetAlgorithmWrapper(backedNet, algorithmBuilders[i], backedNet.supportsPredication()); + this.netAlgorithms[i] = new NetAlgorithmWrapper(backedNet, algorithmBuilders[i], + backedNet.supportsPredication()); } this.vertexMap = new Object2ObjectOpenHashMap<>(); } diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index 546d421ff56..0135cf2a8ee 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -28,6 +28,7 @@ default boolean usesDynamicWeights(int algorithmID) { /** * Controls whether predication of edges is allowed for this net. When false, path caching is improved by * skipping the recomputation required in order to compensate for predication. + * * @return whether predication should be allowed for this net. */ default boolean supportsPredication() { diff --git a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java index 078b71f80dd..ca117fdb98b 100644 --- a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java +++ b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java @@ -1,8 +1,8 @@ package gregtech.api.graphnet; -import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.INetLogicEntryListener; import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.NetLogicEntry; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; diff --git a/src/main/java/gregtech/api/graphnet/NetGroup.java b/src/main/java/gregtech/api/graphnet/NetGroup.java index a5b8393cdc5..351538142c4 100644 --- a/src/main/java/gregtech/api/graphnet/NetGroup.java +++ b/src/main/java/gregtech/api/graphnet/NetGroup.java @@ -1,6 +1,5 @@ package gregtech.api.graphnet; -import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; @@ -8,7 +7,6 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; -import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; diff --git a/src/main/java/gregtech/api/graphnet/NetNode.java b/src/main/java/gregtech/api/graphnet/NetNode.java index 236a9b0acd0..d659506081c 100644 --- a/src/main/java/gregtech/api/graphnet/NetNode.java +++ b/src/main/java/gregtech/api/graphnet/NetNode.java @@ -5,7 +5,6 @@ import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.path.INetPath; - import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java b/src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java index 55d009e77ae..6fb0c6eee88 100644 --- a/src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java +++ b/src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java @@ -7,5 +7,6 @@ @FunctionalInterface public interface AlgorithmBuilder { - @NotNull INetAlgorithm build(@NotNull IGraphNet net, boolean recomputeEveryCall); + @NotNull + INetAlgorithm build(@NotNull IGraphNet net, boolean recomputeEveryCall); } diff --git a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java index b10f8e01299..dcb84e5a66f 100644 --- a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java @@ -6,5 +6,6 @@ public interface INetAlgorithm { - > IteratorFactory getPathsIteratorFactory(GraphVertex source, NetPathMapper remapper); + > IteratorFactory getPathsIteratorFactory(GraphVertex source, + NetPathMapper remapper); } diff --git a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java index 6567f97afd4..54f1e19ec0e 100644 --- a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java +++ b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java @@ -10,9 +10,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Iterator; -import java.util.function.Function; - public class NetAlgorithmWrapper { private final IGraphNet net; diff --git a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java index ea64027bca3..1b5971882f9 100644 --- a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java @@ -8,7 +8,6 @@ import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.path.INetPath; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; import java.util.Collections; diff --git a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java index 81a5c244ee2..e19798dcbf4 100644 --- a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java @@ -1,7 +1,5 @@ package gregtech.api.graphnet.alg; -import com.github.bsideup.jabel.Desugar; - import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.alg.iter.IteratorFactory; import gregtech.api.graphnet.alg.iter.SimpleIteratorFactories; @@ -9,6 +7,7 @@ import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.path.INetPath; +import com.github.bsideup.jabel.Desugar; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.Iterator; @@ -48,7 +47,7 @@ public SinglePathAlgorithm(IGraphNet pipenet, boolean recomputeEveryCall) { } private Results compute(GraphVertex source, - List nodes, List graphEdges) { + List nodes, List graphEdges) { nodes.add(source); GraphVertex lastNode = null; GraphVertex node = source; @@ -69,8 +68,7 @@ private Results compute(GraphVertex source, graphEdge = i.next(); reversedEdge = !this.net.getGraph().isDirected() && graphEdge.getTarget() == node; // we know that the new edge cannot point to the previous node - } - else break; // we've reached the end, exit the loop while still valid + } else break; // we've reached the end, exit the loop while still valid } else if (i.hasNext()) i.next(); if (i.hasNext()) valid = false; // third graphEdge detected - that's an invalid group lastNode = node; diff --git a/src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java b/src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java index 4a98d516671..0a9a4455280 100644 --- a/src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java +++ b/src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java @@ -1,6 +1,5 @@ package gregtech.api.graphnet.alg.iter; -import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; @@ -16,9 +15,11 @@ public interface IteratorFactory { * The provided iterator must always be used and discarded before the end of the tick. */ @Contract("_, _, _, _ -> new") - Iterator newIterator(INetGraph graph, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick); + Iterator newIterator(INetGraph graph, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, + long queryTick); - static void defaultPrepareRun(INetGraph graph, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, long queryTick) { + static void defaultPrepareRun(INetGraph graph, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, + long queryTick) { graph.prepareForAlgorithmRun(testObject, simulator, queryTick); } diff --git a/src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java b/src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java index e7118d6b11c..f72432b23d1 100644 --- a/src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java +++ b/src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java @@ -1,18 +1,11 @@ package gregtech.api.graphnet.alg.iter; -import com.cleanroommc.modularui.utils.math.functions.trig.Sin; - -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import org.jetbrains.annotations.Nullable; - import java.util.Iterator; public final class SimpleIteratorFactories { public static IteratorFactory emptyFactory() { - return (graph, testObject, simulator, queryTick) -> new SingletonIterator<>(null); + return (graph, testObject, simulator, queryTick) -> new SingletonIterator<>(null); } public static IteratorFactory fromIterable(Iterable prototype) { diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java index ac126e05f94..fdedd851ddf 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java @@ -17,7 +17,6 @@ public class NetFlowSharedEdge extends AbstractNetFlowEdge { private final int flowBufferTicks; private final int regenerationTime; - /** * NetEdge that provides flow behavior where the capacity along an edge is shared by all channels. * @@ -30,13 +29,12 @@ public NetFlowSharedEdge(int flowBufferTicks) { this.regenerationTime = 1; } - /** * NetEdge that provides flow behavior where the capacity along an edge is shared by all channels. * - * @param flowBufferTicks Determines how many ticks of 'buffer' flow capacity can be built up along edges. Allows - * for once-an-interval push/pull operations instead of needing them every tick for maximum - * throughput. + * @param flowBufferTicks Determines how many ticks of 'buffer' flow capacity can be built up along edges. Allows + * for once-an-interval push/pull operations instead of needing them every tick for maximum + * throughput. * @param regenerationTime Ticks required for flow to regenerate once. Allows slowing down the rate of regeneration. */ public NetFlowSharedEdge(int flowBufferTicks, int regenerationTime) { diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java index 0e13ac497d7..e04b6cc73a3 100644 --- a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java +++ b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java @@ -33,6 +33,7 @@ public GraphVertex getTarget() { /** * Use this very sparingly. It's significantly better to go through {@link org.jgrapht.Graph#getEdgeWeight(Object)} * instead, unless you are doing nbt serialization for example. + * * @return the edge weight. */ @Override diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java index c46f823505a..68785c1516d 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java @@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull; public abstract class AbstractDoubleLogicData> - extends NetLogicEntry { + extends NetLogicEntry { private double value; diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index b75b43a0b9b..0717e693934 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -114,7 +114,8 @@ public void markLogicEntryAsUpdated(NetLogicEntry entry, boolean fullChang } @Contract("null, null -> null; !null, _ -> new; _, !null -> new") - public static @Nullable NetLogicData unionNullable(@Nullable NetLogicData sourceData, @Nullable NetLogicData targetData) { + public static @Nullable NetLogicData unionNullable(@Nullable NetLogicData sourceData, + @Nullable NetLogicData targetData) { if (sourceData == null && targetData == null) return null; return union(sourceData == null ? targetData : sourceData, sourceData == null ? null : targetData); } diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java index 75b7b95091e..52e4a2042f0 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java @@ -10,7 +10,6 @@ import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,7 +18,7 @@ * {@link #union(NetLogicEntry)} behavior. */ public abstract class NetLogicEntry, N extends NBTBase> - implements INBTSerializable, IStringSerializable, IPacket { + implements INBTSerializable, IStringSerializable, IPacket { private final @NotNull String name; diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java index 4e3ea2f3ccf..98dc76b57bf 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java @@ -24,7 +24,7 @@ static void register(NetLogicEntry entry) { } public static @NotNull Supplier<@NotNull NetLogicEntry> getSupplierErroring(String name) { - Supplier> supplier = REGISTRY.get(name); + Supplier> supplier = REGISTRY.get(name); if (supplier == null) throwNonexistenceError(); return supplier; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java index 3c08f16bcde..61a10f222ad 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java @@ -22,6 +22,7 @@ public interface IPipeNetNodeHandler { void removeFromNets(World world, BlockPos pos, IPipeStructure structure); - void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn, + void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, + @NotNull ITooltipFlag flagIn, IPipeStructure structure); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index af826deea2a..26dd790f6ca 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -5,7 +5,6 @@ import gregtech.api.graphnet.MultiNodeHelper; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.alg.AlgorithmBuilder; -import gregtech.api.graphnet.alg.INetAlgorithm; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; @@ -15,14 +14,13 @@ import gregtech.api.util.GTUtility; import gregtech.api.util.IDirtyNotifiable; -import it.unimi.dsi.fastutil.Hash; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; - import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; +import it.unimi.dsi.fastutil.Hash; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -64,7 +62,6 @@ public final void updatePredication(@NotNull WorldPipeNetNode node, @NotNull Pip if (supportsPredication()) updatePredicationInternal(node, tile); } - /** * Called when a PipeTileEntity is marked dirty through {@link IDirtyNotifiable#markAsDirty()}, which is generally * when the state of its covers is changed. @@ -97,10 +94,11 @@ protected void updatePredicationInternal(@NotNull WorldPipeNetNode node, @NotNul * @param coverTarget the cover on the target facing the source. * @return whether the predication state has changed and this net needs to be marked dirty. */ - protected boolean predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode source, @Nullable Cover coverSource, - @NotNull WorldPipeNetNode target, @Nullable Cover coverTarget) { - Map> prevValue = - new Object2ObjectOpenHashMap<>(edge.getPredicateHandler().getPredicateSet()); + protected boolean predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode source, + @Nullable Cover coverSource, + @NotNull WorldPipeNetNode target, @Nullable Cover coverTarget) { + Map> prevValue = new Object2ObjectOpenHashMap<>( + edge.getPredicateHandler().getPredicateSet()); edge.getPredicateHandler().clearPredicates(); coverPredication(edge, coverSource, coverTarget); boolean edgeSame = !prevValue.equals(edge.getPredicateHandler().getPredicateSet()); @@ -122,11 +120,12 @@ protected boolean predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode /** * Preferred method to override if your net has custom predication rules that only depend on covers. - * If the net is directed, this method will be called twice, so no special handling for directedness is needed. + * If the net is directed, this method will be called twice, so no special handling for directedness is + * needed. * * @param edge the edge to predicate - * @param a the cover on the source of the edge - * @param b the cover on the sink of the edge + * @param a the cover on the source of the edge + * @param b the cover on the sink of the edge */ protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) {} @@ -145,7 +144,8 @@ protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nulla } protected Stream<@NotNull WorldPipeNet> sameDimensionNetsStream() { - return dimensionNets.getOrDefault(this.getDimension(), Collections.emptySet()).stream().filter(Objects::nonNull); + return dimensionNets.getOrDefault(this.getDimension(), Collections.emptySet()).stream() + .filter(Objects::nonNull); } public void synchronizeNode(WorldPipeNetNode node) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java index 56fd5599760..ead3ccc7dc4 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java @@ -1,11 +1,9 @@ package gregtech.api.graphnet.pipenet; import gregtech.api.graphnet.MultiNodeHelper; -import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.worldnet.WorldNetNode; -import net.minecraft.block.Block; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index 2328e4b3811..b477ca278c7 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -2,9 +2,9 @@ import gregtech.api.graphnet.MultiNodeHelper; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.INetLogicEntryListener; import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.IFreezable; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java index 14072b3f2c7..84948da43dc 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java @@ -3,16 +3,14 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.client.renderer.pipe.AbstractPipeModel; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.util.EnumFacing; import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.AxisAlignedBB; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; import java.util.List; public interface IPipeStructure extends IStringSerializable { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java index 4a908cebbb1..8281952f72c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeActivableBlock.java @@ -1,14 +1,12 @@ package gregtech.api.graphnet.pipenet.physical.block; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; - import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.ActivablePipeModel; import net.minecraft.block.state.BlockStateContainer; - import net.minecraft.block.state.IBlockState; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 19796bbc410..8dd46a36fc5 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -1,7 +1,5 @@ package gregtech.api.graphnet.pipenet.physical.block; -import codechicken.lib.raytracer.IndexedCuboid6; - import gregtech.api.block.BuiltInRenderBlock; import gregtech.api.cover.Cover; import gregtech.api.cover.CoverRayTracer; @@ -19,17 +17,13 @@ import gregtech.api.util.EntityDamageUtil; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.AbstractPipeModel; -import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.pipe.cover.CoverRendererPackage; import gregtech.client.utils.BloomEffectUtil; import gregtech.client.utils.TooltipHelper; import gregtech.common.ConfigHolder; import gregtech.common.blocks.BlockFrame; - import gregtech.common.blocks.MetaBlocks; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.block.Block; import net.minecraft.block.SoundType; import net.minecraft.block.state.BlockFaceShape; @@ -76,7 +70,8 @@ public abstract class PipeBlock extends BuiltInRenderBlock { // do not touch these two unless you know what you are doing protected final ThreadLocal lastTilePos = ThreadLocal.withInitial(() -> new BlockPos(0, 0, 0)); - protected final ThreadLocal> lastTile = ThreadLocal.withInitial(() -> new WeakReference<>(null)); + protected final ThreadLocal> lastTile = ThreadLocal + .withInitial(() -> new WeakReference<>(null)); private final IPipeStructure structure; @@ -144,7 +139,8 @@ public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @ } RayTraceAABB trace = collisionRayTrace(playerIn, worldIn, pos); - if (trace == null) return super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ); + if (trace == null) + return super.onBlockActivated(worldIn, pos, state, playerIn, hand, facing, hitX, hitY, hitZ); EnumFacing actualSide = CoverRayTracer.determineGridSideHit(trace); if (actualSide != null) facing = actualSide; @@ -211,8 +207,7 @@ public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @ ToolHelper.damageItem(item, playerIn); ToolHelper.playToolSound(item, playerIn); disconnectTile(tile, other, facing); - } - else if (coverCheck(tile, other, facing)) { + } else if (coverCheck(tile, other, facing)) { ToolHelper.damageItem(item, playerIn); ToolHelper.playToolSound(item, playerIn); connectTile(tile, other, facing); @@ -250,15 +245,20 @@ public void onBlockClicked(@NotNull World worldIn, @NotNull BlockPos pos, @NotNu /** * Should be called to verify if a connection can be formed before * {@link #connectTile(PipeTileEntity, PipeTileEntity, EnumFacing)} is called. + * * @return whether the connection is allowed. */ - public static boolean coverCheck(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, EnumFacing facing) { + public static boolean coverCheck(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, + EnumFacing facing) { Cover tileCover = tile.getCoverHolder().getCoverAtSide(facing); - Cover acrossCover = tileAcross != null ? tileAcross.getCoverHolder().getCoverAtSide(facing.getOpposite()) : null; - return (tileCover == null || tileCover.canPipePassThrough()) && (acrossCover == null || acrossCover.canPipePassThrough()); + Cover acrossCover = tileAcross != null ? tileAcross.getCoverHolder().getCoverAtSide(facing.getOpposite()) : + null; + return (tileCover == null || tileCover.canPipePassThrough()) && + (acrossCover == null || acrossCover.canPipePassThrough()); } - public static void connectTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, EnumFacing facing) { + public static void connectTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, + EnumFacing facing) { // abort connection if either tile refuses it. if (!tile.canConnectTo(facing) || tileAcross != null && !tileAcross.canConnectTo(facing.getOpposite())) return; @@ -291,7 +291,8 @@ public static void connectTile(@NotNull PipeTileEntity tile, @Nullable PipeTileE } } - public static void disconnectTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, EnumFacing facing) { + public static void disconnectTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, + EnumFacing facing) { tile.setDisconnected(facing); if (tileAcross == null) return; tileAcross.setDisconnected(facing.getOpposite()); @@ -327,7 +328,8 @@ public static void blockTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEnt } } - public static void unblockTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, EnumFacing facing) { + public static void unblockTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEntity tileAcross, + EnumFacing facing) { tile.setUnblocked(facing); if (tileAcross == null || tile.getWorld().isRemote) return; @@ -357,7 +359,7 @@ public static Collection getNodesForTile(PipeTileEntity tile) @Override public void onBlockAdded(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { super.onBlockAdded(worldIn, pos, state); -// if (!worldIn.isRemote) getHandler(worldIn, pos).getOrCreateFromNets(worldIn, pos, getStructure()); + // if (!worldIn.isRemote) getHandler(worldIn, pos).getOrCreateFromNets(worldIn, pos, getStructure()); } @Override @@ -377,7 +379,8 @@ public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull I // misc stuff // @Override - public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { + public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, + @NotNull ITooltipFlag flagIn) { if (getStructure() instanceof IPipeChanneledStructure channeledStructure) { if (channeledStructure.getChannelCount() > 1) tooltip.add(I18n.format("gregtech.pipe.channels", channeledStructure.getChannelCount())); @@ -495,13 +498,13 @@ public RayTraceResult collisionRayTrace(@NotNull IBlockState blockState, @NotNul } public @Nullable RayTraceAABB collisionRayTrace(@NotNull EntityPlayer player, - @NotNull World world, @NotNull BlockPos pos) { + @NotNull World world, @NotNull BlockPos pos) { return collisionRayTrace(player, world, pos, RayTracer.getStartVec(player), RayTracer.getEndVec(player)); } public @Nullable RayTraceAABB collisionRayTrace(@Nullable EntityPlayer player, - @NotNull World worldIn, @NotNull BlockPos pos, - @NotNull Vec3d start, @NotNull Vec3d end) { + @NotNull World worldIn, @NotNull BlockPos pos, + @NotNull Vec3d start, @NotNull Vec3d end) { if (hasPipeCollisionChangingItem(worldIn, pos, player)) { return RayTraceAABB.of(rayTrace(pos, start, end, FULL_BLOCK_AABB), FULL_BLOCK_AABB); } @@ -634,7 +637,7 @@ public PipeTileEntity getTileEntity(@NotNull IBlockAccess world, @NotNull BlockP @Override public final PipeTileEntity createTileEntity(@NotNull World world, @NotNull IBlockState state) { try { - //noinspection deprecation + // noinspection deprecation return getTileClass(world, state).newInstance(); } catch (Throwable ignored) { return null; @@ -663,7 +666,8 @@ public int getLightValue(@NotNull IBlockState state, @NotNull IBlockAccess world PipeTileEntity tile = getTileEntity(world, pos); if (tile != null) { TemperatureLogic temperatureLogic = tile.getTemperatureLogic(); - int temp = temperatureLogic == null ? 0 : temperatureLogic.getTemperature(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); + int temp = temperatureLogic == null ? 0 : temperatureLogic + .getTemperature(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); // max light at 5000 K // min light at 500 K if (temp >= 5000) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index 91cbf9e1847..8be23ce16dc 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -10,9 +10,7 @@ import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.unification.material.registry.MaterialRegistry; import gregtech.api.util.GTUtility; - import gregtech.client.renderer.pipe.AbstractPipeModel; - import gregtech.common.ConfigHolder; import net.minecraft.block.state.BlockStateContainer; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java index 9726edcd474..91f69fe336d 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java @@ -3,10 +3,7 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.client.renderer.pipe.ActivablePipeModel; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java index 6e7be13bbe9..6d6dfd76ce3 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java @@ -12,8 +12,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 9fd456b5dab..bbcdc80e311 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -4,8 +4,8 @@ import gregtech.api.GregTechAPI; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; -import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.NetLogicRegistry; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; @@ -16,15 +16,12 @@ import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.metatileentity.NeighborCacheTileEntityBase; import gregtech.api.unification.material.Material; -import gregtech.api.util.GTUtility; import gregtech.client.particle.GTOverheatParticle; import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.pipe.cover.CoverRendererPackage; import gregtech.common.blocks.MetaBlocks; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; - import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; @@ -50,6 +47,7 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.MustBeInvokedByOverriders; @@ -85,7 +83,8 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick protected final PipeCoverHolder covers = new PipeCoverHolder(this); private final Object2ObjectOpenHashMap, IPipeCapabilityObject> capabilities = new Object2ObjectOpenHashMap<>(); - private final Object2ObjectOpenCustomHashMap netCapabilities = WorldPipeNet.getSensitiveHashMap(); + private final Object2ObjectOpenCustomHashMap netCapabilities = WorldPipeNet + .getSensitiveHashMap(); @Nullable private TemperatureLogic temperatureLogic; @@ -696,7 +695,8 @@ public void markAsDirty() { } /** - * Note - the block corresponding to this tile entity must register any new unlisted properties to the default state. + * Note - the block corresponding to this tile entity must register any new unlisted properties to the default + * state. */ @MustBeInvokedByOverriders public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java b/src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java index 638606598bb..9ac2199ac92 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java @@ -4,7 +4,6 @@ import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTTagByte; -import net.minecraft.nbt.NBTTagString; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java b/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java index 921de9b56d9..c37ee85c253 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java @@ -1,17 +1,12 @@ package gregtech.api.graphnet.pipenet.predicate; import gregtech.api.graphnet.predicate.EdgePredicate; - -import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - import gregtech.common.covers.filter.BaseFilterContainer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraftforge.fluids.FluidStack; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java index db7267691df..0f67a5e3828 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java +++ b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java @@ -6,7 +6,6 @@ import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,7 +14,7 @@ * {@link #union(EdgePredicate)} behavior. */ public abstract class EdgePredicate, N extends NBTBase> - implements INBTSerializable, IStringSerializable { + implements INBTSerializable, IStringSerializable { private final @NotNull String name; diff --git a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java index 6a5f92257cd..affd03080a7 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java +++ b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java @@ -82,7 +82,8 @@ public boolean test(IPredicateTestObject iPredicateTestObject) { if (shouldIgnore()) return true; boolean result = false; for (EdgePredicate predicate : predicateSet.values()) { - // TODO predicate 'categories' or 'affinities' that determine order of operations with and-y and or-y behavior? + // TODO predicate 'categories' or 'affinities' that determine order of operations with and-y and or-y + // behavior? boolean test = predicate.test(iPredicateTestObject); if (predicate.andy() && !test) return false; else result |= test; diff --git a/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java index 761274a2f66..3ea6eb82c36 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java +++ b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java @@ -1,7 +1,5 @@ package gregtech.api.graphnet.predicate; -import gregtech.api.graphnet.logic.NetLogicEntry; - import gregtech.api.util.function.NullableSupplier; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -28,7 +26,7 @@ static void register(EdgePredicate predicate) { } public static @NotNull Supplier> getSupplierErroring(String name) { - Supplier> supplier = REGISTRY.get(name); + Supplier> supplier = REGISTRY.get(name); if (supplier == null) throwNonexistenceError(); return supplier; } diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java index d2ead1561d5..6773cb99745 100644 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java @@ -4,12 +4,10 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.alg.AlgorithmBuilder; -import gregtech.api.graphnet.alg.INetAlgorithm; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.graph.NetDirectedGraph; import gregtech.api.graphnet.graph.NetUndirectedGraph; -import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.util.DimensionPos; diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java b/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java index 0d2e8b58195..af0469ae203 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java +++ b/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java @@ -2,10 +2,7 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.path.INetPath; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.api.graphnet.predicate.test.ItemTestObject; import org.jetbrains.annotations.Nullable; @@ -13,5 +10,6 @@ public interface ITraverseGuideProvider> TraverseGuide getGuide( - TraverseDataProvider provider, T testObject, long flow, boolean simulate); + TraverseDataProvider provider, T testObject, + long flow, boolean simulate); } diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java index ac498f6f0de..d76ff3a5e7e 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java @@ -16,7 +16,8 @@ public class TraverseGuide, T extend private final long flow; private final LongConsumer consumptionReport; - public TraverseGuide(T data, Supplier> pathsSupplier, long flow, @Nullable LongConsumer consumptionReport) { + public TraverseGuide(T data, Supplier> pathsSupplier, long flow, + @Nullable LongConsumer consumptionReport) { this.data = data; this.pathsSupplier = pathsSupplier; this.flow = flow; @@ -42,5 +43,4 @@ public Iterator

getPaths() { public long getFlow() { return flow; } - } diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index 9a4bc76a489..eaa1f2c8935 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -20,7 +20,6 @@ import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Consumer; -import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; @@ -382,8 +381,7 @@ D extends ITraverseData & IRoundRobinTraverseData> long traverseRoun // keep iterating over paths in order to collect destinations into the cache if (availableFlow <= 0) continue; skippedPaths.put(destIdentifier, path); - } - else { + } else { // keep iterating over paths in order to collect destinations into the cache if (availableFlow <= 0) { cache.addFirst(destIdentifier); diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java index a6c50e8d128..3a513cc1259 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -4,7 +4,6 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.alg.AlgorithmBuilder; -import gregtech.api.graphnet.alg.INetAlgorithm; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.INetGraph; diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index f31ab9ec6ce..c1a48b7a643 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -6,17 +6,13 @@ import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; - -import it.unimi.dsi.fastutil.objects.Object2ObjectRBTreeMap; - import net.minecraft.client.util.ITooltipFlag; import net.minecraft.item.ItemStack; import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectRBTreeMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,8 +24,8 @@ public class PipeNetProperties implements IMaterialProperty, IPipeNetNodeHandler { - protected final Map, IPipeNetMaterialProperty> properties = - new Object2ObjectRBTreeMap<>(Comparator.comparing(IPipeNetMaterialProperty.MaterialPropertyKey::getName)); + protected final Map, IPipeNetMaterialProperty> properties = new Object2ObjectRBTreeMap<>( + Comparator.comparing(IPipeNetMaterialProperty.MaterialPropertyKey::getName)); public void setProperty(IPipeNetMaterialProperty property) { this.properties.put(property.getKey(), property); @@ -59,7 +55,8 @@ public boolean generatesStructure(IPipeStructure structure) { } @Override - public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, + IPipeStructure structure) { List list = new ObjectArrayList<>(); for (IPipeNetMaterialProperty p : properties.values()) { if (p.supportsStructure(structure)) { diff --git a/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java b/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java index b845f067d5f..d19fcc1b76c 100644 --- a/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java +++ b/src/main/java/gregtech/api/unification/material/properties/WoodProperty.java @@ -1,8 +1,6 @@ package gregtech.api.unification.material.properties; import gregtech.api.unification.material.info.MaterialFlags; -import gregtech.api.unification.ore.OrePrefix; -import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; public class WoodProperty implements IMaterialProperty { diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 817e8e748e2..9e0afe06833 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -980,8 +980,10 @@ public static Set createWeakHashSet() { /** * Forces the initialization of a class; this includes things like loading its static fields. * This can be useful because a statement like {@code AClass.class} does not initialize a class. - *

+ *
+ *
* Does nothing if the class is already initialized. + * * @param clazz the class object to initialize. */ public static void forceInitialization(Class clazz) { diff --git a/src/main/java/gregtech/api/util/function/NullableSupplier.java b/src/main/java/gregtech/api/util/function/NullableSupplier.java index 54f1f928418..e66e41429d2 100644 --- a/src/main/java/gregtech/api/util/function/NullableSupplier.java +++ b/src/main/java/gregtech/api/util/function/NullableSupplier.java @@ -8,5 +8,6 @@ public interface NullableSupplier extends Supplier { @Override - @Nullable T get(); + @Nullable + T get(); } diff --git a/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java b/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java index 47c1986c551..d5fcf0453cd 100644 --- a/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java +++ b/src/main/java/gregtech/client/renderer/handler/FacadeRenderer.java @@ -28,7 +28,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.IBlockAccess; @@ -53,7 +52,6 @@ import org.lwjgl.opengl.GL11; import java.util.ArrayList; -import java.util.EnumMap; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; diff --git a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java index 8e0e6d790ea..6fd8a19e06f 100644 --- a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java @@ -13,7 +13,6 @@ import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.util.CacheKey; - import gregtech.client.renderer.pipe.util.SpriteInformation; import net.minecraft.block.state.IBlockState; @@ -76,7 +75,7 @@ public AbstractPipeModel(ModelResourceLocation loc) { CoverRendererPackage rendererPackage = ext.getValue(CoverRendererPackage.PROPERTY); byte coverMask = rendererPackage == null ? 0 : rendererPackage.getMask(); if (canRenderInLayer(getCurrentRenderLayer())) { - quads = getQuads(toKey(ext), safeByte(ext.getValue(CONNECTION_MASK_PROPERTY)), + quads = getQuads(toKey(ext), safeByte(ext.getValue(CONNECTION_MASK_PROPERTY)), safeByte(ext.getValue(CLOSED_MASK_PROPERTY)), safeByte(ext.getValue(BLOCKED_MASK_PROPERTY)), data, ext.getValue(FRAME_MATERIAL_PROPERTY), safeByte(ext.getValue(FRAME_MASK_PROPERTY)), coverMask); @@ -115,7 +114,8 @@ protected static int safeInt(@Nullable Integer integer) { return integer == null ? 0 : integer; } - public @NotNull List getQuads(K key, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, + public @NotNull List getQuads(K key, byte connectionMask, byte closedMask, byte blockedMask, + ColorData data, @Nullable Material frameMaterial, byte frameMask, byte coverMask) { List quads = new ObjectArrayList<>(); @@ -135,7 +135,8 @@ protected static int safeInt(@Nullable Integer integer) { .createFrame(Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(rl.toString()))); frameCache.put(rl, frame); } - List frameQuads = frame.getQuads(new ColorData(GTUtility.convertRGBtoARGB(frameMaterial.getMaterialRGB()))); + List frameQuads = frame + .getQuads(new ColorData(GTUtility.convertRGBtoARGB(frameMaterial.getMaterialRGB()))); for (int i = 0; i < 6; i++) { if ((frameMask & (1 << i)) > 0) { quads.add(frameQuads.get(i)); diff --git a/src/main/java/gregtech/client/renderer/pipe/CableModel.java b/src/main/java/gregtech/client/renderer/pipe/CableModel.java index 9bf1e8ad453..7b598ccc957 100644 --- a/src/main/java/gregtech/client/renderer/pipe/CableModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/CableModel.java @@ -1,7 +1,7 @@ package gregtech.client.renderer.pipe; -import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.unification.material.Material; import gregtech.api.util.GTUtility; diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java index 0bd73563993..084d1699e3f 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java @@ -10,29 +10,32 @@ import net.minecraft.client.renderer.block.model.ItemOverrideList; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.EnumFacing; - import net.minecraftforge.common.model.TRSRTransformation; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; +import java.util.EnumMap; +import java.util.List; + import javax.vecmath.Matrix4f; import javax.vecmath.Quat4f; import javax.vecmath.Vector3f; -import java.util.EnumMap; -import java.util.List; public class PipeItemModel implements IBakedModel { - private static final EnumMap CAMERA_TRANSFORMS = - new EnumMap<>(ItemCameraTransforms.TransformType.class); + private static final EnumMap CAMERA_TRANSFORMS = new EnumMap<>( + ItemCameraTransforms.TransformType.class); static { CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.NONE, TRSRTransformation.mul(null, null, null, null)); - CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.GUI, TRSRTransformation.mul(null, rotDegrees(30, -45, 0), scale(0.625f), null)); - CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.GROUND, TRSRTransformation.mul(null, null, scale(0.25f), null)); - CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.FIXED, TRSRTransformation.mul(null, rotDegrees(0, 90, 0), scale(0.5f), null)); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.GUI, + TRSRTransformation.mul(null, rotDegrees(30, -45, 0), scale(0.625f), null)); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.GROUND, + TRSRTransformation.mul(null, null, scale(0.25f), null)); + CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.FIXED, + TRSRTransformation.mul(null, rotDegrees(0, 90, 0), scale(0.5f), null)); Matrix4f matrix4f = TRSRTransformation.mul(null, rotDegrees(75, 45, 0), scale(0.375f), null); CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.THIRD_PERSON_RIGHT_HAND, matrix4f); CAMERA_TRANSFORMS.put(ItemCameraTransforms.TransformType.THIRD_PERSON_LEFT_HAND, matrix4f); @@ -82,7 +85,7 @@ public boolean isBuiltInRenderer() { @Override public @NotNull Pair handlePerspective( - ItemCameraTransforms.@NotNull TransformType cameraTransformType) { + ItemCameraTransforms.@NotNull TransformType cameraTransformType) { return ImmutablePair.of(this, CAMERA_TRANSFORMS.get(cameraTransformType)); } diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java index da9650d732b..63f7ee082b5 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java @@ -1,7 +1,7 @@ package gregtech.client.renderer.pipe; -import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.PropertyKey; diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java index 5b868652e7d..6c321f8527d 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java @@ -28,13 +28,15 @@ protected ActivableSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteIn super(helper, endTex, sideTex); this.overlayTex = overlayTex; this.overlayActiveTex = overlayActiveTex; - if (helper.getLayerCount() < 2) throw new IllegalStateException("Cannot create an ActivableSQC without 2 or more layers present on the helper!"); + if (helper.getLayerCount() < 2) throw new IllegalStateException( + "Cannot create an ActivableSQC without 2 or more layers present on the helper!"); } public static @NotNull ActivableSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation overlayTex, SpriteInformation overlayActiveTex) { - helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, + OVERLAY_DIST_1)); ActivableSQC cache = new ActivableSQC(helper, endTex, sideTex, overlayTex, overlayActiveTex); cache.buildPrototype(); return cache; diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java index d20f20838ba..fea9003c5ad 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java @@ -28,12 +28,14 @@ protected BlockableSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteIn SpriteInformation blockedTex) { super(helper, endTex, sideTex); this.blockedTex = blockedTex; - if (helper.getLayerCount() < 2) throw new IllegalStateException("Cannot create a BlockableSQC without 2 or more layers present on the helper!"); + if (helper.getLayerCount() < 2) throw new IllegalStateException( + "Cannot create a BlockableSQC without 2 or more layers present on the helper!"); } public static @NotNull BlockableSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation blockedTex) { - helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, + OVERLAY_DIST_1)); BlockableSQC cache = new BlockableSQC(helper, endTex, sideTex, blockedTex); cache.buildPrototype(); return cache; @@ -56,7 +58,8 @@ protected void buildBlocked(List list) { } @Override - public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, byte coverMask) { + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, + byte coverMask) { List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, connectionMask)) { diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java index 463cb7b3b18..82b9740d775 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java @@ -3,12 +3,11 @@ import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; - import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.List; @@ -40,5 +39,4 @@ public List getQuads(ColorData data) { } return existing; } - } diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java index 72876c1e827..762ce21bb87 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ExtraCappedSQC.java @@ -28,12 +28,14 @@ protected ExtraCappedSQC(PipeQuadHelper helper, SpriteInformation endTex, Sprite SpriteInformation extraEndTex) { super(helper, endTex, sideTex); this.extraEndTex = extraEndTex; - if (helper.getLayerCount() < 2) throw new IllegalStateException("Cannot create an ExtraCappedSQC without 2 or more layers present on the helper!"); + if (helper.getLayerCount() < 2) throw new IllegalStateException( + "Cannot create an ExtraCappedSQC without 2 or more layers present on the helper!"); } public static @NotNull ExtraCappedSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation extraEndTex) { - helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.capOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.capOverlay(facing, x1, y1, z1, x2, y2, z2, + OVERLAY_DIST_1)); ExtraCappedSQC cache = new ExtraCappedSQC(helper, endTex, sideTex, extraEndTex); cache.buildPrototype(); return cache; @@ -56,7 +58,8 @@ protected void buildExtraCapper(List list) { } @Override - public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, byte coverMask) { + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, + byte coverMask) { List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, connectionMask)) { diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java index aff38ae1792..91a08988745 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java @@ -28,14 +28,18 @@ protected RestrictiveSQC(PipeQuadHelper helper, SpriteInformation endTex, Sprite SpriteInformation blockedTex, SpriteInformation restrictiveTex) { super(helper, endTex, sideTex, blockedTex); this.restrictiveTex = restrictiveTex; - if (helper.getLayerCount() < 3) throw new IllegalStateException("Cannot create a RestrictiveSQC without 3 or more layers present on the helper!"); + if (helper.getLayerCount() < 3) throw new IllegalStateException( + "Cannot create a RestrictiveSQC without 3 or more layers present on the helper!"); } public static @NotNull RestrictiveSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation blockedTex, SpriteInformation restrictiveTex) { - helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_2), - (facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, OVERLAY_DIST_1)); + helper.initialize( + (facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, + OVERLAY_DIST_2), + (facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, + OVERLAY_DIST_1)); RestrictiveSQC sqc = new RestrictiveSQC(helper, endTex, sideTex, blockedTex, restrictiveTex); sqc.buildPrototype(); return sqc; @@ -58,7 +62,8 @@ protected void buildRestrictive(List list) { } @Override - public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, byte coverMask) { + public void addToList(List list, byte connectionMask, byte closedMask, byte blockedMask, ColorData data, + byte coverMask) { List quads = cache.getQuads(data); for (EnumFacing facing : EnumFacing.VALUES) { if (GTUtility.evalMask(facing, connectionMask)) { diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java index 73f38248ae3..8bedc13581e 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/StructureQuadCache.java @@ -38,7 +38,8 @@ protected StructureQuadCache(PipeQuadHelper helper, SpriteInformation endTex, Sp this.helper = helper; this.endTex = endTex; this.sideTex = sideTex; - if (helper.getLayerCount() < 1) throw new IllegalStateException("Cannot create an SQC without at least one layer present on the helper!"); + if (helper.getLayerCount() < 1) + throw new IllegalStateException("Cannot create an SQC without at least one layer present on the helper!"); } public static @NotNull StructureQuadCache create(PipeQuadHelper helper, SpriteInformation endTex, @@ -115,5 +116,4 @@ public void addToList(List list, byte connectionMask, byte closedMask } } } - } diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java index 49472431824..2b4400991e0 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java @@ -12,6 +12,6 @@ @FunctionalInterface public interface CoverRenderer { - void addQuads(List quads, EnumFacing facing, EnumSet renderPlate, boolean renderBackside, - BlockRenderLayer renderLayer, ColorData data); + void addQuads(List quads, EnumFacing facing, EnumSet renderPlate, boolean renderBackside, + BlockRenderLayer renderLayer, ColorData data); } diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java index f39ecf4988f..8897f3cd303 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java @@ -11,21 +11,16 @@ import gregtech.client.renderer.pipe.util.SpriteInformation; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; - import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; - import gregtech.client.utils.BloomEffectUtil; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.texture.TextureAtlasSprite; - import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; - import net.minecraft.util.math.AxisAlignedBB; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; @@ -46,8 +41,10 @@ public class CoverRendererBuilder { public static final EnumMap PLATE_AABBS = new EnumMap<>(EnumFacing.class); private static final EnumMap> PLATE_BOXES = new EnumMap<>(EnumFacing.class); - private static final EnumMap> OVERLAY_BOXES_1 = new EnumMap<>(EnumFacing.class); - private static final EnumMap> OVERLAY_BOXES_2 = new EnumMap<>(EnumFacing.class); + private static final EnumMap> OVERLAY_BOXES_1 = new EnumMap<>( + EnumFacing.class); + private static final EnumMap> OVERLAY_BOXES_2 = new EnumMap<>( + EnumFacing.class); private static final UVMapper defaultMapper = UVMapper.standard(0); @@ -58,8 +55,10 @@ public class CoverRendererBuilder { for (var value : PLATE_AABBS.entrySet()) { // make sure that plates render slightly below any normal block quad PLATE_BOXES.put(value.getKey(), QuadHelper.fullOverlay(value.getKey(), value.getValue(), -OVERLAY_DIST_1)); - OVERLAY_BOXES_1.put(value.getKey(), QuadHelper.fullOverlay(value.getKey(), value.getValue(), OVERLAY_DIST_1)); - OVERLAY_BOXES_2.put(value.getKey(), QuadHelper.fullOverlay(value.getKey(), value.getValue(), OVERLAY_DIST_2)); + OVERLAY_BOXES_1.put(value.getKey(), + QuadHelper.fullOverlay(value.getKey(), value.getValue(), OVERLAY_DIST_1)); + OVERLAY_BOXES_2.put(value.getKey(), + QuadHelper.fullOverlay(value.getKey(), value.getValue(), OVERLAY_DIST_2)); } PLATE_QUADS = buildPlates(new SpriteInformation(defaultPlateSprite(), 0)); } @@ -78,7 +77,7 @@ public static ColorQuadCache buildPlates(SpriteInformation sprite) { } protected static SubListAddress buildPlates(List quads, EnumFacing facing, - UVMapper mapper, SpriteInformation sprite) { + UVMapper mapper, SpriteInformation sprite) { int start = quads.size(); Pair box = PLATE_BOXES.get(facing); for (EnumFacing dir : EnumFacing.values()) { @@ -131,14 +130,16 @@ protected static List getPlates(EnumFacing facing, ColorData data, Co public CoverRenderer build() { EnumMap> spriteQuads = new EnumMap<>(EnumFacing.class); - EnumMap> spriteEmissiveQuads = spriteEmissive != null ? new EnumMap<>(EnumFacing.class) : null; + EnumMap> spriteEmissiveQuads = spriteEmissive != null ? + new EnumMap<>(EnumFacing.class) : null; for (EnumFacing facing : EnumFacing.VALUES) { spriteQuads.put(facing, ImmutablePair.of( QuadHelper.buildQuad(facing, OVERLAY_BOXES_1.get(facing), mapper, sprite), QuadHelper.buildQuad(facing.getOpposite(), OVERLAY_BOXES_1.get(facing), mapper, sprite))); if (spriteEmissive != null) spriteEmissiveQuads.put(facing, ImmutablePair.of( QuadHelper.buildQuad(facing, OVERLAY_BOXES_2.get(facing), mapperEmissive, spriteEmissive), - QuadHelper.buildQuad(facing.getOpposite(), OVERLAY_BOXES_2.get(facing), mapperEmissive, spriteEmissive))); + QuadHelper.buildQuad(facing.getOpposite(), OVERLAY_BOXES_2.get(facing), mapperEmissive, + spriteEmissive))); } return (quads, facing, renderPlate, renderBackside, renderLayer, data) -> { diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java index 3dcd7485e16..6ddf36b88f1 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java @@ -5,7 +5,6 @@ import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; - import net.minecraftforge.common.property.IUnlistedProperty; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java b/src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java index b6a9f468a4e..1da3a447357 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java @@ -9,5 +9,6 @@ @FunctionalInterface public interface OverlayLayerDefinition { - ImmutablePair computeBox(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2); + ImmutablePair computeBox(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, + float y2, float z2); } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java index 6661c54a38d..6f13eb6a301 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -32,7 +32,7 @@ public PipeQuadHelper(float x, float y, float z, float small, float large) { float yL = (y + large) * 16; float zS = (z + small) * 16; float zL = (z + large) * 16; - definition = new float[] {xS, xL, yS, yL, zS, zL}; + definition = new float[] { xS, xL, yS, yL, zS, zL }; } @Contract("_ -> this") @@ -45,8 +45,8 @@ public PipeQuadHelper initialize(OverlayLayerDefinition... overlayLayers) { float zS = definition[4]; float zL = definition[5]; definition = null; - generateBox(xS, xL, yS, yL, zS, zL, (facing, x1, y1, z1, x2, y2, z2) -> - QuadHelper.toPair(x1, y1, z1, x2, y2, z2)); + generateBox(xS, xL, yS, yL, zS, zL, + (facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.toPair(x1, y1, z1, x2, y2, z2)); for (OverlayLayerDefinition definition : overlayLayers) { generateBox(xS, xL, yS, yL, zS, zL, definition); } @@ -58,7 +58,8 @@ public int getLayerCount() { return coreBoxList.size(); } - private void generateBox(float xS, float xL, float yS, float yL, float zS, float zL, OverlayLayerDefinition definition) { + private void generateBox(float xS, float xL, float yS, float yL, float zS, float zL, + OverlayLayerDefinition definition) { coreBoxList.add(definition.computeBox(null, xS, yS, zS, xL, yL, zL)); EnumMap> sideBoxes = new EnumMap<>(EnumFacing.class); sideBoxes.put(EnumFacing.DOWN, definition.computeBox(EnumFacing.DOWN, xS, 0, zS, xL, yS, zL)); @@ -145,5 +146,4 @@ public static List createFrame(TextureAtlasSprite sprite) } return list; } - } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java index 671054017c8..97bf213c2b2 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java @@ -8,7 +8,6 @@ import net.minecraft.client.renderer.block.model.ModelRotation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.EnumFacing; - import net.minecraft.util.math.AxisAlignedBB; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -27,7 +26,8 @@ private QuadHelper() {} public static RecolorableBakedQuad buildQuad(EnumFacing normal, Pair box, UVMapper uv, SpriteInformation targetSprite) { BlockPartFace face = new BlockPartFace(null, -1, targetSprite.sprite().getIconName(), uv.map(normal, box)); - BakedQuad quad = BAKERY.makeBakedQuad(box.getLeft(), box.getRight(), face, targetSprite.sprite(), normal, ModelRotation.X0_Y0, null, false, true); + BakedQuad quad = BAKERY.makeBakedQuad(box.getLeft(), box.getRight(), face, targetSprite.sprite(), normal, + ModelRotation.X0_Y0, null, false, true); RecolorableBakedQuad.Builder builder = new RecolorableBakedQuad.Builder(quad.getFormat()); builder.setTexture(targetSprite); quad.pipe(builder); @@ -37,7 +37,8 @@ public static RecolorableBakedQuad buildQuad(EnumFacing normal, Pair box, UVMapper uv, TextureAtlasSprite targetSprite) { BlockPartFace face = new BlockPartFace(null, -1, targetSprite.getIconName(), uv.map(normal, box)); - return BAKERY.makeBakedQuad(box.getLeft(), box.getRight(), face, targetSprite, normal, ModelRotation.X0_Y0, null, false, true); + return BAKERY.makeBakedQuad(box.getLeft(), box.getRight(), face, targetSprite, normal, ModelRotation.X0_Y0, + null, false, true); } @Contract("_ -> new") @@ -47,18 +48,23 @@ public static BakedQuad buildQuad(EnumFacing normal, Pair bo } @Contract("_, _, _, _, _, _ -> new") - public static @NotNull ImmutablePair toPair(float x1, float y1, float z1, float x2, float y2, float z2) { + public static @NotNull ImmutablePair toPair(float x1, float y1, float z1, float x2, float y2, + float z2) { return ImmutablePair.of(new Vector3f(x1, y1, z1), new Vector3f(x2, y2, z2)); } @Contract("_, _, _ -> new") - public static @NotNull ImmutablePair capOverlay(@Nullable EnumFacing facing, @NotNull AxisAlignedBB bb, float g) { - return capOverlay(facing, (float) bb.minX * 16, (float) bb.minY * 16, (float) bb.minZ * 16, (float) bb.maxX * 16, (float) bb.maxY * 16, + public static @NotNull ImmutablePair capOverlay(@Nullable EnumFacing facing, + @NotNull AxisAlignedBB bb, float g) { + return capOverlay(facing, (float) bb.minX * 16, (float) bb.minY * 16, (float) bb.minZ * 16, + (float) bb.maxX * 16, (float) bb.maxY * 16, (float) bb.maxZ * 16, g); } @Contract("_, _, _, _, _, _, _, _ -> new") - public static @NotNull ImmutablePair capOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { + public static @NotNull ImmutablePair capOverlay(@Nullable EnumFacing facing, float x1, float y1, + float z1, float x2, float y2, float z2, + float g) { if (facing == null) return toPair(x1 - g, y1 - g, z1 - g, x2 + g, y2 + g, z2 + g); return switch (facing.getAxis()) { case X -> toPair(x1 - g, y1, z1, x2 + g, y2, z2); @@ -68,13 +74,17 @@ public static BakedQuad buildQuad(EnumFacing normal, Pair bo } @Contract("_, _, _ -> new") - public static @NotNull ImmutablePair tubeOverlay(@Nullable EnumFacing facing, @NotNull AxisAlignedBB bb, float g) { - return tubeOverlay(facing, (float) bb.minX * 16, (float) bb.minY * 16, (float) bb.minZ * 16, (float) bb.maxX * 16, (float) bb.maxY * 16, + public static @NotNull ImmutablePair tubeOverlay(@Nullable EnumFacing facing, + @NotNull AxisAlignedBB bb, float g) { + return tubeOverlay(facing, (float) bb.minX * 16, (float) bb.minY * 16, (float) bb.minZ * 16, + (float) bb.maxX * 16, (float) bb.maxY * 16, (float) bb.maxZ * 16, g); } @Contract("_, _, _, _, _, _, _, _ -> new") - public static @NotNull ImmutablePair tubeOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { + public static @NotNull ImmutablePair tubeOverlay(@Nullable EnumFacing facing, float x1, + float y1, float z1, float x2, float y2, + float z2, float g) { if (facing == null) return toPair(x1, y1, z1, x2, y2, z2); return switch (facing.getAxis()) { case X -> toPair(x1, y1 - g, z1 - g, x2, y2 + g, z2 + g); @@ -84,13 +94,17 @@ public static BakedQuad buildQuad(EnumFacing normal, Pair bo } @Contract("_, _, _ -> new") - public static @NotNull ImmutablePair fullOverlay(@Nullable EnumFacing facing, @NotNull AxisAlignedBB bb, float g) { - return fullOverlay(facing, (float) bb.minX * 16, (float) bb.minY * 16, (float) bb.minZ * 16, (float) bb.maxX * 16, (float) bb.maxY * 16, + public static @NotNull ImmutablePair fullOverlay(@Nullable EnumFacing facing, + @NotNull AxisAlignedBB bb, float g) { + return fullOverlay(facing, (float) bb.minX * 16, (float) bb.minY * 16, (float) bb.minZ * 16, + (float) bb.maxX * 16, (float) bb.maxY * 16, (float) bb.maxZ * 16, g); } @Contract("_, _, _, _, _, _, _, _ -> new") - public static @NotNull ImmutablePair fullOverlay(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, float y2, float z2, float g) { + public static @NotNull ImmutablePair fullOverlay(@Nullable EnumFacing facing, float x1, + float y1, float z1, float x2, float y2, + float z2, float g) { return toPair(x1 - g, y1 - g, z1 - g, x2 + g, y2 + g, z2 + g); } } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java index 7b84209727b..60c0abe8f99 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java @@ -14,9 +14,9 @@ static UVMapper standard(int rot) { Vector3f small = box.getLeft(); Vector3f large = box.getRight(); return switch (normal.getAxis()) { - case X -> new BlockFaceUV(new float[] {small.y, large.z, large.y, small.z}, rot); - case Y -> new BlockFaceUV(new float[] {small.x, large.z, large.x, small.z}, rot); - case Z -> new BlockFaceUV(new float[] {small.x, large.y, large.x, small.y}, rot); + case X -> new BlockFaceUV(new float[] { small.y, large.z, large.y, small.z }, rot); + case Y -> new BlockFaceUV(new float[] { small.x, large.z, large.x, small.z }, rot); + case Z -> new BlockFaceUV(new float[] { small.x, large.y, large.x, small.y }, rot); }; }; } diff --git a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java index 76b6dd9869e..ade1fd83d54 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformation.java @@ -9,6 +9,7 @@ @SideOnly(Side.CLIENT) @Desugar public record SpriteInformation(TextureAtlasSprite sprite, int colorID) { + public boolean colorable() { return colorID >= 0; } diff --git a/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java index 54c83841515..ea214767051 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java @@ -1,7 +1,6 @@ package gregtech.client.renderer.pipe.util; import gregtech.api.unification.material.Material; - import gregtech.api.unification.material.properties.PropertyKey; import org.jetbrains.annotations.NotNull; @@ -17,7 +16,7 @@ public WoodCacheKey(float thickness, boolean wood) { super(thickness); this.wood = wood; } - + public static WoodCacheKey of(@Nullable Float thickness, @Nullable Boolean wood) { float thick = thickness == null ? 0.5f : thickness; boolean wd = wood != null && wood; diff --git a/src/main/java/gregtech/client/renderer/texture/Textures.java b/src/main/java/gregtech/client/renderer/texture/Textures.java index 94cc907b1aa..2244f7bf97f 100644 --- a/src/main/java/gregtech/client/renderer/texture/Textures.java +++ b/src/main/java/gregtech/client/renderer/texture/Textures.java @@ -626,7 +626,6 @@ public static void register(TextureMap textureMap) { PIPE_LARGE_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_large_in_wood")), 0); PIPE_SIDE_WOOD.accept(textureMap.registerSprite(gregtechId("blocks/pipe/pipe_side_wood")), 0); - OPTICAL_PIPE_IN.accept(textureMap .registerSprite(new ResourceLocation(GTValues.MODID, "blocks/pipe/pipe_optical_in")), -1); OPTICAL_PIPE_SIDE.accept(textureMap diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 17804c23493..45c51b32e38 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -197,7 +197,8 @@ public static void init() { } CABLES.put(modid, cables); - Set structuresPipe = PipeStructureRegistry.getStructures(MaterialPipeStructure.class); + Set structuresPipe = PipeStructureRegistry + .getStructures(MaterialPipeStructure.class); MaterialPipeBlock[] pipes = new MaterialPipeBlock[structuresPipe.size()]; i = 0; for (MaterialPipeStructure struct : structuresPipe) { diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index dda0abd477c..8278daf8a53 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -11,16 +11,12 @@ import gregtech.api.cover.filter.CoverWithItemFilter; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.transfer.TransferControl; import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverse.TraverseGuide; import gregtech.api.graphnet.traverse.TraverseHelpers; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; -import gregtech.api.util.GTTransferUtils; import gregtech.api.util.ItemStackHashStrategy; import gregtech.api.util.function.BiIntConsumer; import gregtech.client.renderer.pipe.cover.CoverRenderer; @@ -28,21 +24,14 @@ import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; import gregtech.common.covers.filter.ItemFilterContainer; - import gregtech.common.covers.filter.MatchResult; import gregtech.common.covers.filter.MergabilityInfo; import gregtech.common.pipelike.net.item.IItemTransferController; - import gregtech.common.pipelike.net.item.IItemTraverseGuideProvider; - import gregtech.common.pipelike.net.item.ItemEQTraverseData; import gregtech.common.pipelike.net.item.ItemRRTraverseData; import gregtech.common.pipelike.net.item.ItemTraverseData; -import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; - -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; - import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -83,6 +72,8 @@ import com.cleanroommc.modularui.widgets.layout.Column; import com.cleanroommc.modularui.widgets.layout.Row; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; +import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; @@ -92,12 +83,10 @@ import java.util.ArrayDeque; import java.util.Map; -import java.util.Objects; -import java.util.Set; import java.util.function.IntUnaryOperator; public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithItemFilter, - TransferControlProvider, IItemTransferController { + TransferControlProvider, IItemTransferController { public final int tier; public final int maxItemTransferRate; @@ -237,13 +226,13 @@ protected void performTransferOnUpdate(@NotNull IItemHandler sourceHandler, @Not /** * Performs transfer * - * @param sourceHandler the handler to pull from - * @param destHandler the handler to push to - * @param byFilterSlot whether to perform the transfer by filter slot. - * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. - * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. + * @param sourceHandler the handler to pull from + * @param destHandler the handler to push to + * @param byFilterSlot whether to perform the transfer by filter slot. + * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. * Each filter slot will report its transfer before the next slot is calculated. * @return how much was transferred in total. @@ -301,11 +290,12 @@ protected int performTransfer(@NotNull IItemHandler sourceHandler, @NotNull IIte int remaining = max - transfer + toExtract; slotTransfer += transfer; if (remaining <= 0) continue; - for (MergabilityInfo.Merge otherMerge : mergabilityInfo.getNonLargestMerges(merge)) { + for (MergabilityInfo.Merge otherMerge : mergabilityInfo + .getNonLargestMerges(merge)) { transfer = Math.min(otherMerge.getCount(), remaining); transfer = insertToHandler(destHandler, merge.getTestObject(), transfer, true); toExtract = transfer; - for (int handlerSlot :otherMerge.getHandlerSlots()) { + for (int handlerSlot : otherMerge.getHandlerSlots()) { toExtract -= sourceHandler.extractItem(handlerSlot, toExtract, false).getCount(); if (toExtract == 0) break; } @@ -338,15 +328,20 @@ protected int insertToHandler(@NotNull IItemHandler destHandler, ItemTestObject case EQUALIZED -> { var guide = provider.getGuide(this::getEQTD, testObject, count, simulate); if (guide == null) return 0; - int consumed = (int) TraverseHelpers.traverseEqualDistribution(guide.getData(), guide.getPathsSupplier(), guide.getFlow(), true); + int consumed = (int) TraverseHelpers.traverseEqualDistribution(guide.getData(), + guide.getPathsSupplier(), guide.getFlow(), true); guide.reportConsumedFlow(consumed); return consumed; } case ROUND_ROBIN -> { - var guide = provider.getGuide((net, testObject1, simulator, queryTick, sourcePos, inputFacing) -> - getRRTD(net, testObject1, simulator, queryTick, sourcePos, inputFacing, simulate), testObject, count, simulate); + var guide = provider + .getGuide( + (net, testObject1, simulator, queryTick, sourcePos, inputFacing) -> getRRTD(net, + testObject1, simulator, queryTick, sourcePos, inputFacing, simulate), + testObject, count, simulate); if (guide == null) return 0; - int consumed = (int) TraverseHelpers.traverseRoundRobin(guide.getData(), guide.getPaths(), guide.getFlow(), true); + int consumed = (int) TraverseHelpers.traverseRoundRobin(guide.getData(), guide.getPaths(), + guide.getFlow(), true); guide.reportConsumedFlow(consumed); return consumed; } @@ -356,27 +351,30 @@ protected int insertToHandler(@NotNull IItemHandler destHandler, ItemTestObject @Contract("_, _, _, _, _, _ -> new") protected @NotNull ItemTraverseData getTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { + long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { return new ItemTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); } @Contract("_, _, _, _, _, _ -> new") protected @NotNull ItemEQTraverseData getEQTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { + long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { return new ItemEQTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); } @Contract("_, _, _, _, _, _, _ -> new") protected @NotNull ItemRRTraverseData getRRTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing, boolean simulate) { - return new ItemRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, getRoundRobinCache(simulate)); + long queryTick, BlockPos sourcePos, EnumFacing inputFacing, + boolean simulate) { + return new ItemRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, + getRoundRobinCache(simulate)); } protected ArrayDeque getRoundRobinCache(boolean simulate) { return simulate ? roundRobinCache.clone() : roundRobinCache; } - protected int simpleInsert(@NotNull IItemHandler destHandler, ItemTestObject testObject, int count, boolean simulate) { + protected int simpleInsert(@NotNull IItemHandler destHandler, ItemTestObject testObject, int count, + boolean simulate) { int available = count; for (int i = 0; i < destHandler.getSlots(); i++) { ItemStack toInsert = testObject.recombine(Math.min(available, destHandler.getSlotLimit(i))); @@ -712,6 +710,7 @@ public void readFromNBT(@NotNull NBTTagCompound tagCompound) { protected CoverRenderer buildRenderer() { return new CoverRendererBuilder(Textures.CONVEYOR_OVERLAY).build(); } + protected CoverRenderer buildRendererInverted() { return new CoverRendererBuilder(Textures.CONVEYOR_OVERLAY_INVERTED).build(); } diff --git a/src/main/java/gregtech/common/covers/CoverDigitalInterfaceWireless.java b/src/main/java/gregtech/common/covers/CoverDigitalInterfaceWireless.java index 7ed51c30bef..917adf66d04 100644 --- a/src/main/java/gregtech/common/covers/CoverDigitalInterfaceWireless.java +++ b/src/main/java/gregtech/common/covers/CoverDigitalInterfaceWireless.java @@ -19,12 +19,12 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; -import net.minecraft.util.math.RayTraceResult; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/common/covers/CoverFacade.java b/src/main/java/gregtech/common/covers/CoverFacade.java index 7eb14607f7f..c73f6ab7485 100644 --- a/src/main/java/gregtech/common/covers/CoverFacade.java +++ b/src/main/java/gregtech/common/covers/CoverFacade.java @@ -8,12 +8,10 @@ import gregtech.api.util.GTLog; import gregtech.client.renderer.handler.FacadeRenderer; import gregtech.client.renderer.pipe.cover.CoverRenderer; -import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.common.covers.facade.FacadeHelper; import gregtech.common.items.behaviors.FacadeItem; import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.Items; @@ -25,15 +23,13 @@ import net.minecraft.util.EnumFacing; import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.MinecraftForgeClient; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; - -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index 1bad8e9eba7..282d6e42f8a 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -3,9 +3,9 @@ import gregtech.api.capability.impl.FluidHandlerDelegate; import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; -import gregtech.api.cover.filter.CoverWithFluidFilter; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; +import gregtech.api.cover.filter.CoverWithFluidFilter; import gregtech.api.graphnet.pipenet.transfer.TransferControl; import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.predicate.test.FluidTestObject; @@ -19,7 +19,6 @@ import gregtech.common.covers.filter.BaseFilter; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.FluidFilterContainer; - import gregtech.common.pipelike.net.fluid.IFluidTransferController; import net.minecraft.entity.player.EntityPlayer; @@ -55,7 +54,7 @@ import java.io.IOException; public class CoverFluidFilter extends CoverBase implements CoverWithUI, CoverWithFluidFilter, TransferControlProvider, - IFluidTransferController { + IFluidTransferController { protected final String titleLocale; protected final SimpleOverlayRenderer texture; diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 8912cd60731..daa00abd5a0 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -11,7 +11,6 @@ import gregtech.api.util.GTUtility; import gregtech.common.covers.filter.FluidFilterContainer; import gregtech.common.covers.filter.SimpleFluidFilter; - import gregtech.common.pipelike.net.fluid.FluidEQTraverseData; import gregtech.common.pipelike.net.fluid.FluidRRTraverseData; import gregtech.common.pipelike.net.fluid.FluidTraverseData; @@ -35,7 +34,6 @@ import com.cleanroommc.modularui.value.sync.StringSyncValue; import com.cleanroommc.modularui.widget.ParentWidget; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -88,8 +86,7 @@ protected void performTransferOnUpdate(@NotNull IFluidHandler sourceHandler, @No if (getFluidsLeftToTransfer() < limit) { noTransferDueToMinimum = true; return 0; - } - else return limit; + } else return limit; }; performTransfer(sourceHandler, destHandler, true, maxflow, maxflow, (a, b) -> reportFluidsTransfer(b)); } @@ -118,7 +115,8 @@ protected void performTransferOnUpdate(@NotNull IFluidHandler sourceHandler, @No long queryTick, BlockPos sourcePos, EnumFacing inputFacing, boolean simulate) { if (transferMode == TransferMode.KEEP_EXACT) { - return new KeepFluidRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, getRoundRobinCache(simulate)); + return new KeepFluidRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, + getRoundRobinCache(simulate)); } return super.getRRTD(net, testObject, simulator, queryTick, sourcePos, inputFacing, simulate); } @@ -288,7 +286,7 @@ protected int computeContained(@NotNull IFluidHandler handler, @NotNull FluidTes protected class KeepFluidTraverseData extends FluidTraverseData { public KeepFluidTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing) { + BlockPos sourcePos, EnumFacing inputFacing) { super(net, testObject, simulator, queryTick, sourcePos, inputFacing); } @@ -301,7 +299,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl continue; // anti insert-to-our-source logic IFluidHandler container = capability.getValue() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + capability.getKey().getOpposite()); if (container != null) { int contained = computeContained(container, getTestObject()); assert getFluidFilter() != null; @@ -309,7 +308,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (contained >= kept) continue; availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() == null); + (int) Math.min(kept - contained, availableFlow), container, + getSimulatorKey() == null); } } return flowReachingDestination - availableFlow; @@ -318,7 +318,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl protected class KeepFluidEQTraverseData extends FluidEQTraverseData { - public KeepFluidEQTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, + public KeepFluidEQTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { super(net, testObject, simulator, queryTick, sourcePos, inputFacing); } @@ -333,7 +334,8 @@ protected void compute(@NotNull WorldPipeNetNode destination) { continue; // anti insert-to-our-source logic IFluidHandler container = capability.getValue() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + capability.getKey().getOpposite()); if (container != null) { int contained = computeContained(container, getTestObject()); assert getFluidFilter() != null; @@ -343,8 +345,9 @@ protected void compute(@NotNull WorldPipeNetNode destination) { destCount += 1; maxMinFlow = Math.min(maxMinFlow, IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), kept - contained, - container, false)); + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + kept - contained, + container, false)); } } } @@ -358,7 +361,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl continue; // anti insert-to-our-source logic IFluidHandler container = capability.getValue() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + capability.getKey().getOpposite()); if (container != null) { int contained = computeContained(container, getTestObject()); assert getFluidFilter() != null; @@ -366,7 +370,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (contained >= kept) continue; availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() == null); + (int) Math.min(kept - contained, availableFlow), container, + getSimulatorKey() == null); } } return flowReachingDestination - availableFlow; @@ -375,7 +380,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl protected class KeepFluidRRTraverseData extends FluidRRTraverseData { - public KeepFluidRRTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, + public KeepFluidRRTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, + long queryTick, BlockPos sourcePos, EnumFacing inputFacing, ArrayDeque cache) { super(net, testObject, simulator, queryTick, sourcePos, inputFacing, cache); } @@ -389,7 +395,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl continue; // anti insert-to-our-source logic IFluidHandler container = capability.getValue() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + capability.getKey().getOpposite()); if (container != null) { int contained = computeContained(container, getTestObject()); assert getFluidFilter() != null; @@ -397,7 +404,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (contained >= kept) continue; availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() == null); + (int) Math.min(kept - contained, availableFlow), container, + getSimulatorKey() == null); } } return flowReachingDestination - availableFlow; diff --git a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java index 969545e3c22..4a5a72497a3 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidVoiding.java +++ b/src/main/java/gregtech/common/covers/CoverFluidVoiding.java @@ -1,7 +1,6 @@ package gregtech.common.covers; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; import gregtech.api.util.GTTransferUtils; diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 16df0cf8a4b..00f81905861 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -19,7 +19,6 @@ import gregtech.common.covers.filter.BaseFilter; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.ItemFilterContainer; - import gregtech.common.pipelike.net.item.IItemTransferController; import net.minecraft.entity.player.EntityPlayer; @@ -54,7 +53,7 @@ import java.io.IOException; public class CoverItemFilter extends CoverBase implements CoverWithUI, CoverWithItemFilter, TransferControlProvider, - IItemTransferController { + IItemTransferController { protected final String titleLocale; protected final SimpleOverlayRenderer texture; diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index d739bad9793..cb987a29447 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -14,40 +14,25 @@ import gregtech.api.graphnet.pipenet.transfer.TransferControl; import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.graphnet.traverse.TraverseHelpers; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; -import gregtech.api.util.GTTransferUtils; import gregtech.api.util.function.BiIntConsumer; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; import gregtech.common.covers.filter.FluidFilterContainer; - -import gregtech.common.covers.filter.ItemFilterContainer; import gregtech.common.covers.filter.MatchResult; import gregtech.common.pipelike.net.fluid.FluidEQTraverseData; import gregtech.common.pipelike.net.fluid.FluidRRTraverseData; import gregtech.common.pipelike.net.fluid.FluidTraverseData; import gregtech.common.pipelike.net.fluid.IFluidTransferController; - import gregtech.common.pipelike.net.fluid.IFluidTraverseGuideProvider; -import gregtech.common.pipelike.net.item.IItemTraverseGuideProvider; -import gregtech.common.pipelike.net.item.ItemEQTraverseData; -import gregtech.common.pipelike.net.item.ItemRRTraverseData; -import gregtech.common.pipelike.net.item.ItemTraverseData; - -import it.unimi.dsi.fastutil.ints.Int2IntArrayMap; - -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; @@ -86,19 +71,16 @@ import com.cleanroommc.modularui.widgets.layout.Column; import com.cleanroommc.modularui.widgets.layout.Row; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; - -import net.minecraftforge.items.IItemHandler; - +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayDeque; -import java.util.Set; import java.util.function.IntUnaryOperator; public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithFluidFilter, - TransferControlProvider, IFluidTransferController { + TransferControlProvider, IFluidTransferController { public final int tier; public final int maxFluidTransferRate; @@ -218,7 +200,8 @@ public void update() { TileEntity tileEntity = getNeighbor(getAttachedSide()); IFluidHandler fluidHandler = tileEntity == null ? null : tileEntity .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, getAttachedSide().getOpposite()); - IFluidHandler myFluidHandler = getCoverableView().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + IFluidHandler myFluidHandler = getCoverableView().getCapability( + CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, getAttachedSide()); if (myFluidHandler != null && fluidHandler != null) { if (pumpMode == PumpMode.EXPORT) { @@ -253,13 +236,13 @@ protected void performTransferOnUpdate(@NotNull IFluidHandler sourceHandler, @No /** * Performs transfer * - * @param sourceHandler the handler to pull from - * @param destHandler the handler to push to - * @param byFilterSlot whether to perform the transfer by filter slot. - * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. - * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. + * @param sourceHandler the handler to pull from + * @param destHandler the handler to push to + * @param byFilterSlot whether to perform the transfer by filter slot. + * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. * Each filter slot will report its transfer before the next slot is calculated. * @return how much was transferred in total. @@ -323,15 +306,20 @@ protected int insertToHandler(@NotNull IFluidHandler destHandler, FluidTestObjec case EQUALIZED -> { var guide = provider.getGuide(this::getEQTD, testObject, count, simulate); if (guide == null) return 0; - int consumed = (int) TraverseHelpers.traverseEqualDistribution(guide.getData(), guide.getPathsSupplier(), guide.getFlow(), true); + int consumed = (int) TraverseHelpers.traverseEqualDistribution(guide.getData(), + guide.getPathsSupplier(), guide.getFlow(), true); guide.reportConsumedFlow(consumed); return consumed; } case ROUND_ROBIN -> { - var guide = provider.getGuide((net, testObject1, simulator, queryTick, sourcePos, inputFacing) -> - getRRTD(net, testObject1, simulator, queryTick, sourcePos, inputFacing, simulate), testObject, count, simulate); + var guide = provider + .getGuide( + (net, testObject1, simulator, queryTick, sourcePos, inputFacing) -> getRRTD(net, + testObject1, simulator, queryTick, sourcePos, inputFacing, simulate), + testObject, count, simulate); if (guide == null) return 0; - int consumed = (int) TraverseHelpers.traverseRoundRobin(guide.getData(), guide.getPaths(), guide.getFlow(), true); + int consumed = (int) TraverseHelpers.traverseRoundRobin(guide.getData(), guide.getPaths(), + guide.getFlow(), true); guide.reportConsumedFlow(consumed); return consumed; } @@ -353,15 +341,18 @@ protected int insertToHandler(@NotNull IFluidHandler destHandler, FluidTestObjec @Contract("_, _, _, _, _, _, _ -> new") protected @NotNull FluidRRTraverseData getRRTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing, boolean simulate) { - return new FluidRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, getRoundRobinCache(simulate)); + long queryTick, BlockPos sourcePos, EnumFacing inputFacing, + boolean simulate) { + return new FluidRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, + getRoundRobinCache(simulate)); } protected ArrayDeque getRoundRobinCache(boolean simulate) { return simulate ? roundRobinCache.clone() : roundRobinCache; } - protected int simpleInsert(@NotNull IFluidHandler destHandler, FluidTestObject testObject, int count, boolean simulate) { + protected int simpleInsert(@NotNull IFluidHandler destHandler, FluidTestObject testObject, int count, + boolean simulate) { return count - destHandler.fill(testObject.recombine(count), !simulate); } @@ -564,6 +555,7 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra protected CoverRenderer buildRenderer() { return new CoverRendererBuilder(Textures.PUMP_OVERLAY).build(); } + protected CoverRenderer buildRendererInverted() { return new CoverRendererBuilder(Textures.PUMP_OVERLAY_INVERTED).build(); } diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index f43fed636eb..8b364e1439f 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -12,9 +12,7 @@ import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; -import gregtech.common.covers.filter.FluidFilterContainer; import gregtech.common.covers.filter.ItemFilterContainer; - import gregtech.common.pipelike.net.item.IItemTransferController; import gregtech.common.pipelike.net.item.ItemEQTraverseData; import gregtech.common.pipelike.net.item.ItemRRTraverseData; @@ -114,8 +112,7 @@ protected void performTransferOnUpdate(@NotNull IItemHandler sourceHandler, @Not if (getItemsLeftToTransfer() < limit) { noTransferDueToMinimum = true; return 0; - } - else return limit; + } else return limit; }; performTransfer(sourceHandler, destHandler, true, maxflow, maxflow, (a, b) -> reportItemsTransfer(b)); } @@ -141,9 +138,11 @@ protected void performTransferOnUpdate(@NotNull IItemHandler sourceHandler, @Not @Override protected @NotNull ItemRRTraverseData getRRTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing, boolean simulate) { + long queryTick, BlockPos sourcePos, EnumFacing inputFacing, + boolean simulate) { if (transferMode == TransferMode.KEEP_EXACT) { - return new KeepItemRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, getRoundRobinCache(simulate)); + return new KeepItemRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, + getRoundRobinCache(simulate)); } return super.getRRTD(net, testObject, simulator, queryTick, sourcePos, inputFacing, simulate); } @@ -313,7 +312,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl continue; // anti insert-to-our-source logic IItemHandler container = capability.getValue() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, + capability.getKey().getOpposite()); if (container != null) { int contained = computeContained(container, getTestObject()); assert getItemFilter() != null; @@ -321,7 +321,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (contained >= kept) continue; availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() != null); + (int) Math.min(kept - contained, availableFlow), container, + getSimulatorKey() != null); } } return flowReachingDestination - availableFlow; @@ -345,7 +346,8 @@ protected void compute(@NotNull WorldPipeNetNode destination) { continue; // anti insert-to-our-source logic IItemHandler container = capability.getValue() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, + capability.getKey().getOpposite()); if (container != null) { int contained = computeContained(container, getTestObject()); assert getItemFilter() != null; @@ -357,7 +359,7 @@ protected void compute(@NotNull WorldPipeNetNode destination) { maxMinFlow = Math.min(maxMinFlow, test - IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), test, - container, true)); + container, true)); } } } @@ -371,7 +373,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl continue; // anti insert-to-our-source logic IItemHandler container = capability.getValue() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, + capability.getKey().getOpposite()); if (container != null) { int contained = computeContained(container, getTestObject()); assert getItemFilter() != null; @@ -379,7 +382,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (contained >= kept) continue; availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() != null); + (int) Math.min(kept - contained, availableFlow), container, + getSimulatorKey() != null); } } return flowReachingDestination - availableFlow; @@ -402,7 +406,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl continue; // anti insert-to-our-source logic IItemHandler container = capability.getValue() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, + capability.getKey().getOpposite()); if (container != null) { int contained = computeContained(container, getTestObject()); assert getItemFilter() != null; @@ -410,7 +415,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (contained >= kept) continue; availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, getSimulatorKey() != null); + (int) Math.min(kept - contained, availableFlow), container, + getSimulatorKey() != null); } } return flowReachingDestination - availableFlow; diff --git a/src/main/java/gregtech/common/covers/CoverShutter.java b/src/main/java/gregtech/common/covers/CoverShutter.java index 70b3eaf577e..c79c939e50f 100644 --- a/src/main/java/gregtech/common/covers/CoverShutter.java +++ b/src/main/java/gregtech/common/covers/CoverShutter.java @@ -25,7 +25,6 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java b/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java index 55015bb194d..e2a0f71b8f3 100644 --- a/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java +++ b/src/main/java/gregtech/common/covers/detector/CoverDetectorEnergyAdvanced.java @@ -20,14 +20,12 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.RayTraceResult; import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; - -import net.minecraft.util.math.RayTraceResult; - import org.jetbrains.annotations.NotNull; public class CoverDetectorEnergyAdvanced extends CoverDetectorEnergy implements CoverWithUI { diff --git a/src/main/java/gregtech/common/covers/filter/MergabilityInfo.java b/src/main/java/gregtech/common/covers/filter/MergabilityInfo.java index 16f6343196a..d961bb84f6d 100644 --- a/src/main/java/gregtech/common/covers/filter/MergabilityInfo.java +++ b/src/main/java/gregtech/common/covers/filter/MergabilityInfo.java @@ -4,16 +4,10 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import net.minecraft.item.ItemStack; - import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jgrapht.alg.util.Pair; import java.util.Comparator; import java.util.List; @@ -23,7 +17,7 @@ public final class MergabilityInfo { private final Object2ObjectOpenHashMap mergeMap = new Object2ObjectOpenHashMap<>(); public void add(int handlerSlot, T testObject, int count) { - mergeMap.compute(testObject, (k , v) -> { + mergeMap.compute(testObject, (k, v) -> { if (v == null) v = new Merge(k); v.count += count; v.handlerSlots.add(handlerSlot); @@ -42,6 +36,7 @@ public Merge getLargestMerge() { } public final class Merge { + private final T testObject; private int count = 0; diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index 864a9b88e29..122ae9621ae 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -1,48 +1,31 @@ package gregtech.common.pipelike.block.cable; import gregtech.api.damagesources.DamageSources; -import gregtech.api.graphnet.AbstractGroupData; -import gregtech.api.graphnet.NetGroup; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.IBurnable; -import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; -import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.unification.material.registry.MaterialRegistry; - -import gregtech.api.util.EntityDamageUtil; import gregtech.api.util.GTUtility; import gregtech.common.creativetab.GTCreativeTabs; - import gregtech.common.pipelike.net.energy.EnergyFlowData; import gregtech.common.pipelike.net.energy.EnergyFlowLogic; import gregtech.common.pipelike.net.energy.SuperconductorLogic; import gregtech.common.pipelike.net.energy.WorldEnergyNet; - -import gregtech.common.pipelikeold.cable.net.EnergyGroupData; - import gregtech.core.advancement.AdvancementTriggers; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayerMP; -import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraftforge.fml.common.FMLCommonHandler; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.lang.ref.WeakReference; import java.util.Map; public class CableBlock extends PipeMaterialBlock implements IBurnable { diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java index 83293082727..336b773d54d 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java @@ -16,7 +16,8 @@ @Desugar public record LaserStructure(String name, float renderThickness, ActivablePipeModel model) implements IPipeStructure { - public static final LaserStructure INSTANCE = new LaserStructure("laser_pipe_normal", 0.375f, ActivablePipeModel.LASER); + public static final LaserStructure INSTANCE = new LaserStructure("laser_pipe_normal", 0.375f, + ActivablePipeModel.LASER); public LaserStructure(String name, float renderThickness, ActivablePipeModel model) { this.name = name; diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java index 9da4d3c226b..6fb375018c4 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java @@ -4,7 +4,6 @@ import gregtech.api.graphnet.pipenet.physical.IFreezable; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.unification.material.registry.MaterialRegistry; - import gregtech.common.creativetab.GTCreativeTabs; public class MaterialPipeBlock extends PipeMaterialBlock implements IBurnable, IFreezable { diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java index 50a25227f81..15c92430d18 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java @@ -17,36 +17,50 @@ public record MaterialPipeStructure(String name, int material, int channelCount, float renderThickness, PipeModel model) implements IPipeMaterialStructure, IPipeChanneledStructure { - public static final MaterialPipeStructure TINY = new MaterialPipeStructure("pipe_tiny", 1, 1, false, OrePrefix.pipeTiny, 0.25f, + public static final MaterialPipeStructure TINY = new MaterialPipeStructure("pipe_tiny", 1, 1, false, + OrePrefix.pipeTiny, 0.25f, PipeModel.INSTANCES[0]); - public static final MaterialPipeStructure SMALL = new MaterialPipeStructure("pipe_small", 2, 1, false, OrePrefix.pipeSmall, 0.375f, + public static final MaterialPipeStructure SMALL = new MaterialPipeStructure("pipe_small", 2, 1, false, + OrePrefix.pipeSmall, 0.375f, PipeModel.INSTANCES[1]); - public static final MaterialPipeStructure NORMAL = new MaterialPipeStructure("pipe_normal", 6, 1, false, OrePrefix.pipeNormal, 0.5f, + public static final MaterialPipeStructure NORMAL = new MaterialPipeStructure("pipe_normal", 6, 1, false, + OrePrefix.pipeNormal, 0.5f, PipeModel.INSTANCES[2]); - public static final MaterialPipeStructure LARGE = new MaterialPipeStructure("pipe_large", 12, 1, false, OrePrefix.pipeLarge, 0.75f, + public static final MaterialPipeStructure LARGE = new MaterialPipeStructure("pipe_large", 12, 1, false, + OrePrefix.pipeLarge, 0.75f, PipeModel.INSTANCES[3]); - public static final MaterialPipeStructure HUGE = new MaterialPipeStructure("pipe_huge", 24, 1, false, OrePrefix.pipeHuge, 0.875f, + public static final MaterialPipeStructure HUGE = new MaterialPipeStructure("pipe_huge", 24, 1, false, + OrePrefix.pipeHuge, 0.875f, PipeModel.INSTANCES[4]); - public static final MaterialPipeStructure QUADRUPLE = new MaterialPipeStructure("pipe_quadruple", 8, 4, false, OrePrefix.pipeQuadruple, + public static final MaterialPipeStructure QUADRUPLE = new MaterialPipeStructure("pipe_quadruple", 8, 4, false, + OrePrefix.pipeQuadruple, 0.95f, PipeModel.INSTANCES[5]); - public static final MaterialPipeStructure NONUPLE = new MaterialPipeStructure("pipe_nonuple", 18, 9, false, OrePrefix.pipeNonuple, 0.95f, + public static final MaterialPipeStructure NONUPLE = new MaterialPipeStructure("pipe_nonuple", 18, 9, false, + OrePrefix.pipeNonuple, 0.95f, PipeModel.INSTANCES[6]); - public static final MaterialPipeStructure TINY_RESTRICTIVE = new MaterialPipeStructure("pipe_tiny_restrictive", 1, 1, true, + public static final MaterialPipeStructure TINY_RESTRICTIVE = new MaterialPipeStructure("pipe_tiny_restrictive", 1, + 1, true, OrePrefix.pipeTinyRestrictive, 0.25f, PipeModel.RESTRICTIVE_INSTANCES[0]); - public static final MaterialPipeStructure SMALL_RESTRICTIVE = new MaterialPipeStructure("pipe_small_restrictive", 2, 1, true, + public static final MaterialPipeStructure SMALL_RESTRICTIVE = new MaterialPipeStructure("pipe_small_restrictive", 2, + 1, true, OrePrefix.pipeSmallRestrictive, 0.375f, PipeModel.RESTRICTIVE_INSTANCES[1]); - public static final MaterialPipeStructure NORMAL_RESTRICTIVE = new MaterialPipeStructure("pipe_normal_restrictive", 6, 1, true, + public static final MaterialPipeStructure NORMAL_RESTRICTIVE = new MaterialPipeStructure("pipe_normal_restrictive", + 6, 1, true, OrePrefix.pipeNormalRestrictive, 0.5f, PipeModel.RESTRICTIVE_INSTANCES[2]); - public static final MaterialPipeStructure LARGE_RESTRICTIVE = new MaterialPipeStructure("pipe_large_restrictive", 12, 1, true, + public static final MaterialPipeStructure LARGE_RESTRICTIVE = new MaterialPipeStructure("pipe_large_restrictive", + 12, 1, true, OrePrefix.pipeLargeRestrictive, 0.75f, PipeModel.RESTRICTIVE_INSTANCES[3]); - public static final MaterialPipeStructure HUGE_RESTRICTIVE = new MaterialPipeStructure("pipe_huge_restrictive", 24, 1, true, + public static final MaterialPipeStructure HUGE_RESTRICTIVE = new MaterialPipeStructure("pipe_huge_restrictive", 24, + 1, true, OrePrefix.pipeHugeRestrictive, 0.875f, PipeModel.RESTRICTIVE_INSTANCES[4]); - public static final MaterialPipeStructure QUADRUPLE_RESTRICTIVE = new MaterialPipeStructure("pipe_quadruple_restrictive", 8, 4, true, + public static final MaterialPipeStructure QUADRUPLE_RESTRICTIVE = new MaterialPipeStructure( + "pipe_quadruple_restrictive", 8, 4, true, OrePrefix.pipeQuadrupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[5]); - public static final MaterialPipeStructure NONUPLE_RESTRICTIVE = new MaterialPipeStructure("pipe_nonuple_restrictive", 18, 9, true, + public static final MaterialPipeStructure NONUPLE_RESTRICTIVE = new MaterialPipeStructure( + "pipe_nonuple_restrictive", 18, 9, true, OrePrefix.pipeNonupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[6]); public MaterialPipeStructure(String name, int material, int channelCount, boolean restrictive, OrePrefix ore, diff --git a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java index 788f630fcca..15d1b0dc95a 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java @@ -23,7 +23,8 @@ public final class LaserNetHandler implements IPipeNetNodeHandler { public static final LaserNetHandler INSTANCE = new LaserNetHandler(); @Override - public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, + IPipeStructure structure) { if (structure instanceof LaserStructure) { return Collections.singletonList(WorldLaserNet.getWorldNet(world).getOrCreateNode(pos)); } diff --git a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java index 16353cd7702..81e82472153 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java @@ -23,7 +23,8 @@ public final class OpticalNetHandler implements IPipeNetNodeHandler { public static final OpticalNetHandler INSTANCE = new OpticalNetHandler(); @Override - public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, + IPipeStructure structure) { if (structure instanceof OpticalStructure) { return Collections.singletonList(WorldOpticalNet.getWorldNet(world).getOrCreateNode(pos)); } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index b11d249b673..70e80bb253a 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -23,9 +23,9 @@ import gregtech.api.util.function.TriConsumer; import gregtech.common.pipelike.block.cable.CableStructure; import gregtech.common.pipelike.block.pipe.MaterialPipeStructure; -import gregtech.common.pipelike.net.energy.VoltageLossLogic; import gregtech.common.pipelike.net.energy.SuperconductorLogic; import gregtech.common.pipelike.net.energy.VoltageLimitLogic; +import gregtech.common.pipelike.net.energy.VoltageLossLogic; import gregtech.common.pipelike.net.energy.WorldEnergyNet; import net.minecraft.client.resources.I18n; @@ -45,7 +45,8 @@ public final class MaterialEnergyProperties implements PipeNetProperties.IPipeNetMaterialProperty { - public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>("EnergyProperties"); + public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>( + "EnergyProperties"); private final long voltageLimit; private final long amperageLimit; @@ -116,7 +117,6 @@ public MaterialPropertyKey getKey() { @Override public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn, IPipeMaterialStructure structure) { - int tier = GTUtility.getTierByVoltage(voltageLimit); if (isSuperconductor()) tooltip.add(I18n.format("gregtech.cable.superconductor", GTValues.VN[tier])); diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index f3e98237b5c..09b5dcf1a5e 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -155,7 +155,8 @@ public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull Lis tooltip.add(I18n.format("gregtech.universal.tooltip.fluid_transfer_rate", getThroughput(structure))); tooltip.add(I18n.format("gregtech.fluid_pipe.max_temperature", getMaxFluidTemperature())); tooltip.add(I18n.format("gregtech.fluid_pipe.min_temperature", getMinFluidTemperature())); - tooltip.add(I18n.format("gregtech.fluid_pipe.priority", TextFormattingUtil.formatNumbers(getFlowPriority(structure)))); + tooltip.add(I18n.format("gregtech.fluid_pipe.priority", + TextFormattingUtil.formatNumbers(getFlowPriority(structure)))); } @Override diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index 0d005293fcf..d33d65023ea 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -49,14 +49,15 @@ public MaterialPropertyKey getKey() { @Override public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn, IPipeMaterialStructure structure) { - if (baseItemsPer5Ticks % 16 != 0) { + if (baseItemsPer5Ticks % 16 != 0) { tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate", baseItemsPer5Ticks * 4)); } else { tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate_stacks", baseItemsPer5Ticks / 16)); } - tooltip.add(I18n.format("gregtech.item_pipe.priority", TextFormattingUtil.formatNumbers(getFlowPriority(structure)))); + tooltip.add(I18n.format("gregtech.item_pipe.priority", + TextFormattingUtil.formatNumbers(getFlowPriority(structure)))); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java index 722146c443b..eb96dc76fb2 100644 --- a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java +++ b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java @@ -1,19 +1,15 @@ package gregtech.common.pipelike.net; -import com.google.common.collect.BiMap; - -import com.google.common.collect.HashBiMap; - import gregtech.api.graphnet.path.AbstractNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.util.TaskScheduler; import gregtech.api.util.function.Task; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.world.World; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,13 +19,15 @@ public class SlowActiveWalker implements Task { private static final int RECENT_WALKER_CUTOFF = 5; - private static final BiMap, SlowActiveWalker> RECENT_WALKERS = HashBiMap.create(); + private static final BiMap, SlowActiveWalker> RECENT_WALKERS = HashBiMap + .create(); /** * Dispatches a slow walker along a path with default parameters. + * * @param world the world to schedule the task in. When this world is unloaded, the task will die no matter * its state, so be careful! - * @param path the path to walk. + * @param path the path to walk. * @param delay the ticks between steps of the walker */ public static void dispatch(World world, AbstractNetPath path, int delay) { @@ -38,11 +36,12 @@ public static void dispatch(World world, AbstractNetPath path, int delay, diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java index e106b9e2e93..d4143680136 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java @@ -2,19 +2,12 @@ import gregtech.api.graphnet.logic.NetLogicEntry; -import it.unimi.dsi.fastutil.longs.Long2LongLinkedOpenHashMap; +import net.minecraft.nbt.NBTTagByte; +import net.minecraft.network.PacketBuffer; -import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; - -import it.unimi.dsi.fastutil.longs.Long2ObjectRBTreeMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectIterator; - -import net.minecraft.nbt.NBTTagByte; -import net.minecraft.network.PacketBuffer; - import org.jetbrains.annotations.NotNull; import java.util.Collections; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index a431be17c72..6d5d4e9ecc1 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -11,7 +11,6 @@ import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; -import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.AbstractTraverseData; import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; @@ -108,7 +107,7 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (container != null) { availableFlow -= IEnergyTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(pathVoltage, availableFlow, container, - capability.getKey(), getSimulatorKey() != null); + capability.getKey(), getSimulatorKey() != null); } } long accepted = flowReachingDestination - availableFlow; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java b/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java index 628c5c3eec9..5c637f0c398 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java @@ -41,7 +41,7 @@ public long insertToHandler(long voltage, long amperage, @NotNull IEnergyContain * @return inserted amperes */ default long insertToHandler(long voltage, long amperage, @NotNull IEnergyContainer destHandler, EnumFacing side, - boolean simulate) { + boolean simulate) { return destHandler.acceptEnergyFromNetwork(side, voltage, amperage, simulate); } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index ad029234483..f7132209dd1 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -14,9 +14,6 @@ import gregtech.api.graphnet.traverse.TraverseDataProvider; import gregtech.api.graphnet.traverse.TraverseGuide; import gregtech.api.graphnet.traverse.TraverseHelpers; -import gregtech.common.pipelike.net.energy.WorldEnergyNet; - -import gregtech.common.pipelike.net.item.ItemCapabilityObject; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; @@ -34,7 +31,8 @@ import java.util.Iterator; import java.util.function.LongConsumer; -public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler, IFluidTankProperties, IFluidTraverseGuideProvider { +public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler, IFluidTankProperties, + IFluidTraverseGuideProvider { private final WorldPipeNet net; private @Nullable PipeTileEntity tile; @@ -47,7 +45,8 @@ public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandl public FluidCapabilityObject(@NotNull N net, WorldPipeNetNode node) { this.net = net; - properties = new IFluidTankProperties[node.getData().getLogicEntryDefaultable(ChannelCountLogic.INSTANCE).getValue()]; + properties = new IFluidTankProperties[node.getData().getLogicEntryDefaultable(ChannelCountLogic.INSTANCE) + .getValue()]; Arrays.fill(properties, this); for (EnumFacing facing : EnumFacing.VALUES) { AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); @@ -108,15 +107,22 @@ public int fill(FluidStack resource, boolean doFill, EnumFacing side) { } @Override - public @Nullable > TraverseGuide getGuide( - TraverseDataProvider provider, FluidTestObject testObject, long flow, - boolean simulate) { + public @Nullable < + D extends ITraverseData> TraverseGuide getGuide( + TraverseDataProvider provider, + FluidTestObject testObject, + long flow, + boolean simulate) { return getGuide(provider, testObject, flow, simulate, null); } - public @Nullable > TraverseGuide getGuide( - TraverseDataProvider provider, FluidTestObject testObject, long flow, - boolean simulate, EnumFacing side) { + public @Nullable < + D extends ITraverseData> TraverseGuide getGuide( + TraverseDataProvider provider, + FluidTestObject testObject, + long flow, + boolean simulate, + EnumFacing side) { if (tile == null || inputDisallowed(side)) return null; SimulatorKey simulator = simulate ? SimulatorKey.getNewSimulatorInstance() : null; long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); @@ -198,9 +204,12 @@ public Wrapper(EnumFacing facing, AbstractNetFlowEdge buffer) { } @Override - public @Nullable > TraverseGuide getGuide( - TraverseDataProvider provider, FluidTestObject testObject, long flow, - boolean simulate) { + public @Nullable < + D extends ITraverseData> TraverseGuide getGuide( + TraverseDataProvider provider, + FluidTestObject testObject, + long flow, + boolean simulate) { return FluidCapabilityObject.this.getGuide(provider, testObject, flow, simulate, facing); } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java index 59880946aa7..ae4c42299d9 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java @@ -6,18 +6,17 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.traverse.IEqualizableTraverseData; - import gregtech.api.util.GTUtility; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; - import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import org.jetbrains.annotations.NotNull; -public class FluidEQTraverseData extends FluidTraverseData implements IEqualizableTraverseData { +public class FluidEQTraverseData extends FluidTraverseData + implements IEqualizableTraverseData { protected int destCount; protected int maxMinFlow; @@ -42,8 +41,9 @@ protected void compute(@NotNull WorldPipeNetNode destination) { destCount += 1; maxMinFlow = Math.min(maxMinFlow, IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), Integer.MAX_VALUE, - container, false)); + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + Integer.MAX_VALUE, + container, false)); } } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java index 6f862e6d29c..52ec65428b0 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java @@ -14,7 +14,8 @@ import java.util.ArrayDeque; -public class FluidRRTraverseData extends FluidTraverseData implements IRoundRobinTraverseData { +public class FluidRRTraverseData extends FluidTraverseData + implements IRoundRobinTraverseData { private final ArrayDeque cache; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index aabbc6bdf61..53b0384acbe 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -154,7 +154,7 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (container != null) { availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(Integer.MAX_VALUE, availableFlow), container, getSimulatorKey() == null); + (int) Math.min(Integer.MAX_VALUE, availableFlow), container, getSimulatorKey() == null); } } return flowReachingDestination - availableFlow; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java index e5e1e1f3ed6..33c83016602 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java @@ -1,7 +1,6 @@ package gregtech.common.pipelike.net.fluid; import gregtech.api.graphnet.pipenet.transfer.TransferControl; - import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.predicate.test.FluidTestObject; @@ -48,7 +47,8 @@ public int insertToHandler(@NotNull FluidTestObject testObject, int amount, /** * @return the amount filled. */ - default int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, boolean doFill) { + default int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, + boolean doFill) { return destHandler.fill(testObject.recombine(amount), doFill); } @@ -57,7 +57,7 @@ default int insertToHandler(@NotNull FluidTestObject testObject, int amount, @No */ @Nullable default FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, IFluidHandler sourceHandler, - boolean doDrain) { + boolean doDrain) { if (testObject == null) return sourceHandler.drain(amount, doDrain); else { FluidStack recombined = testObject.recombine(); diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java index 89e08a61e4a..e40e81a2e70 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java @@ -3,7 +3,6 @@ import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.graphnet.traverse.ITraverseData; import gregtech.api.graphnet.traverse.ITraverseGuideProvider; import gregtech.api.graphnet.traverse.TraverseDataProvider; @@ -11,10 +10,14 @@ import org.jetbrains.annotations.Nullable; -public interface IFluidTraverseGuideProvider extends ITraverseGuideProvider { +public interface IFluidTraverseGuideProvider extends + ITraverseGuideProvider { @Nullable @Override > TraverseGuide getGuide( - TraverseDataProvider provider, FluidTestObject testObject, long flow, boolean simulate); + TraverseDataProvider provider, + FluidTestObject testObject, + long flow, + boolean simulate); } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 98f17f61ade..7effff1be8a 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -11,8 +11,8 @@ import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; -import gregtech.api.graphnet.pipenet.predicate.FilterPredicate; import gregtech.api.graphnet.pipenet.predicate.BlockedPredicate; +import gregtech.api.graphnet.pipenet.predicate.FilterPredicate; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.common.covers.FluidFilterMode; import gregtech.common.covers.ManualImportExportMode; @@ -66,9 +66,9 @@ protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nulla return; } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && filter.getFilterMode() != FluidFilterMode.FILTER_FILL) { - predicate = FilterPredicate.INSTANCE.getNew(); - predicate.setSourceFilter(filter.getFluidFilter()); - } + predicate = FilterPredicate.INSTANCE.getNew(); + predicate.setSourceFilter(filter.getFluidFilter()); + } } if (b instanceof CoverWithFluidFilter filter) { if (filter.getManualMode() == ManualImportExportMode.DISABLED) { @@ -77,9 +77,9 @@ protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nulla return; } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && filter.getFilterMode() != FluidFilterMode.FILTER_DRAIN) { - if (predicate == null) predicate = FilterPredicate.INSTANCE.getNew(); - predicate.setTargetFilter(filter.getFluidFilter()); - } + if (predicate == null) predicate = FilterPredicate.INSTANCE.getNew(); + predicate.setTargetFilter(filter.getFluidFilter()); + } } if (predicate != null) edge.getPredicateHandler().setPredicate(predicate); } diff --git a/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java b/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java index 462437b570f..3c9f3e3f128 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java +++ b/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java @@ -1,12 +1,10 @@ package gregtech.common.pipelike.net.item; -import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.pipenet.transfer.TransferControl; - +import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.predicate.test.ItemTestObject; import net.minecraft.item.ItemStack; - import net.minecraftforge.items.IItemHandler; import org.jetbrains.annotations.NotNull; @@ -50,7 +48,7 @@ public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, * @return the amount left uninserted; aka the remainder */ default int insertToHandler(@NotNull ItemTestObject testObject, int amount, - @NotNull IItemHandler destHandler, boolean simulate) { + @NotNull IItemHandler destHandler, boolean simulate) { int available = amount; for (int i = 0; i < destHandler.getSlots(); i++) { int allowed = Math.min(available, Math.min(destHandler.getSlotLimit(i), testObject.getStackLimit())); @@ -63,7 +61,7 @@ default int insertToHandler(@NotNull ItemTestObject testObject, int amount, * @return the amount extracted */ default int extractFromHandler(@NotNull ItemTestObject testObject, int amount, - @NotNull IItemHandler sourceHandler, boolean simulate) { + @NotNull IItemHandler sourceHandler, boolean simulate) { int extracted = 0; for (int i = 0; i < sourceHandler.getSlots(); i++) { ItemStack stack = sourceHandler.extractItem(i, amount - extracted, true); diff --git a/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java b/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java index a955651d7e4..3bd33cce2ad 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java +++ b/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java @@ -10,10 +10,14 @@ import org.jetbrains.annotations.Nullable; -public interface IItemTraverseGuideProvider extends ITraverseGuideProvider { +public interface IItemTraverseGuideProvider extends + ITraverseGuideProvider { @Nullable @Override > TraverseGuide getGuide( - TraverseDataProvider provider, ItemTestObject testObject, long flow, boolean simulate); + TraverseDataProvider provider, + ItemTestObject testObject, + long flow, + boolean simulate); } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index c93539952c6..755adb97a8b 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -97,13 +97,21 @@ public T getCapabilityForSide(Capability capability, @Nullable EnumFacing @Nullable @Override public > TraverseGuide getGuide( - TraverseDataProvider provider, ItemTestObject testObject, long flow, boolean simulate) { + TraverseDataProvider provider, + ItemTestObject testObject, + long flow, + boolean simulate) { return getGuide(provider, testObject, flow, simulate, null); } @Nullable - protected > TraverseGuide getGuide( - TraverseDataProvider provider, ItemTestObject testObject, long flow, boolean simulate, EnumFacing side) { + protected < + D extends ITraverseData> TraverseGuide getGuide( + TraverseDataProvider provider, + ItemTestObject testObject, + long flow, + boolean simulate, + EnumFacing side) { if (tile == null || inputDisallowed(side)) return null; SimulatorKey simulator = simulate ? SimulatorKey.getNewSimulatorInstance() : null; @@ -165,8 +173,10 @@ public Wrapper(EnumFacing facing, AbstractNetFlowEdge buffer) { @Nullable @Override public > TraverseGuide getGuide( - TraverseDataProvider provider, ItemTestObject testObject, long flow, - boolean simulate) { + TraverseDataProvider provider, + ItemTestObject testObject, + long flow, + boolean simulate) { return ItemCapabilityObject.this.getGuide(provider, testObject, flow, simulate, facing); } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java index 94e9794ad76..2caa35f7371 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java @@ -6,7 +6,6 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.graphnet.traverse.IEqualizableTraverseData; - import gregtech.api.util.GTUtility; import net.minecraft.util.EnumFacing; @@ -16,7 +15,8 @@ import org.jetbrains.annotations.NotNull; -public class ItemEQTraverseData extends ItemTraverseData implements IEqualizableTraverseData { +public class ItemEQTraverseData extends ItemTraverseData + implements IEqualizableTraverseData { protected int destCount; protected int maxMinFlow; @@ -43,7 +43,7 @@ protected void compute(@NotNull WorldPipeNetNode destination) { maxMinFlow = Math.min(maxMinFlow, test - IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), test, - container, true)); + container, true)); } } } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java index 2b7b1db92c2..c417305eb61 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java @@ -14,7 +14,8 @@ import java.util.ArrayDeque; -public class ItemRRTraverseData extends ItemTraverseData implements IRoundRobinTraverseData { +public class ItemRRTraverseData extends ItemTraverseData + implements IRoundRobinTraverseData { private final ArrayDeque cache; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java index 05676341359..c1c319d2921 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java @@ -55,8 +55,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); if (container != null) { availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(Integer.MAX_VALUE, availableFlow), container, getSimulatorKey() != null); + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + (int) Math.min(Integer.MAX_VALUE, availableFlow), container, getSimulatorKey() != null); } } return flowReachingDestination - availableFlow; diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 50ab0def139..007e20041fd 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -6,14 +6,13 @@ import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.edge.NetFlowSharedEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; -import gregtech.api.graphnet.pipenet.predicate.FilterPredicate; import gregtech.api.graphnet.pipenet.predicate.BlockedPredicate; +import gregtech.api.graphnet.pipenet.predicate.FilterPredicate; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.common.covers.ItemFilterMode; import gregtech.common.covers.ManualImportExportMode; @@ -67,9 +66,9 @@ protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nulla return; } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && filter.getFilterMode() != ItemFilterMode.FILTER_INSERT) { - predicate = FilterPredicate.INSTANCE.getNew(); - predicate.setSourceFilter(filter.getItemFilter()); - } + predicate = FilterPredicate.INSTANCE.getNew(); + predicate.setSourceFilter(filter.getItemFilter()); + } } if (b instanceof CoverWithItemFilter filter) { if (filter.getManualMode() == ManualImportExportMode.DISABLED) { @@ -78,9 +77,9 @@ protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nulla return; } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT) { - if (predicate == null) predicate = FilterPredicate.INSTANCE.getNew(); - predicate.setTargetFilter(filter.getItemFilter()); - } + if (predicate == null) predicate = FilterPredicate.INSTANCE.getNew(); + predicate.setTargetFilter(filter.getItemFilter()); + } } if (predicate != null) edge.getPredicateHandler().setPredicate(predicate); } diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index c997af781a5..35fe4fb0dbe 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -59,8 +59,10 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { capability.getKey().getOpposite()); if (access != null) { queryObject.setShouldTriggerWalker(false); - boolean cancelled = IOpticalTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).queryHandler(queryObject, access); + boolean cancelled = IOpticalTransferController.CONTROL + .get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())) + .queryHandler(queryObject, access); if (queryObject.shouldTriggerWalker()) { SlowActiveWalker.dispatch(tile.getWorld(), path, 1); } diff --git a/src/test/java/gregtech/common/covers/CoverFluidRegulatorTest.java b/src/test/java/gregtech/common/covers/CoverFluidRegulatorTest.java index 291b241e02d..6bdb78b62c5 100644 --- a/src/test/java/gregtech/common/covers/CoverFluidRegulatorTest.java +++ b/src/test/java/gregtech/common/covers/CoverFluidRegulatorTest.java @@ -1,25 +1,14 @@ package gregtech.common.covers; import gregtech.Bootstrap; -import gregtech.api.capability.impl.FluidHandlerProxy; -import gregtech.api.capability.impl.FluidTankList; -import net.minecraft.util.EnumFacing; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidTankProperties; -import org.hamcrest.MatcherAssert; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; import java.util.function.Predicate; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; - public class CoverFluidRegulatorTest { public static final Predicate isWater = fs -> fs.getFluid() == FluidRegistry.WATER; @@ -32,219 +21,219 @@ public static void bootstrap() { Bootstrap.perform(); } -// @Test -// public void doKeepExact_does_nothing_if_no_destination_tank_exists() { -// // Create a regulator for testing with, and set it to "Keep Exact" mode -// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); -// cfr.transferMode = TransferMode.KEEP_EXACT; -// -// FluidStack water = new FluidStack(FluidRegistry.WATER, 1234); -// -// // Source consists of only an output tank containing a bit of water -// IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), -// new FluidTankList(false, new FluidTank(water.copy(), 64000))); -// -// // Tell it to keep exact from a machine with an empty fluid tank and null target fluid tank -// int amountTransferred = cfr.doKeepExact(1000, source, null, isWater, 1000); -// -// MatcherAssert.assertThat("Unexpectedly moved fluids, nothing is supposed to happen", amountTransferred, is(0)); -// } -// -// @Test -// public void doKeepExact_moves_one_fluid_into_an_empty_tank() { -// // Create a regulator for testing with, and set it to "Keep Exact" mode -// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); -// cfr.transferMode = TransferMode.KEEP_EXACT; -// -// FluidStack water = new FluidStack(FluidRegistry.WATER, 1234); -// -// IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), -// new FluidTankList(false, new FluidTank(water.copy(), 64000))); -// -// // Dest consists of one empty input tank -// IFluidHandler dest = new FluidHandlerProxy(new FluidTankList(false, new FluidTank(64000)), -// new FluidTankList(false)); -// -// // Tell it to keep exact from a machine with an empty fluid tank and no target fluid tank -// int amountTransferred = cfr.doKeepExact(1000, source, dest, isWater, 1000); -// -// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(1000)); -// } -// -// @Test -// public void doKeepExact_moves_only_as_much_fluid_as_exists_in_the_source() { -// // Create a regulator for testing with, and set it to "Keep Exact" mode -// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); -// cfr.transferMode = TransferMode.KEEP_EXACT; -// -// IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 1234), 64000))); -// -// IFluidHandler dest = new FluidHandlerProxy(new FluidTankList(false, new FluidTank(64000)), -// new FluidTankList(false)); -// -// int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 10000); -// -// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(1234)); -// } -// -// @Test -// public void doKeepExact_moves_only_the_fluid_required_if_more_could_be_moved() { -// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); -// cfr.transferMode = TransferMode.KEEP_EXACT; -// -// IFluidHandler source = new FluidHandlerProxy( -// new FluidTankList(false), -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000))); -// -// IFluidHandler dest = new FluidHandlerProxy( -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000)), -// new FluidTankList(false)); -// -// int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 144); -// -// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(44)); -// } -// -// @Test -// public void doKeepExact_moves_multiple_valid_fluids() { -// // Create a regulator for testing with, and set it to "Keep Exact" mode -// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); -// cfr.transferMode = TransferMode.KEEP_EXACT; -// -// IFluidHandler source = new FluidHandlerProxy( -// new FluidTankList(false), -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), -// new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); -// -// // One tank with 100mB water, another with nothing -// IFluidHandler dest = new FluidHandlerProxy( -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000), -// new FluidTank(64000)), -// new FluidTankList(false)); -// -// // accept any fluid this time -// int amountTransferred = cfr.doKeepExact(10000, source, dest, fs -> true, 144); -// -// // expect that 44mB of water and 144mB of lava will be moved -// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(44 + 144)); -// -// // verify final fluid quantities -// MatcherAssert.assertThat(dest.getTankProperties().length, is(2)); -// IFluidTankProperties tank1 = dest.getTankProperties()[0]; -// IFluidTankProperties tank2 = dest.getTankProperties()[1]; -// MatcherAssert.assertThat(tank1.getContents(), notNullValue()); -// MatcherAssert.assertThat(tank2.getContents(), notNullValue()); -// MatcherAssert.assertThat(tank1.getContents().isFluidStackIdentical(new FluidStack(FluidRegistry.WATER, 144)), -// is(true)); -// MatcherAssert.assertThat(tank2.getContents().isFluidStackIdentical(new FluidStack(FluidRegistry.LAVA, 144)), -// is(true)); -// } -// -// @Test -// public void doKeepExact_respects_transfer_limit_with_one_fluid() { -// // Create a regulator for testing with, and set it to "Keep Exact" mode -// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); -// cfr.transferMode = TransferMode.KEEP_EXACT; -// -// // One output tank full of water -// IFluidHandler source = new FluidHandlerProxy( -// new FluidTankList(false), -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000))); -// -// // One input tank with nothing in it -// IFluidHandler dest = new FluidHandlerProxy( -// new FluidTankList(false, new FluidTank(64000)), -// new FluidTankList(false)); -// -// // accept any fluid this time -// int amountTransferred = cfr.doKeepExact(100, source, dest, fs -> true, 144); -// -// // expect that at most 100mB of fluids total will be moved this tick, as if possible it would do 144mB -// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(100)); -// } -// -// @Test -// public void doKeepExact_respects_transfer_limit_with_multiple_fluids() { -// // Create a regulator for testing with, and set it to "Keep Exact" mode -// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); -// cfr.transferMode = TransferMode.KEEP_EXACT; -// -// IFluidHandler source = new FluidHandlerProxy( -// new FluidTankList(false), -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), -// new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); -// -// // One tank with 100mB water, another with nothing -// IFluidHandler dest = new FluidHandlerProxy( -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000), -// new FluidTank(64000)), -// new FluidTankList(false)); -// -// // accept any fluid this time -// int amountTransferred = cfr.doKeepExact(100, source, dest, fs -> true, 144); -// -// // expect that at most 100mB of fluids total will be moved this tick, as if possible it would do 188mB -// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(100)); -// } -// -// @Test -// public void doKeepExact_does_nothing_if_levels_are_already_correct_in_dest() { -// // Create a regulator for testing with, and set it to "Keep Exact" mode -// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); -// cfr.transferMode = TransferMode.KEEP_EXACT; -// -// IFluidHandler source = new FluidHandlerProxy( -// new FluidTankList(false), -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), -// new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); -// -// // One tank with 144mB water, another with 144mB lava -// IFluidHandler dest = new FluidHandlerProxy( -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 144), 64000), -// new FluidTank(new FluidStack(FluidRegistry.LAVA, 144), 64000)), -// new FluidTankList(false)); -// -// // accept any fluid this time -// int amountTransferred = cfr.doKeepExact(10000, source, dest, fs -> true, 144); -// -// // expect that no fluids are moved because Keep Exact levels are already met -// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(0)); -// } -// -// @Test -// public void doKeepExact_ignores_fluids_not_in_filter() { -// // Create a regulator for testing with, and set it to "Keep Exact" mode -// CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); -// cfr.transferMode = TransferMode.KEEP_EXACT; -// -// IFluidHandler source = new FluidHandlerProxy( -// new FluidTankList(false), -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), -// new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); -// -// // One tank with 144mB water, another with 100mB lava -// IFluidHandler dest = new FluidHandlerProxy( -// new FluidTankList(false, -// new FluidTank(new FluidStack(FluidRegistry.WATER, 144), 64000), -// new FluidTank(new FluidStack(FluidRegistry.LAVA, 100), 64000)), -// new FluidTankList(false)); -// -// // accept any fluid this time -// int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 144); -// -// // expect that no fluids are moved because already have enough water and lava isn't in the filter -// MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(0)); -// } + // @Test + // public void doKeepExact_does_nothing_if_no_destination_tank_exists() { + // // Create a regulator for testing with, and set it to "Keep Exact" mode + // CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); + // cfr.transferMode = TransferMode.KEEP_EXACT; + // + // FluidStack water = new FluidStack(FluidRegistry.WATER, 1234); + // + // // Source consists of only an output tank containing a bit of water + // IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), + // new FluidTankList(false, new FluidTank(water.copy(), 64000))); + // + // // Tell it to keep exact from a machine with an empty fluid tank and null target fluid tank + // int amountTransferred = cfr.doKeepExact(1000, source, null, isWater, 1000); + // + // MatcherAssert.assertThat("Unexpectedly moved fluids, nothing is supposed to happen", amountTransferred, is(0)); + // } + // + // @Test + // public void doKeepExact_moves_one_fluid_into_an_empty_tank() { + // // Create a regulator for testing with, and set it to "Keep Exact" mode + // CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); + // cfr.transferMode = TransferMode.KEEP_EXACT; + // + // FluidStack water = new FluidStack(FluidRegistry.WATER, 1234); + // + // IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), + // new FluidTankList(false, new FluidTank(water.copy(), 64000))); + // + // // Dest consists of one empty input tank + // IFluidHandler dest = new FluidHandlerProxy(new FluidTankList(false, new FluidTank(64000)), + // new FluidTankList(false)); + // + // // Tell it to keep exact from a machine with an empty fluid tank and no target fluid tank + // int amountTransferred = cfr.doKeepExact(1000, source, dest, isWater, 1000); + // + // MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(1000)); + // } + // + // @Test + // public void doKeepExact_moves_only_as_much_fluid_as_exists_in_the_source() { + // // Create a regulator for testing with, and set it to "Keep Exact" mode + // CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); + // cfr.transferMode = TransferMode.KEEP_EXACT; + // + // IFluidHandler source = new FluidHandlerProxy(new FluidTankList(false), + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 1234), 64000))); + // + // IFluidHandler dest = new FluidHandlerProxy(new FluidTankList(false, new FluidTank(64000)), + // new FluidTankList(false)); + // + // int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 10000); + // + // MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(1234)); + // } + // + // @Test + // public void doKeepExact_moves_only_the_fluid_required_if_more_could_be_moved() { + // CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); + // cfr.transferMode = TransferMode.KEEP_EXACT; + // + // IFluidHandler source = new FluidHandlerProxy( + // new FluidTankList(false), + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000))); + // + // IFluidHandler dest = new FluidHandlerProxy( + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000)), + // new FluidTankList(false)); + // + // int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 144); + // + // MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(44)); + // } + // + // @Test + // public void doKeepExact_moves_multiple_valid_fluids() { + // // Create a regulator for testing with, and set it to "Keep Exact" mode + // CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); + // cfr.transferMode = TransferMode.KEEP_EXACT; + // + // IFluidHandler source = new FluidHandlerProxy( + // new FluidTankList(false), + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), + // new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); + // + // // One tank with 100mB water, another with nothing + // IFluidHandler dest = new FluidHandlerProxy( + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000), + // new FluidTank(64000)), + // new FluidTankList(false)); + // + // // accept any fluid this time + // int amountTransferred = cfr.doKeepExact(10000, source, dest, fs -> true, 144); + // + // // expect that 44mB of water and 144mB of lava will be moved + // MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(44 + 144)); + // + // // verify final fluid quantities + // MatcherAssert.assertThat(dest.getTankProperties().length, is(2)); + // IFluidTankProperties tank1 = dest.getTankProperties()[0]; + // IFluidTankProperties tank2 = dest.getTankProperties()[1]; + // MatcherAssert.assertThat(tank1.getContents(), notNullValue()); + // MatcherAssert.assertThat(tank2.getContents(), notNullValue()); + // MatcherAssert.assertThat(tank1.getContents().isFluidStackIdentical(new FluidStack(FluidRegistry.WATER, 144)), + // is(true)); + // MatcherAssert.assertThat(tank2.getContents().isFluidStackIdentical(new FluidStack(FluidRegistry.LAVA, 144)), + // is(true)); + // } + // + // @Test + // public void doKeepExact_respects_transfer_limit_with_one_fluid() { + // // Create a regulator for testing with, and set it to "Keep Exact" mode + // CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); + // cfr.transferMode = TransferMode.KEEP_EXACT; + // + // // One output tank full of water + // IFluidHandler source = new FluidHandlerProxy( + // new FluidTankList(false), + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000))); + // + // // One input tank with nothing in it + // IFluidHandler dest = new FluidHandlerProxy( + // new FluidTankList(false, new FluidTank(64000)), + // new FluidTankList(false)); + // + // // accept any fluid this time + // int amountTransferred = cfr.doKeepExact(100, source, dest, fs -> true, 144); + // + // // expect that at most 100mB of fluids total will be moved this tick, as if possible it would do 144mB + // MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(100)); + // } + // + // @Test + // public void doKeepExact_respects_transfer_limit_with_multiple_fluids() { + // // Create a regulator for testing with, and set it to "Keep Exact" mode + // CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); + // cfr.transferMode = TransferMode.KEEP_EXACT; + // + // IFluidHandler source = new FluidHandlerProxy( + // new FluidTankList(false), + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), + // new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); + // + // // One tank with 100mB water, another with nothing + // IFluidHandler dest = new FluidHandlerProxy( + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 100), 64000), + // new FluidTank(64000)), + // new FluidTankList(false)); + // + // // accept any fluid this time + // int amountTransferred = cfr.doKeepExact(100, source, dest, fs -> true, 144); + // + // // expect that at most 100mB of fluids total will be moved this tick, as if possible it would do 188mB + // MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(100)); + // } + // + // @Test + // public void doKeepExact_does_nothing_if_levels_are_already_correct_in_dest() { + // // Create a regulator for testing with, and set it to "Keep Exact" mode + // CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); + // cfr.transferMode = TransferMode.KEEP_EXACT; + // + // IFluidHandler source = new FluidHandlerProxy( + // new FluidTankList(false), + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), + // new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); + // + // // One tank with 144mB water, another with 144mB lava + // IFluidHandler dest = new FluidHandlerProxy( + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 144), 64000), + // new FluidTank(new FluidStack(FluidRegistry.LAVA, 144), 64000)), + // new FluidTankList(false)); + // + // // accept any fluid this time + // int amountTransferred = cfr.doKeepExact(10000, source, dest, fs -> true, 144); + // + // // expect that no fluids are moved because Keep Exact levels are already met + // MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(0)); + // } + // + // @Test + // public void doKeepExact_ignores_fluids_not_in_filter() { + // // Create a regulator for testing with, and set it to "Keep Exact" mode + // CoverFluidRegulator cfr = new CoverFluidRegulator(null, null, EnumFacing.UP, 0, 1000); + // cfr.transferMode = TransferMode.KEEP_EXACT; + // + // IFluidHandler source = new FluidHandlerProxy( + // new FluidTankList(false), + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 64000), 64000), + // new FluidTank(new FluidStack(FluidRegistry.LAVA, 64000), 64000))); + // + // // One tank with 144mB water, another with 100mB lava + // IFluidHandler dest = new FluidHandlerProxy( + // new FluidTankList(false, + // new FluidTank(new FluidStack(FluidRegistry.WATER, 144), 64000), + // new FluidTank(new FluidStack(FluidRegistry.LAVA, 100), 64000)), + // new FluidTankList(false)); + // + // // accept any fluid this time + // int amountTransferred = cfr.doKeepExact(10000, source, dest, isWater, 144); + // + // // expect that no fluids are moved because already have enough water and lava isn't in the filter + // MatcherAssert.assertThat("Wrong fluid amount moved", amountTransferred, is(0)); + // } } From c778444cb4b01b597a7ef00331604e736be24dff Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 11 Aug 2024 08:41:05 -0600 Subject: [PATCH 092/157] Tile Interface --- .../graphnet/pipenet/WorldPipeNetNode.java | 15 ++++---- .../physical/tile/IWorldPipeNetTile.java | 34 +++++++++++++++++++ .../pipenet/physical/tile/PipeTileEntity.java | 4 ++- .../net/fluid/ContainmentFailure.java | 15 ++++---- .../pipelike/net/fluid/FluidTraverseData.java | 7 ++-- 5 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java index ead3ccc7dc4..97a364f8912 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java @@ -1,6 +1,7 @@ package gregtech.api.graphnet.pipenet; import gregtech.api.graphnet.MultiNodeHelper; +import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.worldnet.WorldNetNode; @@ -20,14 +21,14 @@ public final class WorldPipeNetNode extends WorldNetNode { @Nullable MultiNodeHelper overlapHelper; - private WeakReference tileReference; + private WeakReference tileReference; public WorldPipeNetNode(WorldPipeNet net) { super(net); } - public @NotNull PipeTileEntity getTileEntity() { - PipeTileEntity tile = getTileEntity(true); + public @NotNull IWorldPipeNetTile getTileEntity() { + IWorldPipeNetTile tile = getTileEntity(true); if (tile == null) { // something went very wrong, return the fallback to prevent NPEs and remove us from the net. getNet().removeNode(this); @@ -37,19 +38,19 @@ public WorldPipeNetNode(WorldPipeNet net) { } @Nullable - public PipeTileEntity getTileEntityNoLoading() { + public IWorldPipeNetTile getTileEntityNoLoading() { return getTileEntity(false); } - private PipeTileEntity getTileEntity(boolean allowLoading) { + private IWorldPipeNetTile getTileEntity(boolean allowLoading) { if (tileReference != null) { - PipeTileEntity tile = tileReference.get(); + IWorldPipeNetTile tile = tileReference.get(); if (tile != null) return tile; } World world = getNet().getWorld(); if (!allowLoading && !world.isBlockLoaded(getEquivalencyData())) return null; TileEntity tile = world.getTileEntity(getEquivalencyData()); - if (tile instanceof PipeTileEntity pipe) { + if (tile instanceof IWorldPipeNetTile pipe) { this.tileReference = new WeakReference<>(pipe); return pipe; } else return null; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java new file mode 100644 index 00000000000..c3744e1b2cc --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java @@ -0,0 +1,34 @@ +package gregtech.api.graphnet.pipenet.physical.tile; + +import gregtech.api.cover.CoverableView; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; + +import java.util.EnumMap; +import java.util.Map; +import java.util.function.Consumer; + +public interface IWorldPipeNetTile { + + // universal (mostly for active nodes) + + EnumMap getTargetsWithCapabilities(WorldPipeNetNode destination); + + CoverableView getCoverHolder(); + + // fluid piping + + void spawnParticles(EnumFacing direction, EnumParticleTypes particleType, int particleCount); + + void dealAreaDamage(int size, Consumer damageFunction); + + void playLossSound(); + + void visuallyExplode(); + + void setNeighborsToFire(); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index bbcdc80e311..31cf360332e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -62,7 +62,7 @@ import static gregtech.api.capability.GregtechDataCodes.*; -public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITickable { +public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITickable, IWorldPipeNetTile { public static final int DEFAULT_COLOR = 0xFFFFFFFF; @@ -637,6 +637,7 @@ public boolean isOverheatParticleAlive() { return overheatParticle != null && overheatParticle.isAlive(); } + @Override public void spawnParticles(EnumFacing direction, EnumParticleTypes particleType, int particleCount) { if (getWorld() instanceof WorldServer server) { server.spawnParticle(particleType, @@ -728,6 +729,7 @@ public void getCoverBoxes(Consumer consumer) { } } + @Override public void dealAreaDamage(int size, Consumer damageFunction) { long timer = getOffsetTimer(); if (timer >= this.nextDamageTime) { diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java b/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java index efc71b5fe1b..995791b718e 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java @@ -5,6 +5,7 @@ import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.graphnet.pipenet.NodeLossResult; +import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.traverse.util.MultLossOperator; import gregtech.api.util.EntityDamageUtil; @@ -56,7 +57,7 @@ static void init() { registerFailure(FluidState.GAS, stack -> { if (GTValues.RNG.nextInt(8) == 0) { return new NodeLossResult(node -> { - PipeTileEntity tile = node.getTileEntityNoLoading(); + IWorldPipeNetTile tile = node.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.SMOKE_NORMAL, 7 + GTValues.RNG.nextInt(2)); @@ -67,7 +68,7 @@ static void init() { } else { return new NodeLossResult(node -> { node.getNet().getWorld().setBlockToAir(node.getEquivalencyData()); - PipeTileEntity tile = node.getTileEntityNoLoading(); + IWorldPipeNetTile tile = node.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); tile.visuallyExplode(); @@ -79,7 +80,7 @@ static void init() { } }); registerFailure(FluidState.LIQUID, stack -> new NodeLossResult(node -> { - PipeTileEntity tile = node.getTileEntityNoLoading(); + IWorldPipeNetTile tile = node.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); for (EnumFacing facing : EnumFacing.HORIZONTALS) { @@ -95,7 +96,7 @@ static void init() { registerFailure(FluidState.PLASMA, stack -> { if (GTValues.RNG.nextInt(4) == 0) { return new NodeLossResult(node -> { - PipeTileEntity tile = node.getTileEntityNoLoading(); + IWorldPipeNetTile tile = node.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.SMOKE_NORMAL, 1 + GTValues.RNG.nextInt(2)); @@ -106,7 +107,7 @@ static void init() { } else { return new NodeLossResult(node -> { node.getNet().getWorld().setBlockToAir(node.getEquivalencyData()); - PipeTileEntity tile = node.getTileEntityNoLoading(); + IWorldPipeNetTile tile = node.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); tile.visuallyExplode(); @@ -120,7 +121,7 @@ static void init() { registerFailure(FluidAttributes.ACID, stack -> { if (GTValues.RNG.nextInt(10) == 0) { return new NodeLossResult(node -> { - PipeTileEntity tile = node.getTileEntityNoLoading(); + IWorldPipeNetTile tile = node.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); boolean gaseous = stack.getFluid().isGaseous(stack); @@ -133,7 +134,7 @@ static void init() { } else { return new NodeLossResult(node -> { node.getNet().getWorld().setBlockToAir(node.getEquivalencyData()); - PipeTileEntity tile = node.getTileEntityNoLoading(); + IWorldPipeNetTile tile = node.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); boolean gaseous = stack.getFluid().isGaseous(stack); diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index 53b0384acbe..d7f4843a669 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -13,6 +13,7 @@ import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.traverse.AbstractTraverseData; @@ -89,7 +90,7 @@ public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, lon l * TEMPERATURE_EFFECT, temperatureSafe)); if (temperatureLogic.isUnderMinimum(fluidTemp)) { result = NodeLossResult.combine(result, new NodeLossResult(pipe -> { - PipeTileEntity tile = pipe.getTileEntityNoLoading(); + IWorldPipeNetTile tile = pipe.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); @@ -100,7 +101,7 @@ public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, lon }, MultLossOperator.EIGHTHS[2])); } else if (temperatureLogic.isOverMaximum(fluidTemp)) { result = NodeLossResult.combine(result, new NodeLossResult(GTValues.RNG.nextInt(4) == 0 ? pipe -> { - PipeTileEntity tile = pipe.getTileEntityNoLoading(); + IWorldPipeNetTile tile = pipe.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); @@ -110,7 +111,7 @@ public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, lon tile.setNeighborsToFire(); } } : pipe -> { - PipeTileEntity tile = pipe.getTileEntityNoLoading(); + IWorldPipeNetTile tile = pipe.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); From 93ffdc8377d3ee42fc08f3d3489e37691374b2ba Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 11 Aug 2024 12:15:54 -0600 Subject: [PATCH 093/157] Bendy lasers & small improvements --- .../physical/PipeStructureRegistry.java | 12 ++--- .../gregtech/common/blocks/MetaBlocks.java | 2 +- .../pipelike/block/laser/LaserStructure.java | 33 ++++++++++---- .../pipelike/handlers/LaserNetHandler.java | 4 ++ .../common/pipelike/net/SlowActiveWalker.java | 43 +++++++++++------- .../loaders/recipe/ComputerRecipes.java | 12 +++++ .../resources/assets/gregtech/lang/en_us.lang | 3 ++ .../textures/blocks/pipe/pipe_laser_in.png | Bin 146 -> 219 bytes 8 files changed, 76 insertions(+), 33 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java index 5981e24685b..64f1b4e5976 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java @@ -2,25 +2,25 @@ import gregtech.api.util.GTUtility; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet; import org.jetbrains.annotations.NotNull; import java.util.Collections; import java.util.Comparator; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; public final class PipeStructureRegistry { - private static final Map, ObjectAVLTreeSet> REGISTRY = new Object2ObjectOpenHashMap<>(); - - private static final Comparator comparator = Comparator.comparing(IPipeStructure::getName); + private static final Map, Set> REGISTRY = new Object2ObjectLinkedOpenHashMap<>(); public static void register(@NotNull T structure) { - ObjectAVLTreeSet structures = (ObjectAVLTreeSet) REGISTRY.get(structure.getClass()); + Set structures = (Set) REGISTRY.get(structure.getClass()); if (structures == null) { - structures = new ObjectAVLTreeSet<>(comparator); + structures = new LinkedHashSet<>(); REGISTRY.put(structure.getClass(), structures); } structures.add(structure); @@ -31,7 +31,7 @@ public static void register(@NotNull T structure) { */ public static @NotNull Set getStructures(Class structureClass) { GTUtility.forceInitialization(structureClass); - ObjectAVLTreeSet structures = (ObjectAVLTreeSet) REGISTRY.get(structureClass); + Set structures = (Set) REGISTRY.get(structureClass); if (structures == null) return Collections.emptySet(); return structures; } diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 45c51b32e38..1f149593e86 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -220,7 +220,7 @@ public static void init() { i++; } Set structuresLaser = PipeStructureRegistry.getStructures(LaserStructure.class); - LASER_PIPES = new LaserPipeBlock[structuresOptical.size()]; + LASER_PIPES = new LaserPipeBlock[structuresLaser.size()]; i = 0; for (LaserStructure struct : structuresLaser) { LaserPipeBlock block = new LaserPipeBlock(struct); diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java index 336b773d54d..22ecb803f41 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java @@ -14,24 +14,39 @@ import java.util.function.Consumer; @Desugar -public record LaserStructure(String name, float renderThickness, ActivablePipeModel model) implements IPipeStructure { +public record LaserStructure(String name, float renderThickness, boolean mirror, ActivablePipeModel model) implements IPipeStructure { - public static final LaserStructure INSTANCE = new LaserStructure("laser_pipe_normal", 0.375f, - ActivablePipeModel.LASER); + public static final LaserStructure NORMAL = new LaserStructure("laser_pipe_normal", 0.375f, + false, ActivablePipeModel.LASER); + public static final LaserStructure MIRROR = new LaserStructure("laser_pipe_mirror", 0.5f, + true, ActivablePipeModel.LASER); - public LaserStructure(String name, float renderThickness, ActivablePipeModel model) { + public LaserStructure(String name, float renderThickness, boolean mirror, ActivablePipeModel model) { this.name = name; this.renderThickness = renderThickness; + this.mirror = mirror; this.model = model; PipeStructureRegistry.register(this); } @Override public boolean canConnectTo(EnumFacing side, byte connectionMask) { - for (EnumFacing facing : EnumFacing.VALUES) { - if (facing == side) continue; - if (GTUtility.evalMask(facing, connectionMask)) { - return facing.getOpposite() == side; + if (mirror) { + byte connectionCount = 0; + for (EnumFacing facing : EnumFacing.VALUES) { + if (facing == side) continue; + if (GTUtility.evalMask(facing, connectionMask)) { + if (facing.getOpposite() == side) return false; // must be a bent connection + connectionCount++; + } + if (connectionCount > 1) return false; + } + } else { + for (EnumFacing facing : EnumFacing.VALUES) { + if (facing == side) continue; + if (GTUtility.evalMask(facing, connectionMask)) { + return facing.getOpposite() == side; + } } } return true; @@ -58,6 +73,6 @@ public AbstractPipeModel getModel() { } public static void registerDefaultStructures(Consumer register) { - register.accept(INSTANCE); + register.accept(NORMAL); } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java index 15d1b0dc95a..5157614c123 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java @@ -52,6 +52,10 @@ public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) @Override public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn, IPipeStructure structure) { + if (structure instanceof LaserStructure laser && laser.mirror()) { + tooltip.add(I18n.format("tile.laser_pipe_mirror.tooltip1")); + return; + } tooltip.add(I18n.format("tile.laser_pipe_normal.tooltip1")); } } diff --git a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java index eb96dc76fb2..d74588876d5 100644 --- a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java +++ b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java @@ -1,26 +1,33 @@ package gregtech.common.pipelike.net; import gregtech.api.graphnet.path.AbstractNetPath; +import gregtech.api.graphnet.path.INetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.util.TaskScheduler; import gregtech.api.util.function.Task; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; + import net.minecraft.world.World; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; + +import net.minecraftforge.fml.common.FMLCommonHandler; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Map; +import java.util.WeakHashMap; public class SlowActiveWalker implements Task { - private static final int RECENT_WALKER_CUTOFF = 5; + private static final int RECENT_WALKER_CUTOFF = 10; - private static final BiMap, SlowActiveWalker> RECENT_WALKERS = HashBiMap - .create(); + private static final Map, Long> RECENT_DISPATCHES = new WeakHashMap<>(); /** * Dispatches a slow walker along a path with default parameters. @@ -30,7 +37,7 @@ public class SlowActiveWalker implements Task { * @param path the path to walk. * @param delay the ticks between steps of the walker */ - public static void dispatch(World world, AbstractNetPath path, int delay) { + public static void dispatch(World world, INetPath path, int delay) { dispatch(world, path, delay, 1, 1); } @@ -44,15 +51,19 @@ public static void dispatch(World world, AbstractNetPath path, int delay, + public static void dispatch(World world, INetPath path, int delay, int stepSize, int activeLength) { - if (RECENT_WALKERS.containsKey(path)) return; // do not dispatch a walker to a path recently walked - SlowActiveWalker walker = new SlowActiveWalker(path, delay, stepSize, activeLength); - RECENT_WALKERS.put(path, walker); - TaskScheduler.scheduleTask(world, walker); + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + RECENT_DISPATCHES.compute(path, (k, v) -> { + if (v == null || v < tick) { + SlowActiveWalker walker = new SlowActiveWalker(path, delay, stepSize, activeLength); + TaskScheduler.scheduleTask(world, walker); + return tick + RECENT_WALKER_CUTOFF; + } else return v; + }); } - private final List path; + private final INetPath path; private final int lastStep; private int index = 0; @@ -61,27 +72,25 @@ public static void dispatch(World world, AbstractNetPath path, int delay, int stepSize, + protected SlowActiveWalker(INetPath path, int delay, int stepSize, int activeLength) { - this.path = path.getOrderedNodes(); + this.path = path; this.delay = delay; this.stepSize = stepSize; this.activeLength = activeLength; - this.lastStep = this.path.size() + activeLength - 1; + this.lastStep = this.path.getOrderedNodes().size() + activeLength - 1; this.step(getSafe(-stepSize), getSafe(0)); } @Override public boolean run() { counter++; - if (counter > RECENT_WALKER_CUTOFF) RECENT_WALKERS.inverse().remove(this); if (counter >= delay) { counter = 0; for (int i = 0; i < stepSize; i++) { index++; this.step(getSafe(index - activeLength), getSafe(index)); if (index >= lastStep) { - if (counter <= RECENT_WALKER_CUTOFF) RECENT_WALKERS.inverse().remove(this); return false; } } @@ -90,9 +99,9 @@ public boolean run() { } protected @Nullable WorldPipeNetNode getSafe(int index) { - if (index >= path.size()) return null; + if (index >= path.getOrderedNodes().size()) return null; else if (index < 0) return null; - else return path.get(index); + else return path.getOrderedNodes().get(index); } protected void step(@Nullable WorldPipeNetNode previous, @Nullable WorldPipeNetNode next) { diff --git a/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java b/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java index 2832ffc5510..06e1e7f4764 100644 --- a/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java @@ -8,6 +8,9 @@ import gregtech.common.blocks.BlockComputerCasing; import gregtech.common.blocks.BlockGlassCasing; +import gregtech.common.items.MetaItems; + +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import static gregtech.api.GTValues.*; @@ -312,5 +315,14 @@ public static void init() { .output(LASER_PIPES[0]) .cleanroom(CleanroomType.CLEANROOM) .duration(100).EUt(VA[IV]).buildAndRegister(); + +// ASSEMBLER_RECIPES.recipeBuilder() +// .input(LASER_PIPES[0], 2) +// .input(foil, Silver, 2) +// .input(NEUTRON_REFLECTOR) +// .fluidInputs(Polytetrafluoroethylene.getFluid(L)) +// .output(LASER_PIPES[1]) +// .cleanroom(CleanroomType.CLEANROOM) +// .duration(150).EUt(VA[IV]).buildAndRegister(); } } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index fe7740b558e..b76a2b004e5 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -2399,6 +2399,9 @@ tile.optical_pipe_normal.tooltip1=Transmitting §fComputation§7 or §fResearch tile.laser_pipe_normal.name=Laser Transmitting Cable tile.laser_pipe_normal.tooltip1=Transmitting power with §fno loss§7 in straight lines +tile.laser_pipe_mirror.name=Laser Mirror Cable +tile.laser_pipe_mirror.tooltip1=Transmitting power with §fno loss§7 around the bend + metaitem.prospector.lv.name=Electric Prospector's Scanner (LV) metaitem.prospector.hv.name=Electric Prospector's Scanner (HV) metaitem.prospector.luv.name=Electric Prospector's Scanner (LuV) diff --git a/src/main/resources/assets/gregtech/textures/blocks/pipe/pipe_laser_in.png b/src/main/resources/assets/gregtech/textures/blocks/pipe/pipe_laser_in.png index 6277967a5fc29115d719ecd4f1c8d9c85ab543a9..39a0e835a712636cc122c31c630731001b9b0ff7 100644 GIT binary patch delta 191 zcmV;w06_ne0owtPB!2;OQb$4nuFf3k0001!Nkl%>wgS z_@x>Ce0++*MpgroWTct_Ad^9W7#AR`W1M^N72FFj&G@_kl7m@>;RTpRSePJ(0lFBB zj}ivxHp3LbXykx}8z5kt5BCDPE!e^Z-B1h{AV(>(V&w2a7C5Ke0IGWdTR`CrMC6o6 tRy0yAA(5Swsg{{wX`GnMgq$V-n&_ah-QBzK00000NkvXXu0mjf006HOP&WVo delta 117 zcmcc3IEitBN*-r{M`SSr1K$x4W}K?cC(XdX;Nt1x7-G?zoFKs}!t9pQWK*U1e`9C; z&Mj=tw!(Io)&1rjGbsFIvPbVgCc`GTnzjd}jD`%$8Gr7KjJWxt;gN$3YX}2_xwv4x T3`flkpm_|Qu6{1-oD!M Date: Sun, 11 Aug 2024 12:51:52 -0600 Subject: [PATCH 094/157] Overdue shuffling --- src/main/java/gregtech/api/block/machines/BlockMachine.java | 2 +- .../pipenetold => }/longdist/BlockLongDistancePipe.java | 2 +- .../api/{graphnet/pipenetold => }/longdist/ILDEndpoint.java | 2 +- .../{graphnet/pipenetold => }/longdist/ILDNetworkPart.java | 2 +- .../pipenetold => }/longdist/LongDistanceNetwork.java | 2 +- .../pipenetold => }/longdist/LongDistancePipeType.java | 6 +++--- .../{graphnet/pipenetold => }/longdist/NetworkBuilder.java | 2 +- src/main/java/gregtech/client/utils/FacadeBlockAccess.java | 2 -- .../pipenetold => client/utils}/IBlockAppearance.java | 2 +- src/main/java/gregtech/common/EventHandlers.java | 2 +- src/main/java/gregtech/common/blocks/MetaBlocks.java | 6 +++--- .../gregtech/common/metatileentities/MetaTileEntities.java | 4 ++-- .../storage/MetaTileEntityLongDistanceEndpoint.java | 6 +++--- .../longdistance/fluid}/LDFluidPipeType.java | 4 ++-- .../longdistance/fluid}/MetaTileEntityLDFluidEndpoint.java | 4 ++-- .../longdistance/item}/LDItemPipeType.java | 4 ++-- .../longdistance/item}/MetaTileEntityLDItemEndpoint.java | 4 ++-- .../common/pipelike/net/energy/EnergyCapabilityObject.java | 1 - .../cable/net => pipelike/net/energy}/EnergyGroupData.java | 2 +- .../common/pipelike/net/energy/EnergyTraverseData.java | 1 - .../integration/theoneprobe/provider/LDPipeProvider.java | 4 ++-- 21 files changed, 30 insertions(+), 34 deletions(-) rename src/main/java/gregtech/api/{graphnet/pipenetold => }/longdist/BlockLongDistancePipe.java (99%) rename src/main/java/gregtech/api/{graphnet/pipenetold => }/longdist/ILDEndpoint.java (97%) rename src/main/java/gregtech/api/{graphnet/pipenetold => }/longdist/ILDNetworkPart.java (94%) rename src/main/java/gregtech/api/{graphnet/pipenetold => }/longdist/LongDistanceNetwork.java (99%) rename src/main/java/gregtech/api/{graphnet/pipenetold => }/longdist/LongDistancePipeType.java (92%) rename src/main/java/gregtech/api/{graphnet/pipenetold => }/longdist/NetworkBuilder.java (99%) rename src/main/java/gregtech/{api/graphnet/pipenetold => client/utils}/IBlockAppearance.java (96%) rename src/main/java/gregtech/common/{pipelikeold/fluidpipe/longdistance => pipelike/longdistance/fluid}/LDFluidPipeType.java (72%) rename src/main/java/gregtech/common/{pipelikeold/fluidpipe/longdistance => pipelike/longdistance/fluid}/MetaTileEntityLDFluidEndpoint.java (97%) rename src/main/java/gregtech/common/{pipelikeold/itempipe/longdistance => pipelike/longdistance/item}/LDItemPipeType.java (72%) rename src/main/java/gregtech/common/{pipelikeold/itempipe/longdistance => pipelike/longdistance/item}/MetaTileEntityLDItemEndpoint.java (97%) rename src/main/java/gregtech/common/{pipelikeold/cable/net => pipelike/net/energy}/EnergyGroupData.java (95%) diff --git a/src/main/java/gregtech/api/block/machines/BlockMachine.java b/src/main/java/gregtech/api/block/machines/BlockMachine.java index 6941bc2e53a..91b937f9673 100644 --- a/src/main/java/gregtech/api/block/machines/BlockMachine.java +++ b/src/main/java/gregtech/api/block/machines/BlockMachine.java @@ -6,7 +6,7 @@ import gregtech.api.block.UnlistedStringProperty; import gregtech.api.cover.Cover; import gregtech.api.cover.IFacadeCover; -import gregtech.api.graphnet.pipenetold.IBlockAppearance; +import gregtech.client.utils.IBlockAppearance; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.metatileentity.MetaTileEntity; diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/BlockLongDistancePipe.java b/src/main/java/gregtech/api/longdist/BlockLongDistancePipe.java similarity index 99% rename from src/main/java/gregtech/api/graphnet/pipenetold/longdist/BlockLongDistancePipe.java rename to src/main/java/gregtech/api/longdist/BlockLongDistancePipe.java index 804831f9721..1211da9828b 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/BlockLongDistancePipe.java +++ b/src/main/java/gregtech/api/longdist/BlockLongDistancePipe.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.pipenetold.longdist; +package gregtech.api.longdist; import gregtech.api.items.toolitem.ToolClasses; import gregtech.common.creativetab.GTCreativeTabs; diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDEndpoint.java b/src/main/java/gregtech/api/longdist/ILDEndpoint.java similarity index 97% rename from src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDEndpoint.java rename to src/main/java/gregtech/api/longdist/ILDEndpoint.java index 42628428f9c..edf36b80507 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDEndpoint.java +++ b/src/main/java/gregtech/api/longdist/ILDEndpoint.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.pipenetold.longdist; +package gregtech.api.longdist; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.interfaces.INeighborCache; diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDNetworkPart.java b/src/main/java/gregtech/api/longdist/ILDNetworkPart.java similarity index 94% rename from src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDNetworkPart.java rename to src/main/java/gregtech/api/longdist/ILDNetworkPart.java index 8bf2d86e273..7aa684f93ca 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/ILDNetworkPart.java +++ b/src/main/java/gregtech/api/longdist/ILDNetworkPart.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.pipenetold.longdist; +package gregtech.api.longdist; import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistanceNetwork.java b/src/main/java/gregtech/api/longdist/LongDistanceNetwork.java similarity index 99% rename from src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistanceNetwork.java rename to src/main/java/gregtech/api/longdist/LongDistanceNetwork.java index 8ec3219eaa2..ea6b3d847fc 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistanceNetwork.java +++ b/src/main/java/gregtech/api/longdist/LongDistanceNetwork.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.pipenetold.longdist; +package gregtech.api.longdist; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistancePipeType.java b/src/main/java/gregtech/api/longdist/LongDistancePipeType.java similarity index 92% rename from src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistancePipeType.java rename to src/main/java/gregtech/api/longdist/LongDistancePipeType.java index ca630fe787e..78b78a1760c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/LongDistancePipeType.java +++ b/src/main/java/gregtech/api/longdist/LongDistancePipeType.java @@ -1,7 +1,7 @@ -package gregtech.api.graphnet.pipenetold.longdist; +package gregtech.api.longdist; -import gregtech.common.pipelikeold.fluidpipe.longdistance.LDFluidPipeType; -import gregtech.common.pipelikeold.itempipe.longdistance.LDItemPipeType; +import gregtech.common.pipelike.longdistance.fluid.LDFluidPipeType; +import gregtech.common.pipelike.longdistance.item.LDItemPipeType; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/NetworkBuilder.java b/src/main/java/gregtech/api/longdist/NetworkBuilder.java similarity index 99% rename from src/main/java/gregtech/api/graphnet/pipenetold/longdist/NetworkBuilder.java rename to src/main/java/gregtech/api/longdist/NetworkBuilder.java index e122da098f0..676f27e1acd 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/longdist/NetworkBuilder.java +++ b/src/main/java/gregtech/api/longdist/NetworkBuilder.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.pipenetold.longdist; +package gregtech.api.longdist; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; diff --git a/src/main/java/gregtech/client/utils/FacadeBlockAccess.java b/src/main/java/gregtech/client/utils/FacadeBlockAccess.java index 57b8866b4f8..38e20e02664 100644 --- a/src/main/java/gregtech/client/utils/FacadeBlockAccess.java +++ b/src/main/java/gregtech/client/utils/FacadeBlockAccess.java @@ -1,7 +1,5 @@ package gregtech.client.utils; -import gregtech.api.graphnet.pipenetold.IBlockAppearance; - import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; diff --git a/src/main/java/gregtech/api/graphnet/pipenetold/IBlockAppearance.java b/src/main/java/gregtech/client/utils/IBlockAppearance.java similarity index 96% rename from src/main/java/gregtech/api/graphnet/pipenetold/IBlockAppearance.java rename to src/main/java/gregtech/client/utils/IBlockAppearance.java index 380b3cda974..556c649390e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenetold/IBlockAppearance.java +++ b/src/main/java/gregtech/client/utils/IBlockAppearance.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.pipenetold; +package gregtech.client.utils; import net.minecraft.block.state.IBlockState; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/EventHandlers.java b/src/main/java/gregtech/common/EventHandlers.java index 4a9b3d3d92a..f1c0c365db6 100644 --- a/src/main/java/gregtech/common/EventHandlers.java +++ b/src/main/java/gregtech/common/EventHandlers.java @@ -3,7 +3,7 @@ import gregtech.api.GTValues; import gregtech.api.block.IWalkingSpeedBonus; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.pipenetold.longdist.LongDistanceNetwork; +import gregtech.api.longdist.LongDistanceNetwork; import gregtech.api.items.armor.ArmorMetaItem; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 1f149593e86..ebdec71ebe4 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -7,7 +7,7 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.pipenetold.longdist.BlockLongDistancePipe; +import gregtech.api.longdist.BlockLongDistancePipe; import gregtech.api.metatileentity.MetaTileEntityHolder; import gregtech.api.unification.OreDictUnifier; import gregtech.api.unification.material.Material; @@ -47,8 +47,8 @@ import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.block.pipe.MaterialPipeBlock; import gregtech.common.pipelike.block.pipe.MaterialPipeStructure; -import gregtech.common.pipelikeold.fluidpipe.longdistance.LDFluidPipeType; -import gregtech.common.pipelikeold.itempipe.longdistance.LDItemPipeType; +import gregtech.common.pipelike.longdistance.fluid.LDFluidPipeType; +import gregtech.common.pipelike.longdistance.item.LDItemPipeType; import net.minecraft.block.Block; import net.minecraft.block.BlockFence; diff --git a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java index a0881c35bbd..b683a666668 100644 --- a/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java +++ b/src/main/java/gregtech/common/metatileentities/MetaTileEntities.java @@ -126,8 +126,8 @@ import gregtech.common.metatileentities.storage.MetaTileEntityQuantumChest; import gregtech.common.metatileentities.storage.MetaTileEntityQuantumTank; import gregtech.common.metatileentities.storage.MetaTileEntityWorkbench; -import gregtech.common.pipelikeold.fluidpipe.longdistance.MetaTileEntityLDFluidEndpoint; -import gregtech.common.pipelikeold.itempipe.longdistance.MetaTileEntityLDItemEndpoint; +import gregtech.common.pipelike.longdistance.fluid.MetaTileEntityLDFluidEndpoint; +import gregtech.common.pipelike.longdistance.item.MetaTileEntityLDItemEndpoint; import gregtech.integration.jei.multiblock.MultiblockInfoCategory; import net.minecraft.util.ResourceLocation; diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java index b4455d1d4bd..91cdb8eeb6b 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityLongDistanceEndpoint.java @@ -1,8 +1,8 @@ package gregtech.common.metatileentities.storage; -import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; -import gregtech.api.graphnet.pipenetold.longdist.LongDistanceNetwork; -import gregtech.api.graphnet.pipenetold.longdist.LongDistancePipeType; +import gregtech.api.longdist.ILDEndpoint; +import gregtech.api.longdist.LongDistanceNetwork; +import gregtech.api.longdist.LongDistancePipeType; import gregtech.api.metatileentity.IDataInfoProvider; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.common.ConfigHolder; diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/LDFluidPipeType.java b/src/main/java/gregtech/common/pipelike/longdistance/fluid/LDFluidPipeType.java similarity index 72% rename from src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/LDFluidPipeType.java rename to src/main/java/gregtech/common/pipelike/longdistance/fluid/LDFluidPipeType.java index 43ad21d7cea..f4a8ca9bc5f 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/LDFluidPipeType.java +++ b/src/main/java/gregtech/common/pipelike/longdistance/fluid/LDFluidPipeType.java @@ -1,6 +1,6 @@ -package gregtech.common.pipelikeold.fluidpipe.longdistance; +package gregtech.common.pipelike.longdistance.fluid; -import gregtech.api.graphnet.pipenetold.longdist.LongDistancePipeType; +import gregtech.api.longdist.LongDistancePipeType; import gregtech.common.ConfigHolder; public class LDFluidPipeType extends LongDistancePipeType { diff --git a/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java b/src/main/java/gregtech/common/pipelike/longdistance/fluid/MetaTileEntityLDFluidEndpoint.java similarity index 97% rename from src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java rename to src/main/java/gregtech/common/pipelike/longdistance/fluid/MetaTileEntityLDFluidEndpoint.java index 3757984676f..eeaf0d2cb0a 100644 --- a/src/main/java/gregtech/common/pipelikeold/fluidpipe/longdistance/MetaTileEntityLDFluidEndpoint.java +++ b/src/main/java/gregtech/common/pipelike/longdistance/fluid/MetaTileEntityLDFluidEndpoint.java @@ -1,8 +1,8 @@ -package gregtech.common.pipelikeold.fluidpipe.longdistance; +package gregtech.common.pipelike.longdistance.fluid; import gregtech.api.GTValues; import gregtech.api.capability.impl.FluidHandlerDelegate; -import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; +import gregtech.api.longdist.ILDEndpoint; import gregtech.api.gui.ModularUI; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/LDItemPipeType.java b/src/main/java/gregtech/common/pipelike/longdistance/item/LDItemPipeType.java similarity index 72% rename from src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/LDItemPipeType.java rename to src/main/java/gregtech/common/pipelike/longdistance/item/LDItemPipeType.java index 3062fe568c7..598219cb38d 100644 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/LDItemPipeType.java +++ b/src/main/java/gregtech/common/pipelike/longdistance/item/LDItemPipeType.java @@ -1,6 +1,6 @@ -package gregtech.common.pipelikeold.itempipe.longdistance; +package gregtech.common.pipelike.longdistance.item; -import gregtech.api.graphnet.pipenetold.longdist.LongDistancePipeType; +import gregtech.api.longdist.LongDistancePipeType; import gregtech.common.ConfigHolder; public class LDItemPipeType extends LongDistancePipeType { diff --git a/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java b/src/main/java/gregtech/common/pipelike/longdistance/item/MetaTileEntityLDItemEndpoint.java similarity index 97% rename from src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java rename to src/main/java/gregtech/common/pipelike/longdistance/item/MetaTileEntityLDItemEndpoint.java index d7005b163d1..7ba81b75725 100644 --- a/src/main/java/gregtech/common/pipelikeold/itempipe/longdistance/MetaTileEntityLDItemEndpoint.java +++ b/src/main/java/gregtech/common/pipelike/longdistance/item/MetaTileEntityLDItemEndpoint.java @@ -1,8 +1,8 @@ -package gregtech.common.pipelikeold.itempipe.longdistance; +package gregtech.common.pipelike.longdistance.item; import gregtech.api.GTValues; import gregtech.api.capability.impl.ItemHandlerDelegate; -import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; +import gregtech.api.longdist.ILDEndpoint; import gregtech.api.gui.ModularUI; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index acaf82ec2b6..58bd5b41248 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -17,7 +17,6 @@ import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.TraverseHelpers; import gregtech.api.util.GTLog; -import gregtech.common.pipelikeold.cable.net.EnergyGroupData; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; diff --git a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java similarity index 95% rename from src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java rename to src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java index 13beb625dd7..809f87745ef 100644 --- a/src/main/java/gregtech/common/pipelikeold/cable/net/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java @@ -1,4 +1,4 @@ -package gregtech.common.pipelikeold.cable.net; +package gregtech.common.pipelike.net.energy; import gregtech.api.graphnet.AbstractGroupData; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index 6d5d4e9ecc1..a2231b18fee 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -15,7 +15,6 @@ import gregtech.api.graphnet.traverse.AbstractTraverseData; import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; import gregtech.api.util.GTUtility; -import gregtech.common.pipelikeold.cable.net.EnergyGroupData; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java index 7e04335a339..92b36d8756e 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/LDPipeProvider.java @@ -1,8 +1,8 @@ package gregtech.integration.theoneprobe.provider; import gregtech.api.GTValues; -import gregtech.api.graphnet.pipenetold.longdist.ILDEndpoint; -import gregtech.api.graphnet.pipenetold.longdist.LongDistanceNetwork; +import gregtech.api.longdist.ILDEndpoint; +import gregtech.api.longdist.LongDistanceNetwork; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; From 358758cfe1211cea61b62c36ee5693b62a8c0d9e Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 11 Aug 2024 13:52:11 -0600 Subject: [PATCH 095/157] Fix pipe autoconnection to mtes & spotless --- .../api/block/machines/BlockMachine.java | 2 +- .../api/block/machines/MachineItemBlock.java | 16 +++++++++++++++- .../physical/PipeStructureRegistry.java | 3 --- .../physical/tile/IWorldPipeNetTile.java | 1 - .../java/gregtech/common/EventHandlers.java | 2 +- .../storage/MetaTileEntityDrum.java | 1 - .../pipelike/block/laser/LaserStructure.java | 3 ++- .../fluid/MetaTileEntityLDFluidEndpoint.java | 2 +- .../item/MetaTileEntityLDItemEndpoint.java | 2 +- .../common/pipelike/net/SlowActiveWalker.java | 8 -------- .../net/fluid/ContainmentFailure.java | 1 - .../pipelike/net/fluid/FluidTraverseData.java | 1 - .../provider/LaserContainerInfoProvider.java | 8 ++++---- .../loaders/recipe/ComputerRecipes.java | 19 ++++++++----------- 14 files changed, 33 insertions(+), 36 deletions(-) diff --git a/src/main/java/gregtech/api/block/machines/BlockMachine.java b/src/main/java/gregtech/api/block/machines/BlockMachine.java index c99cc8521c3..b7d02db448c 100644 --- a/src/main/java/gregtech/api/block/machines/BlockMachine.java +++ b/src/main/java/gregtech/api/block/machines/BlockMachine.java @@ -7,7 +7,6 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.Cover; import gregtech.api.cover.IFacadeCover; -import gregtech.client.utils.IBlockAppearance; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; import gregtech.api.metatileentity.MetaTileEntity; @@ -18,6 +17,7 @@ import gregtech.api.util.GTUtility; import gregtech.api.util.Mods; import gregtech.client.renderer.handler.MetaTileEntityRenderer; +import gregtech.client.utils.IBlockAppearance; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.items.MetaItems; import gregtech.integration.ctm.IFacadeWrapper; diff --git a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java index 82fc9f48fd2..46f8c28e9b1 100644 --- a/src/main/java/gregtech/api/block/machines/MachineItemBlock.java +++ b/src/main/java/gregtech/api/block/machines/MachineItemBlock.java @@ -1,6 +1,8 @@ package gregtech.api.block.machines; import gregtech.api.GTValues; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.metatileentity.ITieredMetaTileEntity; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.util.GTUtility; @@ -9,6 +11,7 @@ import gregtech.common.ConfigHolder; import gregtech.common.creativetab.GTCreativeTabs; +import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.resources.I18n; import net.minecraft.client.util.ITooltipFlag; @@ -87,8 +90,19 @@ public boolean placeBlockAt(@NotNull ItemStack stack, @NotNull EntityPlayer play MetaTileEntity metaTileEntity = GTUtility.getMetaTileEntity(stack); // prevent rendering glitch before meta tile entity sync to client, but after block placement // set opaque property on the placing on block, instead during set of meta tile entity - return super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, + boolean superVal = super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, newState.withProperty(BlockMachine.OPAQUE, metaTileEntity == null || metaTileEntity.isOpaqueCube())); + if (superVal && !world.isRemote) { + BlockPos possiblePipe = pos.offset(side.getOpposite()); + Block block = world.getBlockState(possiblePipe).getBlock(); + if (block instanceof PipeBlock pipeBlock) { + PipeTileEntity tile = pipeBlock.getTileEntity(world, possiblePipe); + if (tile != null) { + tile.updateActiveStatus(side, true); + } + } + } + return superVal; } @Nullable diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java index 64f1b4e5976..3d2b0c9266e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java @@ -3,12 +3,9 @@ import gregtech.api.util.GTUtility; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet; import org.jetbrains.annotations.NotNull; import java.util.Collections; -import java.util.Comparator; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java index c3744e1b2cc..e773f1dc036 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java @@ -9,7 +9,6 @@ import net.minecraft.util.EnumParticleTypes; import java.util.EnumMap; -import java.util.Map; import java.util.function.Consumer; public interface IWorldPipeNetTile { diff --git a/src/main/java/gregtech/common/EventHandlers.java b/src/main/java/gregtech/common/EventHandlers.java index f1c0c365db6..0ede85aae5a 100644 --- a/src/main/java/gregtech/common/EventHandlers.java +++ b/src/main/java/gregtech/common/EventHandlers.java @@ -3,10 +3,10 @@ import gregtech.api.GTValues; import gregtech.api.block.IWalkingSpeedBonus; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.longdist.LongDistanceNetwork; import gregtech.api.items.armor.ArmorMetaItem; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.items.toolitem.ToolHelper; +import gregtech.api.longdist.LongDistanceNetwork; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.unification.material.Materials; import gregtech.api.util.BlockUtility; diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java index 68038140207..e5c5ec252ad 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java @@ -8,7 +8,6 @@ import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.recipes.ModHandler; import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java index 22ecb803f41..c03c8279e37 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java @@ -14,7 +14,8 @@ import java.util.function.Consumer; @Desugar -public record LaserStructure(String name, float renderThickness, boolean mirror, ActivablePipeModel model) implements IPipeStructure { +public record LaserStructure(String name, float renderThickness, boolean mirror, ActivablePipeModel model) + implements IPipeStructure { public static final LaserStructure NORMAL = new LaserStructure("laser_pipe_normal", 0.375f, false, ActivablePipeModel.LASER); diff --git a/src/main/java/gregtech/common/pipelike/longdistance/fluid/MetaTileEntityLDFluidEndpoint.java b/src/main/java/gregtech/common/pipelike/longdistance/fluid/MetaTileEntityLDFluidEndpoint.java index 7d12205ea41..38381fd29c3 100644 --- a/src/main/java/gregtech/common/pipelike/longdistance/fluid/MetaTileEntityLDFluidEndpoint.java +++ b/src/main/java/gregtech/common/pipelike/longdistance/fluid/MetaTileEntityLDFluidEndpoint.java @@ -2,8 +2,8 @@ import gregtech.api.GTValues; import gregtech.api.capability.impl.FluidHandlerDelegate; -import gregtech.api.longdist.ILDEndpoint; import gregtech.api.gui.ModularUI; +import gregtech.api.longdist.ILDEndpoint; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.util.GTUtility; diff --git a/src/main/java/gregtech/common/pipelike/longdistance/item/MetaTileEntityLDItemEndpoint.java b/src/main/java/gregtech/common/pipelike/longdistance/item/MetaTileEntityLDItemEndpoint.java index f4a29975104..6a78460cf52 100644 --- a/src/main/java/gregtech/common/pipelike/longdistance/item/MetaTileEntityLDItemEndpoint.java +++ b/src/main/java/gregtech/common/pipelike/longdistance/item/MetaTileEntityLDItemEndpoint.java @@ -2,8 +2,8 @@ import gregtech.api.GTValues; import gregtech.api.capability.impl.ItemHandlerDelegate; -import gregtech.api.longdist.ILDEndpoint; import gregtech.api.gui.ModularUI; +import gregtech.api.longdist.ILDEndpoint; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.util.GTUtility; diff --git a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java index d74588876d5..6fb83a841c6 100644 --- a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java +++ b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java @@ -1,25 +1,17 @@ package gregtech.common.pipelike.net; -import gregtech.api.graphnet.path.AbstractNetPath; import gregtech.api.graphnet.path.INetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.util.TaskScheduler; import gregtech.api.util.function.Task; -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; - import net.minecraft.world.World; - -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; - import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; import java.util.Map; import java.util.WeakHashMap; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java b/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java index 995791b718e..f6ff9c755a9 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java @@ -6,7 +6,6 @@ import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; -import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.traverse.util.MultLossOperator; import gregtech.api.util.EntityDamageUtil; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index d7f4843a669..4031e096442 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -14,7 +14,6 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; -import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.traverse.AbstractTraverseData; import gregtech.api.graphnet.traverse.util.MultLossOperator; diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java index 41fe8596c08..9f5e96b73a7 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/LaserContainerInfoProvider.java @@ -4,7 +4,6 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserContainer; import gregtech.api.capability.ILaserRelay; -import gregtech.api.util.TextFormattingUtil; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; @@ -34,11 +33,12 @@ protected void addProbeInfo(ILaserRelay cap, IProbeInfo probeInfo, EntityPlayer TileEntity tileEntity, IProbeHitData data) { if (cap instanceof ILaserContainer capability) { long maxStorage = capability.getEnergyCapacity(); - long stored = capability.getEnergyStored();if (maxStorage == 0) return; // do not add empty max storage progress bar + long stored = capability.getEnergyStored(); + if (maxStorage == 0) return; // do not add empty max storage progress bar probeInfo.progress(stored, maxStorage, probeInfo.defaultProgressStyle() - .numberFormat(player.isSneaking() || stored < 10000 ? NumberFormat.FULL : NumberFormat.COMPACT) + .numberFormat(player.isSneaking() || stored < 10000 ? NumberFormat.FULL : NumberFormat.COMPACT) .suffix(" / " + (player.isSneaking() || maxStorage < 10000 ? maxStorage + " EU" : - ElementProgress.format(maxStorage, NumberFormat.COMPACT, "EU"))) + ElementProgress.format(maxStorage, NumberFormat.COMPACT, "EU"))) .filledColor(0xFFEEE600) .alternateFilledColor(0xFFEEE600) .borderColor(0xFF555555)); diff --git a/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java b/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java index 06e1e7f4764..de8cb2d3e2e 100644 --- a/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java @@ -8,9 +8,6 @@ import gregtech.common.blocks.BlockComputerCasing; import gregtech.common.blocks.BlockGlassCasing; -import gregtech.common.items.MetaItems; - -import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import static gregtech.api.GTValues.*; @@ -316,13 +313,13 @@ public static void init() { .cleanroom(CleanroomType.CLEANROOM) .duration(100).EUt(VA[IV]).buildAndRegister(); -// ASSEMBLER_RECIPES.recipeBuilder() -// .input(LASER_PIPES[0], 2) -// .input(foil, Silver, 2) -// .input(NEUTRON_REFLECTOR) -// .fluidInputs(Polytetrafluoroethylene.getFluid(L)) -// .output(LASER_PIPES[1]) -// .cleanroom(CleanroomType.CLEANROOM) -// .duration(150).EUt(VA[IV]).buildAndRegister(); + // ASSEMBLER_RECIPES.recipeBuilder() + // .input(LASER_PIPES[0], 2) + // .input(foil, Silver, 2) + // .input(NEUTRON_REFLECTOR) + // .fluidInputs(Polytetrafluoroethylene.getFluid(L)) + // .output(LASER_PIPES[1]) + // .cleanroom(CleanroomType.CLEANROOM) + // .duration(150).EUt(VA[IV]).buildAndRegister(); } } From ce0c597d65b2e2c62e57acbd16dee8bc5e4c0e0b Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 11 Aug 2024 16:47:58 -0600 Subject: [PATCH 096/157] address review --- .../api/capability/IEnergyContainer.java | 6 +---- .../data/IComputationDataAccess.java | 4 +++- ...ionConsumer.java => IComputationUser.java} | 6 ++--- .../api/capability/data/IDataAccess.java | 5 ++-- .../capability/data/IStandardDataAccess.java | 4 +++- .../impl/ComputationRecipeLogic.java | 24 +++++++++---------- .../electric/MetaTileEntityNetworkSwitch.java | 2 +- .../MetaTileEntityResearchStation.java | 8 +++---- .../MetaTileEntityComputationHatch.java | 2 +- .../MetaTileEntityDataAccessHatch.java | 2 +- .../MetaTileEntityOpticalDataHatch.java | 4 ++-- .../net/optical/DataCapabilityObject.java | 2 +- .../resources/assets/gregtech/lang/en_us.lang | 6 ++--- 13 files changed, 38 insertions(+), 37 deletions(-) rename src/main/java/gregtech/api/capability/data/{IComputationConsumer.java => IComputationUser.java} (67%) diff --git a/src/main/java/gregtech/api/capability/IEnergyContainer.java b/src/main/java/gregtech/api/capability/IEnergyContainer.java index e88dae53274..388d7df1693 100644 --- a/src/main/java/gregtech/api/capability/IEnergyContainer.java +++ b/src/main/java/gregtech/api/capability/IEnergyContainer.java @@ -14,10 +14,6 @@ public interface IEnergyContainer { */ long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate); - default long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage) { - return acceptEnergyFromNetwork(side, voltage, amperage, false); - } - /** * @return if this container accepts energy from the given side */ @@ -33,7 +29,7 @@ default boolean outputsEnergy(EnumFacing side) { /** * This changes the amount stored. * This should only be used internally (f.e. draining while working or filling while generating). - * For transfer between blocks use {@link #acceptEnergyFromNetwork(EnumFacing, long, long)}!!! + * For transfer between blocks use {@link #acceptEnergyFromNetwork(EnumFacing, long, long, boolean)}!!! * * @param differenceAmount amount of energy to add (>0) or remove (<0) * @return amount of energy added or removed diff --git a/src/main/java/gregtech/api/capability/data/IComputationDataAccess.java b/src/main/java/gregtech/api/capability/data/IComputationDataAccess.java index f97bbce4406..f4047683646 100644 --- a/src/main/java/gregtech/api/capability/data/IComputationDataAccess.java +++ b/src/main/java/gregtech/api/capability/data/IComputationDataAccess.java @@ -2,10 +2,12 @@ import gregtech.api.capability.data.query.DataAccessFormat; +import org.jetbrains.annotations.NotNull; + public interface IComputationDataAccess extends IHatchDataAccess { @Override - default DataAccessFormat getFormat() { + default @NotNull DataAccessFormat getFormat() { return DataAccessFormat.COMPUTATION; } } diff --git a/src/main/java/gregtech/api/capability/data/IComputationConsumer.java b/src/main/java/gregtech/api/capability/data/IComputationUser.java similarity index 67% rename from src/main/java/gregtech/api/capability/data/IComputationConsumer.java rename to src/main/java/gregtech/api/capability/data/IComputationUser.java index c524b23436d..3d93d495b47 100644 --- a/src/main/java/gregtech/api/capability/data/IComputationConsumer.java +++ b/src/main/java/gregtech/api/capability/data/IComputationUser.java @@ -3,14 +3,14 @@ /** * Used for {@link gregtech.api.capability.impl.ComputationRecipeLogic} */ -public interface IComputationConsumer { +public interface IComputationUser { /** - * Called to supply CWU. + * Called to request CWU for recipe logic. * * @param requested the requested CWU * @param simulate whether to simulate the request * @return the amount of CWU supplied. */ - long supplyCWU(long requested, boolean simulate); + long requestCWU(long requested, boolean simulate); } diff --git a/src/main/java/gregtech/api/capability/data/IDataAccess.java b/src/main/java/gregtech/api/capability/data/IDataAccess.java index e9cf3e0e48a..c6599e6a87a 100644 --- a/src/main/java/gregtech/api/capability/data/IDataAccess.java +++ b/src/main/java/gregtech/api/capability/data/IDataAccess.java @@ -19,6 +19,7 @@ public interface IDataAccess { /** * @return the {@link DataAccessFormat} this {@link IDataAccess} uses. */ + @NotNull DataAccessFormat getFormat(); /** @@ -36,8 +37,8 @@ default boolean supportsQuery(@NotNull DataQueryObject queryObject) { * @param query the object representing the query. * @return if the query has been cancelled */ - static boolean accessDatas(@NotNull Iterable accesses, - @NotNull DataQueryObject query) { + static boolean accessData(@NotNull Iterable accesses, + @NotNull DataQueryObject query) { boolean walk = false; boolean cancelled = false; for (IDataAccess access : accesses) { diff --git a/src/main/java/gregtech/api/capability/data/IStandardDataAccess.java b/src/main/java/gregtech/api/capability/data/IStandardDataAccess.java index 02dfb6400ae..3117e295c3e 100644 --- a/src/main/java/gregtech/api/capability/data/IStandardDataAccess.java +++ b/src/main/java/gregtech/api/capability/data/IStandardDataAccess.java @@ -2,10 +2,12 @@ import gregtech.api.capability.data.query.DataAccessFormat; +import org.jetbrains.annotations.NotNull; + public interface IStandardDataAccess extends IHatchDataAccess { @Override - default DataAccessFormat getFormat() { + default @NotNull DataAccessFormat getFormat() { return DataAccessFormat.STANDARD; } } diff --git a/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java index 6892f40035a..9683d0dfa85 100644 --- a/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/ComputationRecipeLogic.java @@ -1,6 +1,6 @@ package gregtech.api.capability.impl; -import gregtech.api.capability.data.IComputationConsumer; +import gregtech.api.capability.data.IComputationUser; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.recipeproperties.ComputationProperty; @@ -13,7 +13,7 @@ /** * Recipe Logic for multiblocks that require computation. * Used with RecipeMaps that contain recipes using the {@link ComputationProperty}. - * The Multiblock holding this logic must implement {@link IComputationConsumer}. + * The Multiblock holding this logic must implement {@link IComputationUser}. */ public class ComputationRecipeLogic extends MultiblockRecipeLogic { @@ -29,15 +29,15 @@ public class ComputationRecipeLogic extends MultiblockRecipeLogic { private boolean hasNotEnoughComputation; private int currentDrawnCWUt; - public ComputationRecipeLogic(T metaTileEntity, - ComputationType type) { + public ComputationRecipeLogic(T metaTileEntity, + ComputationType type) { super(metaTileEntity); this.type = type; } @NotNull - public IComputationConsumer getComputationProvider() { - return (IComputationConsumer) getMetaTileEntity(); + public IComputationUser getComputationProvider() { + return (IComputationUser) getMetaTileEntity(); } @Override @@ -48,9 +48,9 @@ public boolean checkRecipe(@NotNull Recipe recipe) { if (!recipe.hasProperty(ComputationProperty.getInstance())) { return true; } - IComputationConsumer provider = getComputationProvider(); + IComputationUser provider = getComputationProvider(); int recipeCWUt = recipe.getProperty(ComputationProperty.getInstance(), 0); - return provider.supplyCWU(recipeCWUt, true) >= recipeCWUt; + return provider.requestCWU(recipeCWUt, true) >= recipeCWUt; } @Override @@ -70,18 +70,18 @@ protected void updateRecipeProgress() { if (canRecipeProgress && drawEnergy(recipeEUt, true)) { drawEnergy(recipeEUt, false); - IComputationConsumer provider = getComputationProvider(); - int availableCWUt = (int) provider.supplyCWU(Integer.MAX_VALUE, true); + IComputationUser provider = getComputationProvider(); + int availableCWUt = (int) provider.requestCWU(Integer.MAX_VALUE, true); if (availableCWUt >= recipeCWUt) { // carry on as normal this.hasNotEnoughComputation = false; if (isDurationTotalCWU) { // draw as much CWU as possible, and increase progress by this amount - currentDrawnCWUt = (int) provider.supplyCWU(availableCWUt, false); + currentDrawnCWUt = (int) provider.requestCWU(availableCWUt, false); progressTime += currentDrawnCWUt; } else { // draw only the recipe CWU/t, and increase progress by 1 - provider.supplyCWU(recipeCWUt, false); + provider.requestCWU(recipeCWUt, false); progressTime++; } if (progressTime > maxProgressTime) { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java index fa99b9a3db6..9375fe34f60 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java @@ -140,7 +140,7 @@ private ComputationQuery queryConnected() { long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); if (tick >= nextQueryTick) { this.query = new ComputationQuery(); - IDataAccess.accessDatas(getAbilities(MultiblockAbility.COMPUTATION_DATA_RECEPTION), query); + IDataAccess.accessData(getAbilities(MultiblockAbility.COMPUTATION_DATA_RECEPTION), query); this.nextQueryTick = tick + 10; } return this.query; diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java index 9dc6a6f63c4..89f9bee4cda 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java @@ -2,7 +2,7 @@ import gregtech.api.GTValues; import gregtech.api.capability.IObjectHolder; -import gregtech.api.capability.data.IComputationConsumer; +import gregtech.api.capability.data.IComputationUser; import gregtech.api.capability.data.IDataAccess; import gregtech.api.capability.data.query.ComputationQuery; import gregtech.api.capability.impl.ComputationRecipeLogic; @@ -45,7 +45,7 @@ import java.util.Collections; import java.util.List; -public class MetaTileEntityResearchStation extends RecipeMapMultiblockController implements IComputationConsumer { +public class MetaTileEntityResearchStation extends RecipeMapMultiblockController implements IComputationUser { private IObjectHolder objectHolder; @@ -96,13 +96,13 @@ public void invalidateStructure() { } @Override - public long supplyCWU(long requested, boolean simulate) { + public long requestCWU(long requested, boolean simulate) { return queryConnected().requestCWU(requested, simulate); } private ComputationQuery queryConnected() { ComputationQuery query = new ComputationQuery(); - IDataAccess.accessDatas(getAbilities(MultiblockAbility.COMPUTATION_DATA_RECEPTION), query); + IDataAccess.accessData(getAbilities(MultiblockAbility.COMPUTATION_DATA_RECEPTION), query); return query; } diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java index 532708723da..da8168e86e5 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java @@ -73,7 +73,7 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { if (queryObject instanceof IBridgeable bridgeable && reception.size() > 1) { bridgeable.setBridged(); } - return IDataAccess.accessDatas(reception, queryObject); + return IDataAccess.accessData(reception, queryObject); } else { TileEntity tileEntity = getNeighbor(getFrontFacing()); if (tileEntity == null) return false; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java index 87dafb5989b..338b86fd2a3 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java @@ -162,7 +162,7 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { } @Override - public DataAccessFormat getFormat() { + public @NotNull DataAccessFormat getFormat() { return DataAccessFormat.STANDARD; } diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java index abb51b7f299..5161b1a0356 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java @@ -70,14 +70,14 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { MultiblockControllerBase controller = getController(); if (!controller.isActive()) return false; - if (IDataAccess.accessDatas(controller.getAbilities(MultiblockAbility.DATA_ACCESS_HATCH), queryObject)) + if (IDataAccess.accessData(controller.getAbilities(MultiblockAbility.DATA_ACCESS_HATCH), queryObject)) return true; List reception = controller.getAbilities(MultiblockAbility.OPTICAL_DATA_RECEPTION); if (queryObject instanceof IBridgeable bridgeable && reception.size() > 1) { bridgeable.setBridged(); } - return IDataAccess.accessDatas(reception, queryObject); + return IDataAccess.accessData(reception, queryObject); } else { TileEntity tileEntity = getNeighbor(getFrontFacing()); if (tileEntity == null) return false; diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index 35fe4fb0dbe..87f2fc85524 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -74,7 +74,7 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { } @Override - public DataAccessFormat getFormat() { + public @NotNull DataAccessFormat getFormat() { return DataAccessFormat.UNIVERSAL; } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index badf2e35180..f9eb22e1362 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -1299,8 +1299,8 @@ cover.generic.manual_io=Manual IO Mode cover.generic.io=IO Mode cover.generic.distribution.name=Distribution Mode cover.generic.distribution.equalized=§bEqual Distribution§r\n§7Fills all destinations by the same amount per operation. -cover.generic.distribution.round_robin=§bRound Robin§r\n§7Fills destinations in a fixed order, but performs no further equalization. -cover.generic.distribution.flood=§bFlood Insert§r\n§7Fills destinations based on their priorities, performing no further equalization. +cover.generic.distribution.round_robin=§bRound Robin§r\n§7Fills destinations in a fixed order, but does not equalize. +cover.generic.distribution.flood=§bFlood Insert§r\n§7Fills destinations based on their priorities and does not equalize. cover.pump.mode=Pump Mode cover.conveyor.title=Conveyor Cover Settings (%s) cover.conveyor.transfer_rate=§7items/sec @@ -2415,7 +2415,7 @@ tile.laser_pipe_normal.name=Laser Transmitting Cable tile.laser_pipe_normal.tooltip1=Transmitting power with §fno loss§7 in straight lines tile.laser_pipe_mirror.name=Laser Mirror Cable -tile.laser_pipe_mirror.tooltip1=Transmitting power with §fno loss§7 around the bend +tile.laser_pipe_mirror.tooltip1=Transmitting power with §fno loss§7 around a bend metaitem.prospector.lv.name=Electric Prospector's Scanner (LV) metaitem.prospector.hv.name=Electric Prospector's Scanner (HV) From fc1c35e9c49d794ed31cafb38220ef034e987c46 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 11 Aug 2024 16:53:33 -0600 Subject: [PATCH 097/157] Oops --- .../impl/EnergyContainerHandler.java | 2 +- .../common/covers/CoverSolarPanel.java | 2 +- .../converter/ConverterTrait.java | 2 +- .../storage/MetaTileEntityCreativeEnergy.java | 4 +-- .../net/energy/EnergyCapabilityObject.java | 6 ++--- .../pipelike/net/energy/EnergyGroupData.java | 27 ++++++++++++------- 6 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java b/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java index c40f25403e5..1da062af4db 100644 --- a/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java +++ b/src/main/java/gregtech/api/capability/impl/EnergyContainerHandler.java @@ -212,7 +212,7 @@ public void update() { .getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, oppositeSide); if (energyContainer == null || !energyContainer.inputsEnergy(oppositeSide)) continue; amperesUsed += energyContainer.acceptEnergyFromNetwork(oppositeSide, outputVoltage, - outputAmperes - amperesUsed); + outputAmperes - amperesUsed, false); if (amperesUsed == outputAmperes) break; } } diff --git a/src/main/java/gregtech/common/covers/CoverSolarPanel.java b/src/main/java/gregtech/common/covers/CoverSolarPanel.java index 419212d89cc..d5275e108f1 100644 --- a/src/main/java/gregtech/common/covers/CoverSolarPanel.java +++ b/src/main/java/gregtech/common/covers/CoverSolarPanel.java @@ -60,7 +60,7 @@ public void update() { IEnergyContainer energyContainer = coverable.getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, getAttachedSide()); if (energyContainer != null) { - energyContainer.acceptEnergyFromNetwork(null, EUt, 1); + energyContainer.acceptEnergyFromNetwork(null, EUt, 1, false); } } } diff --git a/src/main/java/gregtech/common/metatileentities/converter/ConverterTrait.java b/src/main/java/gregtech/common/metatileentities/converter/ConverterTrait.java index 1c7529131f7..645746f46ec 100644 --- a/src/main/java/gregtech/common/metatileentities/converter/ConverterTrait.java +++ b/src/main/java/gregtech/common/metatileentities/converter/ConverterTrait.java @@ -124,7 +124,7 @@ protected void pushEnergy() { // send out energy energyInserted = container.acceptEnergyFromNetwork(metaTileEntity.getFrontFacing().getOpposite(), voltage, - ampsToInsert) * voltage; + ampsToInsert, false) * voltage; } else { // push out FE // Get the FE capability in front of us IEnergyStorage storage = getCapabilityAtFront(CapabilityEnergy.ENERGY); diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java index cdbd6218e9d..951747c2a50 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCreativeEnergy.java @@ -208,7 +208,7 @@ public void update() { } } else { if (!container.inputsEnergy(opposite) || container.getEnergyCanBeInserted() == 0) continue; - ampsUsed += container.acceptEnergyFromNetwork(opposite, voltage, amps - ampsUsed); + ampsUsed += container.acceptEnergyFromNetwork(opposite, voltage, amps - ampsUsed, false); } if (ampsUsed >= amps) break; @@ -242,7 +242,7 @@ public void readFromNBT(NBTTagCompound data) { @Override public long receiveLaser(long laserVoltage, long laserAmperage) { - return acceptEnergyFromNetwork(null, laserVoltage, laserAmperage); + return acceptEnergyFromNetwork(null, laserVoltage, laserAmperage, false); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 58bd5b41248..3bd461e2118 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -153,7 +153,7 @@ public long getInputPerSec() { EnergyGroupData data = getEnergyData(); if (data == null) return 0; else return data - .getEnergyFluxPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter())[0]; + .getEnergyInPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); } @Override @@ -161,7 +161,7 @@ public long getOutputPerSec() { EnergyGroupData data = getEnergyData(); if (data == null) return 0; else return data - .getEnergyFluxPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter())[1]; + .getEnergyOutPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); } @Override @@ -179,7 +179,7 @@ public long changeEnergy(long differenceAmount) { GTLog.logger.fatal("Do not use changeEnergy() for cables! Use acceptEnergyFromNetwork()"); return acceptEnergyFromNetwork(null, differenceAmount / getInputAmperage(), - differenceAmount / getInputVoltage()) * getInputVoltage(); + differenceAmount / getInputVoltage(), false) * getInputVoltage(); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java index 809f87745ef..672912b7e0a 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java @@ -4,23 +4,30 @@ public class EnergyGroupData extends AbstractGroupData { - private final long[] lastEnergyFluxPerSec = new long[2]; - private final long[] energyFluxPerSec = new long[2]; + private long lastEnergyInPerSec; + private long lastEnergyOutPerSec; + private long energyInPerSec; + private long energyOutPerSec; private long updateTime; - public long[] getEnergyFluxPerSec(long queryTick) { + public long getEnergyInPerSec(long queryTick) { updateCache(queryTick); - return lastEnergyFluxPerSec; + return lastEnergyInPerSec; + } + + public long getEnergyOutPerSec(long queryTick) { + updateCache(queryTick); + return lastEnergyOutPerSec; } public void addEnergyInPerSec(long energy, long queryTick) { updateCache(queryTick); - energyFluxPerSec[0] += energy; + energyInPerSec += energy; } public void addEnergyOutPerSec(long energy, long queryTick) { updateCache(queryTick); - energyFluxPerSec[1] += energy; + energyOutPerSec += energy; } private void updateCache(long queryTick) { @@ -31,9 +38,9 @@ private void updateCache(long queryTick) { } public void clearCache() { - lastEnergyFluxPerSec[0] = energyFluxPerSec[0]; - lastEnergyFluxPerSec[1] = energyFluxPerSec[1]; - energyFluxPerSec[0] = 0; - energyFluxPerSec[1] = 0; + lastEnergyInPerSec = energyInPerSec; + lastEnergyOutPerSec = energyOutPerSec; + energyInPerSec = 0; + energyOutPerSec = 0; } } From d26a3e8334bc4c7e5bbdb52047f1b03fd72adbba Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 11 Aug 2024 18:03:11 -0600 Subject: [PATCH 098/157] Review stuff I missed --- .../data/query/ComputationQuery.java | 6 +- .../data/query/DataQueryObject.java | 3 + .../data/query/RecipeDataQuery.java | 4 +- .../gregtech/api/graphnet/GraphNetBacker.java | 33 ++++---- .../java/gregtech/api/graphnet/IGraphNet.java | 22 ++--- .../gregtech/api/graphnet/INBTBuilder.java | 7 -- .../api/graphnet/MultiNodeHelper.java | 9 ++- .../java/gregtech/api/graphnet/NetGroup.java | 21 ++--- .../api/graphnet/alg/SinglePathAlgorithm.java | 2 +- .../api/graphnet/edge/NetFlowEdge.java | 3 +- .../api/graphnet/edge/NetFlowSharedEdge.java | 3 +- .../api/graphnet/path/AbstractNetPath.java | 4 +- .../logic/TemperatureLossFunction.java | 6 +- .../physical/block/ItemMaterialPipeBlock.java | 2 +- .../pipenet/physical/block/PipeBlock.java | 10 +-- .../tile/PipeActivableTileEntity.java | 3 + .../physical/tile/PipeCoverHolder.java | 3 + .../physical/tile/PipeMaterialTileEntity.java | 8 +- .../pipenet/physical/tile/PipeTileEntity.java | 47 ++++++----- .../predicate/NetPredicateRegistry.java | 10 +-- .../predicate/test/FluidTestObject.java | 5 +- .../predicate/test/ItemTestObject.java | 5 +- .../traverse/IRoundRobinTraverseData.java | 3 +- .../graphnet/traverse/TraverseHelpers.java | 4 +- .../java/gregtech/api/util/GTUtility.java | 3 - .../api/util/function/NullableSupplier.java | 13 --- .../renderer/pipe/ActivablePipeModel.java | 3 + .../client/renderer/pipe/PipeItemModel.java | 3 + .../renderer/pipe/cache/ActivableSQC.java | 3 + .../renderer/pipe/cover/CoverRenderer.java | 3 + .../pipe/cover/CoverRendererBuilder.java | 3 + .../pipe/cover/CoverRendererPackage.java | 3 + .../client/renderer/pipe/quad/ColorData.java | 4 + .../pipe/quad/OverlayLayerDefinition.java | 3 + .../client/renderer/pipe/quad/QuadHelper.java | 3 + .../client/renderer/pipe/quad/UVMapper.java | 3 + .../renderer/pipe/util/ActivableCacheKey.java | 4 + .../client/renderer/pipe/util/CacheKey.java | 3 + .../pipe/util/SpriteInformationWrapper.java | 3 + .../renderer/pipe/util/WoodCacheKey.java | 4 + .../blocks/properties/PropertyByte.java | 80 ------------------- .../blocks/properties/PropertyShort.java | 80 ------------------- .../gregtech/common/covers/CoverConveyor.java | 5 -- .../filter/oreglob/impl/NodeInterpreter.java | 2 +- .../filter/oreglob/impl/NodeOreGlob.java | 2 +- .../net/energy/EnergyCapabilityObject.java | 4 +- .../pipelike/net/energy/WorldEnergyNet.java | 5 ++ .../pipelike/net/fluid/WorldFluidNet.java | 5 ++ .../pipelike/net/item/WorldItemNet.java | 5 ++ .../pipelike/net/laser/WorldLaserNet.java | 5 ++ .../pipelike/net/optical/WorldOpticalNet.java | 5 ++ 51 files changed, 194 insertions(+), 288 deletions(-) delete mode 100644 src/main/java/gregtech/api/graphnet/INBTBuilder.java delete mode 100644 src/main/java/gregtech/api/util/function/NullableSupplier.java delete mode 100644 src/main/java/gregtech/common/blocks/properties/PropertyByte.java delete mode 100644 src/main/java/gregtech/common/blocks/properties/PropertyShort.java diff --git a/src/main/java/gregtech/api/capability/data/query/ComputationQuery.java b/src/main/java/gregtech/api/capability/data/query/ComputationQuery.java index e28640d3c96..acb94a80f50 100644 --- a/src/main/java/gregtech/api/capability/data/query/ComputationQuery.java +++ b/src/main/java/gregtech/api/capability/data/query/ComputationQuery.java @@ -3,6 +3,7 @@ import gregtech.api.capability.data.IComputationProvider; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.NotNull; import java.util.Set; @@ -18,6 +19,7 @@ public ComputationQuery() { } @Override + @NotNull public DataQueryFormat getFormat() { return DataQueryFormat.COMPUTATION; } @@ -40,6 +42,7 @@ public void registerProvider(IComputationProvider provider) { providers.add(provider); } + @NotNull public Set getProviders() { return providers; } @@ -48,7 +51,8 @@ public long requestCWU(long amount, boolean simulate) { long remaining = amount; for (IComputationProvider provider : getProviders()) { remaining -= provider.supplyCWU(remaining, simulate); - if (remaining <= 0) return amount; + assert remaining >= 0; + if (remaining == 0) return amount; } return amount - remaining; } diff --git a/src/main/java/gregtech/api/capability/data/query/DataQueryObject.java b/src/main/java/gregtech/api/capability/data/query/DataQueryObject.java index 441c98fcb99..68a5666b562 100644 --- a/src/main/java/gregtech/api/capability/data/query/DataQueryObject.java +++ b/src/main/java/gregtech/api/capability/data/query/DataQueryObject.java @@ -1,5 +1,7 @@ package gregtech.api.capability.data.query; +import org.jetbrains.annotations.NotNull; + public abstract class DataQueryObject { private static int ID = 0; @@ -20,6 +22,7 @@ public boolean shouldTriggerWalker() { return shouldTriggerWalker; } + @NotNull public abstract DataQueryFormat getFormat(); @Override diff --git a/src/main/java/gregtech/api/capability/data/query/RecipeDataQuery.java b/src/main/java/gregtech/api/capability/data/query/RecipeDataQuery.java index ffb05a10079..f0dea08e21c 100644 --- a/src/main/java/gregtech/api/capability/data/query/RecipeDataQuery.java +++ b/src/main/java/gregtech/api/capability/data/query/RecipeDataQuery.java @@ -2,6 +2,8 @@ import gregtech.api.recipes.Recipe; +import org.jetbrains.annotations.NotNull; + public class RecipeDataQuery extends DataQueryObject { private final Recipe recipe; @@ -13,7 +15,7 @@ public RecipeDataQuery(Recipe recipe) { } @Override - public DataQueryFormat getFormat() { + public @NotNull DataQueryFormat getFormat() { return DataQueryFormat.RECIPE; } diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index c17632193c1..d3ad18bfa99 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -13,11 +13,13 @@ import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -74,7 +76,7 @@ public boolean removeNode(@Nullable NetNode node) { NetGroup group = node.getGroupUnsafe(); if (group != null) group.removeNode(node); } - if (this.getGraph().edgesOf(node.wrapper).size() != 0) this.invalidateAlgs(); + if (!this.getGraph().edgesOf(node.wrapper).isEmpty()) this.invalidateAlgs(); NetGroup group = node.getGroupUnsafe(); if (group != null) { group.splitNode(node); @@ -197,15 +199,15 @@ public INetGraph getGraph() { // the number of unnecessary references in the graphnet on, say, a large server is drastically reduced. // however, since there are necessarily more read/write actions to disk, the cpu load would increase in turn. - public void readFromNBT(NBTTagCompound nbt) { + public void readFromNBT(@NotNull NBTTagCompound nbt) { // construct map of node ids -> nodes, while building nodes to groups // construct edges using map Int2ObjectOpenHashMap groupMap = new Int2ObjectOpenHashMap<>(); - NBTTagCompound vertices = nbt.getCompoundTag("Vertices"); - int vertexCount = vertices.getInteger("Count"); + NBTTagList vertices = nbt.getTagList("Vertices", 10); + int vertexCount = vertices.tagCount(); Int2ObjectOpenHashMap vertexMap = new Int2ObjectOpenHashMap<>(vertexCount); for (int i = 0; i < vertexCount; i++) { - NBTTagCompound tag = vertices.getCompoundTag(String.valueOf(i)); + NBTTagCompound tag = vertices.getCompoundTagAt(i); NetNode node = this.backedNet.getNewNode(); node.deserializeNBT(tag); if (tag.hasKey("GroupID")) { @@ -223,10 +225,10 @@ public void readFromNBT(NBTTagCompound nbt) { this.vertexMap.put(node.getEquivalencyData(), vertex); } - NBTTagCompound edges = nbt.getCompoundTag("Edges"); - int edgeCount = edges.getInteger("Count"); + NBTTagList edges = nbt.getTagList("Edges", 10); + int edgeCount = edges.tagCount(); for (int i = 0; i < edgeCount; i++) { - NBTTagCompound tag = edges.getCompoundTag(String.valueOf(i)); + NBTTagCompound tag = edges.getCompoundTagAt(i); GraphEdge graphEdge = this.getGraph().addEdge(vertexMap.get(tag.getInteger("SourceID")), vertexMap.get(tag.getInteger("TargetID"))); this.getGraph().setEdgeWeight(graphEdge, tag.getDouble("Weight")); @@ -234,7 +236,8 @@ public void readFromNBT(NBTTagCompound nbt) { } } - public NBTTagCompound writeToNBT(NBTTagCompound compound) { + @Contract("_ -> param1") + public @NotNull NBTTagCompound writeToNBT(NBTTagCompound compound) { // map of net groups -> autogenerated ids; // tag of autogenerated vertex ids -> node nbt & group id // tag of autogenerated edge ids -> edge nbt & source/target ids @@ -242,7 +245,7 @@ public NBTTagCompound writeToNBT(NBTTagCompound compound) { Object2IntOpenHashMap vertexMap = new Object2IntOpenHashMap<>(); int i = 0; int g = 0; - NBTTagCompound vertices = new NBTTagCompound(); + NBTTagList vertices = new NBTTagList(); for (GraphVertex graphVertex : this.getGraph().vertexSet()) { vertexMap.put(graphVertex, i); NetGroup group = graphVertex.wrapped.getGroupUnsafe(); @@ -256,23 +259,19 @@ public NBTTagCompound writeToNBT(NBTTagCompound compound) { } else groupID = groupMap.getInt(group); tag.setInteger("GroupID", groupID); } - vertices.setTag(String.valueOf(i), tag); + vertices.appendTag(tag); i++; } - vertices.setInteger("Count", i); compound.setTag("Vertices", vertices); - i = 0; - NBTTagCompound edges = new NBTTagCompound(); + NBTTagList edges = new NBTTagList(); for (GraphEdge graphEdge : this.getGraph().edgeSet()) { NBTTagCompound tag = graphEdge.wrapped.serializeNBT(); tag.setInteger("SourceID", vertexMap.getInt(graphEdge.getSource())); tag.setInteger("TargetID", vertexMap.getInt(graphEdge.getTarget())); tag.setDouble("Weight", graphEdge.getWeight()); - edges.setTag(String.valueOf(i), tag); - i++; + edges.appendTag(tag); } - edges.setInteger("Count", i); compound.setTag("Edges", edges); return compound; diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index 0135cf2a8ee..8b7faf043d3 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -80,20 +80,6 @@ default boolean supportsPredication() { @Nullable NetEdge getEdge(@NotNull NetNode source, @NotNull NetNode target); - /** - * Returns the edge linking two nodes together, if one exists and both provided nodes are not null. - * - * @param source Source node. - * @param target Target node. - * @return the linking edge, if one exists. - */ - @Contract("null, _ -> null; _, null -> null; _, _ -> _") - @Nullable - default NetEdge getEdgeNullSafe(@Nullable NetNode source, @Nullable NetNode target) { - if (source == null || target == null) return null; - else return getEdge(source, target); - } - /** * Removes the edge linking two nodes together, if one exists. * @@ -224,4 +210,12 @@ default NetEdge getNewEdge() { */ @ApiStatus.Internal void markDirty(); + + /** + * Get the network ID for this net. Must be unique and deterministic between server and client, but can change + * between mod versions. + * + * @return the net's network id. + */ + int getNetworkID(); } diff --git a/src/main/java/gregtech/api/graphnet/INBTBuilder.java b/src/main/java/gregtech/api/graphnet/INBTBuilder.java deleted file mode 100644 index 62a358b23cb..00000000000 --- a/src/main/java/gregtech/api/graphnet/INBTBuilder.java +++ /dev/null @@ -1,7 +0,0 @@ -package gregtech.api.graphnet; - -@FunctionalInterface -public interface INBTBuilder { - - void build(); -} diff --git a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java index ca117fdb98b..475085d4175 100644 --- a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java +++ b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java @@ -4,6 +4,7 @@ import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; @@ -26,7 +27,7 @@ public class MultiNodeHelper implements INetLogicEntryListener { protected final Object2ObjectOpenHashMap handledDatas = new Object2ObjectOpenHashMap<>(); - protected final Object2ObjectOpenHashMap recentTransferNets = new Object2ObjectOpenHashMap<>(); + protected final Object2LongOpenHashMap recentTransferNets = new Object2LongOpenHashMap<>(); protected final int transferTimeout; protected final NetLogicData mergedData = new NetLogicData(); @@ -36,12 +37,12 @@ public MultiNodeHelper(int transferTimeout) { } public boolean traverse(IGraphNet net, long queryTick, boolean simulate) { - var iter = recentTransferNets.object2ObjectEntrySet().fastIterator(); + var iter = recentTransferNets.object2LongEntrySet().fastIterator(); boolean allowed = true; while (iter.hasNext()) { var next = iter.next(); if (net.clashesWith(next.getKey())) { - if (next.getValue() <= queryTick) { + if (next.getLongValue() <= queryTick) { iter.remove(); } else { allowed = false; @@ -81,7 +82,7 @@ public void addNode(@NotNull NetNode node) { } } - public void removeNode(NetNode node) { + public void removeNode(@NotNull NetNode node) { LogicDataHandler removed = handledDatas.remove(node.getNet()); if (removed != null) { removed.invalidate(); diff --git a/src/main/java/gregtech/api/graphnet/NetGroup.java b/src/main/java/gregtech/api/graphnet/NetGroup.java index 351538142c4..c6442d49aeb 100644 --- a/src/main/java/gregtech/api/graphnet/NetGroup.java +++ b/src/main/java/gregtech/api/graphnet/NetGroup.java @@ -2,11 +2,11 @@ import gregtech.api.graphnet.graph.GraphVertex; +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import java.util.Collection; import java.util.Iterator; -import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -98,17 +98,18 @@ protected void mergeNode(NetNode node) { public void splitNode(NetNode source) { if (!this.net.containsNode(source)) return; this.clearPathCaches(); - List targets = this.net.getGraph().outgoingEdgesOf(source.wrapper).stream().map(a -> { - GraphVertex target = a.getTarget(); - // handling so undirected graphs don't throw an error - if (!net.getGraph().isDirected() && target == source.wrapper) - return a.getSource().wrapped; - return target.wrapped; - }).collect(Collectors.toList()); + ObjectLinkedOpenHashSet targets = this.net.getGraph().outgoingEdgesOf(source.wrapper).stream() + .map(a -> { + GraphVertex target = a.getTarget(); + // handling so undirected graphs don't throw an error + if (!net.getGraph().isDirected() && target == source.wrapper) + return a.getSource().wrapped; + return target.wrapped; + }).collect(Collectors.toCollection(ObjectLinkedOpenHashSet::new)); this.net.getBacker().removeVertex(source.wrapper); this.removeNode(source); while (!targets.isEmpty()) { - NetNode target = targets.remove(targets.size() - 1); + NetNode target = targets.removeLast(); Set targetGroup = new ObjectOpenHashSet<>(); Iterator i = this.net.breadthIterator(target); @@ -120,7 +121,7 @@ public void splitNode(NetNode source) { targets.remove(temp); } this.removeNodes(targetGroup); - if (targetGroup.size() != 0) { + if (!targetGroup.isEmpty()) { new NetGroup(this.net, targetGroup); } } diff --git a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java index e19798dcbf4..3c73b8c78d4 100644 --- a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java @@ -69,7 +69,7 @@ private Results compute(GraphVertex source, reversedEdge = !this.net.getGraph().isDirected() && graphEdge.getTarget() == node; // we know that the new edge cannot point to the previous node } else break; // we've reached the end, exit the loop while still valid - } else if (i.hasNext()) i.next(); + } else if (i.hasNext()) i.next(); // remove the second edge, if it exists. if (i.hasNext()) valid = false; // third graphEdge detected - that's an invalid group lastNode = node; node = reversedEdge ? graphEdge.getSource() : graphEdge.getTarget(); diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java index 46964945f72..ffe518dfea5 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java @@ -49,7 +49,8 @@ protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, @Nullable private NetFlowEdge getInverse(IGraphNet graph) { - NetEdge edge = graph.getEdgeNullSafe(getTarget(), getSource()); + if (getTarget() == null || getSource() == null) return null; + NetEdge edge = graph.getEdge(getTarget(), getSource()); if (edge instanceof NetFlowEdge i && i != this) { return i; } diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java index fdedd851ddf..0da255830c5 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java @@ -51,7 +51,8 @@ protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, @Nullable private NetFlowSharedEdge getInverse(IGraphNet graph) { - NetEdge edge = graph.getEdgeNullSafe(getTarget(), getSource()); + if (getTarget() == null || getSource() == null) return null; + NetEdge edge = graph.getEdge(getTarget(), getSource()); if (edge instanceof NetFlowSharedEdge i && i != this) { return i; } diff --git a/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java b/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java index aaa8c5719ab..5e515ed7eea 100644 --- a/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java @@ -50,7 +50,7 @@ public NetLogicData getUnifiedNodeData() { unifiedNodeData = NetLogicData.union(nodes.get(0).getData(), nodes.get(1).getData()); } else { unifiedNodeData = NetLogicData.union(nodes.get(0).getData(), - nodes.subList(1, nodes.size()).stream().map(NetNode::getData).toArray(NetLogicData[]::new)); + nodes.stream().skip(1).map(NetNode::getData).toArray(NetLogicData[]::new)); } } return unifiedNodeData; @@ -68,7 +68,7 @@ public NetLogicData getUnifiedEdgeData() { unifiedEdgeData = NetLogicData.union(edges.get(0).getData(), edges.get(1).getData()); } else { unifiedEdgeData = NetLogicData.union(edges.get(0).getData(), - edges.subList(1, edges.size()).stream().map(NetEdge::getData).toArray(NetLogicData[]::new)); + edges.stream().skip(1).map(NetEdge::getData).toArray(NetLogicData[]::new)); } } return unifiedEdgeData; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java index acefce9b259..e32acca8355 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java @@ -8,12 +8,10 @@ import it.unimi.dsi.fastutil.floats.Float2ObjectArrayMap; -import java.util.Map; - public class TemperatureLossFunction implements INBTSerializable, IPacket { - private static final Map CABLE_LOSS_CACHE = new Float2ObjectArrayMap<>(); - private static final Map PIPE_LOSS_CACHE = new Float2ObjectArrayMap<>(); + private static final Float2ObjectArrayMap CABLE_LOSS_CACHE = new Float2ObjectArrayMap<>(); + private static final Float2ObjectArrayMap PIPE_LOSS_CACHE = new Float2ObjectArrayMap<>(); private EnumLossFunction function; private float factorX; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemMaterialPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemMaterialPipeBlock.java index 3aed6208b2e..2016a779e5f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemMaterialPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemMaterialPipeBlock.java @@ -27,6 +27,6 @@ public int getMetadata(int damage) { @Override public String getItemStackDisplayName(@NotNull ItemStack stack) { Material material = getBlock().getMaterialForStack(stack); - return material == null ? " " : getBlock().getStructure().getOrePrefix().getLocalNameForItem(material); + return material == null ? "unnamed" : getBlock().getStructure().getOrePrefix().getLocalNameForItem(material); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 8dd46a36fc5..4759fe6d563 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -95,8 +95,8 @@ public IPipeStructure getStructure() { public void doPlacementLogic(PipeTileEntity tile, EnumFacing placedBlockSearchSide) { for (EnumFacing facing : EnumFacing.VALUES) { - TileEntity otherr = tile.getNeighbor(facing); - if (otherr instanceof PipeTileEntity other) { + TileEntity neighbor = tile.getNeighbor(facing); + if (neighbor instanceof PipeTileEntity other) { // first check -- does the other tile have a cover that would prevent connection Cover cover = other.getCoverHolder().getCoverAtSide(facing.getOpposite()); if (cover != null && !cover.canPipePassThrough()) continue; @@ -356,12 +356,6 @@ public static Collection getNodesForTile(PipeTileEntity tile) .getOrCreateFromNets(tile.getWorld(), tile.getPos(), tile.getStructure()); } - @Override - public void onBlockAdded(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { - super.onBlockAdded(worldIn, pos, state); - // if (!worldIn.isRemote) getHandler(worldIn, pos).getOrCreateFromNets(worldIn, pos, getStructure()); - } - @Override public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { super.breakBlock(worldIn, pos, state); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java index 91f69fe336d..72b67a02c29 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeActivableTileEntity.java @@ -5,6 +5,8 @@ import net.minecraft.network.PacketBuffer; import net.minecraftforge.common.property.IExtendedBlockState; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.jetbrains.annotations.NotNull; @@ -27,6 +29,7 @@ public boolean isActive() { } @Override + @SideOnly(Side.CLIENT) public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { return super.getRenderInformation(state).withProperty(ActivablePipeModel.ACTIVE_PROPERTY, isActive()); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java index 629c6ccf6c6..5cff74d916c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCoverHolder.java @@ -18,6 +18,8 @@ import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -293,6 +295,7 @@ public T getCapability(@NotNull Capability capability, EnumFacing side) { return holder.getCapabilityCoverQuery(capability, side); } + @SideOnly(Side.CLIENT) public CoverRendererPackage createPackage() { if (covers.isEmpty()) return CoverRendererPackage.EMPTY; CoverRendererPackage rendererPackage = new CoverRendererPackage(shouldRenderCoverBackSides()); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java index 6d6dfd76ce3..257ce8fea0e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java @@ -13,6 +13,8 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraftforge.common.property.IExtendedBlockState; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.jetbrains.annotations.NotNull; @@ -60,6 +62,7 @@ public int getDefaultPaintingColor() { } @Override + @SideOnly(Side.CLIENT) public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { return super.getRenderInformation(state).withProperty(AbstractPipeModel.MATERIAL_PROPERTY, getMaterial()); } @@ -82,13 +85,14 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { @Override public void writeInitialSyncData(@NotNull PacketBuffer buf) { buf.writeBoolean(material != null); - if (material != null) buf.writeString(material.getRegistryName()); + if (material != null) encodeMaterialToBuffer(material, buf); super.writeInitialSyncData(buf); } @Override public void receiveInitialSyncData(@NotNull PacketBuffer buf) { - if (buf.readBoolean()) material = GregTechAPI.materialManager.getMaterial(buf.readString(255)); + if (buf.readBoolean()) material = decodeMaterialFromBuffer(buf); + else material = null; super.receiveInitialSyncData(buf); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 31cf360332e..b2bfc13b2f0 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -4,6 +4,7 @@ import gregtech.api.GregTechAPI; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; +import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.NetLogicRegistry; @@ -47,6 +48,7 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; @@ -56,7 +58,6 @@ import java.util.EnumMap; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.function.Consumer; @@ -66,7 +67,7 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick public static final int DEFAULT_COLOR = 0xFFFFFFFF; - private final Object2ObjectOpenHashMap netLogicDatas = new Object2ObjectOpenHashMap<>(); + private final Int2ObjectOpenHashMap netLogicDatas = new Int2ObjectOpenHashMap<>(); private final ObjectOpenHashSet listeners = new ObjectOpenHashSet<>(); // information that is only required for determining graph topology should be stored on the tile entity level, @@ -430,8 +431,8 @@ public T getCapability(@NotNull Capability capability, @Nullable EnumFaci // data sync management // - public NetLogicData getNetLogicData(String netName) { - return netLogicDatas.get(netName); + public NetLogicData getNetLogicData(IGraphNet net) { + return netLogicDatas.get(net.getNetworkID()); } @Override @@ -456,11 +457,11 @@ protected void initialize() { for (WorldPipeNetNode node : PipeBlock.getNodesForTile(this)) { this.addCapabilities(node.getNet().getNewCapabilityObjects(node)); this.netCapabilities.put(node, new PipeCapabilityWrapper(this, node)); - String netName = node.getNet().mapName; - netLogicDatas.put(netName, node.getData()); + int networkID = node.getNet().getNetworkID(); + netLogicDatas.put(networkID, node.getData()); var listener = node.getData().createListener( (e, r, f) -> writeCustomData(UPDATE_PIPE_LOGIC, buf -> { - buf.writeString(netName); + buf.writeVarInt(networkID); buf.writeString(e.getName()); buf.writeBoolean(r); buf.writeBoolean(f); @@ -512,6 +513,15 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { this.getCoverHolder().deserializeNBT(compound.getCompoundTag("Covers")); } + protected void encodeMaterialToBuffer(@NotNull Material material, @NotNull PacketBuffer buf) { + buf.writeVarInt(material.getRegistry().getNetworkId()); + buf.writeInt(material.getId()); + } + + protected Material decodeMaterialFromBuffer(@NotNull PacketBuffer buf) { + return GregTechAPI.materialManager.getRegistry(buf.readVarInt()).getObjectById(buf.readInt()); + } + @Override public void writeInitialSyncData(@NotNull PacketBuffer buf) { buf.writeByte(connectionMask); @@ -519,10 +529,10 @@ public void writeInitialSyncData(@NotNull PacketBuffer buf) { buf.writeByte(blockedMask); buf.writeInt(paintingColor); buf.writeBoolean(frameMaterial != null); - if (frameMaterial != null) buf.writeString(frameMaterial.getRegistryName()); + if (frameMaterial != null) encodeMaterialToBuffer(frameMaterial, buf); buf.writeVarInt(netLogicDatas.size()); - for (Map.Entry entry : netLogicDatas.entrySet()) { - buf.writeString(entry.getKey()); + for (var entry : netLogicDatas.entrySet()) { + buf.writeVarInt(entry.getKey()); entry.getValue().encode(buf); } this.getCoverHolder().writeInitialSyncData(buf); @@ -535,15 +545,15 @@ public void receiveInitialSyncData(@NotNull PacketBuffer buf) { renderMask = buf.readByte(); blockedMask = buf.readByte(); paintingColor = buf.readInt(); - if (buf.readBoolean()) frameMaterial = GregTechAPI.materialManager.getMaterial(buf.readString(255)); + if (buf.readBoolean()) frameMaterial = decodeMaterialFromBuffer(buf); else frameMaterial = null; netLogicDatas.clear(); int count = buf.readVarInt(); for (int i = 0; i < count; i++) { - String key = buf.readString(255); + int networkID = buf.readVarInt(); NetLogicData data = new NetLogicData(); data.decode(buf); - netLogicDatas.put(key, data); + netLogicDatas.put(networkID, data); } this.getCoverHolder().readInitialSyncData(buf); } @@ -555,30 +565,30 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { if (discriminator == UPDATE_PIPE_LOGIC) { // extra check just to make sure we don't affect actual net data with our writes if (world.isRemote) { - String netName = buf.readString(255); + int networkID = buf.readVarInt(); String identifier = buf.readString(255); boolean removed = buf.readBoolean(); boolean fullChange = buf.readBoolean(); if (removed) { - this.netLogicDatas.computeIfPresent(netName, (k, v) -> v.removeLogicEntry(identifier)); + this.netLogicDatas.computeIfPresent(networkID, (k, v) -> v.removeLogicEntry(identifier)); } else { if (fullChange) { NetLogicEntry logic = NetLogicRegistry.getSupplierErroring(identifier).get(); logic.decode(buf, fullChange); - this.netLogicDatas.compute(netName, (k, v) -> { + this.netLogicDatas.compute(networkID, (k, v) -> { if (v == null) v = new NetLogicData(); v.setLogicEntry(logic); return v; }); } else { - NetLogicData data = this.netLogicDatas.get(netName); + NetLogicData data = this.netLogicDatas.get(networkID); if (data != null) { NetLogicEntry entry = data.getLogicEntryNullable(identifier); if (entry != null) entry.decode(buf); } else return; } if (identifier.equals(TemperatureLogic.INSTANCE.getName())) { - TemperatureLogic tempLogic = this.netLogicDatas.get(netName) + TemperatureLogic tempLogic = this.netLogicDatas.get(networkID) .getLogicEntryNullable(TemperatureLogic.INSTANCE); if (tempLogic != null) updateTemperatureLogic(tempLogic); } @@ -699,6 +709,7 @@ public void markAsDirty() { * Note - the block corresponding to this tile entity must register any new unlisted properties to the default * state. */ + @SideOnly(Side.CLIENT) @MustBeInvokedByOverriders public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { byte frameMask = 0; diff --git a/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java index 3ea6eb82c36..df5429d7a2e 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java +++ b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java @@ -1,7 +1,5 @@ package gregtech.api.graphnet.predicate; -import gregtech.api.util.function.NullableSupplier; - import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -11,17 +9,17 @@ public final class NetPredicateRegistry { - private static final Map>> REGISTRY = new Object2ObjectOpenHashMap<>(); + private static final Map>> REGISTRY = new Object2ObjectOpenHashMap<>(); - static void register(EdgePredicate predicate) { + static void register(@NotNull EdgePredicate predicate) { REGISTRY.putIfAbsent(predicate.getName(), predicate::getNew); } - public static @Nullable Supplier> getSupplierNullable(String name) { + public static @Nullable Supplier<@NotNull EdgePredicate> getSupplierNullable(String name) { return REGISTRY.get(name); } - public static @NotNull NullableSupplier> getSupplierNotNull(String name) { + public static @NotNull Supplier<@Nullable EdgePredicate> getSupplierNotNull(String name) { return REGISTRY.getOrDefault(name, () -> null); } diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java index 842f106d9d4..bf49a7392e7 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java @@ -16,9 +16,12 @@ public final class FluidTestObject implements IPredicateTestObject, Predicate> { @@ -19,7 +20,7 @@ public interface IRoundRobinTraverseData getTraversalCache(); + Deque getTraversalCache(); /** * Whether a path should be skipped before checking it against the round robin cache. diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index eaa1f2c8935..76dd2d4b0ad 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -14,7 +14,7 @@ import org.jetbrains.annotations.Nullable; import org.jgrapht.alg.util.Pair; -import java.util.ArrayDeque; +import java.util.Deque; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -344,7 +344,7 @@ D extends ITraverseData & IRoundRobinTraverseData> long traverseRoun long flowIn, boolean strict) { long availableFlow = flowIn; - ArrayDeque cache = data.getTraversalCache(); + Deque cache = data.getTraversalCache(); Predicate invalidityCheck = null; Map skippedPaths = new Object2ObjectOpenHashMap<>(); diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index f6004c37001..d4f120611cc 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -53,8 +53,6 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandlerItem; import net.minecraftforge.fml.relauncher.ReflectionHelper; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; @@ -918,7 +916,6 @@ public static double geometricMean(double first, double... numbers) { } @NotNull - @SideOnly(Side.CLIENT) public static EntityPlayer getSP() { return Minecraft.getMinecraft().player; } diff --git a/src/main/java/gregtech/api/util/function/NullableSupplier.java b/src/main/java/gregtech/api/util/function/NullableSupplier.java deleted file mode 100644 index e66e41429d2..00000000000 --- a/src/main/java/gregtech/api/util/function/NullableSupplier.java +++ /dev/null @@ -1,13 +0,0 @@ -package gregtech.api.util.function; - -import org.jetbrains.annotations.Nullable; - -import java.util.function.Supplier; - -@FunctionalInterface -public interface NullableSupplier extends Supplier { - - @Override - @Nullable - T get(); -} diff --git a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java index 41e0feab4bc..1aeb2a2477e 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java @@ -27,6 +27,8 @@ import net.minecraft.util.registry.IRegistry; import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; @@ -36,6 +38,7 @@ import java.util.function.Supplier; import java.util.stream.Collectors; +@SideOnly(Side.CLIENT) public class ActivablePipeModel extends AbstractPipeModel { private static final ResourceLocation loc = GTUtility.gregtechId("block/pipe_activable"); diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java index 084d1699e3f..a6f15763c36 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java @@ -11,6 +11,8 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.model.TRSRTransformation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -23,6 +25,7 @@ import javax.vecmath.Quat4f; import javax.vecmath.Vector3f; +@SideOnly(Side.CLIENT) public class PipeItemModel implements IBakedModel { private static final EnumMap CAMERA_TRANSFORMS = new EnumMap<>( diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java index 6c321f8527d..4b213b6f847 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ActivableSQC.java @@ -9,12 +9,15 @@ import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.util.EnumFacing; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.jetbrains.annotations.NotNull; import java.util.EnumMap; import java.util.List; +@SideOnly(Side.CLIENT) public class ActivableSQC extends StructureQuadCache { protected final EnumMap overlayCoords = new EnumMap<>(EnumFacing.class); diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java index 2b4400991e0..995a89992a8 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRenderer.java @@ -5,11 +5,14 @@ import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import java.util.EnumSet; import java.util.List; @FunctionalInterface +@SideOnly(Side.CLIENT) public interface CoverRenderer { void addQuads(List quads, EnumFacing facing, EnumSet renderPlate, boolean renderBackside, diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java index 8897f3cd303..a46534f3929 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java @@ -19,6 +19,8 @@ import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -31,6 +33,7 @@ import java.util.EnumSet; import java.util.List; +@SideOnly(Side.CLIENT) public class CoverRendererBuilder { private static final float OVERLAY_DIST_1 = 0.003f; diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java index 6ddf36b88f1..347404b2060 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererPackage.java @@ -6,6 +6,8 @@ import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.property.IUnlistedProperty; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.jetbrains.annotations.NotNull; @@ -13,6 +15,7 @@ import java.util.EnumSet; import java.util.List; +@SideOnly(Side.CLIENT) public final class CoverRendererPackage { public static final UnlistedCRPProperty PROPERTY = new UnlistedCRPProperty("CRP"); diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java b/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java index b650383a14a..d28907b6272 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java @@ -1,6 +1,10 @@ package gregtech.client.renderer.pipe.quad; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + import com.github.bsideup.jabel.Desugar; @Desugar +@SideOnly(Side.CLIENT) public record ColorData(int... colorsARGB) {} diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java b/src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java index 1da3a447357..719bbe583fb 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/OverlayLayerDefinition.java @@ -1,12 +1,15 @@ package gregtech.client.renderer.pipe.quad; import net.minecraft.util.EnumFacing; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.ImmutablePair; import org.jetbrains.annotations.Nullable; import org.lwjgl.util.vector.Vector3f; @FunctionalInterface +@SideOnly(Side.CLIENT) public interface OverlayLayerDefinition { ImmutablePair computeBox(@Nullable EnumFacing facing, float x1, float y1, float z1, float x2, diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java index 97bf213c2b2..03502642fec 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java @@ -9,6 +9,8 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -17,6 +19,7 @@ import org.jetbrains.annotations.Nullable; import org.lwjgl.util.vector.Vector3f; +@SideOnly(Side.CLIENT) public final class QuadHelper { private static final FaceBakery BAKERY = new FaceBakery(); diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java index 60c0abe8f99..1fdb61f8870 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java @@ -2,11 +2,14 @@ import net.minecraft.client.renderer.block.model.BlockFaceUV; import net.minecraft.util.EnumFacing; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.util.vector.Vector3f; @FunctionalInterface +@SideOnly(Side.CLIENT) public interface UVMapper { static UVMapper standard(int rot) { diff --git a/src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java index 69044f5ee2f..3091ae3f28c 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/ActivableCacheKey.java @@ -1,7 +1,11 @@ package gregtech.client.renderer.pipe.util; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + import org.jetbrains.annotations.Nullable; +@SideOnly(Side.CLIENT) public class ActivableCacheKey extends CacheKey { private final boolean active; diff --git a/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java index ad2197c9a9a..76e5667585c 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/CacheKey.java @@ -1,12 +1,15 @@ package gregtech.client.renderer.pipe.util; import net.minecraft.util.IStringSerializable; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Objects; +@SideOnly(Side.CLIENT) public class CacheKey implements IStringSerializable { protected final float thickness; diff --git a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java index 8f33845d353..8ea4f1bbccf 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/SpriteInformationWrapper.java @@ -1,11 +1,14 @@ package gregtech.client.renderer.pipe.util; import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; +@SideOnly(Side.CLIENT) public class SpriteInformationWrapper implements Supplier, Consumer, BiConsumer { diff --git a/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java index ea214767051..5db92932248 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java @@ -3,11 +3,15 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.PropertyKey; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Objects; +@SideOnly(Side.CLIENT) public class WoodCacheKey extends CacheKey { private final boolean wood; diff --git a/src/main/java/gregtech/common/blocks/properties/PropertyByte.java b/src/main/java/gregtech/common/blocks/properties/PropertyByte.java deleted file mode 100644 index 3a270a0c5f4..00000000000 --- a/src/main/java/gregtech/common/blocks/properties/PropertyByte.java +++ /dev/null @@ -1,80 +0,0 @@ -package gregtech.common.blocks.properties; - -import net.minecraft.block.properties.PropertyHelper; - -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableSet; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Set; - -public class PropertyByte extends PropertyHelper { - - private final ImmutableSet allowedValues; - - protected PropertyByte(String name, byte min, byte max) { - super(name, Byte.class); - - if (min < 0) { - throw new IllegalArgumentException("Min value of " + name + " must be 0 or greater"); - } else if (max <= min) { - throw new IllegalArgumentException("Max value of " + name + " must be greater than min (" + min + ")"); - } else { - Set set = new ObjectOpenHashSet<>(); - - for (byte i = min; i <= max; ++i) { - set.add(i); - } - - this.allowedValues = ImmutableSet.copyOf(set); - } - } - - @Override - public @NotNull Collection getAllowedValues() { - return this.allowedValues; - } - - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } else if (other instanceof PropertyByte propertyByte && super.equals(other)) { - return this.allowedValues.equals(propertyByte.allowedValues); - } else { - return false; - } - } - - @Override - public int hashCode() { - return 31 * super.hashCode() + this.allowedValues.hashCode(); - } - - @Contract("_, _, _ -> new") - public static @NotNull PropertyByte create(String name, byte min, byte max) { - return new PropertyByte(name, min, max); - } - - @SuppressWarnings("Guava") - @Override - public @NotNull Optional parseValue(@NotNull String value) { - try { - Byte val = Byte.valueOf(value); - return this.allowedValues.contains(val) ? Optional.of(val) : Optional.absent(); - } catch (NumberFormatException var3) { - return Optional.absent(); - } - } - - /** - * Get the name for the given value. - */ - @Override - public @NotNull String getName(Byte value) { - return value.toString(); - } -} diff --git a/src/main/java/gregtech/common/blocks/properties/PropertyShort.java b/src/main/java/gregtech/common/blocks/properties/PropertyShort.java deleted file mode 100644 index 7f8c0f0cf51..00000000000 --- a/src/main/java/gregtech/common/blocks/properties/PropertyShort.java +++ /dev/null @@ -1,80 +0,0 @@ -package gregtech.common.blocks.properties; - -import net.minecraft.block.properties.PropertyHelper; - -import com.google.common.base.Optional; -import com.google.common.collect.ImmutableSet; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Set; - -public class PropertyShort extends PropertyHelper { - - private final ImmutableSet allowedValues; - - protected PropertyShort(String name, short min, short max) { - super(name, Short.class); - - if (min < 0) { - throw new IllegalArgumentException("Min value of " + name + " must be 0 or greater"); - } else if (max <= min) { - throw new IllegalArgumentException("Max value of " + name + " must be greater than min (" + min + ")"); - } else { - Set set = new ObjectOpenHashSet<>(); - - for (short i = min; i <= max; ++i) { - set.add(i); - } - - this.allowedValues = ImmutableSet.copyOf(set); - } - } - - @Override - public @NotNull Collection getAllowedValues() { - return this.allowedValues; - } - - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } else if (other instanceof PropertyShort propertyByte && super.equals(other)) { - return this.allowedValues.equals(propertyByte.allowedValues); - } else { - return false; - } - } - - @Override - public int hashCode() { - return 31 * super.hashCode() + this.allowedValues.hashCode(); - } - - @Contract("_, _, _ -> new") - public static @NotNull PropertyShort create(String name, short min, short max) { - return new PropertyShort(name, min, max); - } - - @SuppressWarnings("Guava") - @Override - public @NotNull Optional parseValue(@NotNull String value) { - try { - Short val = Short.valueOf(value); - return this.allowedValues.contains(val) ? Optional.of(val) : Optional.absent(); - } catch (NumberFormatException var3) { - return Optional.absent(); - } - } - - /** - * Get the name for the given value. - */ - @Override - public @NotNull String getName(Short value) { - return value.toString(); - } -} diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index f1c2475d05a..f795dcf7dd1 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -138,11 +138,6 @@ public void setTransferRate(int transferRate) { this.transferRate = MathHelper.clamp(transferRate, 1, maxItemTransferRate); CoverableView coverable = getCoverableView(); coverable.markDirty(); - - if (getWorld() != null && getWorld().isRemote) { - // tile at cover holder pos - TileEntity te = getTileEntityHere(); - } } public int getTransferRate() { diff --git a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java index 10b6d46675c..35ef46bd4aa 100644 --- a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java +++ b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeInterpreter.java @@ -9,7 +9,7 @@ import java.util.List; /** - * WorldPipeNetNode-based, state-based evaluator for oreGlob. + * Node-based, state-based evaluator for oreGlob. *

* OreGlob nodes are evaluated by simulating match for each possible branch of states. * Each state corresponds to index of character the next match will start. All matches diff --git a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java index ae357edf28f..5c7410b78e8 100644 --- a/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java +++ b/src/main/java/gregtech/common/covers/filter/oreglob/impl/NodeOreGlob.java @@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull; /** - * WorldPipeNetNode-based implementation of oreglob. + * Node-based implementation of oreglob. */ public final class NodeOreGlob extends OreGlob { diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 3bd461e2118..8b4bec4bf48 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -120,13 +120,13 @@ private EnergyGroupData getEnergyData() { @Override public long getInputAmperage() { if (tile == null) return 0; - return tile.getNetLogicData(net.mapName).getLogicEntryDefaultable(ThroughputLogic.INSTANCE).getValue(); + return tile.getNetLogicData(net).getLogicEntryDefaultable(ThroughputLogic.INSTANCE).getValue(); } @Override public long getInputVoltage() { if (tile == null) return 0; - return tile.getNetLogicData(net.mapName).getLogicEntryDefaultable(VoltageLimitLogic.INSTANCE).getValue(); + return tile.getNetLogicData(net).getLogicEntryDefaultable(VoltageLimitLogic.INSTANCE).getValue(); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java index 1d317991ce1..e20b093658d 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java @@ -65,4 +65,9 @@ public Iterator getPaths(WorldPipeNetNode node, IPredicate public @NotNull NetFlowEdge getNewEdge() { return new NetFlowEdge(1); } + + @Override + public int getNetworkID() { + return 0; + } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 7effff1be8a..66e43f04014 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -114,4 +114,9 @@ public Iterator getPaths(WorldPipeNetNode node, IPredicate public @NotNull NetFlowEdge getNewEdge() { return new NetFlowEdge(10); } + + @Override + public int getNetworkID() { + return 1; + } } diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 007e20041fd..ba3843ab923 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -114,4 +114,9 @@ public Iterator getPaths(WorldPipeNetNode node, IPredicate public @NotNull NetFlowEdge getNewEdge() { return new NetFlowEdge(2, 5); } + + @Override + public int getNetworkID() { + return 2; + } } diff --git a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java index cb61572b4e7..13d4f2bb206 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java @@ -53,4 +53,9 @@ public Capability[] getTargetCapabilities() { public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { return new IPipeCapabilityObject[] { new LaserCapabilityObject(this) }; } + + @Override + public int getNetworkID() { + return 3; + } } diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java index 34bdbfe91f3..c36dbbb8bea 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -54,4 +54,9 @@ public Capability[] getTargetCapabilities() { public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { return new IPipeCapabilityObject[] { new DataCapabilityObject(this) }; } + + @Override + public int getNetworkID() { + return 4; + } } From 4df3020b100f9eec94035b273ff62135a47286e1 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 11 Aug 2024 19:49:16 -0600 Subject: [PATCH 099/157] Fix tricorder reporting of EU flow through cables --- .../pipenet/physical/block/PipeBlock.java | 6 +-- .../pipenet/physical/tile/PipeTileEntity.java | 5 +-- .../api/graphnet/traverse/ITraverseData.java | 2 +- .../graphnet/traverse/TraverseHelpers.java | 13 +++++-- .../items/behaviors/TricorderBehavior.java | 39 +++++++++++++++++++ .../net/energy/EnergyCapabilityObject.java | 4 +- .../pipelike/net/energy/EnergyFlowLogic.java | 4 ++ .../net/energy/EnergyTraverseData.java | 17 +++++--- .../pipelike/net/fluid/FluidTraverseData.java | 10 +++-- 9 files changed, 76 insertions(+), 24 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 4759fe6d563..46b8f6dfc84 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -466,11 +466,7 @@ public void addCollisionBoxToList(@NotNull IBlockState state, @NotNull World wor @Nullable Entity entityIn, boolean isActualState) { PipeTileEntity tile = getTileEntity(worldIn, pos); if (tile != null) { - if (hasPipeCollisionChangingItem(worldIn, pos, entityIn)) { - addCollisionBoxToList(pos, entityBox, collidingBoxes, FULL_BLOCK_AABB); - } else { - tile.getCoverBoxes(bb -> addCollisionBoxToList(pos, entityBox, collidingBoxes, bb)); - } + tile.getCoverBoxes(bb -> addCollisionBoxToList(pos, entityBox, collidingBoxes, bb)); if (tile.getFrameMaterial() != null) { addCollisionBoxToList(pos, entityBox, collidingBoxes, BlockFrame.COLLISION_BOX); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index b2bfc13b2f0..81717f99aa6 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -4,7 +4,6 @@ import gregtech.api.GregTechAPI; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; -import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.NetLogicRegistry; @@ -431,8 +430,8 @@ public T getCapability(@NotNull Capability capability, @Nullable EnumFaci // data sync management // - public NetLogicData getNetLogicData(IGraphNet net) { - return netLogicDatas.get(net.getNetworkID()); + public NetLogicData getNetLogicData(int networkID) { + return netLogicDatas.get(networkID); } @Override diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java index bd1f6b08665..c8aee73c526 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java @@ -70,7 +70,7 @@ default long getFlowLimit(@NotNull AbstractNetFlowEdge edge) { * @param consumption the amount to consume from the edge's flow limit. */ @MustBeInvokedByOverriders - default void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { + default void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, long consumption) { edge.consumeFlowLimit(this.getTestObject(), this.getGraphNet(), consumption, this.getQueryTick(), this.getSimulatorKey()); } diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index 76dd2d4b0ad..5dd5ffef2cf 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -60,6 +60,7 @@ D extends ITraverseData> long traverseFlood( for (int i = 0; i < edges.size(); i++) { E edge = edges.get(i); + N sourceNode = nodes.get(i); N targetNode = nodes.get(i + 1); if (targetNode.traverse(data.getQueryTick(), true)) { @@ -69,7 +70,7 @@ D extends ITraverseData> long traverseFlood( } else continue pathloop; pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); - stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), + stack.add(flow -> data.consumeFlowLimit(edge, sourceNode, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); @@ -126,6 +127,7 @@ D extends ITraverseData> long traverseDumb( for (int i = 0; i < edges.size(); i++) { E edge = edges.get(i); + N sourceNode = nodes.get(i); N targetNode = nodes.get(i + 1); if (targetNode.traverse(data.getQueryTick(), true)) { @@ -145,7 +147,7 @@ D extends ITraverseData> long traverseDumb( if (finalOverflow > 0) overflowListener.accept(targetNode, finalOverflow); }); } - stack.add(flow -> data.consumeFlowLimit(flowEdge, targetNode, flow), + stack.add(flow -> data.consumeFlowLimit(flowEdge, sourceNode, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); } @@ -265,6 +267,7 @@ D extends ITraverseData & IEqualizableTraverseData> long traverseEqu for (int i = 0; i < edges.size(); i++) { E edge = edges.get(i); + N sourceNode = nodes.get(i); N targetNode = nodes.get(i + 1); if (targetNode.traverse(data.getQueryTick(), true)) { @@ -274,7 +277,7 @@ D extends ITraverseData & IEqualizableTraverseData> long traverseEqu } else continue pathloop; pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); - stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), + stack.add(flow -> data.consumeFlowLimit(edge, sourceNode, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); @@ -436,6 +439,7 @@ D extends ITraverseData & IRoundRobinTraverseData> long rrTraverse( for (int i = 0; i < edges.size(); i++) { E edge = edges.get(i); + N sourceNode = nodes.get(i); N targetNode = nodes.get(i + 1); if (targetNode.traverse(data.getQueryTick(), true)) { @@ -445,7 +449,8 @@ D extends ITraverseData & IRoundRobinTraverseData> long rrTraverse( } else return strict ? -1 : 0; pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); - stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); + stack.add(flow -> data.consumeFlowLimit(edge, sourceNode, targetNode, flow), + data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); if (pathFlow <= 0) return 0; diff --git a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java index dae5050e986..fa404f5ae31 100644 --- a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java @@ -7,6 +7,8 @@ import gregtech.api.capability.IEnergyContainer; import gregtech.api.capability.IWorkable; import gregtech.api.capability.impl.FluidTankList; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.metaitem.stats.IItemBehaviour; import gregtech.api.metatileentity.IDataInfoProvider; @@ -18,6 +20,9 @@ import gregtech.api.util.TextFormattingUtil; import gregtech.api.worldgen.bedrockFluids.BedrockFluidVeinHandler; import gregtech.common.ConfigHolder; +import gregtech.common.pipelike.net.energy.EnergyFlowData; +import gregtech.common.pipelike.net.energy.EnergyFlowLogic; +import gregtech.common.pipelike.net.energy.WorldEnergyNet; import gregtech.core.sound.GTSoundEvents; import net.minecraft.block.Block; @@ -41,6 +46,7 @@ import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; @@ -277,6 +283,39 @@ else if (metaTileEntity instanceof IDataInfoProvider) TextFormattingUtil.formatNumbers(block.getMetaFromState(world.getBlockState(pos)))) .setStyle(new Style().setColor(TextFormatting.BLUE)))); } + NetLogicData data = pipeTile.getNetLogicData(WorldEnergyNet.getWorldNet(world).getNetworkID()); + if (data != null) { + int cumulativeCount = 0; + long cumulativeVoltage = 0; + long cumulativeAmperage = 0; + for (var memory : data.getLogicEntryDefaultable(EnergyFlowLogic.INSTANCE).getMemory().entrySet()) { + cumulativeCount++; + int count = 0; + double voltage = 0; + long amperage = 0; + for (EnergyFlowData flow : memory.getValue()) { + count++; + long prev = amperage; + amperage += flow.amperage(); + // weighted average + voltage = voltage * prev / amperage + (double) (flow.voltage() * flow.amperage()) / amperage; + } + if (count != 0) { + cumulativeVoltage += voltage / count; + cumulativeAmperage += amperage / count; + } + } + if (cumulativeCount != 0) { + cumulativeVoltage /= cumulativeCount; + cumulativeAmperage /= cumulativeCount; + } + list.add(new TextComponentTranslation("behavior.tricorder.eut_per_sec", + new TextComponentTranslation(TextFormattingUtil.formatNumbers(cumulativeVoltage)) + .setStyle(new Style().setColor(TextFormatting.RED)))); + list.add(new TextComponentTranslation("behavior.tricorder.amp_per_sec", + new TextComponentTranslation(TextFormattingUtil.formatNumbers(cumulativeAmperage)) + .setStyle(new Style().setColor(TextFormatting.RED)))); + } // pipe-specific info if (tileEntity instanceof IDataInfoProvider provider) { diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 8b4bec4bf48..c15d94b2525 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -120,13 +120,13 @@ private EnergyGroupData getEnergyData() { @Override public long getInputAmperage() { if (tile == null) return 0; - return tile.getNetLogicData(net).getLogicEntryDefaultable(ThroughputLogic.INSTANCE).getValue(); + return tile.getNetLogicData(net.getNetworkID()).getLogicEntryDefaultable(ThroughputLogic.INSTANCE).getValue(); } @Override public long getInputVoltage() { if (tile == null) return 0; - return tile.getNetLogicData(net).getLogicEntryDefaultable(VoltageLimitLogic.INSTANCE).getValue(); + return tile.getNetLogicData(net.getNetworkID()).getLogicEntryDefaultable(VoltageLimitLogic.INSTANCE).getValue(); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java index d4143680136..78cc4e34b9b 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java @@ -25,6 +25,10 @@ protected EnergyFlowLogic() { super("EnergyFlow"); } + public @NotNull Long2ObjectOpenHashMap> getMemory() { + return memory; + } + public @NotNull List getFlow(long tick) { return memory.getOrDefault(tick, Collections.emptyList()); } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index a2231b18fee..1cd35ebc4f5 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -114,20 +114,27 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl destination.getGroupSafe().getData() instanceof EnergyGroupData data) { data.addEnergyOutPerSec(accepted * pathVoltage, getQueryTick()); } + if (accepted > 0) recordFlow(destination, accepted); return accepted; } @Override - public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { - super.consumeFlowLimit(edge, targetNode, consumption); - EnergyFlowLogic logic = targetNode.getData().getLogicEntryNullable(EnergyFlowLogic.INSTANCE); + public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, long consumption) { + super.consumeFlowLimit(edge, sourceNode, targetNode, consumption); + if (consumption > 0) recordFlow(sourceNode, consumption); + } + + private void recordFlow(@NotNull NetNode node, long amperes) { + EnergyFlowLogic logic = node.getData().getLogicEntryNullable(EnergyFlowLogic.INSTANCE); if (logic == null) { logic = EnergyFlowLogic.INSTANCE.getNew(); - targetNode.getData().setLogicEntry(logic); + node.getData().setLogicEntry(logic); } - logic.recordFlow(getQueryTick(), new EnergyFlowData(consumption, pathVoltage)); + logic.recordFlow(getQueryTick(), new EnergyFlowData(amperes, pathVoltage)); } + + private static int calculateHeatV(long amperage, long voltage, long maxVoltage) { return (int) (amperage * (Math.log1p(Math.log((double) voltage / maxVoltage)) * 45 + 36.5)); } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index 4031e096442..8b548102065 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -157,12 +157,14 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl (int) Math.min(Integer.MAX_VALUE, availableFlow), container, getSimulatorKey() == null); } } - return flowReachingDestination - availableFlow; + long accepted = flowReachingDestination - availableFlow; + temperatureUpdates.getOrDefault(destination, l -> {}).accept(accepted); + return accepted; } @Override - public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { - super.consumeFlowLimit(edge, targetNode, consumption); - temperatureUpdates.getOrDefault(targetNode, l -> {}).accept(consumption); + public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, long consumption) { + super.consumeFlowLimit(edge, sourceNode, targetNode, consumption); + temperatureUpdates.getOrDefault(sourceNode, l -> {}).accept(consumption); } } From b5ce31f63bc8a1d1077c58af91b649cb1b3d460b Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 11 Aug 2024 19:49:47 -0600 Subject: [PATCH 100/157] spotless --- .../java/gregtech/api/graphnet/traverse/ITraverseData.java | 3 ++- .../gregtech/common/items/behaviors/TricorderBehavior.java | 2 -- .../common/pipelike/net/energy/EnergyTraverseData.java | 5 ++--- .../common/pipelike/net/fluid/FluidTraverseData.java | 3 ++- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java index c8aee73c526..98846c95036 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java @@ -70,7 +70,8 @@ default long getFlowLimit(@NotNull AbstractNetFlowEdge edge) { * @param consumption the amount to consume from the edge's flow limit. */ @MustBeInvokedByOverriders - default void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, long consumption) { + default void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, + long consumption) { edge.consumeFlowLimit(this.getTestObject(), this.getGraphNet(), consumption, this.getQueryTick(), this.getSimulatorKey()); } diff --git a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java index fa404f5ae31..719a3ada31a 100644 --- a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java @@ -8,7 +8,6 @@ import gregtech.api.capability.IWorkable; import gregtech.api.capability.impl.FluidTankList; import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.metaitem.stats.IItemBehaviour; import gregtech.api.metatileentity.IDataInfoProvider; @@ -46,7 +45,6 @@ import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.IFluidTank; -import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index 1cd35ebc4f5..0d4f8470520 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -119,7 +119,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl } @Override - public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, long consumption) { + public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, + long consumption) { super.consumeFlowLimit(edge, sourceNode, targetNode, consumption); if (consumption > 0) recordFlow(sourceNode, consumption); } @@ -133,8 +134,6 @@ private void recordFlow(@NotNull NetNode node, long amperes) { logic.recordFlow(getQueryTick(), new EnergyFlowData(amperes, pathVoltage)); } - - private static int calculateHeatV(long amperage, long voltage, long maxVoltage) { return (int) (amperage * (Math.log1p(Math.log((double) voltage / maxVoltage)) * 45 + 36.5)); } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index 8b548102065..be18bbad203 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -163,7 +163,8 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl } @Override - public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, long consumption) { + public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, + long consumption) { super.consumeFlowLimit(edge, sourceNode, targetNode, consumption); temperatureUpdates.getOrDefault(sourceNode, l -> {}).accept(consumption); } From 0df54641664947a7433231f1681928124c725b53 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 13 Aug 2024 14:41:00 -0600 Subject: [PATCH 101/157] Fix round robin behavior --- .../physical/tile/IWorldPipeNetTile.java | 10 ++ .../physical/tile/PipeCapabilityWrapper.java | 11 +- .../pipenet/physical/tile/PipeTileEntity.java | 12 +++ .../traverse/AbstractTileRoundRobinData.java | 73 +++++++++++++ .../traverse/SimpleTileRoundRobinData.java | 41 +++++++ .../traverse/IEqualizableTraverseData.java | 2 +- .../graphnet/traverse/IRoundRobinData.java | 32 ++++++ .../traverse/IRoundRobinTraverseData.java | 30 +++++- .../graphnet/traverse/TraverseHelpers.java | 100 +++++++++++------- .../gregtech/common/covers/CoverConveyor.java | 7 +- .../common/covers/CoverFluidRegulator.java | 40 +++---- .../gregtech/common/covers/CoverPump.java | 7 +- .../common/covers/CoverRoboticArm.java | 40 +++---- .../net/fluid/FluidRRTraverseData.java | 44 ++++++-- .../pipelike/net/item/ItemRRTraverseData.java | 43 ++++++-- 15 files changed, 385 insertions(+), 107 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/IRoundRobinData.java diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java index e773f1dc036..9a68bab2964 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java @@ -8,6 +8,9 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import java.util.EnumMap; import java.util.function.Consumer; @@ -15,8 +18,15 @@ public interface IWorldPipeNetTile { // universal (mostly for active nodes) + @NotNull EnumMap getTargetsWithCapabilities(WorldPipeNetNode destination); + @Nullable + TileEntity getTargetWithCapabilities(WorldPipeNetNode destination, EnumFacing facing); + + PipeCapabilityWrapper getWrapperForNode(WorldPipeNetNode node); + + @NotNull CoverableView getCoverHolder(); // fluid piping diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java index f7dd0cff3f9..4468816ab6d 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java @@ -7,6 +7,8 @@ import org.jetbrains.annotations.NotNull; +import java.util.Objects; + public class PipeCapabilityWrapper { private byte activeMask; @@ -14,12 +16,19 @@ public class PipeCapabilityWrapper { private final WorldPipeNetNode node; public final Capability[] capabilities; - public PipeCapabilityWrapper(PipeTileEntity owner, WorldPipeNetNode node) { + public PipeCapabilityWrapper(PipeTileEntity owner, @NotNull WorldPipeNetNode node) { this.owner = owner; this.node = node; this.capabilities = node.getNet().getTargetCapabilities(); } + public boolean supports(Capability capability) { + for (Capability cap : capabilities) { + if (Objects.equals(cap, capability)) return true; + } + return false; + } + public void setActive(@NotNull EnumFacing facing) { if (!isActive(facing)) { this.activeMask |= 1 << facing.ordinal(); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 81717f99aa6..537600d6481 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -334,6 +334,18 @@ public void onNeighborChanged(@NotNull EnumFacing facing) { return caps; } + @Override + public @Nullable TileEntity getTargetWithCapabilities(WorldPipeNetNode node, EnumFacing facing) { + PipeCapabilityWrapper wrapper = netCapabilities.get(node); + if (wrapper == null || !wrapper.isActive(facing)) return null; + else return getNeighbor(facing); + } + + @Override + public PipeCapabilityWrapper getWrapperForNode(WorldPipeNetNode node) { + return netCapabilities.get(node); + } + /** * Updates the pipe's active status based on the tile entity connected to the side. * diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java new file mode 100644 index 00000000000..c814979e520 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java @@ -0,0 +1,73 @@ +package gregtech.api.graphnet.pipenet.traverse; + +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; +import gregtech.api.graphnet.traverse.IRoundRobinData; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.Capability; + +import org.apache.commons.lang3.mutable.MutableByte; +import org.jetbrains.annotations.MustBeInvokedByOverriders; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.WeakHashMap; + +public abstract class AbstractTileRoundRobinData implements IRoundRobinData { + + private final MutableByte pointer = new MutableByte(); + + // I'm sorry but a weak Object2Byte map doesn't exist + private final Map simulatorMap = new WeakHashMap<>(); + + @Override + @MustBeInvokedByOverriders + public void resetIfFinished(WorldPipeNetNode node, @Nullable SimulatorKey simulator) { + if (!hasNextInternalDestination(node, simulator)) getPointer(simulator).setValue(0); + } + + public @NotNull MutableByte getPointer(@Nullable SimulatorKey simulator) { + if (simulator == null) return pointer; + MutableByte value = simulatorMap.get(simulator); + if (value == null) { + value = new MutableByte(); + simulatorMap.put(simulator, value); + } + return value; + } + + public final boolean pointerFinished(@Nullable SimulatorKey simulator) { + return pointerFinished(getPointer(simulator)); + } + + public final boolean pointerFinished(@NotNull MutableByte pointer) { + return pointer.byteValue() >= EnumFacing.VALUES.length; + } + + public final EnumFacing getPointerFacing(SimulatorKey simulator) { + MutableByte pointer = getPointer(simulator); + if (pointerFinished(pointer)) throw new IllegalStateException("Pointer is finished!"); + return EnumFacing.VALUES[pointer.byteValue()]; + } + + public boolean hasCapabilityAtPointer(@NotNull Capability capability, WorldPipeNetNode node, + @Nullable SimulatorKey simulator) { + return getCapabilityAtPointer(capability, node, simulator) != null; + } + + @Nullable + public E getCapabilityAtPointer(@NotNull Capability capability, WorldPipeNetNode node, + @Nullable SimulatorKey simulator) { + if (pointerFinished(simulator)) return null; + PipeCapabilityWrapper wrapper = node.getTileEntity().getWrapperForNode(node); + EnumFacing pointer = getPointerFacing(simulator); + + if (!wrapper.isActive(pointer) || !wrapper.supports(capability)) return null; + TileEntity target = node.getTileEntity().getTargetWithCapabilities(node, pointer); + return target == null ? null : target.getCapability(capability, pointer.getOpposite()); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java new file mode 100644 index 00000000000..0fd76f7a1ee --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java @@ -0,0 +1,41 @@ +package gregtech.api.graphnet.pipenet.traverse; + +import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; + +import net.minecraftforge.common.capabilities.Capability; + +import org.apache.commons.lang3.mutable.MutableByte; +import org.jetbrains.annotations.Nullable; + +public class SimpleTileRoundRobinData extends AbstractTileRoundRobinData { + + private final Capability cap; + + public SimpleTileRoundRobinData(Capability capability) { + this.cap = capability; + } + + @Override + public boolean hasNextInternalDestination(WorldPipeNetNode node, @Nullable SimulatorKey simulator) { + MutableByte pointer = getPointer(simulator); + byte val = pointer.byteValue(); + progressToNextInternalDestination(node, simulator); + boolean hasNext = !pointerFinished(pointer); + pointer.setValue(val); + return hasNext; + } + + @Override + public void progressToNextInternalDestination(WorldPipeNetNode node, @Nullable SimulatorKey simulator) { + MutableByte pointer = getPointer(simulator); + pointer.increment(); + while (!pointerFinished(pointer) && !hasCapabilityAtPointer(cap, node, simulator)) { + pointer.increment(); + } + } + + public @Nullable T getAtPointer(WorldPipeNetNode node, @Nullable SimulatorKey simulator) { + return getCapabilityAtPointer(cap, node, simulator); + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java index 67e8e57d558..ecc8cac2b04 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java @@ -5,7 +5,7 @@ import org.jetbrains.annotations.NotNull; -public interface IEqualizableTraverseData> { +public interface IEqualizableTraverseData> extends ITraverseData { int getDestinationsAtNode(@NotNull N node); diff --git a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinData.java b/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinData.java new file mode 100644 index 00000000000..5ccf9156e94 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinData.java @@ -0,0 +1,32 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.SimulatorKey; + +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; + +public interface IRoundRobinData { + + /** + * Called to notify this {@link IRoundRobinData} to reset its internals to prepare for iteration over internal + * destinations. If this object has not finished progressing over its internal destinations, this should do nothing. + */ + void resetIfFinished(N node, @Nullable SimulatorKey simulator); + + /** + * Similar to {@link Iterator#hasNext()}, this method determines whether there is another internal destination in + * this {@link IRoundRobinData} to finalize at. When false is returned, the RR traversal will move on from + * this {@link IRoundRobinData} + * + * @return whether another internal destination is present + */ + boolean hasNextInternalDestination(N node, @Nullable SimulatorKey simulator); + + /** + * Similar to {@link Iterator#next()}, this is called to notify this {@link IRoundRobinData} that it should + * progress to the next internal destination. + */ + void progressToNextInternalDestination(N node, @Nullable SimulatorKey simulator); +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java index a70a313db2e..2e974fe2f48 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java @@ -3,12 +3,13 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.path.INetPath; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.jetbrains.annotations.NotNull; import java.util.ArrayDeque; -import java.util.Deque; -public interface IRoundRobinTraverseData> { +public interface IRoundRobinTraverseData, N extends NetNode, P extends INetPath> + extends ITraverseData { /** * The traversal cache must be cached and persistent between traversals, @@ -20,11 +21,32 @@ public interface IRoundRobinTraverseData getTraversalCache(); + Object2ObjectLinkedOpenHashMap getTraversalCache(); /** * Whether a path should be skipped before checking it against the round robin cache. * The return of {@link ITraverseData#prepareForPathWalk(INetPath, long)} will be ignored during traversal. */ - boolean shouldSkipPath(P path); + boolean shouldSkipPath(@NotNull P path); + + /** + * @return The {@link IRoundRobinData} for the particular destination. Will be mutated; should then be referenced + * in {@link ITraverseData#finalizeAtDestination(NetNode, long)} to do proper round robin within the + * destination. + */ + @NotNull + T createRRData(@NotNull N destination); + + /** + * Called in preference to {@link ITraverseData#finalizeAtDestination(NetNode, long)} to provide the round robin + * data for the destination. + */ + long finalizeAtDestination(@NotNull T data, @NotNull N destination, long flowReachingDestination); + + /** + * @deprecated use {@link #finalizeAtDestination(IRoundRobinData, NetNode, long)} instead. + */ + @Override + @Deprecated + long finalizeAtDestination(@NotNull N destination, long flowReachingDestination); } diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index 5dd5ffef2cf..e5540eca769 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -8,13 +8,13 @@ import gregtech.api.util.GTUtility; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.alg.util.Pair; -import java.util.Deque; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -192,11 +192,11 @@ D extends ITraverseData> long traverseDumb( * @return the consumed flow. */ public static , - D extends ITraverseData & IEqualizableTraverseData> long traverseEqualDistribution( - @NotNull D data, - @NotNull Iterator

paths, - long flowIn, - boolean strict) { + D extends IEqualizableTraverseData> long traverseEqualDistribution( + @NotNull D data, + @NotNull Iterator

paths, + long flowIn, + boolean strict) { // collection Map, DistributorHelper> distributorHelperMap = new Object2ObjectOpenHashMap<>(); Object2IntOpenHashMap

desiredMap = new Object2IntOpenHashMap<>(); @@ -296,9 +296,11 @@ D extends ITraverseData & IEqualizableTraverseData> long traverseEqu /** * Provides logic for traversing a flow net in an equal distribution manner within a dynamic weights context. - * Calls {@link #traverseEqualDistribution(ITraverseData, Iterator, long, boolean)} repeatedly, using a fresh + * Calls {@link #traverseEqualDistribution(IEqualizableTraverseData, Iterator, long, boolean)} repeatedly, using a + * fresh * collection of paths from the {@code pathsSupplier} until - * {@link #traverseEqualDistribution(ITraverseData, Iterator, long, boolean)} returns 0 or 100 iterations are + * {@link #traverseEqualDistribution(IEqualizableTraverseData, Iterator, long, boolean)} returns 0 or 100 iterations + * are * performed. * * @param data the traversal data. @@ -310,11 +312,11 @@ D extends ITraverseData & IEqualizableTraverseData> long traverseEqu * @return the consumed flow. */ public static , - D extends ITraverseData & IEqualizableTraverseData> long traverseEqualDistribution( - @NotNull D data, - @NotNull Supplier> pathsSupplier, - long flowIn, - boolean strict) { + D extends IEqualizableTraverseData> long traverseEqualDistribution( + @NotNull D data, + @NotNull Supplier> pathsSupplier, + long flowIn, + boolean strict) { long availableFlow = flowIn; byte iterationCount = 0; while (iterationCount <= 100) { @@ -340,14 +342,14 @@ D extends ITraverseData & IEqualizableTraverseData> long traverseEqu * not edge restrictions. * @return the consumed flow. */ - public static , - D extends ITraverseData & IRoundRobinTraverseData> long traverseRoundRobin( - @NotNull D data, - @NotNull Iterator

paths, - long flowIn, - boolean strict) { + public static , N extends NetNode, E extends AbstractNetFlowEdge, + P extends INetPath, D extends IRoundRobinTraverseData> long traverseRoundRobin( + @NotNull D data, + @NotNull Iterator

paths, + long flowIn, + boolean strict) { long availableFlow = flowIn; - Deque cache = data.getTraversalCache(); + Object2ObjectLinkedOpenHashMap cache = data.getTraversalCache(); Predicate invalidityCheck = null; Map skippedPaths = new Object2ObjectOpenHashMap<>(); @@ -363,35 +365,42 @@ D extends ITraverseData & IRoundRobinTraverseData> long traverseRoun }; } Object destIdentifier = destinationNode.getEquivalencyData(); - Object nextUp = cache.peekFirst(); + Object nextUp = cache.isEmpty() ? null : cache.firstKey(); // filter out invalid equivalency data while (invalidityCheck.test(nextUp)) { cache.removeFirst(); - nextUp = cache.peekFirst(); + nextUp = cache.isEmpty() ? null : cache.firstKey(); } if (destIdentifier.equals(nextUp)) { // keep iterating over paths in order to collect destinations into the cache if (availableFlow <= 0) continue; // path is next up in the ordering, we can traverse. - cache.removeFirst(); - cache.addLast(destIdentifier); - long accepted = rrTraverse(data, path, availableFlow, strict); + T rr = cache.get(destIdentifier); + long accepted = rrTraverse(data, path, rr, availableFlow, strict); + if (!rr.hasNextInternalDestination(destinationNode, data.getSimulatorKey())) { + cache.getAndMoveToLast(destIdentifier); + } if (accepted == -1) return flowIn - availableFlow; else availableFlow -= accepted; } else { // this path isn't the next one up, skip it unless it's a completely new destination. - if (cache.contains(destIdentifier)) { + if (cache.containsKey(destIdentifier)) { // keep iterating over paths in order to collect destinations into the cache if (availableFlow <= 0) continue; skippedPaths.put(destIdentifier, path); } else { // keep iterating over paths in order to collect destinations into the cache if (availableFlow <= 0) { - cache.addFirst(destIdentifier); + cache.putAndMoveToFirst(destIdentifier, data.createRRData(destinationNode)); continue; } - cache.addLast(destIdentifier); - long accepted = rrTraverse(data, path, availableFlow, strict); + T rr = data.createRRData(destinationNode); + long accepted = rrTraverse(data, path, rr, availableFlow, strict); + if (rr.hasNextInternalDestination(destinationNode, data.getSimulatorKey())) { + cache.putAndMoveToFirst(destIdentifier, rr); + } else { + cache.putAndMoveToLast(destIdentifier, rr); + } if (accepted == -1) return flowIn - availableFlow; else availableFlow -= accepted; } @@ -399,7 +408,7 @@ D extends ITraverseData & IRoundRobinTraverseData> long traverseRoun } // finally, try and work through skipped paths while (availableFlow > 0) { - Object nextUp = cache.peekFirst(); + Object nextUp = cache.isEmpty() ? null : cache.firstKey(); if (nextUp == null) break; P path = skippedPaths.get(nextUp); if (path == null) break; @@ -408,9 +417,11 @@ D extends ITraverseData & IRoundRobinTraverseData> long traverseRoun cache.removeFirst(); continue; } - cache.removeFirst(); - cache.addLast(nextUp); - long accepted = rrTraverse(data, path, availableFlow, strict); + T rr = data.createRRData(path.getTargetNode()); + long accepted = rrTraverse(data, path, rr, availableFlow, strict); + if (!rr.hasNextInternalDestination(path.getTargetNode(), data.getSimulatorKey())) { + cache.getAndMoveToLast(nextUp); + } if (accepted == -1) return flowIn - availableFlow; else availableFlow -= accepted; } @@ -418,12 +429,13 @@ D extends ITraverseData & IRoundRobinTraverseData> long traverseRoun return flowIn - availableFlow; } - private static , - D extends ITraverseData & IRoundRobinTraverseData> long rrTraverse( - @NotNull D data, - @NotNull P path, - long flowIn, - boolean strict) { + private static , N extends NetNode, E extends AbstractNetFlowEdge, + P extends INetPath, D extends ITraverseData & IRoundRobinTraverseData> long rrTraverse( + @NotNull D data, + @NotNull P path, + @NotNull T rr, + long flowIn, + boolean strict) { boolean simulate = data.getSimulatorKey() != null; List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); long pathFlow = flowIn; @@ -455,8 +467,14 @@ D extends ITraverseData & IRoundRobinTraverseData> long rrTraverse( if (pathFlow <= 0) return 0; } - - long accepted = data.finalizeAtDestination(nodes.get(nodes.size() - 1), pathFlow); + N dest = nodes.get(nodes.size() - 1); + rr.resetIfFinished(dest, data.getSimulatorKey()); + long accepted = 0; + while (rr.hasNextInternalDestination(dest, data.getSimulatorKey())) { + rr.progressToNextInternalDestination(dest, data.getSimulatorKey()); + accepted += data.finalizeAtDestination(rr, dest, pathFlow - accepted); + if (accepted == pathFlow) break; + } if (!simulate) pathTraverseCalls.forEach(Runnable::run); return stack.consumeWithEndValue(accepted); diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index f795dcf7dd1..0b3bb887a4f 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -13,6 +13,7 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.transfer.TransferControl; import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; +import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.graphnet.traverse.TraverseHelpers; import gregtech.api.mui.GTGuiTextures; @@ -78,12 +79,12 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayDeque; import java.util.Map; import java.util.function.IntUnaryOperator; @@ -102,7 +103,7 @@ public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, private CoverableItemHandlerWrapper itemHandlerWrapper; protected boolean isWorkingAllowed = true; - protected final ArrayDeque roundRobinCache = new ArrayDeque<>(); + protected final Object2ObjectLinkedOpenHashMap> roundRobinCache = new Object2ObjectLinkedOpenHashMap<>(); protected @Nullable CoverRenderer rendererInverted; @@ -366,7 +367,7 @@ protected int insertToHandler(@NotNull IItemHandler destHandler, ItemTestObject getRoundRobinCache(simulate)); } - protected ArrayDeque getRoundRobinCache(boolean simulate) { + protected Object2ObjectLinkedOpenHashMap> getRoundRobinCache(boolean simulate) { return simulate ? roundRobinCache.clone() : roundRobinCache; } diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 7f644f1d821..970442586ee 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -6,6 +6,7 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTUtility; @@ -34,10 +35,10 @@ import com.cleanroommc.modularui.value.sync.StringSyncValue; import com.cleanroommc.modularui.widget.ParentWidget; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayDeque; import java.util.function.IntUnaryOperator; public class CoverFluidRegulator extends CoverPump { @@ -381,34 +382,37 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl protected class KeepFluidRRTraverseData extends FluidRRTraverseData { public KeepFluidRRTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, - long queryTick, - BlockPos sourcePos, EnumFacing inputFacing, ArrayDeque cache) { + long queryTick, BlockPos sourcePos, EnumFacing inputFacing, + @NotNull Object2ObjectLinkedOpenHashMap> cache) { super(net, testObject, simulator, queryTick, sourcePos, inputFacing, cache); } @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { + public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData data, + @NotNull WorldPipeNetNode destination, long flowReachingDestination) { long availableFlow = flowReachingDestination; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IFluidHandler container = capability.getValue() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - capability.getKey().getOpposite()); + EnumFacing pointerFacing = data.getPointerFacing(getSimulatorKey()); + // anti insert-to-our-source logic + if (!GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) || + !(pointerFacing == inputFacing)) { + IFluidHandler container = data.getAtPointer(destination, getSimulatorKey()); if (container != null) { int contained = computeContained(container, getTestObject()); assert getFluidFilter() != null; int kept = getFluidFilter().getTransferLimit(getTestObject().recombine()); - if (contained >= kept) continue; - availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, - getSimulatorKey() == null); + if (contained < kept) { + availableFlow -= IFluidTransferController.CONTROL.get( + destination.getTileEntity().getCoverHolder() + .getCoverAtSide(pointerFacing)) + .insertToHandler(getTestObject(), + (int) Math.min(kept - contained, availableFlow), container, + getSimulatorKey() == null); + } } } - return flowReachingDestination - availableFlow; + long accepted = flowReachingDestination - availableFlow; + temperatureUpdates.getOrDefault(destination, l -> {}).accept(accepted); + return accepted; } } } diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index 2016e87f4e6..ff9ffbc9dbf 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -13,6 +13,7 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.transfer.TransferControl; import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; +import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.traverse.TraverseHelpers; import gregtech.api.mui.GTGuiTextures; @@ -74,11 +75,11 @@ import com.cleanroommc.modularui.widgets.layout.Row; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayDeque; import java.util.function.IntUnaryOperator; public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithFluidFilter, @@ -96,7 +97,7 @@ public class CoverPump extends CoverBase implements CoverWithUI, ITickable, ICon protected FluidFilterContainer fluidFilterContainer; protected BucketMode bucketMode = BucketMode.MILLI_BUCKET; - protected final ArrayDeque roundRobinCache = new ArrayDeque<>(); + protected final Object2ObjectLinkedOpenHashMap> roundRobinCache = new Object2ObjectLinkedOpenHashMap<>(); protected @Nullable CoverRenderer rendererInverted; @@ -349,7 +350,7 @@ protected int insertToHandler(@NotNull IFluidHandler destHandler, FluidTestObjec getRoundRobinCache(simulate)); } - protected ArrayDeque getRoundRobinCache(boolean simulate) { + protected Object2ObjectLinkedOpenHashMap> getRoundRobinCache(boolean simulate) { return simulate ? roundRobinCache.clone() : roundRobinCache; } diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 4f04777b9b3..5bcf3015574 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -6,6 +6,7 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTUtility; @@ -41,9 +42,9 @@ import com.cleanroommc.modularui.widgets.layout.Column; import com.cleanroommc.modularui.widgets.layout.Row; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.jetbrains.annotations.NotNull; -import java.util.ArrayDeque; import java.util.function.IntUnaryOperator; public class CoverRoboticArm extends CoverConveyor { @@ -393,31 +394,30 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl protected class KeepItemRRTraverseData extends ItemRRTraverseData { public KeepItemRRTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing, ArrayDeque cache) { + BlockPos sourcePos, EnumFacing inputFacing, + @NotNull Object2ObjectLinkedOpenHashMap> cache) { super(net, testObject, simulator, queryTick, sourcePos, inputFacing, cache); } @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { + public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData data, + @NotNull WorldPipeNetNode destination, + long flowReachingDestination) { long availableFlow = flowReachingDestination; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic + EnumFacing pointerFacing = data.getPointerFacing(getSimulatorKey()); + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && pointerFacing == inputFacing) + return 0; // anti insert-to-our-source logic - IItemHandler container = capability.getValue() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, - capability.getKey().getOpposite()); - if (container != null) { - int contained = computeContained(container, getTestObject()); - assert getItemFilter() != null; - int kept = getItemFilter().getTransferLimit(getTestObject().recombine()); - if (contained >= kept) continue; - availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, - getSimulatorKey() != null); - } + IItemHandler container = data.getAtPointer(destination, getSimulatorKey()); + if (container != null) { + int contained = computeContained(container, getTestObject()); + assert getItemFilter() != null; + int kept = getItemFilter().getTransferLimit(getTestObject().recombine()); + if (contained >= kept) return 0; + availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(pointerFacing)).insertToHandler(getTestObject(), + (int) Math.min(kept - contained, availableFlow), container, + getSimulatorKey() != null); } return flowReachingDestination - availableFlow; } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java index 52ec65428b0..1a818f64ee2 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java @@ -4,34 +4,62 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.traverse.IRoundRobinTraverseData; +import gregtech.api.util.GTUtility; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.jetbrains.annotations.NotNull; -import java.util.ArrayDeque; +public class FluidRRTraverseData extends FluidTraverseData implements + IRoundRobinTraverseData, WorldPipeNetNode, FlowWorldPipeNetPath> { -public class FluidRRTraverseData extends FluidTraverseData - implements IRoundRobinTraverseData { - - private final ArrayDeque cache; + private final Object2ObjectLinkedOpenHashMap> cache; public FluidRRTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing, @NotNull ArrayDeque cache) { + BlockPos sourcePos, EnumFacing inputFacing, + @NotNull Object2ObjectLinkedOpenHashMap> cache) { super(net, testObject, simulator, queryTick, sourcePos, inputFacing); this.cache = cache; } @Override - public @NotNull ArrayDeque getTraversalCache() { + public @NotNull Object2ObjectLinkedOpenHashMap> getTraversalCache() { return cache; } @Override - public boolean shouldSkipPath(FlowWorldPipeNetPath path) { + public boolean shouldSkipPath(@NotNull FlowWorldPipeNetPath path) { return false; } + + @Override + public @NotNull SimpleTileRoundRobinData createRRData(@NotNull WorldPipeNetNode destination) { + return new SimpleTileRoundRobinData<>(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); + } + + @Override + public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData data, + @NotNull WorldPipeNetNode destination, long flowReachingDestination) { + long availableFlow = flowReachingDestination; + EnumFacing pointerFacing = data.getPointerFacing(getSimulatorKey()); + // anti insert-to-our-source logic + if (!GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) || !(pointerFacing == inputFacing)) { + IFluidHandler container = data.getAtPointer(destination, getSimulatorKey()); + if (container != null) { + availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(pointerFacing)).insertToHandler(getTestObject(), + (int) Math.min(Integer.MAX_VALUE, availableFlow), container, getSimulatorKey() == null); + } + } + long accepted = flowReachingDestination - availableFlow; + temperatureUpdates.getOrDefault(destination, l -> {}).accept(accepted); + return accepted; + } } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java index c417305eb61..3ea60ad6b8f 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java @@ -4,34 +4,61 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.graphnet.traverse.IRoundRobinTraverseData; +import gregtech.api.util.GTUtility; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.jetbrains.annotations.NotNull; -import java.util.ArrayDeque; +public class ItemRRTraverseData extends ItemTraverseData implements + IRoundRobinTraverseData, WorldPipeNetNode, FlowWorldPipeNetPath> { -public class ItemRRTraverseData extends ItemTraverseData - implements IRoundRobinTraverseData { - - private final ArrayDeque cache; + private final Object2ObjectLinkedOpenHashMap> cache; public ItemRRTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing, @NotNull ArrayDeque cache) { + BlockPos sourcePos, EnumFacing inputFacing, + @NotNull Object2ObjectLinkedOpenHashMap> cache) { super(net, testObject, simulator, queryTick, sourcePos, inputFacing); this.cache = cache; } @Override - public @NotNull ArrayDeque getTraversalCache() { + public @NotNull Object2ObjectLinkedOpenHashMap> getTraversalCache() { return cache; } @Override - public boolean shouldSkipPath(FlowWorldPipeNetPath path) { + public boolean shouldSkipPath(@NotNull FlowWorldPipeNetPath path) { return false; } + + @Override + public @NotNull SimpleTileRoundRobinData createRRData(@NotNull WorldPipeNetNode destination) { + return new SimpleTileRoundRobinData<>(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); + } + + @Override + public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData data, + @NotNull WorldPipeNetNode destination, + long flowReachingDestination) { + long availableFlow = flowReachingDestination; + EnumFacing pointerFacing = data.getPointerFacing(getSimulatorKey()); + if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && pointerFacing == inputFacing) + return 0; // anti insert-to-our-source logic + + IItemHandler container = data.getAtPointer(destination, getSimulatorKey()); + if (container != null) { + availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(pointerFacing)).insertToHandler(getTestObject(), + (int) Math.min(Integer.MAX_VALUE, availableFlow), container, getSimulatorKey() != null); + } + return flowReachingDestination - availableFlow; + } } From c54d8f2b347cdfdaad521494ca4d83b4f5f6ef2a Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 14 Aug 2024 11:01:11 -0600 Subject: [PATCH 102/157] Remove unecessary generalization --- src/main/java/gregtech/api/graphnet/IGraphNet.java | 8 -------- .../gregtech/api/graphnet/pipenet/WorldPipeNet.java | 12 +++++++++++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index 8b7faf043d3..42f9dd65d2b 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -210,12 +210,4 @@ default NetEdge getNewEdge() { */ @ApiStatus.Internal void markDirty(); - - /** - * Get the network ID for this net. Must be unique and deterministic between server and client, but can change - * between mod versions. - * - * @return the net's network id. - */ - int getNetworkID(); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 26dd790f6ca..8d45d8652e6 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -22,6 +22,7 @@ import it.unimi.dsi.fastutil.Hash; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -179,6 +180,14 @@ public static String getDataID(final String baseID, final World world) { return baseID + '.' + dimension; } + /** + * Get the network ID for this net. Must be unique and deterministic between server and client, but can change + * between mod versions. + * + * @return the net's network id. + */ + public abstract int getNetworkID(); + @Override public final Class getNodeClass() { return WorldPipeNetNode.class; @@ -189,7 +198,8 @@ public final Class getNodeClass() { return new WorldPipeNetNode(this); } - public static Object2ObjectOpenCustomHashMap getSensitiveHashMap() { + @Contract(value = " -> new", pure = true) + public static @NotNull Object2ObjectOpenCustomHashMap getSensitiveHashMap() { return new Object2ObjectOpenCustomHashMap<>(SensitiveStrategy.INSTANCE); } From 6f0fd56521fa1641a208bf4d8e004c02925d11cf Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 14 Aug 2024 12:30:32 -0600 Subject: [PATCH 103/157] Tweaks to logic data handling --- .../api/graphnet/logic/NetLogicData.java | 18 ++++++++++++++--- .../api/graphnet/logic/NetLogicEntry.java | 20 +++++++++++++++---- .../logic/EdgeCoverReferenceLogic.java | 10 +++++----- .../pipelike/net/energy/EnergyFlowLogic.java | 5 +++++ 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index 0717e693934..8bd62838e17 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -2,6 +2,7 @@ import gregtech.api.network.IPacket; +import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.network.PacketBuffer; @@ -89,6 +90,14 @@ public void markLogicEntryAsUpdated(NetLogicEntry entry, boolean fullChang this.listeners.forEach(l -> l.markChanged(entry, false, fullChange)); } + public boolean hasLogicEntry(@NotNull String key) { + return logicEntrySet.containsKey(key); + } + + public boolean hasLogicEntry(@NotNull NetLogicEntry key) { + return logicEntrySet.containsKey(key.getName()); + } + @Nullable public NetLogicEntry getLogicEntryNullable(@NotNull String key) { return logicEntrySet.get(key); @@ -155,8 +164,9 @@ public NBTTagList serializeNBT() { NBTTagList list = new NBTTagList(); for (NetLogicEntry entry : getEntries()) { NBTTagCompound tag = new NBTTagCompound(); - tag.setTag("Tag", entry.serializeNBT()); tag.setString("Name", entry.getName()); + NBTBase nbt = entry.serializeNBT(); + if (nbt != null) tag.setTag("Tag", nbt); list.appendTag(tag); } return list; @@ -178,8 +188,10 @@ public void deserializeNBT(NBTTagList nbt) { public void encode(PacketBuffer buf) { buf.writeVarInt(getEntries().size()); for (NetLogicEntry entry : getEntries()) { - buf.writeString(entry.getName()); - entry.encode(buf, true); + if (entry.shouldEncode()) { + buf.writeString(entry.getName()); + entry.encode(buf, true); + } } } diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java index 52e4a2042f0..709c9fab28e 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java @@ -32,10 +32,14 @@ protected NetLogicEntry(@NotNull String name) { return name; } - public void deserializeNBTNaive(NBTBase nbt) { - deserializeNBT((N) nbt); + public void deserializeNBTNaive(@Nullable NBTBase nbt) { + if (nbt != null) deserializeNBT((N) nbt); } + @Override + @Nullable + public abstract N serializeNBT(); + /** * Returns null if the operation is not supported. */ @@ -93,7 +97,15 @@ public T cast(NetLogicEntry entry) { return (T) entry; } - public void encode(PacketBuffer buf) { + /** + * Controls whether this {@link NetLogicEntry} will be synced to the client or not. + * @return + */ + public boolean shouldEncode() { + return true; + } + + public final void encode(PacketBuffer buf) { encode(buf, true); } @@ -103,7 +115,7 @@ public void encode(PacketBuffer buf) { */ public abstract void encode(PacketBuffer buf, boolean fullChange); - public void decode(PacketBuffer buf) { + public final void decode(PacketBuffer buf) { decode(buf, true); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java index de0a1cd21fb..0288c27ddbd 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java @@ -133,15 +133,15 @@ public void deserializeNBT(NBTTagCompound nbt) { return new EdgeCoverReferenceLogic(); } - // this logic never needs to be sent to the client, it is purely for graph calculations + @Override + public boolean shouldEncode() { + return false; + } + @Override public void encode(PacketBuffer buf, boolean fullChange) {} @Override public void decode(PacketBuffer buf, boolean fullChange) {} - public interface IThroughputLimiterCover extends Cover { - - long getLimit(); - } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java index 78cc4e34b9b..fdb5769892a 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java @@ -65,6 +65,11 @@ public void deserializeNBT(NBTTagByte nbt) {} return new EnergyFlowLogic(); } + @Override + public boolean shouldEncode() { + return false; + } + @Override public void encode(PacketBuffer buf, boolean fullChange) {} From 28a2752ac03e437284b3cce771e46a7f5a12aa51 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 15 Aug 2024 11:38:17 -0600 Subject: [PATCH 104/157] Misc improvements and fix #2582 --- .../api/graphnet/AbstractGroupData.java | 10 +++ .../gregtech/api/graphnet/GraphNetBacker.java | 7 +- .../java/gregtech/api/graphnet/NetGroup.java | 30 ++++++-- .../gregtech/api/graphnet/edge/NetEdge.java | 3 + .../api/graphnet/logic/NetLogicEntry.java | 1 + .../logic/EdgeCoverReferenceLogic.java | 1 - .../pipenet/physical/block/PipeBlock.java | 70 +++++++++++++++++-- .../pipenet/physical/tile/PipeTileEntity.java | 1 - .../api/graphnet/servernet/ServerNetNode.java | 2 +- .../api/graphnet/worldnet/WorldNetNode.java | 2 +- .../gregtech/api/pattern/BlockPattern.java | 2 +- .../gregtech/api/pattern/BlockWorldState.java | 2 +- .../java/gregtech/api/util/GTUtility.java | 2 +- .../renderer/pipe/AbstractPipeModel.java | 4 +- .../pipelike/net/energy/EnergyGroupData.java | 15 ++++ .../pipelike/net/energy/WorldEnergyNet.java | 6 ++ 16 files changed, 134 insertions(+), 24 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/AbstractGroupData.java b/src/main/java/gregtech/api/graphnet/AbstractGroupData.java index 4cb51981b7c..677d06d211c 100644 --- a/src/main/java/gregtech/api/graphnet/AbstractGroupData.java +++ b/src/main/java/gregtech/api/graphnet/AbstractGroupData.java @@ -1,5 +1,8 @@ package gregtech.api.graphnet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + public abstract class AbstractGroupData { protected NetGroup group; @@ -7,4 +10,11 @@ public abstract class AbstractGroupData { public void withGroup(NetGroup group) { this.group = group; } + + public abstract boolean mergeAllowed(@NotNull AbstractGroupData other); + + @Nullable + public AbstractGroupData merge(@NotNull AbstractGroupData other) { + return null; + } } diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index d3ad18bfa99..22193c068f5 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -96,7 +96,8 @@ public void removeVertex(GraphVertex vertex) { } @Nullable - public NetEdge addEdge(NetNode source, NetNode target, double weight) { + public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, double weight) { + if (!NetGroup.isEdgeAllowed(source, target)) return null; GraphEdge graphEdge = getGraph().addEdge(source.wrapper, target.wrapper); if (graphEdge != null) { getGraph().setEdgeWeight(graphEdge, weight); @@ -107,12 +108,12 @@ public NetEdge addEdge(NetNode source, NetNode target, double weight) { } @Nullable - public NetEdge getEdge(NetNode source, NetNode target) { + public NetEdge getEdge(@NotNull NetNode source, @NotNull NetNode target) { GraphEdge graphEdge = getGraph().getEdge(source.wrapper, target.wrapper); return graphEdge == null ? null : graphEdge.wrapped; } - public boolean removeEdge(NetNode source, NetNode target) { + public boolean removeEdge(@NotNull NetNode source, NetNode target) { NetGroup group = source.getGroupUnsafe(); if (group == null) { // weird since there should always be a group for two joined nodes, but whatever diff --git a/src/main/java/gregtech/api/graphnet/NetGroup.java b/src/main/java/gregtech/api/graphnet/NetGroup.java index c6442d49aeb..1c1a7d1f507 100644 --- a/src/main/java/gregtech/api/graphnet/NetGroup.java +++ b/src/main/java/gregtech/api/graphnet/NetGroup.java @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.Iterator; @@ -16,13 +17,13 @@ public class NetGroup { private final Set nodes; - private final AbstractGroupData data; + private AbstractGroupData data; public NetGroup(IGraphNet net) { this(net, new ObjectOpenHashSet<>()); } - public NetGroup(IGraphNet net, + public NetGroup(@NotNull IGraphNet net, Set nodes) { this.net = net; this.data = net.getBlankGroupData(); @@ -53,17 +54,29 @@ protected void clearNodes() { this.nodes.clear(); } - protected void onAddedToGroup(NetNode node) { + protected void onAddedToGroup(@NotNull NetNode node) { node.setGroup(this); } + public static boolean isEdgeAllowed(@NotNull NetNode source, @NotNull NetNode target) { + NetGroup sourceGroup = source.getGroupUnsafe(); + NetGroup targetGroup = target.getGroupUnsafe(); + + if (sourceGroup == null || targetGroup == null) return true; + AbstractGroupData sourceData = sourceGroup.getData(); + AbstractGroupData targetData = targetGroup.getData(); + if (sourceData == null || targetData == null) return true; + + return sourceData.mergeAllowed(targetData) && targetData.mergeAllowed(sourceData); + } + /** * Merges the groups of an edge if necessary. Does not actually perform the edge creation. * * @param source the source node of the edge * @param target the target node of the edge */ - public static void mergeEdge(NetNode source, NetNode target) { + public static void mergeEdge(@NotNull NetNode source, @NotNull NetNode target) { NetGroup sourceGroup = source.getGroupUnsafe(); NetGroup targetGroup = target.getGroupUnsafe(); if (sourceGroup == targetGroup) { @@ -81,11 +94,16 @@ public static void mergeEdge(NetNode source, NetNode target) { } } - protected void mergeNode(NetNode node) { + protected void mergeNode(@NotNull NetNode node) { NetGroup group = node.getGroupUnsafe(); if (group != null) { this.addNodes(group.getNodes()); group.clearNodes(); + AbstractGroupData data = group.getData(); + if (data != null) { + if (this.data == null) this.data = data; + else this.data.merge(data); + } } else addNode(node); this.clearPathCaches(); } @@ -134,7 +152,7 @@ public void splitNode(NetNode source) { * @param target target of the edge * @return Whether the edge existed in the graph */ - public boolean splitEdge(NetNode source, NetNode target) { + public boolean splitEdge(@NotNull NetNode source, @NotNull NetNode target) { if (this.net.getBacker().removeEdge(source.wrapper, target.wrapper) != null) { this.clearPathCaches(); Set targetGroup = new ObjectOpenHashSet<>(); diff --git a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java index e7d2be4d3ab..7ca69a83f79 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java @@ -44,6 +44,9 @@ public void setData(@NotNull NetLogicData data) { if (this.wrapper == null) this.data = data; } + /** + * This data is transient and should not be written to. + */ public @NotNull NetLogicData getData() { if (this.data == null) { this.data = NetLogicData.unionNullable(getSource() == null ? null : getSource().getData(), diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java index 709c9fab28e..e0cfd1e78c1 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java @@ -99,6 +99,7 @@ public T cast(NetLogicEntry entry) { /** * Controls whether this {@link NetLogicEntry} will be synced to the client or not. + * * @return */ public boolean shouldEncode() { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java index 0288c27ddbd..bba5d655887 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java @@ -143,5 +143,4 @@ public void encode(PacketBuffer buf, boolean fullChange) {} @Override public void decode(PacketBuffer buf, boolean fullChange) {} - } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 46b8f6dfc84..429158f8bf7 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -26,6 +26,7 @@ import net.minecraft.block.Block; import net.minecraft.block.SoundType; +import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.state.BlockFaceShape; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; @@ -63,11 +64,34 @@ import java.lang.ref.WeakReference; import java.util.Collection; +import java.util.EnumMap; import java.util.List; import java.util.Map; public abstract class PipeBlock extends BuiltInRenderBlock { + public static final PropertyBool NORTH = PropertyBool.create("north"); + public static final PropertyBool EAST = PropertyBool.create("east"); + public static final PropertyBool SOUTH = PropertyBool.create("south"); + public static final PropertyBool WEST = PropertyBool.create("west"); + public static final PropertyBool UP = PropertyBool.create("up"); + public static final PropertyBool DOWN = PropertyBool.create("down"); + + public static final EnumMap FACINGS = buildFacings(); + + private static @NotNull EnumMap buildFacings() { + EnumMap map = new EnumMap<>(EnumFacing.class); + map.put(EnumFacing.NORTH, NORTH); + map.put(EnumFacing.EAST, EAST); + map.put(EnumFacing.SOUTH, SOUTH); + map.put(EnumFacing.WEST, WEST); + map.put(EnumFacing.UP, UP); + map.put(EnumFacing.DOWN, DOWN); + return map; + } + + public static final PropertyBool FRAMED = PropertyBool.create("framed"); + // do not touch these two unless you know what you are doing protected final ThreadLocal lastTilePos = ThreadLocal.withInitial(() -> new BlockPos(0, 0, 0)); protected final ThreadLocal> lastTile = ThreadLocal @@ -583,16 +607,50 @@ public String getToolClass() { // blockstate // + @Override + public int getMetaFromState(@NotNull IBlockState state) { + return 0; + } + @Override protected @NotNull BlockStateContainer createBlockState() { - return constructState(new BlockStateContainer.Builder(this)).build(); + return constructState(new BlockStateContainer.Builder(this)) + .add(NORTH, SOUTH, EAST, WEST, UP, DOWN, FRAMED) + .build(); } protected @NotNull BlockStateContainer.Builder constructState(BlockStateContainer.@NotNull Builder builder) { - return builder.add(AbstractPipeModel.THICKNESS_PROPERTY).add(AbstractPipeModel.CONNECTION_MASK_PROPERTY) - .add(AbstractPipeModel.CLOSED_MASK_PROPERTY).add(AbstractPipeModel.BLOCKED_MASK_PROPERTY) - .add(AbstractPipeModel.COLOR_PROPERTY).add(AbstractPipeModel.FRAME_MATERIAL_PROPERTY) - .add(AbstractPipeModel.FRAME_MASK_PROPERTY).add(CoverRendererPackage.PROPERTY); + return builder.add(AbstractPipeModel.THICKNESS_PROPERTY).add(AbstractPipeModel.CLOSED_MASK_PROPERTY) + .add(AbstractPipeModel.BLOCKED_MASK_PROPERTY).add(AbstractPipeModel.COLOR_PROPERTY) + .add(AbstractPipeModel.FRAME_MATERIAL_PROPERTY).add(AbstractPipeModel.FRAME_MASK_PROPERTY) + .add(CoverRendererPackage.PROPERTY); + } + + @SuppressWarnings("deprecation") + @Override + public @NotNull IBlockState getActualState(@NotNull IBlockState state, @NotNull IBlockAccess worldIn, + @NotNull BlockPos pos) { + PipeTileEntity tile = getTileEntity(worldIn, pos); + if (tile == null) return state; + state = writeConnectionMask(state, tile.getConnectionMask()); + return state.withProperty(FRAMED, tile.getFrameMaterial() != null); + } + + public static IBlockState writeConnectionMask(@NotNull IBlockState state, byte connectionMask) { + for (EnumFacing facing : EnumFacing.VALUES) { + state = state.withProperty(FACINGS.get(facing), GTUtility.evalMask(facing, connectionMask)); + } + return state; + } + + public static byte readConnectionMask(@NotNull IBlockState state) { + byte mask = 0; + for (EnumFacing facing : EnumFacing.VALUES) { + if (state.getValue(FACINGS.get(facing))) { + mask |= 1 << facing.ordinal(); + } + } + return mask; } @Override @@ -600,7 +658,7 @@ public String getToolClass() { @NotNull BlockPos pos) { PipeTileEntity tile = getTileEntity(world, pos); if (tile == null) return state; - else return tile.getRenderInformation((IExtendedBlockState) state); + else return tile.getRenderInformation((IExtendedBlockState) state.getActualState(world, pos)); } // tile entity // diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 537600d6481..24d4955e23f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -734,7 +734,6 @@ public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { } frameMask = (byte) ~frameMask; return state.withProperty(AbstractPipeModel.THICKNESS_PROPERTY, this.getStructure().getRenderThickness()) - .withProperty(AbstractPipeModel.CONNECTION_MASK_PROPERTY, connectionMask) .withProperty(AbstractPipeModel.CLOSED_MASK_PROPERTY, renderMask) .withProperty(AbstractPipeModel.BLOCKED_MASK_PROPERTY, blockedMask) .withProperty(AbstractPipeModel.COLOR_PROPERTY, getPaintingColor()) diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java index 432556aa478..31d10bded76 100644 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java @@ -31,7 +31,7 @@ public void deserializeNBT(NBTTagCompound nbt) { } @Override - public Object getEquivalencyData() { + public DimensionPos getEquivalencyData() { return pos; } } diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java index 8086db069b4..904a13c88be 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java @@ -39,7 +39,7 @@ public void deserializeNBT(NBTTagCompound nbt) { } @Override - public Object getEquivalencyData() { + public BlockPos getEquivalencyData() { return pos; } } diff --git a/src/main/java/gregtech/api/pattern/BlockPattern.java b/src/main/java/gregtech/api/pattern/BlockPattern.java index f392ba1b26e..d77bde0c7b8 100644 --- a/src/main/java/gregtech/api/pattern/BlockPattern.java +++ b/src/main/java/gregtech/api/pattern/BlockPattern.java @@ -111,7 +111,7 @@ public PatternMatchContext checkPatternFastAt(World world, BlockPos centerPos, E boolean pass = true; for (Map.Entry entry : cache.entrySet()) { BlockPos pos = BlockPos.fromLong(entry.getKey()); - IBlockState blockState = world.getBlockState(pos); + IBlockState blockState = world.getBlockState(pos).getActualState(world, pos); if (blockState != entry.getValue().getBlockState()) { pass = false; break; diff --git a/src/main/java/gregtech/api/pattern/BlockWorldState.java b/src/main/java/gregtech/api/pattern/BlockWorldState.java index 74dfa1c4526..aff74b90948 100644 --- a/src/main/java/gregtech/api/pattern/BlockWorldState.java +++ b/src/main/java/gregtech/api/pattern/BlockWorldState.java @@ -57,7 +57,7 @@ public PatternMatchContext getMatchContext() { public IBlockState getBlockState() { if (this.state == null) { - this.state = this.world.getBlockState(this.pos); + this.state = this.world.getBlockState(this.pos).getActualState(this.world, this.pos); } return this.state; diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index d4f120611cc..7e9867335c4 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -943,7 +943,7 @@ public static int[] convertARGBtoArray(int argb) { @Contract(pure = true) public static boolean evalMask(@NotNull Enum anEnum, byte mask) { - return (mask & (1L << anEnum.ordinal())) > 0; + return (mask & (1 << anEnum.ordinal())) > 0; } @Contract(pure = true) diff --git a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java index 6fd8a19e06f..5aab7a1756d 100644 --- a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java @@ -4,6 +4,7 @@ import gregtech.api.block.UnlistedFloatProperty; import gregtech.api.block.UnlistedIntegerProperty; import gregtech.api.block.UnlistedPropertyMaterial; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.info.MaterialIconType; import gregtech.api.util.GTUtility; @@ -51,7 +52,6 @@ public abstract class AbstractPipeModel implements IBakedMod public static UnlistedPropertyMaterial FRAME_MATERIAL_PROPERTY = new UnlistedPropertyMaterial("frame_material"); public static UnlistedByteProperty FRAME_MASK_PROPERTY = new UnlistedByteProperty("frame_mask"); - public static UnlistedByteProperty CONNECTION_MASK_PROPERTY = new UnlistedByteProperty("connection_mask"); public static UnlistedByteProperty CLOSED_MASK_PROPERTY = new UnlistedByteProperty("closed_mask"); public static UnlistedByteProperty BLOCKED_MASK_PROPERTY = new UnlistedByteProperty("blocked_mask"); @@ -75,7 +75,7 @@ public AbstractPipeModel(ModelResourceLocation loc) { CoverRendererPackage rendererPackage = ext.getValue(CoverRendererPackage.PROPERTY); byte coverMask = rendererPackage == null ? 0 : rendererPackage.getMask(); if (canRenderInLayer(getCurrentRenderLayer())) { - quads = getQuads(toKey(ext), safeByte(ext.getValue(CONNECTION_MASK_PROPERTY)), + quads = getQuads(toKey(ext), PipeBlock.readConnectionMask(ext), safeByte(ext.getValue(CLOSED_MASK_PROPERTY)), safeByte(ext.getValue(BLOCKED_MASK_PROPERTY)), data, ext.getValue(FRAME_MATERIAL_PROPERTY), safeByte(ext.getValue(FRAME_MASK_PROPERTY)), coverMask); diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java index 672912b7e0a..b5f10b325c8 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java @@ -2,6 +2,9 @@ import gregtech.api.graphnet.AbstractGroupData; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + public class EnergyGroupData extends AbstractGroupData { private long lastEnergyInPerSec; @@ -43,4 +46,16 @@ public void clearCache() { energyInPerSec = 0; energyOutPerSec = 0; } + + @Override + public boolean mergeAllowed(@NotNull AbstractGroupData other) { + return true; + } + + @Override + public @Nullable AbstractGroupData merge(@NotNull AbstractGroupData other) { + if (other instanceof EnergyGroupData) + return new EnergyGroupData(); + else return null; + } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java index e20b093658d..3a69ec2e40c 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java @@ -1,6 +1,7 @@ package gregtech.common.pipelike.net.energy; import gregtech.api.capability.GregtechCapabilities; +import gregtech.api.graphnet.AbstractGroupData; import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; @@ -66,6 +67,11 @@ public Iterator getPaths(WorldPipeNetNode node, IPredicate return new NetFlowEdge(1); } + @Override + public AbstractGroupData getBlankGroupData() { + return new EnergyGroupData(); + } + @Override public int getNetworkID() { return 0; From b5e1ab7ee44152073c0ff7c5352726be306e97a3 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 16 Aug 2024 18:10:11 -0600 Subject: [PATCH 105/157] Fix some very large issues --- .../impl/LaserContainerHandler.java | 1 + .../gregtech/api/fluids/FluidBuilder.java | 16 ++++- .../gregtech/api/graphnet/GraphNetBacker.java | 2 +- .../api/graphnet/logic/NetLogicData.java | 6 +- .../pipenet/logic/EnumLossFunction.java | 5 +- .../pipenet/logic/TemperatureLogic.java | 30 ++++---- .../pipenet/physical/tile/PipeTileEntity.java | 9 ++- .../api/graphnet/traverse/ITraverseData.java | 4 +- .../graphnet/traverse/TraverseHelpers.java | 28 ++++---- .../api/unification/material/Material.java | 17 +---- .../materials/FirstDegreeMaterials.java | 18 ++--- .../client/particle/GTOverheatParticle.java | 7 +- .../common/covers/CoverFluidRegulator.java | 4 +- .../properties/MaterialEnergyProperties.java | 40 +++++------ .../properties/MaterialFluidProperties.java | 27 ++----- .../net/energy/EnergyCapabilityObject.java | 18 +++-- .../net/energy/EnergyTraverseData.java | 9 ++- .../net/fluid/FluidCapabilityObject.java | 7 +- .../net/fluid/FluidContainmentLogic.java | 26 +++++-- .../net/fluid/FluidRRTraverseData.java | 4 +- .../pipelike/net/fluid/FluidTraverseData.java | 70 +++++++++++-------- .../net/item/ItemCapabilityObject.java | 6 +- .../material/CTMaterialBuilder.java | 4 +- .../material/MaterialPropertyExpansion.java | 4 +- .../groovy/MaterialPropertyExpansion.java | 16 ++--- 25 files changed, 198 insertions(+), 180 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java b/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java index a66aeb7d8e0..d8903cbd200 100644 --- a/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java +++ b/src/main/java/gregtech/api/capability/impl/LaserContainerHandler.java @@ -29,6 +29,7 @@ public static LaserContainerHandler receiverContainer(MetaTileEntity tileEntity, @Override public long receiveLaser(long laserVoltage, long laserAmperage) { + if (getInputVoltage() == 0) return 0; long allowedAmps = getEnergyCanBeInserted() / laserVoltage; addEnergy(laserVoltage * allowedAmps); // over voltage explosion diff --git a/src/main/java/gregtech/api/fluids/FluidBuilder.java b/src/main/java/gregtech/api/fluids/FluidBuilder.java index 7c8fe7aab09..4f0f647001d 100644 --- a/src/main/java/gregtech/api/fluids/FluidBuilder.java +++ b/src/main/java/gregtech/api/fluids/FluidBuilder.java @@ -418,7 +418,20 @@ private void determineTextures(@Nullable Material material, @Nullable FluidStora } private void determineTemperature(@Nullable Material material) { - if (temperature != INFER_TEMPERATURE) return; + this.temperature = getDeterminedTemperature(material, null); + } + + public int getDeterminedTemperature(@Nullable Material material, @Nullable FluidStorageKey key) { + FluidState state = this.state; + if (state == null) { + if (key != null && key.getDefaultFluidState() != null) { + state = key.getDefaultFluidState(); + } else { + state = FluidState.LIQUID; // default fallback + } + } + int temperature = this.temperature; + if (temperature != INFER_TEMPERATURE) return temperature; if (material == null) { temperature = ROOM_TEMPERATURE; } else { @@ -447,6 +460,7 @@ private void determineTemperature(@Nullable Material material) { }; } } + return temperature; } private void determineColor(@Nullable Material material) { diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index 22193c068f5..a568287e564 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -45,7 +45,7 @@ public GraphNetBacker(IGraphNet backedNet, INetGraph graph, this.netAlgorithms = new NetAlgorithmWrapper[algorithmBuilders.length]; for (int i = 0; i < algorithmBuilders.length; i++) { this.netAlgorithms[i] = new NetAlgorithmWrapper(backedNet, algorithmBuilders[i], - backedNet.supportsPredication()); + backedNet.supportsPredication() || backedNet.usesDynamicWeights(i)); } this.vertexMap = new Object2ObjectOpenHashMap<>(); } diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index 8bd62838e17..0988f458855 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -191,6 +191,8 @@ public void encode(PacketBuffer buf) { if (entry.shouldEncode()) { buf.writeString(entry.getName()); entry.encode(buf, true); + } else { + buf.writeString(""); } } } @@ -201,10 +203,8 @@ public void decode(PacketBuffer buf) { int entryCount = buf.readVarInt(); for (int i = 0; i < entryCount; i++) { String name = buf.readString(255); + if (name.equals("")) continue; NetLogicEntry existing = NetLogicRegistry.getSupplierErroring(name).get(); - if (existing == null) - throw new RuntimeException("Could not find a matching supplier for an encoded NetLogicEntry. " + - "This suggests that the server and client have different GT versions or modifications."); existing.registerToNetLogicData(this); existing.decode(buf); this.logicEntrySet.put(name, existing); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java index bd0fac3e198..202c99b4f51 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/EnumLossFunction.java @@ -94,9 +94,10 @@ public float applyLoss(float value, float factorX, float factorY, int timePassed @Override public float applyLoss(float value, float factorX, float factorY, int timePassed) { for (int i = 0; i < timePassed; i++) { - value -= factorX * Math.pow(value, factorY); + if (value < 0) value += factorX * Math.pow(-value, factorY); + else if (value > 0) value -= factorX * Math.pow(value, factorY); } - return 0; + return tolerate(value); } }; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index b477ca278c7..bc8bb261f51 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -10,12 +10,12 @@ import gregtech.api.graphnet.pipenet.physical.IFreezable; import gregtech.api.graphnet.traverse.util.CompleteLossOperator; import gregtech.api.graphnet.traverse.util.MultLossOperator; +import gregtech.client.particle.GTOverheatParticle; import net.minecraft.block.state.IBlockState; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -28,7 +28,7 @@ public final class TemperatureLogic extends NetLogicEntry netListener; private boolean isMultiNodeHelper = false; @@ -43,7 +43,7 @@ public final class TemperatureLogic extends NetLogicEntry this.energy) return; + if (thermalEnergy + this.energy > thermalMax) { + thermalEnergy = thermalMax - this.energy; + } + } + if (thermalEnergy > 0) applyThermalEnergy(thermalEnergy, tick); } public int getTemperature(long tick) { @@ -176,7 +180,7 @@ public int getTemperature(long tick) { } private void restoreTemperature(long tick) { - long timePassed = lastRestorationTick - tick; + long timePassed = tick - lastRestorationTick; this.lastRestorationTick = tick; float energy = this.energy; if (timePassed != 0) { @@ -249,9 +253,9 @@ public boolean mergedToMultiNodeHelper() { @Override public void merge(NetNode otherOwner, NetLogicEntry unknown) { if (!(unknown instanceof TemperatureLogic other)) return; - if (other.getTemperatureMinimum() < this.getTemperatureMinimum()) + if (other.getTemperatureMinimum() > this.getTemperatureMinimum()) this.setTemperatureMinimum(other.getTemperatureMinimum()); - if (other.getTemperatureMaximum() > this.getTemperatureMaximum()) + if (other.getTemperatureMaximum() < this.getTemperatureMaximum()) this.setTemperatureMaximum(other.getTemperatureMaximum()); // since merge also occurs during nbt load, ignore the other's thermal energy. if (other.getThermalMass() < this.getThermalMass()) this.setThermalMass(other.getThermalMass()); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 24d4955e23f..8927402f738 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -17,6 +17,7 @@ import gregtech.api.metatileentity.NeighborCacheTileEntityBase; import gregtech.api.unification.material.Material; import gregtech.client.particle.GTOverheatParticle; +import gregtech.client.particle.GTParticleManager; import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.pipe.cover.CoverRendererPackage; @@ -477,7 +478,7 @@ protected void initialize() { buf.writeBoolean(r); buf.writeBoolean(f); if (!r) { - e.encode(buf); + e.encode(buf, f); } })); this.listeners.add(listener); @@ -585,7 +586,7 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { } else { if (fullChange) { NetLogicEntry logic = NetLogicRegistry.getSupplierErroring(identifier).get(); - logic.decode(buf, fullChange); + logic.decode(buf, true); this.netLogicDatas.compute(networkID, (k, v) -> { if (v == null) v = new NetLogicData(); v.setLogicEntry(logic); @@ -595,7 +596,8 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { NetLogicData data = this.netLogicDatas.get(networkID); if (data != null) { NetLogicEntry entry = data.getLogicEntryNullable(identifier); - if (entry != null) entry.decode(buf); + if (entry != null) entry.decode(buf, false); + data.markLogicEntryAsUpdated(entry, false); } else return; } if (identifier.equals(TemperatureLogic.INSTANCE.getName())) { @@ -635,6 +637,7 @@ public void updateTemperatureLogic(@NotNull TemperatureLogic logic) { IPipeStructure structure = this.getStructure(); overheatParticle = new GTOverheatParticle(this, logic, structure.getPipeBoxes(this), structure instanceof IInsulatable i && i.isInsulated()); + GTParticleManager.INSTANCE.addEffect(overheatParticle); } } else { overheatParticle.setTemperatureLogic(logic); diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java index 98846c95036..4955d50e318 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java @@ -64,13 +64,13 @@ default long getFlowLimit(@NotNull AbstractNetFlowEdge edge) { /** * Allows for consuming more than just the edge flow limits on a consumption event. Must always consume the correct * amount of edge flow or things will break. - * + * * @param edge the edge to consume along. * @param targetNode the target node of the edge. * @param consumption the amount to consume from the edge's flow limit. */ @MustBeInvokedByOverriders - default void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, + default void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { edge.consumeFlowLimit(this.getTestObject(), this.getGraphNet(), consumption, this.getQueryTick(), this.getSimulatorKey()); diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index e5540eca769..a9a7f8e6a04 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -19,7 +19,7 @@ import java.util.List; import java.util.Map; import java.util.function.BiConsumer; -import java.util.function.Consumer; +import java.util.function.LongUnaryOperator; import java.util.function.Predicate; import java.util.function.Supplier; @@ -70,7 +70,7 @@ D extends ITraverseData> long traverseFlood( } else continue pathloop; pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); - stack.add(flow -> data.consumeFlowLimit(edge, sourceNode, targetNode, flow), + stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); @@ -118,7 +118,7 @@ D extends ITraverseData> long traverseDumb( List nodes = path.getOrderedNodes(); List edges = path.getOrderedEdges(); - List> overflowReporters = isFlow ? new ObjectArrayList<>() : null; + List overflowReporters = isFlow ? new ObjectArrayList<>() : null; assert nodes.size() == edges.size() + 1; FlowConsumptionStack stack = isFlow ? @@ -139,26 +139,28 @@ D extends ITraverseData> long traverseDumb( if (isFlow) { AbstractNetFlowEdge flowEdge = (AbstractNetFlowEdge) edge; long limit = data.getFlowLimit(flowEdge); - if (pathFlow > limit) { - long overflow = pathFlow - limit; + long overflow = pathFlow - limit; + if (overflow > 0) { pathFlow = limit; overflowReporters.add(reduction -> { long finalOverflow = overflow - reduction; - if (finalOverflow > 0) overflowListener.accept(targetNode, finalOverflow); + if (finalOverflow > 0) { + overflowListener.accept(targetNode, finalOverflow); + return finalOverflow; + } + return 0; }); } - stack.add(flow -> data.consumeFlowLimit(flowEdge, sourceNode, targetNode, flow), + stack.add(flow -> data.consumeFlowLimit(flowEdge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); } - - if (pathFlow <= 0) continue pathloop; } long accepted = data.finalizeAtDestination(nodes.get(edges.size()), pathFlow); long unaccepted = pathFlow - accepted; if (isFlow) { - availableFlow -= stack.consumeWithEndValue(accepted); - overflowReporters.forEach((c) -> c.accept(unaccepted)); + availableFlow -= stack.consumeWithEndValue(accepted) + + overflowReporters.stream().mapToLong(u -> u.applyAsLong(unaccepted)).sum(); } if (!simulate) pathTraverseCalls.forEach(Runnable::run); @@ -277,7 +279,7 @@ D extends IEqualizableTraverseData> long traverseEqualDistribution( } else continue pathloop; pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); - stack.add(flow -> data.consumeFlowLimit(edge, sourceNode, targetNode, flow), + stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); @@ -461,7 +463,7 @@ P extends INetPath, D extends ITraverseData & IRoundRobinTraverseDat } else return strict ? -1 : 0; pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); - stack.add(flow -> data.consumeFlowLimit(edge, sourceNode, targetNode, flow), + stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), data.traverseToNode(targetNode, pathFlow)); pathFlow = stack.applyLatestLossFunction(pathFlow); diff --git a/src/main/java/gregtech/api/unification/material/Material.java b/src/main/java/gregtech/api/unification/material/Material.java index a3f5a47dbfa..fc261c305d9 100644 --- a/src/main/java/gregtech/api/unification/material/Material.java +++ b/src/main/java/gregtech/api/unification/material/Material.java @@ -1050,22 +1050,9 @@ public Builder cableProperties(long voltage, long amperage, long loss) { return this; } - public Builder cablePropertiesT(long voltage, long amperage, long loss, int meltTemperature) { + public Builder cableProperties(long voltage, long amperage, long loss, int superconductorTemperature) { getOrCreatePipeNetProperties() - .setProperty(MaterialEnergyProperties.createT(voltage, amperage, loss, meltTemperature)); - return this; - } - - public Builder cablePropertiesS(long voltage, long amperage, long loss, int superconductorTemperature) { - getOrCreatePipeNetProperties() - .setProperty(MaterialEnergyProperties.createS(voltage, amperage, loss, superconductorTemperature)); - return this; - } - - public Builder cableProperties(long voltage, long amperage, long loss, int meltTemperature, - int superconductorTemperature) { - getOrCreatePipeNetProperties().setProperty( - new MaterialEnergyProperties(voltage, amperage, loss, meltTemperature, superconductorTemperature)); + .setProperty(MaterialEnergyProperties.create(voltage, amperage, loss, superconductorTemperature)); return this; } diff --git a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java index cb85e922828..f457551a10e 100644 --- a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java @@ -1341,7 +1341,7 @@ public static void register() { .color(0xE1B454).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Manganese, 1, Phosphorus, 1) - .cablePropertiesS(GTValues.V[GTValues.LV], 2, GTValues.V[GTValues.ULV], 500) + .cableProperties(GTValues.V[GTValues.LV], 2, GTValues.V[GTValues.ULV], 500) .blast(1200, GasTier.LOW) .build(); @@ -1351,7 +1351,7 @@ public static void register() { .color(0x331900).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Magnesium, 1, Boron, 2) - .cablePropertiesS(GTValues.V[GTValues.MV], 4, GTValues.V[GTValues.LV], 500) + .cableProperties(GTValues.V[GTValues.MV], 4, GTValues.V[GTValues.LV], 500) .blast(b -> b .temp(2500, GasTier.LOW) .blastStats(VA[HV], 1000) @@ -1364,7 +1364,7 @@ public static void register() { .color(0x555555).iconSet(SHINY) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Mercury, 1, Barium, 2, Calcium, 2, Copper, 3, Oxygen, 8) - .cablePropertiesS(GTValues.V[GTValues.HV], 4, GTValues.V[GTValues.MV], 500) + .cableProperties(GTValues.V[GTValues.HV], 4, GTValues.V[GTValues.MV], 500) .blast(b -> b .temp(3300, GasTier.LOW) .blastStats(VA[HV], 1500) @@ -1377,7 +1377,7 @@ public static void register() { .color(0x008700).iconSet(SHINY) .flags(DECOMPOSITION_BY_CENTRIFUGING) .components(Uranium, 1, Platinum, 3) - .cablePropertiesS(GTValues.V[GTValues.EV], 6, GTValues.V[GTValues.HV], 500) + .cableProperties(GTValues.V[GTValues.EV], 6, GTValues.V[GTValues.HV], 500) .blast(b -> b .temp(4400, GasTier.MID) .blastStats(VA[EV], 1000) @@ -1390,7 +1390,7 @@ public static void register() { .color(0x330033).iconSet(SHINY) .flags(DECOMPOSITION_BY_CENTRIFUGING) .components(Samarium, 1, Iron, 1, Arsenic, 1, Oxygen, 1) - .cablePropertiesS(GTValues.V[GTValues.IV], 6, GTValues.V[GTValues.EV], 500) + .cableProperties(GTValues.V[GTValues.IV], 6, GTValues.V[GTValues.EV], 500) .blast(b -> b .temp(5200, GasTier.MID) .blastStats(VA[EV], 1500) @@ -1403,7 +1403,7 @@ public static void register() { .color(0x994C00).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING, GENERATE_FINE_WIRE) .components(Indium, 4, Tin, 2, Barium, 2, Titanium, 1, Copper, 7, Oxygen, 14) - .cablePropertiesS(GTValues.V[GTValues.LuV], 8, GTValues.V[GTValues.IV], 500) + .cableProperties(GTValues.V[GTValues.LuV], 8, GTValues.V[GTValues.IV], 500) .blast(b -> b .temp(6000, GasTier.HIGH) .blastStats(VA[IV], 1000) @@ -1416,7 +1416,7 @@ public static void register() { .color(0x0A0A0A) .flags(DECOMPOSITION_BY_CENTRIFUGING, GENERATE_FINE_WIRE) .components(Uranium, 1, Rhodium, 1, Naquadah, 2) - .cablePropertiesS(GTValues.V[GTValues.ZPM], 8, GTValues.V[LuV], 500) + .cableProperties(GTValues.V[GTValues.ZPM], 8, GTValues.V[LuV], 500) .blast(b -> b .temp(9000, GasTier.HIGH) .blastStats(VA[IV], 1500) @@ -1430,7 +1430,7 @@ public static void register() { .color(0x7D9673).iconSet(METALLIC) .flags(DECOMPOSITION_BY_CENTRIFUGING, GENERATE_FINE_WIRE) .components(NaquadahEnriched, 4, Trinium, 3, Europium, 2, Duranium, 1) - .cablePropertiesS(GTValues.V[GTValues.UV], 16, GTValues.V[GTValues.ZPM], 500) + .cableProperties(GTValues.V[GTValues.UV], 16, GTValues.V[GTValues.ZPM], 500) .blast(b -> b .temp(9900, GasTier.HIGH) .blastStats(VA[LuV], 1200) @@ -1444,7 +1444,7 @@ public static void register() { .color(0xFFFFFF).iconSet(BRIGHT) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Ruthenium, 1, Trinium, 2, Americium, 1, Neutronium, 2, Oxygen, 8) - .cablePropertiesS(GTValues.V[GTValues.UHV], 24, GTValues.V[GTValues.UV], 500) + .cableProperties(GTValues.V[GTValues.UHV], 24, GTValues.V[GTValues.UV], 500) .blast(b -> b .temp(10800, GasTier.HIGHER) .blastStats(VA[ZPM], 1000) diff --git a/src/main/java/gregtech/client/particle/GTOverheatParticle.java b/src/main/java/gregtech/client/particle/GTOverheatParticle.java index 09d82a051eb..82f8470c41b 100644 --- a/src/main/java/gregtech/client/particle/GTOverheatParticle.java +++ b/src/main/java/gregtech/client/particle/GTOverheatParticle.java @@ -175,9 +175,7 @@ private int getTemperature() { public void updatePipeBoxes(@NotNull List pipeBoxes) { this.pipeBoxes = pipeBoxes; - for (AxisAlignedBB cuboid : this.pipeBoxes) { - cuboid.expand(0.001, 0.001, 0.001); - } + pipeBoxes.replaceAll(axisAlignedBB -> axisAlignedBB.expand(0.001, 0.001, 0.001)); } public void setTemperatureLogic(@NotNull TemperatureLogic logic) { @@ -263,7 +261,8 @@ public void renderBloomEffect(@NotNull BufferBuilder buffer, @NotNull EffectRend public boolean shouldRenderBloomEffect(@NotNull EffectRenderContext context) { if (this.insulated) return false; for (AxisAlignedBB cuboid : pipeBoxes) { - if (!context.camera().isBoundingBoxInFrustum(cuboid)) { + if (!context.camera().isBoxInFrustum(cuboid.minX + posX, cuboid.minY + posY, cuboid.minZ + posZ, + cuboid.maxX + posX, cuboid.maxY + posY, cuboid.maxZ + posZ)) { return false; } } diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 970442586ee..06b6e0f4815 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -410,9 +410,7 @@ public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData {}).accept(accepted); - return accepted; + return flowReachingDestination - availableFlow; } } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 70e80bb253a..af7e414b780 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -50,7 +50,7 @@ public final class MaterialEnergyProperties implements PipeNetProperties.IPipeNe private final long voltageLimit; private final long amperageLimit; - private int temperatureLimit; + private int materialMeltTemperature; private final long lossPerAmp; private final int superconductorCriticalTemperature; @@ -60,18 +60,15 @@ public final class MaterialEnergyProperties implements PipeNetProperties.IPipeNe * @param voltageLimit the voltage limit for the cable * @param amperageLimit the base amperage for the cable. * @param lossPerAmp the base loss per amp per block traveled. - * @param temperatureLimit the melt temperature of the cable. If zero, autogeneration will be - * attempted. * @param superconductorCriticalTemperature the superconductor temperature. When the temperature is at or below * superconductor temperature, loss will be treated as zero. A * superconductor * temperature of 0 or less will be treated as not a superconductor. */ - public MaterialEnergyProperties(long voltageLimit, long amperageLimit, long lossPerAmp, int temperatureLimit, + public MaterialEnergyProperties(long voltageLimit, long amperageLimit, long lossPerAmp, int superconductorCriticalTemperature) { this.voltageLimit = voltageLimit; this.amperageLimit = amperageLimit; - this.temperatureLimit = temperatureLimit; this.lossPerAmp = lossPerAmp; this.superconductorCriticalTemperature = superconductorCriticalTemperature; } @@ -80,19 +77,14 @@ public long getVoltageLimit() { return voltageLimit; } - public static MaterialEnergyProperties createT(long voltageLimit, long amperageLimit, long lossPerAmp, - int temperatureLimit) { - return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, temperatureLimit, 0); - } - - public static MaterialEnergyProperties createS(long voltageLimit, long amperageLimit, long lossPerAmp, - int superconductorCriticalTemperature) { - return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, 0, + public static MaterialEnergyProperties create(long voltageLimit, long amperageLimit, long lossPerAmp, + int superconductorCriticalTemperature) { + return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, superconductorCriticalTemperature); } public static MaterialEnergyProperties create(long voltageLimit, long amperageLimit, long lossPerAmp) { - return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, 0, 0); + return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, 0); } public static IOreRegistrationHandler registrationHandler(TriConsumer handler) { @@ -138,19 +130,24 @@ public void verifyProperty(MaterialProperties properties) { thisMaterial.addFlags(GENERATE_FOIL); } } - if (this.temperatureLimit == 0 && properties.hasProperty(PropertyKey.FLUID)) { + this.materialMeltTemperature = computeMaterialMeltTemperature(properties); + } + + public static int computeMaterialMeltTemperature(@NotNull MaterialProperties properties) { + if (properties.hasProperty(PropertyKey.FLUID)) { // autodetermine melt temperature from registered fluid FluidProperty prop = properties.getProperty(PropertyKey.FLUID); - Fluid fluid = prop.getStorage().get(FluidStorageKeys.LIQUID); + Fluid fluid = prop.get(FluidStorageKeys.LIQUID); if (fluid == null) { - FluidBuilder builder = prop.getStorage().getQueuedBuilder(FluidStorageKeys.LIQUID); + FluidBuilder builder = prop.getQueuedBuilder(FluidStorageKeys.LIQUID); if (builder != null) { - this.temperatureLimit = builder.currentTemp(); + return builder.getDeterminedTemperature(properties.getMaterial(), FluidStorageKeys.LIQUID); } } else { - this.temperatureLimit = fluid.getTemperature(); + return fluid.getTemperature(); } } + return 3000; } @Override @@ -183,7 +180,8 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) .setLogicEntry(TemperatureLogic.INSTANCE - .getWith(TemperatureLossFunction.getOrCreateCable(coolingFactor), temperatureLimit, 1, + .getWith(TemperatureLossFunction.getOrCreateCable(coolingFactor), materialMeltTemperature, + 1, 100 * cable.material(), cable.partialBurnThreshold())); if (superconductorCriticalTemperature > 0) { data.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorCriticalTemperature)); @@ -198,7 +196,7 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) .setLogicEntry(TemperatureLogic.INSTANCE - .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), temperatureLimit, 1, + .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), materialMeltTemperature, 1, 50 * pipe.material(), null)); if (superconductorCriticalTemperature > 0) { data.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorCriticalTemperature)); diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index 09b5dcf1a5e..14bd462343c 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -1,11 +1,9 @@ package gregtech.common.pipelike.handlers.properties; import gregtech.api.capability.IPropertyFluidFilter; -import gregtech.api.fluids.FluidBuilder; import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.fluids.store.FluidStorageKeys; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.ThroughputLogic; @@ -15,7 +13,6 @@ import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.unification.material.properties.FluidProperty; import gregtech.api.unification.material.properties.MaterialProperties; import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; @@ -29,7 +26,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraftforge.fluids.Fluid; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; @@ -48,8 +44,9 @@ public final class MaterialFluidProperties implements PipeNetProperties.IPipeNet private final Set containableAttributes = new ObjectOpenHashSet<>(); private final EnumSet containableStates = EnumSet.of(FluidState.LIQUID); - private int maxFluidTemperature; + private final int maxFluidTemperature; private final int minFluidTemperature; + private int materialMeltTemperature; private final long baseThroughput; private final float priority; @@ -164,20 +161,7 @@ public void verifyProperty(MaterialProperties properties) { if (!properties.hasProperty(PropertyKey.WOOD)) { properties.ensureSet(PropertyKey.INGOT, true); } - - if (this.maxFluidTemperature == 0 && properties.hasProperty(PropertyKey.FLUID)) { - // autodetermine melt temperature from registered fluid - FluidProperty prop = properties.getProperty(PropertyKey.FLUID); - Fluid fluid = prop.getStorage().get(FluidStorageKeys.LIQUID); - if (fluid == null) { - FluidBuilder builder = prop.getStorage().getQueuedBuilder(FluidStorageKeys.LIQUID); - if (builder != null) { - this.maxFluidTemperature = builder.currentTemp(); - } - } else { - this.maxFluidTemperature = fluid.getTemperature(); - } - } + this.materialMeltTemperature = MaterialEnergyProperties.computeMaterialMeltTemperature(properties); } @Override @@ -198,9 +182,10 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { float coolingFactor = (float) Math.sqrt((double) pipe.material() / (4 + pipe.channelCount())); data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(getFlowPriority(structure))) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)) - .setLogicEntry(FluidContainmentLogic.INSTANCE.getWith(containableStates, containableAttributes)) + .setLogicEntry(FluidContainmentLogic.INSTANCE.getWith(containableStates, containableAttributes, + maxFluidTemperature)) .setLogicEntry(TemperatureLogic.INSTANCE - .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), maxFluidTemperature, + .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), materialMeltTemperature, minFluidTemperature, 50 * pipe.material(), null)); } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index c15d94b2525..5ad60648ecf 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -34,12 +34,14 @@ public class EnergyCapabilityObject implements IPipeCapabilityObject, IEnergyCon private @Nullable PipeTileEntity tile; private final EnumMap internalBuffers = new EnumMap<>(EnumFacing.class); + private final WorldPipeNetNode node; private boolean transferring = false; public EnergyCapabilityObject(@NotNull N net, WorldPipeNetNode node) { this.net = net; + this.node = node; for (EnumFacing facing : EnumFacing.VALUES) { AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); edge.setData(NetLogicData.union(node.getData(), (NetLogicData) null)); @@ -67,28 +69,27 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); AbstractNetFlowEdge internalBuffer = this.internalBuffers.get(side); - long availableAmperage = amperage; if (internalBuffer != null) { long limit = internalBuffer.getFlowLimit(IPredicateTestObject.INSTANCE, net, tick, simulator); if (limit <= 0) { this.transferring = false; return 0; + } else if (amperage > limit) { + amperage = limit; } - - availableAmperage = Math.min(amperage, limit); } + long availableAmperage = amperage; EnergyTraverseData data = new EnergyTraverseData(net, IPredicateTestObject.INSTANCE, simulator, tick, voltage, tile.getPos(), side); - availableAmperage -= TraverseHelpers.traverseFlood(data, getPaths(data), amperage); + availableAmperage -= TraverseHelpers.traverseFlood(data, getPaths(data), availableAmperage); if (availableAmperage > 0) { availableAmperage -= TraverseHelpers.traverseDumb(data, getPaths(data), data::handleOverflow, availableAmperage); } long accepted = amperage - availableAmperage; - if (internalBuffer != null) - internalBuffer.consumeFlowLimit(IPredicateTestObject.INSTANCE, net, accepted, tick, simulator); + if (internalBuffer != null) data.consumeFlowLimit(internalBuffer, node, accepted); if (!simulate) { EnergyGroupData group = getEnergyData(); if (group != null) { @@ -191,4 +192,9 @@ public long getEnergyStored() { public long getEnergyCapacity() { return getInputAmperage() * getInputVoltage(); } + + @Override + public boolean isOneProbeHidden() { + return true; + } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index 0d4f8470520..875278dae18 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -81,7 +81,7 @@ public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, lon } } - public void handleOverflow(WorldPipeNetNode node, long overflow) { + public void handleOverflow(@NotNull WorldPipeNetNode node, long overflow) { TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); if (logic != null) { // this occurs after finalization but before path reset. @@ -114,15 +114,14 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl destination.getGroupSafe().getData() instanceof EnergyGroupData data) { data.addEnergyOutPerSec(accepted * pathVoltage, getQueryTick()); } - if (accepted > 0) recordFlow(destination, accepted); return accepted; } @Override - public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, + public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { - super.consumeFlowLimit(edge, sourceNode, targetNode, consumption); - if (consumption > 0) recordFlow(sourceNode, consumption); + super.consumeFlowLimit(edge, targetNode, consumption); + if (consumption > 0) recordFlow(targetNode, consumption); } private void recordFlow(@NotNull NetNode node, long amperes) { diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index f7132209dd1..c3ef8072e92 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -38,6 +38,7 @@ public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandl private @Nullable PipeTileEntity tile; private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); + private final WorldPipeNetNode node; private final IFluidTankProperties[] properties; private boolean transferring = false; @@ -45,6 +46,7 @@ public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandl public FluidCapabilityObject(@NotNull N net, WorldPipeNetNode node) { this.net = net; + this.node = node; properties = new IFluidTankProperties[node.getData().getLogicEntryDefaultable(ChannelCountLogic.INSTANCE) .getValue()]; Arrays.fill(properties, this); @@ -101,6 +103,7 @@ public int fill(FluidStack resource, boolean doFill, EnumFacing side) { var guide = getGuide(FluidTraverseData::new, new FluidTestObject(resource), resource.amount, !doFill, side); if (guide == null) return 0; int accepted = (int) TraverseHelpers.traverseFlood(guide.getData(), guide.getPaths(), guide.getFlow()); + guide.reportConsumedFlow(accepted); this.transferring = false; return accepted; @@ -126,6 +129,7 @@ D extends ITraverseData> TraverseGuide> TraverseGuide internalBuffer.consumeFlowLimit(testObject, net, l, tick, simulator); + flowReport = l -> data.consumeFlowLimit(internalBuffer, node, l); } } - D data = provider.of(net, testObject, simulator, tick, tile.getPos(), side); return new TraverseGuide<>(data, () -> getPaths(data), flow, flowReport); } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java index 19a5fc561cb..5641537e177 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java @@ -12,6 +12,7 @@ import net.minecraft.util.ResourceLocation; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -24,6 +25,8 @@ public final class FluidContainmentLogic extends NetLogicEntry containableAttributes = new ObjectOpenHashSet<>(); private @NotNull EnumSet containableStates = EnumSet.noneOf(FluidState.class); @@ -31,31 +34,38 @@ public FluidContainmentLogic() { super("FluidContainment"); } - public FluidContainmentLogic getWith(Collection states, Collection attributes) { + public @NotNull FluidContainmentLogic getWith(Collection states, + @NotNull Collection attributes, + int maximumTemperature) { FluidContainmentLogic logic = getNew(); logic.containableStates.addAll(states); for (FluidAttribute attribute : attributes) { logic.contain(attribute); } + logic.maximumTemperature = maximumTemperature; return logic; } + @Contract("_ -> this") public FluidContainmentLogic contain(FluidState state) { this.containableStates.add(state); return this; } - public FluidContainmentLogic contain(FluidAttribute attribute) { + @Contract("_ -> this") + public FluidContainmentLogic contain(@NotNull FluidAttribute attribute) { this.containableAttributes.add(attribute.getResourceLocation()); return this; } + @Contract("_ -> this") public FluidContainmentLogic notContain(FluidState state) { this.containableStates.remove(state); return this; } - public FluidContainmentLogic notContain(FluidAttribute attribute) { + @Contract("_ -> this") + public FluidContainmentLogic notContain(@NotNull FluidAttribute attribute) { this.containableAttributes.remove(attribute.getResourceLocation()); return this; } @@ -64,10 +74,18 @@ public boolean contains(FluidState state) { return this.containableStates.contains(state); } - public boolean contains(FluidAttribute attribute) { + public boolean contains(@NotNull FluidAttribute attribute) { return this.containableAttributes.contains(attribute.getResourceLocation()); } + public void setMaximumTemperature(int maximumTemperature) { + this.maximumTemperature = maximumTemperature; + } + + public int getMaximumTemperature() { + return maximumTemperature; + } + @Override public @Nullable FluidContainmentLogic union(NetLogicEntry other) { if (other instanceof FluidContainmentLogic logic) { diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java index 1a818f64ee2..260c4de33d4 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java @@ -58,8 +58,6 @@ public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData {}).accept(accepted); - return accepted; + return flowReachingDestination - availableFlow; } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index be18bbad203..39c787aa2dd 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -28,14 +28,14 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.function.LongConsumer; +import java.util.Collection; public class FluidTraverseData extends AbstractTraverseData { - public static final float TEMPERATURE_EFFECT = 0.005f; + public static final float TEMPERATURE_EFFECT = 0.05f; static { ContainmentFailure.init(); @@ -44,13 +44,24 @@ public class FluidTraverseData extends AbstractTraverseData temperatureUpdates = new Object2ObjectOpenHashMap<>(); + protected final FluidStack stack; + protected final FluidState state; + protected final int fluidTemp; + protected final boolean gaseous; + protected final @Nullable Collection attributes; public FluidTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { super(net, testObject, simulator, queryTick); this.sourcePos = sourcePos; this.inputFacing = inputFacing; + this.stack = testObject.recombine(); + this.state = FluidState.inferState(stack); + this.fluidTemp = stack.getFluid().getTemperature(stack); + this.gaseous = stack.getFluid().isGaseous(stack); + if (stack.getFluid() instanceof AttributedFluid at) { + attributes = at.getAttributes(); + } else attributes = null; } @Override @@ -60,10 +71,7 @@ public FluidTestObject getTestObject() { @Override public boolean prepareForPathWalk(@NotNull FlowWorldPipeNetPath path, long flow) { - if (flow <= 0) return true; - temperatureUpdates.clear(); - temperatureUpdates.trim(16); - return false; + return flow <= 0; } @Override @@ -73,22 +81,16 @@ public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, lon if (result != null) { return result.getLossFunction(); } else { - FluidStack stack = getTestObject().recombine(); FluidContainmentLogic containmentLogic = node.getData() .getLogicEntryDefaultable(FluidContainmentLogic.INSTANCE); - FluidState state = FluidState.inferState(stack); TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); if (temperatureLogic != null) { result = temperatureLogic.getLossResult(getQueryTick()); - int fluidTemp = stack.getFluid().getTemperature(stack); - boolean gaseous = stack.getFluid().isGaseous(stack); - // prevent plasmas from melting valid pipes due to raw temperature - boolean temperatureSafe = state == FluidState.PLASMA && containmentLogic.contains(FluidState.PLASMA); - temperatureUpdates.put(node, l -> temperatureLogic.moveTowardsTemperature(fluidTemp, getQueryTick(), - l * TEMPERATURE_EFFECT, temperatureSafe)); - if (temperatureLogic.isUnderMinimum(fluidTemp)) { - result = NodeLossResult.combine(result, new NodeLossResult(pipe -> { + boolean overMax = fluidTemp > containmentLogic.getMaximumTemperature() && + !(state == FluidState.PLASMA && containmentLogic.contains(FluidState.PLASMA)); + if (overMax) { + result = NodeLossResult.combine(result, new NodeLossResult(GTValues.RNG.nextInt(4) == 0 ? pipe -> { IWorldPipeNetTile tile = pipe.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); @@ -96,10 +98,9 @@ public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, lon tile.dealAreaDamage(gaseous ? 2 : 1, entity -> EntityDamageUtil.applyTemperatureDamage(entity, fluidTemp, 2.0F, 10)); + tile.setNeighborsToFire(); } - }, MultLossOperator.EIGHTHS[2])); - } else if (temperatureLogic.isOverMaximum(fluidTemp)) { - result = NodeLossResult.combine(result, new NodeLossResult(GTValues.RNG.nextInt(4) == 0 ? pipe -> { + } : pipe -> { IWorldPipeNetTile tile = pipe.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); @@ -107,9 +108,10 @@ public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, lon tile.dealAreaDamage(gaseous ? 2 : 1, entity -> EntityDamageUtil.applyTemperatureDamage(entity, fluidTemp, 2.0F, 10)); - tile.setNeighborsToFire(); } - } : pipe -> { + }, MultLossOperator.EIGHTHS[2])); + } else if (temperatureLogic.isUnderMinimum(fluidTemp)) { + result = NodeLossResult.combine(result, new NodeLossResult(pipe -> { IWorldPipeNetTile tile = pipe.getTileEntityNoLoading(); if (tile != null) { tile.playLossSound(); @@ -126,8 +128,8 @@ public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, lon result = NodeLossResult.combine(result, ContainmentFailure.getFailure(state).computeLossResult(stack)); } - if (stack instanceof AttributedFluid fluid) { - for (FluidAttribute attribute : fluid.getAttributes()) { + if (attributes != null) { + for (FluidAttribute attribute : attributes) { if (!containmentLogic.contains(attribute)) { result = NodeLossResult.combine(result, ContainmentFailure.getFailure(attribute).computeLossResult(stack)); @@ -157,15 +159,21 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl (int) Math.min(Integer.MAX_VALUE, availableFlow), container, getSimulatorKey() == null); } } - long accepted = flowReachingDestination - availableFlow; - temperatureUpdates.getOrDefault(destination, l -> {}).accept(accepted); - return accepted; + return flowReachingDestination - availableFlow; } @Override - public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode sourceNode, NetNode targetNode, + public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { - super.consumeFlowLimit(edge, sourceNode, targetNode, consumption); - temperatureUpdates.getOrDefault(sourceNode, l -> {}).accept(consumption); + super.consumeFlowLimit(edge, targetNode, consumption); + TemperatureLogic temperatureLogic = targetNode.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + if (temperatureLogic != null) { + FluidContainmentLogic containmentLogic = targetNode.getData() + .getLogicEntryDefaultable(FluidContainmentLogic.INSTANCE); + boolean overMax = fluidTemp > containmentLogic.getMaximumTemperature() && + !(state == FluidState.PLASMA && containmentLogic.contains(FluidState.PLASMA)); + temperatureLogic.moveTowardsTemperature(fluidTemp, + getQueryTick(), consumption * TEMPERATURE_EFFECT, !overMax); + } } } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index 755adb97a8b..522729b7f8f 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -34,12 +34,14 @@ public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler private @Nullable PipeTileEntity tile; private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); + private final WorldPipeNetNode node; private boolean transferring = false; public ItemCapabilityObject(@NotNull N net, WorldPipeNetNode node) { this.net = net; + this.node = node; for (EnumFacing facing : EnumFacing.VALUES) { AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); edge.setData(NetLogicData.union(node.getData(), (NetLogicData) null)); @@ -116,6 +118,7 @@ D extends ITraverseData> TraverseGuide> TraverseGuide internalBuffer.consumeFlowLimit(testObject, net, l, tick, simulator); + flowReport = l -> data.consumeFlowLimit(internalBuffer, node, l); } } - D data = provider.of(net, testObject, simulator, tick, tile.getPos(), side); return new TraverseGuide<>(data, () -> getPaths(data), flow, flowReport); } diff --git a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java index 7a59679d7d1..67c86b81532 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java @@ -239,9 +239,9 @@ public CTMaterialBuilder ingotSmeltInto(Material m) { } @ZenMethod - public CTMaterialBuilder cableProperties(long voltage, int amperage, int loss, @Optional int meltTemperature, + public CTMaterialBuilder cableProperties(long voltage, int amperage, int loss, @Optional int superConTemperature) { - backingBuilder.cableProperties(voltage, amperage, loss, meltTemperature, superConTemperature); + backingBuilder.cableProperties(voltage, amperage, loss, superConTemperature); return this; } diff --git a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java index 4e1f9b3a34f..d27118d708a 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java @@ -259,14 +259,14 @@ public static void addItemPipes(Material m, int priority, float transferRate) { @ZenMethod public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock, - @Optional int meltTemperature, @Optional int superconductorTemp) { + @Optional int superconductorTemp) { if (checkFrozen("add Wires to a material")) return; PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); if (properties == null) { properties = new PipeNetProperties(); m.setProperty(PropertyKey.PIPENET_PROPERTIES, properties); } - properties.setProperty(new MaterialEnergyProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, + properties.setProperty(MaterialEnergyProperties.create(voltage, baseAmperage, lossPerBlock, superconductorTemp)); } } diff --git a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java index 898168557a6..beb2883b791 100644 --- a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java @@ -334,11 +334,7 @@ public static void addWires(Material m, long voltage, long baseAmperage, long lo addWires(m, voltage, baseAmperage, lossPerBlock, 0); } - public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock, int meltTemperature) { - addWires(m, voltage, baseAmperage, lossPerBlock, meltTemperature, 0); - } - - public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock, int meltTemperature, + public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock, int superconductorTemp) { if (checkFrozen("add Wires to a material")) return; PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); @@ -346,7 +342,7 @@ public static void addWires(Material m, long voltage, long baseAmperage, long lo properties = new PipeNetProperties(); m.setProperty(PropertyKey.PIPENET_PROPERTIES, properties); } - properties.setProperty(new MaterialEnergyProperties(voltage, baseAmperage, lossPerBlock, meltTemperature, + properties.setProperty(MaterialEnergyProperties.create(voltage, baseAmperage, lossPerBlock, superconductorTemp)); } @@ -354,12 +350,8 @@ public static void addCables(Material m, long voltage, long baseAmperage, long l addWires(m, voltage, baseAmperage, lossPerBlock); } - public static void addCables(Material m, long voltage, long baseAmperage, long lossPerBlock, int meltTemperature) { - addWires(m, voltage, baseAmperage, lossPerBlock, meltTemperature); - } - - public static void addCables(Material m, int voltage, int baseAmperage, int lossPerBlock, int meltTemperature, + public static void addCables(Material m, int voltage, int baseAmperage, int lossPerBlock, int superconductorTemp) { - addWires(m, voltage, baseAmperage, lossPerBlock, meltTemperature, superconductorTemp); + addWires(m, voltage, baseAmperage, lossPerBlock, superconductorTemp); } } From fbdb32d4e62d5008164d7bb9209c888151ff5da3 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 21 Aug 2024 12:46:35 -0600 Subject: [PATCH 106/157] Add misc. frame logic --- .../pipenet/physical/block/PipeBlock.java | 37 ++++++++++--------- .../gregtech/common/blocks/BlockFrame.java | 12 ++++-- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 429158f8bf7..fc7e091cbaa 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -46,7 +46,6 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.NonNullList; -import net.minecraft.util.SoundCategory; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; @@ -148,18 +147,10 @@ public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @ ItemStack item = playerIn.getHeldItem(hand); PipeTileEntity tile = getTileEntity(worldIn, pos); if (tile != null) { - if (tile.getFrameMaterial() == null) { - BlockFrame frame = BlockFrame.getFrameBlockFromItem(item); - if (frame != null) { - tile.setFrameMaterial(frame.getGtMaterial(item)); - SoundType type = frame.getSoundType(item); - worldIn.playSound(playerIn, pos, type.getPlaceSound(), SoundCategory.BLOCKS, - (type.getVolume() + 1.0F) / 2.0F, type.getPitch() * 0.8F); - if (!playerIn.capabilities.isCreativeMode) { - item.shrink(1); - } - return true; - } + BlockFrame frame = BlockFrame.getFrameBlockFromItem(item); + if (frame != null) { + if (playerIn.isSneaking()) return false; + return BlockFrame.runPlacementLogic(frame, pos, worldIn, item, playerIn); } RayTraceAABB trace = collisionRayTrace(playerIn, worldIn, pos); @@ -209,10 +200,10 @@ public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @ if (result == EnumActionResult.FAIL) return false; } // frame removal - Material frame = tile.getFrameMaterial(); - if (frame != null && ToolHelper.isTool(item, ToolClasses.CROWBAR)) { + Material frameMaterial = tile.getFrameMaterial(); + if (frameMaterial != null && ToolHelper.isTool(item, ToolClasses.CROWBAR)) { tile.setFrameMaterial(null); - spawnAsEntity(worldIn, pos, MetaBlocks.FRAMES.get(frame).getItem(frame)); + spawnAsEntity(worldIn, pos, MetaBlocks.FRAMES.get(frameMaterial).getItem(frameMaterial)); ToolHelper.damageItem(item, playerIn); ToolHelper.playToolSound(item, playerIn); return true; @@ -433,9 +424,19 @@ public boolean canCreatureSpawn(@NotNull IBlockState state, @NotNull IBlockAcces @Override public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state, @NotNull Entity entityIn) { - if (worldIn.isRemote || !(entityIn instanceof EntityLivingBase living)) return; PipeTileEntity tile = getTileEntity(worldIn, pos); - if (tile != null && tile.getFrameMaterial() == null && tile.getOffsetTimer() % 10 == 0) { + if (tile == null) return; + if (tile.getFrameMaterial() != null) { + BlockFrame frame = MetaBlocks.FRAMES.get(tile.getFrameMaterial()); + if (frame == null) { + tile.setFrameMaterial(null); + return; + } + frame.onEntityCollision(worldIn, pos, state, entityIn); + return; + } + if (worldIn.isRemote || !(entityIn instanceof EntityLivingBase living)) return; + if (tile.getOffsetTimer() % 10 == 0) { TemperatureLogic logic = tile.getTemperatureLogic(); if (logic != null) { long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); diff --git a/src/main/java/gregtech/common/blocks/BlockFrame.java b/src/main/java/gregtech/common/blocks/BlockFrame.java index 192ef3f4bf2..dc25f148126 100644 --- a/src/main/java/gregtech/common/blocks/BlockFrame.java +++ b/src/main/java/gregtech/common/blocks/BlockFrame.java @@ -177,6 +177,11 @@ public boolean onBlockActivated(@NotNull World world, @NotNull BlockPos pos, @No BlockFrame frameBlock = getFrameBlockFromItem(stack); if (frameBlock == null) return false; + return runPlacementLogic(frameBlock, pos, world, stack, player); + } + + public static boolean runPlacementLogic(@NotNull BlockFrame frameBlock, @NotNull BlockPos pos, @NotNull World world, + @NotNull ItemStack stack, @NotNull EntityPlayer player) { BlockPos.PooledMutableBlockPos blockPos = BlockPos.PooledMutableBlockPos.retain(); blockPos.setPos(pos); for (int i = 0; i < 32; i++) { @@ -187,13 +192,12 @@ public boolean onBlockActivated(@NotNull World world, @NotNull BlockPos pos, @No TileEntity te = world.getTileEntity(blockPos); if (te instanceof PipeTileEntity tile && tile.getFrameMaterial() != null) { blockPos.move(EnumFacing.UP); - te = world.getTileEntity(blockPos); continue; } - if (canPlaceBlockAt(world, blockPos)) { + if (frameBlock.canPlaceBlockAt(world, blockPos)) { world.setBlockState(blockPos, frameBlock.getStateFromMeta(stack.getItem().getMetadata(stack.getItemDamage()))); - SoundType type = getSoundType(stack); + SoundType type = frameBlock.getSoundType(stack); world.playSound(null, pos, type.getPlaceSound(), SoundCategory.BLOCKS, (type.getVolume() + 1.0F) / 2.0F, type.getPitch() * 0.8F); if (!player.capabilities.isCreativeMode) { @@ -203,7 +207,7 @@ public boolean onBlockActivated(@NotNull World world, @NotNull BlockPos pos, @No return true; } else if (te instanceof PipeTileEntity tile && tile.getFrameMaterial() == null) { tile.setFrameMaterial(frameBlock.getGtMaterial(stack)); - SoundType type = getSoundType(stack); + SoundType type = frameBlock.getSoundType(stack); world.playSound(null, pos, type.getPlaceSound(), SoundCategory.BLOCKS, (type.getVolume() + 1.0F) / 2.0F, type.getPitch() * 0.8F); if (!player.capabilities.isCreativeMode) { From bdb51f340fe2c1518c92bad9e733a6d84d60043a Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 23 Aug 2024 12:40:43 -0600 Subject: [PATCH 107/157] Better weak sets --- .../api/capability/data/IDataAccess.java | 4 +- .../api/graphnet/pipenet/WorldPipeNet.java | 7 +- .../java/gregtech/api/util/GTUtility.java | 8 -- .../reference/ExpiringReferenceHashSet.java | 114 ++++++++++++++++++ .../api/util/reference/SoftHashSet.java | 46 +++++++ .../api/util/reference/WeakHashSet.java | 46 +++++++ .../MetaTileEntityComputationHatch.java | 11 +- .../MetaTileEntityOpticalDataHatch.java | 11 +- .../net/optical/DataCapabilityObject.java | 6 - 9 files changed, 228 insertions(+), 25 deletions(-) create mode 100644 src/main/java/gregtech/api/util/reference/ExpiringReferenceHashSet.java create mode 100644 src/main/java/gregtech/api/util/reference/SoftHashSet.java create mode 100644 src/main/java/gregtech/api/util/reference/WeakHashSet.java diff --git a/src/main/java/gregtech/api/capability/data/IDataAccess.java b/src/main/java/gregtech/api/capability/data/IDataAccess.java index c6599e6a87a..67b6a9a507b 100644 --- a/src/main/java/gregtech/api/capability/data/IDataAccess.java +++ b/src/main/java/gregtech/api/capability/data/IDataAccess.java @@ -10,8 +10,8 @@ public interface IDataAccess { /** * Queries this {@link IDataAccess} with the specified query. * - * @param queryObject the object representing the query. Can be cached in a weak set created by - * {@link gregtech.api.util.GTUtility#createWeakHashSet()} in order to prevent endless recursion. + * @param queryObject the object representing the query. Can be cached in a + * {@link gregtech.api.util.reference.WeakHashSet} in order to prevent endless recursion. * @return if the query has been cancelled */ boolean accessData(@NotNull DataQueryObject queryObject); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 8d45d8652e6..09c1de55427 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -11,8 +11,8 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.EdgePredicate; import gregtech.api.graphnet.worldnet.WorldNet; -import gregtech.api.util.GTUtility; import gregtech.api.util.IDirtyNotifiable; +import gregtech.api.util.reference.WeakHashSet; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -20,6 +20,7 @@ import net.minecraftforge.common.capabilities.Capability; import it.unimi.dsi.fastutil.Hash; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.Contract; @@ -37,7 +38,7 @@ public abstract class WorldPipeNet extends WorldNet { public static final int MULTI_NET_TIMEOUT = 10; - private static final Object2ObjectOpenHashMap> dimensionNets = new Object2ObjectOpenHashMap<>(); + private static final Int2ObjectOpenHashMap> dimensionNets = new Int2ObjectOpenHashMap<>(); public WorldPipeNet(String name, Function graphBuilder, AlgorithmBuilder... algorithmBuilders) { @@ -53,7 +54,7 @@ public void setWorld(World world) { if (getWorld() == world) return; super.setWorld(world); dimensionNets.compute(getDimension(), (k, v) -> { - if (v == null) v = GTUtility.createWeakHashSet(); + if (v == null) v = new WeakHashSet<>(); v.add(this); return v; }); diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 7e9867335c4..73b3f841a04 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -67,7 +67,6 @@ import java.util.AbstractList; import java.util.ArrayList; import java.util.BitSet; -import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Map; @@ -75,7 +74,6 @@ import java.util.Objects; import java.util.Random; import java.util.Set; -import java.util.WeakHashMap; import java.util.function.BooleanSupplier; import java.util.function.DoubleSupplier; import java.util.function.Function; @@ -981,12 +979,6 @@ public static BitSet setToMask(@NotNull EnumSet enumSet) { return mask; } - @Contract(pure = true, value = "-> new") - @NotNull - public static Set createWeakHashSet() { - return Collections.newSetFromMap(new WeakHashMap<>()); - } - /** * Forces the initialization of a class; this includes things like loading its static fields. * This can be useful because a statement like {@code AClass.class} does not initialize a class. diff --git a/src/main/java/gregtech/api/util/reference/ExpiringReferenceHashSet.java b/src/main/java/gregtech/api/util/reference/ExpiringReferenceHashSet.java new file mode 100644 index 00000000000..d0be91f036c --- /dev/null +++ b/src/main/java/gregtech/api/util/reference/ExpiringReferenceHashSet.java @@ -0,0 +1,114 @@ +package gregtech.api.util.reference; + +import it.unimi.dsi.fastutil.objects.AbstractObjectIterator; +import it.unimi.dsi.fastutil.objects.AbstractObjectSet; +import it.unimi.dsi.fastutil.objects.ObjectIterator; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.Nullable; + +public abstract class ExpiringReferenceHashSet extends AbstractObjectSet { + + private final ObjectOpenHashSet> backer = new ObjectOpenHashSet<>(); + + @Override + public int size() { + return backer.size(); + } + + @Override + public boolean isEmpty() { + return backer.isEmpty(); + } + + @Override + public boolean contains(Object o) { + // noinspection unchecked + return backer.contains(wrapObject((T) o)); + } + + @Override + public ObjectIterator iterator() { + return new SetIterator(); + } + + @Override + public boolean add(T t) { + return backer.add(wrapObject(t)); + } + + public void clearStaleEntries() { + // iteration automatically removes stale entries. + // noinspection StatementWithEmptyBody + for (T ignored : this); + } + + /** + * Clears stale entries and then performs {@link ObjectOpenHashSet#trim()} + */ + public void trim() { + clearStaleEntries(); + backer.trim(); + } + + /** + * Clears stale entries and then performs {@link ObjectOpenHashSet#trim(int)} + */ + public void trim(final int n) { + clearStaleEntries(); + backer.trim(n); + } + + protected abstract ExpiringReference wrapObject(T obj); + + /** + * Implementations must override equals() and hashCode() with calls to their referenced object. + * If expired, return false or 0. + */ + protected interface ExpiringReference { + + @Nullable + T get(); + + default boolean expired() { + return get() == null; + } + } + + protected class SetIterator extends AbstractObjectIterator { + + protected final ObjectIterator> backer = ExpiringReferenceHashSet.this.backer.iterator(); + + protected T next; + + @Override + public boolean hasNext() { + if (!backer.hasNext()) return false; + if (this.next == null) computeNext(); + return this.next != null; + } + + @Override + public T next() { + if (this.next == null) computeNext(); + T next = this.next; + this.next = null; + return next; + } + + protected void computeNext() { + while (true) { + ExpiringReference ref = backer.next(); + this.next = ref.get(); + if (ref.expired()) { + backer.remove(); + } else break; + if (!backer.hasNext()) break; + } + } + + @Override + public void remove() { + backer.remove(); + } + } +} diff --git a/src/main/java/gregtech/api/util/reference/SoftHashSet.java b/src/main/java/gregtech/api/util/reference/SoftHashSet.java new file mode 100644 index 00000000000..a585188754f --- /dev/null +++ b/src/main/java/gregtech/api/util/reference/SoftHashSet.java @@ -0,0 +1,46 @@ +package gregtech.api.util.reference; + +import java.lang.ref.SoftReference; +import java.util.Objects; + +public class SoftHashSet extends ExpiringReferenceHashSet { + + @Override + protected ExpiringReference wrapObject(T obj) { + return new Reference(obj); + } + + protected class Reference extends SoftReference implements ExpiringReference { + + public Reference(T referent) { + super(referent); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + Reference that; + try { + // noinspection unchecked + that = (Reference) obj; + } catch (ClassCastException e) { + return false; + } + + T contained = this.get(); + T other = that.get(); + if (this.expired() || that.expired()) return false; + return Objects.equals(contained, other); + } + + @Override + public int hashCode() { + T contained = this.get(); + if (contained == null) { + return 0; + } + return contained.hashCode(); + } + } +} diff --git a/src/main/java/gregtech/api/util/reference/WeakHashSet.java b/src/main/java/gregtech/api/util/reference/WeakHashSet.java new file mode 100644 index 00000000000..110cb559f2f --- /dev/null +++ b/src/main/java/gregtech/api/util/reference/WeakHashSet.java @@ -0,0 +1,46 @@ +package gregtech.api.util.reference; + +import java.lang.ref.WeakReference; +import java.util.Objects; + +public class WeakHashSet extends ExpiringReferenceHashSet { + + @Override + protected ExpiringReference wrapObject(T obj) { + return new Reference(obj); + } + + protected class Reference extends WeakReference implements ExpiringReference { + + public Reference(T referent) { + super(referent); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + Reference that; + try { + // noinspection unchecked + that = (Reference) obj; + } catch (ClassCastException e) { + return false; + } + + T contained = this.get(); + T other = that.get(); + if (this.expired() || that.expired()) return false; + return Objects.equals(contained, other); + } + + @Override + public int hashCode() { + T contained = this.get(); + if (contained == null || this.expired()) { + return 0; + } + return contained.hashCode(); + } + } +} diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java index da8168e86e5..a95a2501969 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java @@ -13,7 +13,7 @@ import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; -import gregtech.api.util.GTUtility; +import gregtech.api.util.reference.WeakHashSet; import gregtech.client.renderer.texture.Textures; import net.minecraft.client.resources.I18n; @@ -31,7 +31,6 @@ import org.jetbrains.annotations.Nullable; import java.util.List; -import java.util.Set; public class MetaTileEntityComputationHatch extends MetaTileEntityMultiblockPart implements IMultiblockAbilityPart, @@ -39,7 +38,7 @@ public class MetaTileEntityComputationHatch extends MetaTileEntityMultiblockPart private final boolean isTransmitter; - private final Set recentQueries = GTUtility.createWeakHashSet(); + private final WeakHashSet recentQueries = new WeakHashSet<>(); public MetaTileEntityComputationHatch(ResourceLocation metaTileEntityId, boolean isTransmitter) { super(metaTileEntityId, GTValues.ZPM); @@ -51,6 +50,12 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { return new MetaTileEntityComputationHatch(metaTileEntityId, isTransmitter); } + @Override + public void update() { + super.update(); + if (getOffsetTimer() % 20 == 0) recentQueries.trim(); + } + @Override public boolean isTransmitter() { return this.isTransmitter; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java index 5161b1a0356..2785e96795a 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java @@ -11,7 +11,7 @@ import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; -import gregtech.api.util.GTUtility; +import gregtech.api.util.reference.WeakHashSet; import gregtech.client.renderer.texture.Textures; import net.minecraft.client.resources.I18n; @@ -29,13 +29,12 @@ import org.jetbrains.annotations.Nullable; import java.util.List; -import java.util.Set; public class MetaTileEntityOpticalDataHatch extends MetaTileEntityMultiblockNotifiablePart implements IMultiblockAbilityPart, IStandardDataAccess { - private final Set recentQueries = GTUtility.createWeakHashSet(); + private final WeakHashSet recentQueries = new WeakHashSet<>(); private final boolean isTransmitter; @@ -49,6 +48,12 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { return new MetaTileEntityOpticalDataHatch(metaTileEntityId, this.isTransmitter); } + @Override + public void update() { + super.update(); + if (getOffsetTimer() % 20 == 0) recentQueries.trim(); + } + @Override protected boolean openGUIOnRightClick() { return false; diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index 87f2fc85524..d0ecd136e62 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -10,7 +10,6 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.api.util.GTUtility; import gregtech.common.pipelike.net.SlowActiveWalker; import net.minecraft.util.EnumFacing; @@ -21,7 +20,6 @@ import org.jetbrains.annotations.Nullable; import java.util.Iterator; -import java.util.Set; public class DataCapabilityObject implements IPipeCapabilityObject, IDataAccess { @@ -29,8 +27,6 @@ public class DataCapabilityObject implements IPipeCapabilityObject, IDataAccess private @Nullable PipeTileEntity tile; - private final Set recentQueries = GTUtility.createWeakHashSet(); - public DataCapabilityObject(@NotNull N net) { this.net = net; } @@ -47,8 +43,6 @@ public void setTile(@Nullable PipeTileEntity tile) { @Override public boolean accessData(@NotNull DataQueryObject queryObject) { if (tile == null) return false; - // if the add call fails (because the object already exists in the set) then do not recurse - if (!recentQueries.add(queryObject)) return false; for (Iterator it = getPaths(); it.hasNext();) { BasicWorldPipeNetPath path = it.next(); From b886cf1a64f53bc912d4e6be084a7def5099ed4c Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 23 Aug 2024 17:01:18 -0600 Subject: [PATCH 108/157] New model registry --- .../pipenet/physical/IPipeStructure.java | 4 +- ...eBlock.java => ItemPipeMaterialBlock.java} | 4 +- .../pipenet/physical/block/PipeBlock.java | 4 +- .../physical/block/PipeMaterialBlock.java | 6 + .../pipenet/physical/tile/PipeTileEntity.java | 5 - .../java/gregtech/client/ClientProxy.java | 8 +- .../renderer/pipe/AbstractPipeModel.java | 78 ++---- .../renderer/pipe/ActivablePipeModel.java | 38 +-- .../client/renderer/pipe/CableModel.java | 40 +--- .../client/renderer/pipe/PipeItemModel.java | 13 +- .../client/renderer/pipe/PipeModel.java | 103 ++------ .../renderer/pipe/PipeModelRedirector.java | 120 ++++++++++ .../renderer/pipe/PipeModelRegistry.java | 223 ++++++++++++++++++ .../pipe/util/MaterialModelOverride.java | 28 +++ .../pipe/util/MaterialModelSupplier.java | 14 ++ .../pipe/util/PipeSpriteWoodClarifier.java | 11 - .../renderer/pipe/util/WoodCacheKey.java | 58 ----- .../client/renderer/texture/Textures.java | 4 +- .../java/gregtech/common/CommonProxy.java | 6 +- .../pipelike/block/cable/CableBlock.java | 2 +- .../pipelike/block/cable/CableStructure.java | 50 ++-- .../pipelike/block/laser/LaserStructure.java | 21 +- .../block/optical/OpticalStructure.java | 19 +- .../block/pipe/MaterialPipeBlock.java | 5 + .../block/pipe/MaterialPipeStructure.java | 78 ++---- 25 files changed, 530 insertions(+), 412 deletions(-) rename src/main/java/gregtech/api/graphnet/pipenet/physical/block/{ItemMaterialPipeBlock.java => ItemPipeMaterialBlock.java} (86%) create mode 100644 src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/util/MaterialModelOverride.java create mode 100644 src/main/java/gregtech/client/renderer/pipe/util/MaterialModelSupplier.java delete mode 100644 src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java delete mode 100644 src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java index 84948da43dc..e047314f99a 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.pipenet.physical; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.client.renderer.pipe.AbstractPipeModel; +import gregtech.client.renderer.pipe.PipeModelRedirector; import net.minecraft.util.EnumFacing; import net.minecraft.util.IStringSerializable; @@ -24,7 +24,7 @@ public interface IPipeStructure extends IStringSerializable { boolean isPaintable(); - AbstractPipeModel getModel(); + PipeModelRedirector getModel(); /** * Allows for controlling what sides can be connected to based on current connections, diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemMaterialPipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeMaterialBlock.java similarity index 86% rename from src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemMaterialPipeBlock.java rename to src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeMaterialBlock.java index 2016a779e5f..328fbf5cf4b 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemMaterialPipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/ItemPipeMaterialBlock.java @@ -6,9 +6,9 @@ import org.jetbrains.annotations.NotNull; -public class ItemMaterialPipeBlock extends ItemPipeBlock { +public class ItemPipeMaterialBlock extends ItemPipeBlock { - public ItemMaterialPipeBlock(PipeMaterialBlock block) { + public ItemPipeMaterialBlock(PipeMaterialBlock block) { super(block); setHasSubtypes(true); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index fc7e091cbaa..816142bbcf9 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -460,9 +460,7 @@ public boolean recolorBlock(@NotNull World world, @NotNull BlockPos pos, @NotNul @Override public boolean canRenderInLayer(@NotNull IBlockState state, @NotNull BlockRenderLayer layer) { - // guaranteed cutout & bloom for covers - return layer == BlockRenderLayer.CUTOUT_MIPPED || layer == BloomEffectUtil.getEffectiveBloomLayer() || - getStructure().getModel().canRenderInLayer(layer); + return layer == BlockRenderLayer.CUTOUT_MIPPED || layer == BloomEffectUtil.getEffectiveBloomLayer(); } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index 8be23ce16dc..88ac5ebb8ca 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -43,6 +43,12 @@ public PipeMaterialBlock(IPipeMaterialStructure structure, MaterialRegistry regi this.registry = registry; } + @Nullable + public static PipeMaterialBlock getBlockFromItem(@NotNull ItemStack stack) { + if (stack.getItem() instanceof ItemPipeMaterialBlock block) return block.getBlock(); + else return null; + } + @Override public void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList items) { for (Material material : registry) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 8927402f738..41e52ec88f6 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -487,16 +487,11 @@ protected void initialize() { firstNode = false; this.temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); } - // TODO - // this and updateActiveStatus() theoretically only need to be called when loading old world data; - // is there a way to detect that and skip if so? - node.getNet().updatePredication(node, this); } this.netLogicDatas.trim(); this.listeners.trim(); this.capabilities.trim(); this.netCapabilities.trim(); - updateActiveStatus(null, false); } } diff --git a/src/main/java/gregtech/client/ClientProxy.java b/src/main/java/gregtech/client/ClientProxy.java index 4f406755bc7..46b5f50081a 100644 --- a/src/main/java/gregtech/client/ClientProxy.java +++ b/src/main/java/gregtech/client/ClientProxy.java @@ -15,9 +15,7 @@ import gregtech.client.model.customtexture.MetadataSectionCTM; import gregtech.client.renderer.handler.FacadeRenderer; import gregtech.client.renderer.handler.MetaTileEntityRenderer; -import gregtech.client.renderer.pipe.ActivablePipeModel; -import gregtech.client.renderer.pipe.CableModel; -import gregtech.client.renderer.pipe.PipeModel; +import gregtech.client.renderer.pipe.PipeModelRegistry; import gregtech.client.utils.ItemRenderCompat; import gregtech.client.utils.TooltipHelper; import gregtech.common.CommonProxy; @@ -110,9 +108,7 @@ public static void registerColors() { @SubscribeEvent public static void registerBakedModels(ModelBakeEvent event) { - PipeModel.registerModels(event.getModelRegistry()); - CableModel.registerModels(event.getModelRegistry()); - ActivablePipeModel.registerModels(event.getModelRegistry()); + PipeModelRegistry.registerModels(event.getModelRegistry()); } @SubscribeEvent diff --git a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java index 5aab7a1756d..ed7cfb09e27 100644 --- a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java @@ -16,12 +16,8 @@ import gregtech.client.renderer.pipe.util.CacheKey; import gregtech.client.renderer.pipe.util.SpriteInformation; -import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.block.model.IBakedModel; -import net.minecraft.client.renderer.block.model.ItemOverrideList; -import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; @@ -45,7 +41,7 @@ import java.util.List; @SideOnly(Side.CLIENT) -public abstract class AbstractPipeModel implements IBakedModel { +public abstract class AbstractPipeModel { public static UnlistedFloatProperty THICKNESS_PROPERTY = new UnlistedFloatProperty("thickness"); @@ -61,26 +57,19 @@ public abstract class AbstractPipeModel implements IBakedMod protected final Object2ObjectOpenHashMap frameCache = new Object2ObjectOpenHashMap<>(); protected final Object2ObjectOpenHashMap pipeCache = new Object2ObjectOpenHashMap<>(); - private final ModelResourceLocation loc; - - public AbstractPipeModel(ModelResourceLocation loc) { - this.loc = loc; - } - - @Override - public @NotNull List getQuads(IBlockState state, EnumFacing side, long rand) { - if (side == null && state instanceof IExtendedBlockState ext) { + public @NotNull List getQuads(IExtendedBlockState state, EnumFacing side, long rand) { + if (side == null) { List quads; - ColorData data = computeColorData(ext); - CoverRendererPackage rendererPackage = ext.getValue(CoverRendererPackage.PROPERTY); + ColorData data = computeColorData(state); + CoverRendererPackage rendererPackage = state.getValue(CoverRendererPackage.PROPERTY); byte coverMask = rendererPackage == null ? 0 : rendererPackage.getMask(); - if (canRenderInLayer(getCurrentRenderLayer())) { - quads = getQuads(toKey(ext), PipeBlock.readConnectionMask(ext), - safeByte(ext.getValue(CLOSED_MASK_PROPERTY)), safeByte(ext.getValue(BLOCKED_MASK_PROPERTY)), - data, ext.getValue(FRAME_MATERIAL_PROPERTY), - safeByte(ext.getValue(FRAME_MASK_PROPERTY)), coverMask); + if (shouldRenderInLayer(getCurrentRenderLayer())) { + quads = getQuads(toKey(state), PipeBlock.readConnectionMask(state), + safeByte(state.getValue(CLOSED_MASK_PROPERTY)), safeByte(state.getValue(BLOCKED_MASK_PROPERTY)), + data, state.getValue(FRAME_MATERIAL_PROPERTY), + safeByte(state.getValue(FRAME_MASK_PROPERTY)), coverMask); } else quads = new ObjectArrayList<>(); - if (rendererPackage != null) renderCovers(quads, rendererPackage, ext); + if (rendererPackage != null) renderCovers(quads, rendererPackage, state); return quads; } return Collections.emptyList(); @@ -161,54 +150,15 @@ public Pair getParticleTexture(int paintColor, @Nul public abstract SpriteInformation getParticleSprite(@Nullable Material material); - @Override - public boolean isAmbientOcclusion() { - return true; - } - - @Override - public boolean isGui3d() { - return true; - } - - @Override - public boolean isBuiltInRenderer() { - return false; - } - - public ModelResourceLocation getLoc() { - return loc; - } - @Nullable - protected abstract PipeItemModel getItemModel(@NotNull ItemStack stack, World world, EntityLivingBase entity); - - @Override - public @NotNull ItemOverrideList getOverrides() { - return FakeItemOverrideList.INSTANCE; - } + protected abstract PipeItemModel getItemModel(PipeModelRedirector redirector, @NotNull ItemStack stack, + World world, EntityLivingBase entity); - public boolean canRenderInLayer(BlockRenderLayer layer) { + protected boolean shouldRenderInLayer(BlockRenderLayer layer) { return layer == BlockRenderLayer.CUTOUT_MIPPED; } protected static BlockRenderLayer getCurrentRenderLayer() { return MinecraftForgeClient.getRenderLayer(); } - - protected static class FakeItemOverrideList extends ItemOverrideList { - - public static final FakeItemOverrideList INSTANCE = new FakeItemOverrideList(); - - @Override - public @NotNull IBakedModel handleItemState(@NotNull IBakedModel originalModel, @NotNull ItemStack stack, - World world, - EntityLivingBase entity) { - if (originalModel instanceof AbstractPipeModelmodel) { - PipeItemModel item = model.getItemModel(stack, world, entity); - if (item != null) return item; - } - return originalModel; - } - } } diff --git a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java index 1aeb2a2477e..6a3fecb0380 100644 --- a/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/ActivablePipeModel.java @@ -4,27 +4,20 @@ import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.unification.material.Material; -import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.cache.ActivableSQC; import gregtech.client.renderer.pipe.cache.StructureQuadCache; import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; import gregtech.client.renderer.pipe.util.ActivableCacheKey; import gregtech.client.renderer.pipe.util.SpriteInformation; -import gregtech.client.renderer.texture.Textures; import gregtech.client.utils.BloomEffectUtil; import gregtech.client.utils.RenderUtil; import gregtech.common.ConfigHolder; import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.block.model.IBakedModel; -import net.minecraft.client.renderer.block.model.ModelResourceLocation; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; import net.minecraft.util.BlockRenderLayer; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.registry.IRegistry; import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fml.relauncher.Side; @@ -41,17 +34,8 @@ @SideOnly(Side.CLIENT) public class ActivablePipeModel extends AbstractPipeModel { - private static final ResourceLocation loc = GTUtility.gregtechId("block/pipe_activable"); - public static final UnlistedBooleanProperty ACTIVE_PROPERTY = new UnlistedBooleanProperty("active"); - public static final ActivablePipeModel OPTICAL = new ActivablePipeModel(Textures.OPTICAL_PIPE_IN, - Textures.OPTICAL_PIPE_SIDE, Textures.OPTICAL_PIPE_SIDE_OVERLAY, Textures.OPTICAL_PIPE_SIDE_OVERLAY_ACTIVE, - false, "optical"); - public static final ActivablePipeModel LASER = new ActivablePipeModel(Textures.LASER_PIPE_IN, - Textures.LASER_PIPE_SIDE, Textures.LASER_PIPE_OVERLAY, Textures.LASER_PIPE_OVERLAY_EMISSIVE, - true, "laser"); - private final Supplier inTex; private final Supplier sideTex; private final Supplier overlayTex; @@ -61,9 +45,7 @@ public class ActivablePipeModel extends AbstractPipeModel { public ActivablePipeModel(@NotNull Supplier inTex, @NotNull Supplier sideTex, @NotNull Supplier overlayTex, - @NotNull Supplier overlayActiveTex, boolean emissiveActive, - String variant) { - super(new ModelResourceLocation(loc, variant)); + @NotNull Supplier overlayActiveTex, boolean emissiveActive) { this.inTex = inTex; this.sideTex = sideTex; this.overlayTex = overlayTex; @@ -99,11 +81,6 @@ public SpriteInformation getParticleSprite(@Nullable Material material) { return sideTex.get(); } - @Override - public @NotNull TextureAtlasSprite getParticleTexture() { - return getParticleSprite(null).sprite(); - } - @Override protected @NotNull ActivableCacheKey toKey(@NotNull IExtendedBlockState state) { return ActivableCacheKey.of(state.getValue(THICKNESS_PROPERTY), state.getValue(ACTIVE_PROPERTY)); @@ -116,7 +93,7 @@ protected StructureQuadCache constructForKey(ActivableCacheKey key) { } @Override - public boolean canRenderInLayer(BlockRenderLayer layer) { + protected boolean shouldRenderInLayer(BlockRenderLayer layer) { return layer == BlockRenderLayer.CUTOUT_MIPPED || (allowActive() && emissiveActive && layer == BloomEffectUtil.getEffectiveBloomLayer()); } @@ -126,16 +103,13 @@ public boolean allowActive() { } @Override - protected @Nullable PipeItemModel getItemModel(@NotNull ItemStack stack, World world, + protected @Nullable PipeItemModel getItemModel(PipeModelRedirector redirector, + @NotNull ItemStack stack, World world, EntityLivingBase entity) { PipeBlock block = PipeBlock.getBlockFromItem(stack); if (block == null) return null; - return new PipeItemModel<>(this, new ActivableCacheKey(block.getStructure().getRenderThickness(), false), + return new PipeItemModel<>(redirector, this, + new ActivableCacheKey(block.getStructure().getRenderThickness(), false), new ColorData(PipeTileEntity.DEFAULT_COLOR)); } - - public static void registerModels(IRegistry registry) { - registry.putObject(OPTICAL.getLoc(), OPTICAL); - registry.putObject(LASER.getLoc(), LASER); - } } diff --git a/src/main/java/gregtech/client/renderer/pipe/CableModel.java b/src/main/java/gregtech/client/renderer/pipe/CableModel.java index 7b598ccc957..df6510abd7c 100644 --- a/src/main/java/gregtech/client/renderer/pipe/CableModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/CableModel.java @@ -13,13 +13,8 @@ import gregtech.client.renderer.pipe.util.SpriteInformation; import gregtech.client.renderer.texture.Textures; -import net.minecraft.client.renderer.block.model.IBakedModel; -import net.minecraft.client.renderer.block.model.ModelResourceLocation; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.registry.IRegistry; import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fml.relauncher.Side; @@ -35,14 +30,12 @@ public class CableModel extends AbstractPipeModel { public static final int DEFAULT_INSULATION_COLOR = 0xFF404040; - private static final ResourceLocation loc = GTUtility.gregtechId("block/cable"); - - public static final CableModel INSTANCE = new CableModel("wire"); + public static final CableModel INSTANCE = new CableModel(); public static final CableModel[] INSULATED_INSTANCES = new CableModel[Textures.INSULATION.length]; static { for (int i = 0; i < INSULATED_INSTANCES.length; i++) { - INSULATED_INSTANCES[i] = new CableModel(Textures.INSULATION[i], Textures.INSULATION_FULL, "insulated_" + i); + INSULATED_INSTANCES[i] = new CableModel(Textures.INSULATION[i], Textures.INSULATION_FULL); } } @@ -51,20 +44,19 @@ public class CableModel extends AbstractPipeModel { private final Supplier fullInsulationTex; public CableModel(@NotNull Supplier wireTex, @Nullable Supplier insulationTex, - @Nullable Supplier fullInsulationTex, String variant) { - super(new ModelResourceLocation(loc, variant)); + @Nullable Supplier fullInsulationTex) { this.wireTex = wireTex; this.insulationTex = insulationTex; this.fullInsulationTex = fullInsulationTex; } public CableModel(@Nullable Supplier insulationTex, - @Nullable Supplier fullInsulationTex, String variant) { - this(Textures.WIRE, insulationTex, fullInsulationTex, variant); + @Nullable Supplier fullInsulationTex) { + this(Textures.WIRE, insulationTex, fullInsulationTex); } - public CableModel(String variant) { - this(null, null, variant); + public CableModel() { + this(null, null); } @Override @@ -88,11 +80,6 @@ public SpriteInformation getParticleSprite(@Nullable Material material) { return wireTex.get(); } - @Override - public @NotNull TextureAtlasSprite getParticleTexture() { - return getParticleSprite(null).sprite(); - } - @Override protected @NotNull CacheKey toKey(@NotNull IExtendedBlockState state) { return defaultKey(state); @@ -110,20 +97,13 @@ protected StructureQuadCache constructForKey(CacheKey key) { } @Override - protected @Nullable PipeItemModel getItemModel(@NotNull ItemStack stack, World world, - EntityLivingBase entity) { + protected @Nullable PipeItemModel getItemModel(PipeModelRedirector redirector, @NotNull ItemStack stack, + World world, EntityLivingBase entity) { PipeBlock block = PipeBlock.getBlockFromItem(stack); if (block == null) return null; Material mater = block instanceof PipeMaterialBlock mat ? mat.getMaterialForStack(stack) : null; - return new PipeItemModel<>(this, new CacheKey(block.getStructure().getRenderThickness()), + return new PipeItemModel<>(redirector, this, new CacheKey(block.getStructure().getRenderThickness()), new ColorData(mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : PipeTileEntity.DEFAULT_COLOR, DEFAULT_INSULATION_COLOR)); } - - public static void registerModels(IRegistry registry) { - registry.putObject(INSTANCE.getLoc(), INSTANCE); - for (CableModel model : INSULATED_INSTANCES) { - registry.putObject(model.getLoc(), model); - } - } } diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java index a6f15763c36..6868489f456 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeItemModel.java @@ -55,11 +55,13 @@ private static Quat4f rotDegrees(float x, float y, float z) { return TRSRTransformation.quatFromXYZDegrees(new Vector3f(x, y, z)); } + private final PipeModelRedirector redirector; private final AbstractPipeModel basis; private final K key; private final ColorData data; - public PipeItemModel(AbstractPipeModel basis, K key, ColorData data) { + public PipeItemModel(PipeModelRedirector redirector, AbstractPipeModel basis, K key, ColorData data) { + this.redirector = redirector; this.basis = basis; this.key = key; this.data = data; @@ -73,12 +75,12 @@ public PipeItemModel(AbstractPipeModel basis, K key, ColorData data) { @Override public boolean isAmbientOcclusion() { - return basis.isAmbientOcclusion(); + return redirector.isAmbientOcclusion(); } @Override public boolean isGui3d() { - return basis.isGui3d(); + return redirector.isGui3d(); } @Override @@ -87,14 +89,13 @@ public boolean isBuiltInRenderer() { } @Override - public @NotNull Pair handlePerspective( - ItemCameraTransforms.@NotNull TransformType cameraTransformType) { + public @NotNull Pair handlePerspective(ItemCameraTransforms.@NotNull TransformType cameraTransformType) { return ImmutablePair.of(this, CAMERA_TRANSFORMS.get(cameraTransformType)); } @Override public @NotNull TextureAtlasSprite getParticleTexture() { - return basis.getParticleTexture(); + return redirector.getParticleTexture(); } @Override diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java index 63f7ee082b5..719504809e4 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModel.java @@ -4,25 +4,18 @@ import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.cache.BlockableSQC; import gregtech.client.renderer.pipe.cache.RestrictiveSQC; import gregtech.client.renderer.pipe.cache.StructureQuadCache; import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; -import gregtech.client.renderer.pipe.util.PipeSpriteWoodClarifier; +import gregtech.client.renderer.pipe.util.CacheKey; import gregtech.client.renderer.pipe.util.SpriteInformation; -import gregtech.client.renderer.pipe.util.WoodCacheKey; import gregtech.client.renderer.texture.Textures; -import net.minecraft.client.renderer.block.model.IBakedModel; -import net.minecraft.client.renderer.block.model.ModelResourceLocation; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.registry.IRegistry; import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fml.relauncher.Side; @@ -31,104 +24,60 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -@SideOnly(Side.CLIENT) -public class PipeModel extends AbstractPipeModel { - - private static final ResourceLocation loc = GTUtility.gregtechId("block/pipe_material"); - - public static final PipeModel[] INSTANCES = new PipeModel[7]; - public static final PipeModel[] RESTRICTIVE_INSTANCES = new PipeModel[INSTANCES.length]; - - static { - model(0, wood -> Textures.PIPE_TINY.get()); - model(1, wood -> wood ? Textures.PIPE_SMALL_WOOD.get() : Textures.PIPE_SMALL.get()); - model(2, wood -> wood ? Textures.PIPE_NORMAL_WOOD.get() : Textures.PIPE_NORMAL.get()); - model(3, wood -> wood ? Textures.PIPE_LARGE_WOOD.get() : Textures.PIPE_LARGE.get()); - model(4, wood -> Textures.PIPE_HUGE.get()); - model(5, wood -> Textures.PIPE_QUADRUPLE.get()); - model(6, wood -> Textures.PIPE_NONUPLE.get()); - } +import java.util.function.Supplier; - private static void model(int i, PipeSpriteWoodClarifier clarifier) { - INSTANCES[i] = new PipeModel(clarifier, false, i + "_standard"); - RESTRICTIVE_INSTANCES[i] = new PipeModel(clarifier, true, i + "_restrictive"); - } +@SideOnly(Side.CLIENT) +public class PipeModel extends AbstractPipeModel { - private final @NotNull PipeSpriteWoodClarifier inTex; - private final @NotNull PipeSpriteWoodClarifier sideTex; - private final @Nullable PipeSpriteWoodClarifier restrictiveTex; - private final @NotNull PipeSpriteWoodClarifier blockedTex; + private final @NotNull Supplier inTex; + private final @NotNull Supplier sideTex; + private final @Nullable Supplier restrictiveTex; + private final @NotNull Supplier blockedTex; - public PipeModel(@NotNull PipeSpriteWoodClarifier inTex, @NotNull PipeSpriteWoodClarifier sideTex, - @Nullable PipeSpriteWoodClarifier restrictiveTex, - @NotNull PipeSpriteWoodClarifier blockedTex, String variant) { - super(new ModelResourceLocation(loc, variant)); + public PipeModel(@NotNull Supplier inTex, @NotNull Supplier sideTex, + @Nullable Supplier restrictiveTex, + @NotNull Supplier blockedTex) { this.inTex = inTex; this.sideTex = sideTex; this.restrictiveTex = restrictiveTex; this.blockedTex = blockedTex; } - public PipeModel(@NotNull PipeSpriteWoodClarifier inTex, @NotNull PipeSpriteWoodClarifier sideTex, - boolean restrictive, String variant) { - this(inTex, sideTex, restrictive ? wood -> Textures.RESTRICTIVE_OVERLAY.get() : null, - wood -> Textures.PIPE_BLOCKED_OVERLAY.get(), variant); - } - - public PipeModel(@NotNull PipeSpriteWoodClarifier inTex, boolean restrictive, String variant) { - this(inTex, wood -> wood ? Textures.PIPE_SIDE_WOOD.get() : Textures.PIPE_SIDE.get(), restrictive, variant); + public PipeModel(@NotNull Supplier inTex, @NotNull Supplier sideTex, + boolean restrictive) { + this(inTex, sideTex, restrictive ? Textures.RESTRICTIVE_OVERLAY : null, Textures.PIPE_BLOCKED_OVERLAY); } @Override public SpriteInformation getParticleSprite(@Nullable Material material) { - return sideTex.getSprite(material != null && material.hasProperty(PropertyKey.WOOD)); + return sideTex.get(); } @Override - public @NotNull TextureAtlasSprite getParticleTexture() { - return getParticleSprite(null).sprite(); - } - - public @NotNull TextureAtlasSprite getParticleTexture(Material material) { - return sideTex.getSprite(material.hasProperty(PropertyKey.WOOD)).sprite(); - } - - @Override - protected @NotNull WoodCacheKey toKey(@NotNull IExtendedBlockState state) { - return WoodCacheKey.of(state.getValue(THICKNESS_PROPERTY), state.getValue(MATERIAL_PROPERTY)); + protected @NotNull CacheKey toKey(@NotNull IExtendedBlockState state) { + return defaultKey(state); } @Override - protected StructureQuadCache constructForKey(WoodCacheKey key) { + protected StructureQuadCache constructForKey(CacheKey key) { if (restrictiveTex != null) { - return RestrictiveSQC.create(PipeQuadHelper.create(key.getThickness()), inTex.getSprite(key.isWood()), - sideTex.getSprite(key.isWood()), blockedTex.getSprite(key.isWood()), - restrictiveTex.getSprite(key.isWood())); + return RestrictiveSQC.create(PipeQuadHelper.create(key.getThickness()), inTex.get(), sideTex.get(), + blockedTex.get(), restrictiveTex.get()); } else { - return BlockableSQC.create(PipeQuadHelper.create(key.getThickness()), inTex.getSprite(key.isWood()), - sideTex.getSprite(key.isWood()), blockedTex.getSprite(key.isWood())); + return BlockableSQC.create(PipeQuadHelper.create(key.getThickness()), inTex.get(), sideTex.get(), + blockedTex.get()); } } @Override @Nullable - protected PipeItemModel getItemModel(@NotNull ItemStack stack, World world, EntityLivingBase entity) { + protected PipeItemModel getItemModel(PipeModelRedirector redirector, @NotNull ItemStack stack, + World world, EntityLivingBase entity) { PipeBlock block = PipeBlock.getBlockFromItem(stack); if (block == null) return null; - Material mater = null; - boolean wood = block instanceof PipeMaterialBlock mat && (mater = mat.getMaterialForStack(stack)) != null && - mater.hasProperty(PropertyKey.WOOD); - return new PipeItemModel<>(this, new WoodCacheKey(block.getStructure().getRenderThickness(), wood), + Material mater = block instanceof PipeMaterialBlock mat ? mat.getMaterialForStack(stack) : null; + return new PipeItemModel<>(redirector, this, new CacheKey(block.getStructure().getRenderThickness()), new ColorData(mater != null ? GTUtility.convertRGBtoARGB(mater.getMaterialRGB()) : PipeTileEntity.DEFAULT_COLOR)); } - - public static void registerModels(IRegistry registry) { - for (PipeModel model : INSTANCES) { - registry.putObject(model.getLoc(), model); - } - for (PipeModel model : RESTRICTIVE_INSTANCES) { - registry.putObject(model.getLoc(), model); - } - } } diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java b/src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java new file mode 100644 index 00000000000..8581b388dc4 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java @@ -0,0 +1,120 @@ +package gregtech.client.renderer.pipe; + +import gregtech.api.unification.material.Material; +import gregtech.client.renderer.pipe.util.MaterialModelSupplier; +import gregtech.client.renderer.texture.Textures; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ItemOverrideList; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; +import net.minecraftforge.common.property.IExtendedBlockState; + +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + +public class PipeModelRedirector implements IBakedModel { + + private final boolean ambientOcclusion; + private final boolean gui3d; + + public final MaterialModelSupplier supplier; + public final Function stackMaterialFunction; + + private final ModelResourceLocation loc; + + private final FakeItemOverrideList fakeItemOverrideList = new FakeItemOverrideList(); + + public PipeModelRedirector(ModelResourceLocation loc, MaterialModelSupplier supplier, + Function stackMaterialFunction) { + this(loc, supplier, stackMaterialFunction, true, true); + } + + public PipeModelRedirector(ModelResourceLocation loc, MaterialModelSupplier supplier, + Function stackMaterialFunction, + boolean ambientOcclusion, boolean gui3d) { + this.loc = loc; + this.supplier = supplier; + this.stackMaterialFunction = stackMaterialFunction; + this.ambientOcclusion = ambientOcclusion; + this.gui3d = gui3d; + } + + @Override + public @NotNull List getQuads(IBlockState state, EnumFacing side, long rand) { + if (state instanceof IExtendedBlockState ext) { + Optional mat = (Optional) ext.getUnlistedProperties() + .get(AbstractPipeModel.MATERIAL_PROPERTY); + // noinspection OptionalAssignedToNull + return supplier.getModel(mat == null ? null : mat.orElse(null)).getQuads(ext, side, rand); + } + return Collections.emptyList(); + } + + @Override + public boolean isAmbientOcclusion() { + return ambientOcclusion; + } + + @Override + public boolean isGui3d() { + return gui3d; + } + + @Override + public boolean isBuiltInRenderer() { + return false; + } + + public Pair getParticleTexture(int paintColor, @Nullable Material material) { + return supplier.getModel(material).getParticleTexture(paintColor, material); + } + + @Override + public @NotNull TextureAtlasSprite getParticleTexture() { + return Textures.WIRE.get().sprite(); + } + + @Override + public @NotNull ItemOverrideList getOverrides() { + return fakeItemOverrideList; + } + + public ModelResourceLocation getLoc() { + return loc; + } + + @FunctionalInterface + public interface Supplier { + + PipeModelRedirector create(ModelResourceLocation loc, MaterialModelSupplier supplier, + Function stackMaterialFunction); + } + + protected class FakeItemOverrideList extends ItemOverrideList { + + @Override + public @NotNull IBakedModel handleItemState(@NotNull IBakedModel originalModel, @NotNull ItemStack stack, + World world, EntityLivingBase entity) { + if (originalModel instanceof PipeModelRedirector model) { + + PipeItemModel item = model.supplier.getModel(model.stackMaterialFunction.apply(stack)) + .getItemModel(PipeModelRedirector.this, stack, world, entity); + if (item != null) return item; + } + return originalModel; + } + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java b/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java new file mode 100644 index 00000000000..f9340a52c49 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java @@ -0,0 +1,223 @@ +package gregtech.client.renderer.pipe; + +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; +import gregtech.api.unification.material.Material; +import gregtech.api.unification.material.properties.PropertyKey; +import gregtech.api.util.GTUtility; +import gregtech.client.renderer.pipe.util.MaterialModelOverride; +import gregtech.client.renderer.pipe.util.MaterialModelSupplier; +import gregtech.client.renderer.texture.Textures; + +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.IRegistry; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Range; + +public final class PipeModelRegistry { + + public static final int PIPE_MODEL_COUNT = 7; + private static final Object2ObjectOpenHashMap PIPE = new Object2ObjectOpenHashMap<>(); + private static final PipeModelRedirector[] PIPE_MODELS = new PipeModelRedirector[PIPE_MODEL_COUNT]; + private static final ObjectLinkedOpenHashSet> PIPE_OVERRIDES = new ObjectLinkedOpenHashSet<>(); + private static final Object2ObjectOpenHashMap PIPE_RESTRICTIVE = new Object2ObjectOpenHashMap<>(); + private static final PipeModelRedirector[] PIPE_RESTRICTIVE_MODELS = new PipeModelRedirector[PIPE_MODEL_COUNT]; + private static final ObjectLinkedOpenHashSet> PIPE_RESTRICTIVE_OVERRIDES = new ObjectLinkedOpenHashSet<>(); + + public static final int CABLE_MODEL_COUNT = 6; + private static final Object2ObjectOpenHashMap CABLE = new Object2ObjectOpenHashMap<>(); + private static final PipeModelRedirector[] CABLE_MODELS = new PipeModelRedirector[CABLE_MODEL_COUNT]; + private static final ObjectLinkedOpenHashSet> CABLE_OVERRIDES = new ObjectLinkedOpenHashSet<>(); + + private static final ActivablePipeModel OPTICAL; + private static final PipeModelRedirector OPTICAL_MODEL; + + private static final ActivablePipeModel LASER; + private static final PipeModelRedirector LASER_MODEL; + + static { + initPipes(); + initCables(); + ResourceLocation loc = GTUtility.gregtechId("block/pipe_activable"); + OPTICAL = new ActivablePipeModel(Textures.OPTICAL_PIPE_IN, Textures.OPTICAL_PIPE_SIDE, + Textures.OPTICAL_PIPE_SIDE_OVERLAY, Textures.OPTICAL_PIPE_SIDE_OVERLAY_ACTIVE, false); + OPTICAL_MODEL = new PipeModelRedirector(new ModelResourceLocation(loc, "optical"), m -> OPTICAL, s -> null); + LASER = new ActivablePipeModel(Textures.LASER_PIPE_IN, Textures.LASER_PIPE_SIDE, Textures.LASER_PIPE_OVERLAY, + Textures.LASER_PIPE_OVERLAY_EMISSIVE, true); + LASER_MODEL = new PipeModelRedirector(new ModelResourceLocation(loc, "laser"), m -> LASER, s -> null); + } + + public static void registerPipeOverride(@NotNull MaterialModelOverride override) { + PIPE_OVERRIDES.addAndMoveToFirst(override); + PIPE.clear(); + PIPE.trim(16); + } + + public static void registerPipeRestrictiveOverride(@NotNull MaterialModelOverride override) { + PIPE_RESTRICTIVE_OVERRIDES.addAndMoveToFirst(override); + PIPE_RESTRICTIVE.clear(); + PIPE_RESTRICTIVE.trim(16); + } + + public static void registerCableOverride(@NotNull MaterialModelOverride override) { + CABLE_OVERRIDES.addAndMoveToFirst(override); + CABLE.clear(); + CABLE.trim(16); + } + + public static PipeModelRedirector getPipeModel(@Range(from = 0, to = PIPE_MODEL_COUNT - 1) int i) { + return PIPE_MODELS[i]; + } + + public static PipeModelRedirector getPipeRestrictiveModel(@Range(from = 0, to = PIPE_MODEL_COUNT - 1) int i) { + return PIPE_RESTRICTIVE_MODELS[i]; + } + + public static PipeModelRedirector getCableModel(@Range(from = 0, to = CABLE_MODEL_COUNT - 1) int i) { + return CABLE_MODELS[i]; + } + + public static PipeModelRedirector getOpticalModel() { + return OPTICAL_MODEL; + } + + public static PipeModelRedirector getLaserModel() { + return LASER_MODEL; + } + + public static void registerModels(@NotNull IRegistry registry) { + for (PipeModelRedirector redirector : PIPE_MODELS) { + registry.putObject(redirector.getLoc(), redirector); + } + for (PipeModelRedirector redirector : PIPE_RESTRICTIVE_MODELS) { + registry.putObject(redirector.getLoc(), redirector); + } + for (PipeModelRedirector redirector : CABLE_MODELS) { + registry.putObject(redirector.getLoc(), redirector); + } + registry.putObject(OPTICAL_MODEL.getLoc(), OPTICAL_MODEL); + registry.putObject(LASER_MODEL.getLoc(), LASER_MODEL); + } + + public static PipeModelRedirector materialModel(@NotNull ResourceLocation loc, MaterialModelSupplier supplier, + @NotNull String variant, + PipeModelRedirector.@NotNull Supplier redirectorSupplier) { + return redirectorSupplier.create(new ModelResourceLocation(loc, variant), supplier, + stack -> { + PipeMaterialBlock pipe = PipeMaterialBlock.getBlockFromItem(stack); + if (pipe == null) return null; + else return pipe.getMaterialForStack(stack); + }); + } + + public static PipeModelRedirector materialModel(@NotNull ResourceLocation loc, MaterialModelSupplier supplier, + @NotNull String variant) { + return new PipeModelRedirector(new ModelResourceLocation(loc, variant), supplier, + stack -> { + PipeMaterialBlock pipe = PipeMaterialBlock.getBlockFromItem(stack); + if (pipe == null) return null; + else return pipe.getMaterialForStack(stack); + }); + } + + private static void initPipes() { + PipeModel[] array = new PipeModel[PIPE_MODEL_COUNT]; + // standard + array[0] = new PipeModel(Textures.PIPE_TINY, Textures.PIPE_SIDE, false); + array[1] = new PipeModel(Textures.PIPE_SMALL, Textures.PIPE_SIDE, false); + array[2] = new PipeModel(Textures.PIPE_NORMAL, Textures.PIPE_SIDE, false); + array[3] = new PipeModel(Textures.PIPE_LARGE, Textures.PIPE_SIDE, false); + array[4] = new PipeModel(Textures.PIPE_HUGE, Textures.PIPE_SIDE, false); + array[5] = new PipeModel(Textures.PIPE_QUADRUPLE, Textures.PIPE_SIDE, false); + array[6] = new PipeModel(Textures.PIPE_NONUPLE, Textures.PIPE_SIDE, false); + PIPE_OVERRIDES.add(new MaterialModelOverride.StandardOverride<>(array, m -> true)); + + array = new PipeModel[PIPE_MODEL_COUNT]; + array[1] = new PipeModel(Textures.PIPE_SMALL_WOOD, Textures.PIPE_SIDE_WOOD, false); + array[2] = new PipeModel(Textures.PIPE_NORMAL_WOOD, Textures.PIPE_SIDE_WOOD, false); + array[3] = new PipeModel(Textures.PIPE_LARGE_WOOD, Textures.PIPE_SIDE_WOOD, false); + registerPipeOverride(new MaterialModelOverride.StandardOverride<>(array, m -> m.hasProperty(PropertyKey.WOOD))); + + array = new PipeModel[PIPE_MODEL_COUNT]; + array[0] = new PipeModel(Textures.PIPE_TINY, Textures.PIPE_SIDE, true); + array[1] = new PipeModel(Textures.PIPE_SMALL, Textures.PIPE_SIDE, true); + array[2] = new PipeModel(Textures.PIPE_NORMAL, Textures.PIPE_SIDE, true); + array[3] = new PipeModel(Textures.PIPE_LARGE, Textures.PIPE_SIDE, true); + array[4] = new PipeModel(Textures.PIPE_HUGE, Textures.PIPE_SIDE, true); + array[5] = new PipeModel(Textures.PIPE_QUADRUPLE, Textures.PIPE_SIDE, true); + array[6] = new PipeModel(Textures.PIPE_NONUPLE, Textures.PIPE_SIDE, true); + PIPE_RESTRICTIVE_OVERRIDES.add(new MaterialModelOverride.StandardOverride<>(array, m -> true)); + + ResourceLocation loc = GTUtility.gregtechId("block/pipe_material"); + for (int i = 0; i < PIPE_MODEL_COUNT; i++) { + int finalI = i; + PIPE_MODELS[i] = materialModel(loc, m -> getOrCachePipeModel(m, finalI), String.valueOf(i)); + PIPE_RESTRICTIVE_MODELS[i] = materialModel(loc, m -> getOrCachePipeRestrictiveModel(m, finalI), + "restrictive_" + i); + } + } + + private static PipeModel getOrCachePipeModel(Material m, int i) { + if (m == null) return PIPE_OVERRIDES.last().getModel(null, i); + PipeModel[] cached = PIPE.computeIfAbsent(m, k -> new PipeModel[PIPE_MODEL_COUNT]); + PipeModel selected = cached[i]; + if (selected == null) { + for (MaterialModelOverride override : PIPE_OVERRIDES) { + selected = override.getModel(m, i); + if (selected != null) break; + } + cached[i] = selected; + } + return selected; + } + + private static PipeModel getOrCachePipeRestrictiveModel(Material m, int i) { + if (m == null) return PIPE_RESTRICTIVE_OVERRIDES.last().getModel(null, i); + PipeModel[] cached = PIPE_RESTRICTIVE.computeIfAbsent(m, k -> new PipeModel[PIPE_MODEL_COUNT]); + PipeModel selected = cached[i]; + if (selected == null) { + for (MaterialModelOverride override : PIPE_RESTRICTIVE_OVERRIDES) { + selected = override.getModel(m, i); + if (selected != null) break; + } + cached[i] = selected; + } + return selected; + } + + private static void initCables() { + CableModel[] array = new CableModel[CABLE_MODEL_COUNT]; + for (int i = 0; i < CABLE_MODEL_COUNT; i++) { + if (i == 0) { + array[i] = new CableModel(); + continue; + } + array[i] = new CableModel(Textures.INSULATION[i - 1], Textures.INSULATION_FULL); + } + CABLE_OVERRIDES.add(new MaterialModelOverride.StandardOverride<>(array, m -> true)); + + ResourceLocation loc = GTUtility.gregtechId("block/cable"); + for (int i = 0; i < CABLE_MODEL_COUNT; i++) { + int finalI = i; + CABLE_MODELS[i] = materialModel(loc, m -> getOrCacheCableModel(m, finalI), String.valueOf(i)); + } + } + + private static CableModel getOrCacheCableModel(Material m, int i) { + if (m == null) return CABLE_OVERRIDES.last().getModel(null, i); + CableModel[] cached = CABLE.computeIfAbsent(m, k -> new CableModel[CABLE_MODEL_COUNT]); + CableModel selected = cached[i]; + if (selected == null) { + for (MaterialModelOverride override : CABLE_OVERRIDES) { + selected = override.getModel(m, i); + if (selected != null) break; + } + cached[i] = selected; + } + return selected; + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/MaterialModelOverride.java b/src/main/java/gregtech/client/renderer/pipe/util/MaterialModelOverride.java new file mode 100644 index 00000000000..8d080b924a6 --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/util/MaterialModelOverride.java @@ -0,0 +1,28 @@ +package gregtech.client.renderer.pipe.util; + +import gregtech.api.unification.material.Material; +import gregtech.client.renderer.pipe.AbstractPipeModel; + +import com.github.bsideup.jabel.Desugar; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Predicate; + +public interface MaterialModelOverride> { + + @Nullable + T getModel(Material material, int i); + + @Desugar + record StandardOverride> (@NotNull T[] models, + @NotNull Predicate predicate) + implements MaterialModelOverride { + + @Override + public @Nullable T getModel(Material material, int i) { + if (material == null || !predicate.test(material)) return null; + else return models[i]; + } + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/MaterialModelSupplier.java b/src/main/java/gregtech/client/renderer/pipe/util/MaterialModelSupplier.java new file mode 100644 index 00000000000..d1631a2dfce --- /dev/null +++ b/src/main/java/gregtech/client/renderer/pipe/util/MaterialModelSupplier.java @@ -0,0 +1,14 @@ +package gregtech.client.renderer.pipe.util; + +import gregtech.api.unification.material.Material; +import gregtech.client.renderer.pipe.AbstractPipeModel; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +@FunctionalInterface +public interface MaterialModelSupplier { + + @NotNull + AbstractPipeModel getModel(@Nullable Material material); +} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java b/src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java deleted file mode 100644 index 8335d4286f4..00000000000 --- a/src/main/java/gregtech/client/renderer/pipe/util/PipeSpriteWoodClarifier.java +++ /dev/null @@ -1,11 +0,0 @@ -package gregtech.client.renderer.pipe.util; - -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -@SideOnly(Side.CLIENT) -@FunctionalInterface -public interface PipeSpriteWoodClarifier { - - SpriteInformation getSprite(boolean isWoodVariant); -} diff --git a/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java b/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java deleted file mode 100644 index 5db92932248..00000000000 --- a/src/main/java/gregtech/client/renderer/pipe/util/WoodCacheKey.java +++ /dev/null @@ -1,58 +0,0 @@ -package gregtech.client.renderer.pipe.util; - -import gregtech.api.unification.material.Material; -import gregtech.api.unification.material.properties.PropertyKey; - -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Objects; - -@SideOnly(Side.CLIENT) -public class WoodCacheKey extends CacheKey { - - private final boolean wood; - - public WoodCacheKey(float thickness, boolean wood) { - super(thickness); - this.wood = wood; - } - - public static WoodCacheKey of(@Nullable Float thickness, @Nullable Boolean wood) { - float thick = thickness == null ? 0.5f : thickness; - boolean wd = wood != null && wood; - return new WoodCacheKey(thick, wd); - } - - public static WoodCacheKey of(@Nullable Float thickness, @Nullable Material material) { - float thick = thickness == null ? 0.5f : thickness; - boolean wood = material != null && material.hasProperty(PropertyKey.WOOD); - return new WoodCacheKey(thick, wood); - } - - public boolean isWood() { - return wood; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - var that = (WoodCacheKey) obj; - return Float.floatToIntBits(thickness) == Float.floatToIntBits(thickness) && - this.wood == that.wood; - } - - @Override - protected int computeHash() { - return Objects.hash(thickness, wood); - } - - @Override - public @NotNull String getName() { - return super.getName() + wood; - } -} diff --git a/src/main/java/gregtech/client/renderer/texture/Textures.java b/src/main/java/gregtech/client/renderer/texture/Textures.java index 22d69a42e43..8df7ad0443d 100644 --- a/src/main/java/gregtech/client/renderer/texture/Textures.java +++ b/src/main/java/gregtech/client/renderer/texture/Textures.java @@ -7,6 +7,7 @@ import gregtech.client.renderer.CubeRendererState; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.cclop.UVMirror; +import gregtech.client.renderer.pipe.PipeModelRegistry; import gregtech.client.renderer.pipe.util.SpriteInformationWrapper; import gregtech.client.renderer.texture.cube.AlignedOrientedOverlayRenderer; import gregtech.client.renderer.texture.cube.LDPipeOverlayRenderer; @@ -535,7 +536,8 @@ public class Textures { @SideOnly(Side.CLIENT) public static final SpriteInformationWrapper INSULATION_FULL = new SpriteInformationWrapper(); @SideOnly(Side.CLIENT) - public static final SpriteInformationWrapper[] INSULATION = SpriteInformationWrapper.array(5); + public static final SpriteInformationWrapper[] INSULATION = SpriteInformationWrapper + .array(PipeModelRegistry.CABLE_MODEL_COUNT - 1); @SideOnly(Side.CLIENT) public static final SpriteInformationWrapper RESTRICTIVE_OVERLAY = new SpriteInformationWrapper(); diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index 30c7890ca98..95db77674e2 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -4,8 +4,8 @@ import gregtech.api.GregTechAPI; import gregtech.api.block.VariantItemBlock; import gregtech.api.block.machines.MachineItemBlock; -import gregtech.api.graphnet.pipenet.physical.block.ItemMaterialPipeBlock; import gregtech.api.graphnet.pipenet.physical.block.ItemPipeBlock; +import gregtech.api.graphnet.pipenet.physical.block.ItemPipeMaterialBlock; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.toolitem.IGTTool; import gregtech.api.metatileentity.registry.MTERegistry; @@ -214,9 +214,9 @@ public static void registerItems(RegistryEvent.Register event) { for (MaterialRegistry materialRegistry : GregTechAPI.materialManager.getRegistries()) { for (CableBlock cable : CABLES.get(materialRegistry.getModid())) - registry.register(createItemBlock(cable, ItemMaterialPipeBlock::new)); + registry.register(createItemBlock(cable, ItemPipeMaterialBlock::new)); for (MaterialPipeBlock cable : MATERIAL_PIPES.get(materialRegistry.getModid())) - registry.register(createItemBlock(cable, ItemMaterialPipeBlock::new)); + registry.register(createItemBlock(cable, ItemPipeMaterialBlock::new)); } for (OpticalPipeBlock pipe : OPTICAL_PIPES) registry.register(createItemBlock(pipe, ItemPipeBlock::new)); for (LaserPipeBlock pipe : LASER_PIPES) registry.register(createItemBlock(pipe, ItemPipeBlock::new)); diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index 122ae9621ae..b7bfe5bc47a 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -59,7 +59,7 @@ protected String getConnectLangKey() { @Override public void partialBurn(IBlockState state, World world, BlockPos pos) { - CableStructure structure = (CableStructure) getStructure(); + CableStructure structure = getStructure(); if (structure.partialBurnStructure() != null) { CableBlock newBlock = CACHE.get(registry).get(structure.partialBurnStructure()); // noinspection deprecation diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java index 3c5b7bd78ed..ae57598f22d 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java @@ -4,48 +4,47 @@ import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; import gregtech.api.unification.ore.OrePrefix; -import gregtech.client.renderer.pipe.AbstractPipeModel; -import gregtech.client.renderer.pipe.CableModel; +import gregtech.client.renderer.pipe.PipeModelRedirector; +import gregtech.client.renderer.pipe.PipeModelRegistry; import com.github.bsideup.jabel.Desugar; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.function.Consumer; - +@SuppressWarnings("unused") @Desugar public record CableStructure(String name, int material, int costFactor, OrePrefix ore, @Nullable CableStructure partialBurnStructure, @Nullable Integer partialBurnThreshold, - float renderThickness, AbstractPipeModel model) + float renderThickness, PipeModelRedirector model) implements IPipeMaterialStructure, IInsulatable { public static final int INSULATION_BURN_TEMP = 1000; public static final CableStructure WIRE_SINGLE = new CableStructure("wire_single", 1, 2, OrePrefix.wireGtSingle, - null, null, 0.125f, CableModel.INSTANCE); + null, null, 0.125f, PipeModelRegistry.getCableModel(0)); public static final CableStructure WIRE_DOUBLE = new CableStructure("wire_double", 2, 2, OrePrefix.wireGtDouble, - null, null, 0.25f, CableModel.INSTANCE); + null, null, 0.25f, PipeModelRegistry.getCableModel(0)); public static final CableStructure WIRE_QUADRUPLE = new CableStructure("wire_quadruple", 4, 3, - OrePrefix.wireGtQuadruple, null, null, 0.375f, CableModel.INSTANCE); + OrePrefix.wireGtQuadruple, null, null, 0.375f, PipeModelRegistry.getCableModel(0)); public static final CableStructure WIRE_OCTAL = new CableStructure("wire_octal", 8, 3, OrePrefix.wireGtOctal, null, - null, 0.5f, CableModel.INSTANCE); + null, 0.5f, PipeModelRegistry.getCableModel(0)); public static final CableStructure WIRE_HEX = new CableStructure("wire_hex", 16, 3, OrePrefix.wireGtHex, null, null, - 0.75f, CableModel.INSTANCE); + 0.75f, PipeModelRegistry.getCableModel(0)); public static final CableStructure CABLE_SINGLE = new CableStructure("cable_single", 1, 1, OrePrefix.cableGtSingle, - WIRE_SINGLE, INSULATION_BURN_TEMP, 0.25f, CableModel.INSULATED_INSTANCES[0]); + WIRE_SINGLE, INSULATION_BURN_TEMP, 0.25f, PipeModelRegistry.getCableModel(1)); public static final CableStructure CABLE_DOUBLE = new CableStructure("cable_double", 2, 1, OrePrefix.cableGtDouble, - WIRE_DOUBLE, INSULATION_BURN_TEMP, 0.375f, CableModel.INSULATED_INSTANCES[1]); + WIRE_DOUBLE, INSULATION_BURN_TEMP, 0.375f, PipeModelRegistry.getCableModel(2)); public static final CableStructure CABLE_QUADRUPLE = new CableStructure("cable_quadruple", 4, 1, - OrePrefix.cableGtQuadruple, WIRE_QUADRUPLE, INSULATION_BURN_TEMP, 0.5f, CableModel.INSULATED_INSTANCES[2]); + OrePrefix.cableGtQuadruple, WIRE_QUADRUPLE, INSULATION_BURN_TEMP, 0.5f, PipeModelRegistry.getCableModel(3)); public static final CableStructure CABLE_OCTAL = new CableStructure("cable_octal", 8, 1, OrePrefix.cableGtOctal, - WIRE_OCTAL, INSULATION_BURN_TEMP, 0.75f, CableModel.INSULATED_INSTANCES[3]); + WIRE_OCTAL, INSULATION_BURN_TEMP, 0.75f, PipeModelRegistry.getCableModel(4)); public static final CableStructure CABLE_HEX = new CableStructure("cable_hex", 16, 1, OrePrefix.cableGtHex, - WIRE_HEX, INSULATION_BURN_TEMP, 1f, CableModel.INSULATED_INSTANCES[4]); + WIRE_HEX, INSULATION_BURN_TEMP, 1f, PipeModelRegistry.getCableModel(5)); public CableStructure(String name, int material, int costFactor, OrePrefix ore, @Nullable CableStructure partialBurnStructure, @Nullable Integer partialBurnThreshold, - float renderThickness, AbstractPipeModel model) { + float renderThickness, PipeModelRedirector model) { this.name = name; this.material = material; this.costFactor = costFactor; @@ -72,11 +71,6 @@ public float getRenderThickness() { return renderThickness; } - @Override - public AbstractPipeModel getModel() { - return model; - } - @Override public boolean isPaintable() { return true; @@ -87,16 +81,8 @@ public boolean isInsulated() { return partialBurnStructure != null; } - public static void registerDefaultStructures(Consumer register) { - register.accept(WIRE_SINGLE); - register.accept(WIRE_DOUBLE); - register.accept(WIRE_QUADRUPLE); - register.accept(WIRE_OCTAL); - register.accept(WIRE_HEX); - register.accept(CABLE_SINGLE); - register.accept(CABLE_DOUBLE); - register.accept(CABLE_QUADRUPLE); - register.accept(CABLE_OCTAL); - register.accept(CABLE_HEX); + @Override + public PipeModelRedirector getModel() { + return model; } } diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java index c03c8279e37..076f38869cd 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java @@ -3,26 +3,25 @@ import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; import gregtech.api.util.GTUtility; -import gregtech.client.renderer.pipe.AbstractPipeModel; -import gregtech.client.renderer.pipe.ActivablePipeModel; +import gregtech.client.renderer.pipe.PipeModelRedirector; +import gregtech.client.renderer.pipe.PipeModelRegistry; import net.minecraft.util.EnumFacing; import com.github.bsideup.jabel.Desugar; import org.jetbrains.annotations.NotNull; -import java.util.function.Consumer; - +@SuppressWarnings("unused") @Desugar -public record LaserStructure(String name, float renderThickness, boolean mirror, ActivablePipeModel model) +public record LaserStructure(String name, float renderThickness, boolean mirror, PipeModelRedirector model) implements IPipeStructure { public static final LaserStructure NORMAL = new LaserStructure("laser_pipe_normal", 0.375f, - false, ActivablePipeModel.LASER); + false, PipeModelRegistry.getLaserModel()); public static final LaserStructure MIRROR = new LaserStructure("laser_pipe_mirror", 0.5f, - true, ActivablePipeModel.LASER); + true, PipeModelRegistry.getLaserModel()); - public LaserStructure(String name, float renderThickness, boolean mirror, ActivablePipeModel model) { + public LaserStructure(String name, float renderThickness, boolean mirror, PipeModelRedirector model) { this.name = name; this.renderThickness = renderThickness; this.mirror = mirror; @@ -69,11 +68,7 @@ public boolean isPaintable() { } @Override - public AbstractPipeModel getModel() { + public PipeModelRedirector getModel() { return model; } - - public static void registerDefaultStructures(Consumer register) { - register.accept(NORMAL); - } } diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java index d561ad3adbd..1d62afaf3df 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java @@ -3,23 +3,22 @@ import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; import gregtech.api.util.GTUtility; -import gregtech.client.renderer.pipe.AbstractPipeModel; -import gregtech.client.renderer.pipe.ActivablePipeModel; +import gregtech.client.renderer.pipe.PipeModelRedirector; +import gregtech.client.renderer.pipe.PipeModelRegistry; import net.minecraft.util.EnumFacing; import com.github.bsideup.jabel.Desugar; import org.jetbrains.annotations.NotNull; -import java.util.function.Consumer; - @Desugar -public record OpticalStructure(String name, float renderThickness, ActivablePipeModel model) implements IPipeStructure { +public record OpticalStructure(String name, float renderThickness, PipeModelRedirector model) + implements IPipeStructure { public static final OpticalStructure INSTANCE = new OpticalStructure("optical_pipe_normal", 0.375f, - ActivablePipeModel.OPTICAL); + PipeModelRegistry.getOpticalModel()); - public OpticalStructure(String name, float renderThickness, ActivablePipeModel model) { + public OpticalStructure(String name, float renderThickness, PipeModelRedirector model) { this.name = name; this.renderThickness = renderThickness; this.model = model; @@ -55,11 +54,7 @@ public boolean isPaintable() { } @Override - public AbstractPipeModel getModel() { + public PipeModelRedirector getModel() { return model; } - - public static void registerDefaultStructures(Consumer register) { - register.accept(INSTANCE); - } } diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java index 6fb375018c4..1ae0698cd3d 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeBlock.java @@ -12,4 +12,9 @@ public MaterialPipeBlock(MaterialPipeStructure structure, MaterialRegistry regis super(structure, registry); setCreativeTab(GTCreativeTabs.TAB_GREGTECH_PIPES); } + + @Override + public MaterialPipeStructure getStructure() { + return (MaterialPipeStructure) super.getStructure(); + } } diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java index 15c92430d18..3faccc5f53d 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java @@ -4,67 +4,54 @@ import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; import gregtech.api.unification.ore.OrePrefix; -import gregtech.client.renderer.pipe.AbstractPipeModel; -import gregtech.client.renderer.pipe.PipeModel; +import gregtech.client.renderer.pipe.PipeModelRedirector; +import gregtech.client.renderer.pipe.PipeModelRegistry; import com.github.bsideup.jabel.Desugar; import org.jetbrains.annotations.NotNull; -import java.util.function.Consumer; - +@SuppressWarnings("unused") @Desugar public record MaterialPipeStructure(String name, int material, int channelCount, boolean restrictive, OrePrefix ore, - float renderThickness, PipeModel model) + float renderThickness, PipeModelRedirector model) implements IPipeMaterialStructure, IPipeChanneledStructure { public static final MaterialPipeStructure TINY = new MaterialPipeStructure("pipe_tiny", 1, 1, false, - OrePrefix.pipeTiny, 0.25f, - PipeModel.INSTANCES[0]); + OrePrefix.pipeTiny, 0.25f, PipeModelRegistry.getPipeModel(0)); public static final MaterialPipeStructure SMALL = new MaterialPipeStructure("pipe_small", 2, 1, false, - OrePrefix.pipeSmall, 0.375f, - PipeModel.INSTANCES[1]); + OrePrefix.pipeSmall, 0.375f, PipeModelRegistry.getPipeModel(1)); public static final MaterialPipeStructure NORMAL = new MaterialPipeStructure("pipe_normal", 6, 1, false, - OrePrefix.pipeNormal, 0.5f, - PipeModel.INSTANCES[2]); + OrePrefix.pipeNormal, 0.5f, PipeModelRegistry.getPipeModel(2)); public static final MaterialPipeStructure LARGE = new MaterialPipeStructure("pipe_large", 12, 1, false, - OrePrefix.pipeLarge, 0.75f, - PipeModel.INSTANCES[3]); + OrePrefix.pipeLarge, 0.75f, PipeModelRegistry.getPipeModel(3)); public static final MaterialPipeStructure HUGE = new MaterialPipeStructure("pipe_huge", 24, 1, false, - OrePrefix.pipeHuge, 0.875f, - PipeModel.INSTANCES[4]); + OrePrefix.pipeHuge, 0.875f, PipeModelRegistry.getPipeModel(4)); public static final MaterialPipeStructure QUADRUPLE = new MaterialPipeStructure("pipe_quadruple", 8, 4, false, - OrePrefix.pipeQuadruple, - 0.95f, PipeModel.INSTANCES[5]); + OrePrefix.pipeQuadruple, 0.95f, PipeModelRegistry.getPipeModel(5)); public static final MaterialPipeStructure NONUPLE = new MaterialPipeStructure("pipe_nonuple", 18, 9, false, - OrePrefix.pipeNonuple, 0.95f, - PipeModel.INSTANCES[6]); + OrePrefix.pipeNonuple, 0.95f, PipeModelRegistry.getPipeModel(6)); public static final MaterialPipeStructure TINY_RESTRICTIVE = new MaterialPipeStructure("pipe_tiny_restrictive", 1, - 1, true, - OrePrefix.pipeTinyRestrictive, 0.25f, PipeModel.RESTRICTIVE_INSTANCES[0]); + 1, true, OrePrefix.pipeTinyRestrictive, 0.25f, PipeModelRegistry.getPipeRestrictiveModel(0)); public static final MaterialPipeStructure SMALL_RESTRICTIVE = new MaterialPipeStructure("pipe_small_restrictive", 2, - 1, true, - OrePrefix.pipeSmallRestrictive, 0.375f, PipeModel.RESTRICTIVE_INSTANCES[1]); + 1, true, OrePrefix.pipeSmallRestrictive, 0.375f, PipeModelRegistry.getPipeRestrictiveModel(1)); public static final MaterialPipeStructure NORMAL_RESTRICTIVE = new MaterialPipeStructure("pipe_normal_restrictive", - 6, 1, true, - OrePrefix.pipeNormalRestrictive, 0.5f, PipeModel.RESTRICTIVE_INSTANCES[2]); + 6, 1, true, OrePrefix.pipeNormalRestrictive, 0.5f, PipeModelRegistry.getPipeRestrictiveModel(2)); public static final MaterialPipeStructure LARGE_RESTRICTIVE = new MaterialPipeStructure("pipe_large_restrictive", - 12, 1, true, - OrePrefix.pipeLargeRestrictive, 0.75f, PipeModel.RESTRICTIVE_INSTANCES[3]); + 12, 1, true, OrePrefix.pipeLargeRestrictive, 0.75f, PipeModelRegistry.getPipeRestrictiveModel(3)); public static final MaterialPipeStructure HUGE_RESTRICTIVE = new MaterialPipeStructure("pipe_huge_restrictive", 24, - 1, true, - OrePrefix.pipeHugeRestrictive, 0.875f, PipeModel.RESTRICTIVE_INSTANCES[4]); + 1, true, OrePrefix.pipeHugeRestrictive, 0.875f, PipeModelRegistry.getPipeRestrictiveModel(4)); public static final MaterialPipeStructure QUADRUPLE_RESTRICTIVE = new MaterialPipeStructure( - "pipe_quadruple_restrictive", 8, 4, true, - OrePrefix.pipeQuadrupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[5]); + "pipe_quadruple_restrictive", 8, 4, true, OrePrefix.pipeQuadrupleRestrictive, 0.95f, + PipeModelRegistry.getPipeRestrictiveModel(5)); public static final MaterialPipeStructure NONUPLE_RESTRICTIVE = new MaterialPipeStructure( - "pipe_nonuple_restrictive", 18, 9, true, - OrePrefix.pipeNonupleRestrictive, 0.95f, PipeModel.RESTRICTIVE_INSTANCES[6]); + "pipe_nonuple_restrictive", 18, 9, true, OrePrefix.pipeNonupleRestrictive, 0.95f, + PipeModelRegistry.getPipeRestrictiveModel(6)); public MaterialPipeStructure(String name, int material, int channelCount, boolean restrictive, OrePrefix ore, - float renderThickness, PipeModel model) { + float renderThickness, PipeModelRedirector model) { this.name = name; this.material = material; this.channelCount = channelCount; @@ -95,30 +82,13 @@ public int getChannelCount() { return channelCount; } - @Override - public AbstractPipeModel getModel() { - return model; - } - @Override public boolean isPaintable() { return true; } - public static void registerDefaultStructures(Consumer register) { - register.accept(TINY); - register.accept(SMALL); - register.accept(NORMAL); - register.accept(LARGE); - register.accept(HUGE); - register.accept(QUADRUPLE); - register.accept(NONUPLE); - register.accept(TINY_RESTRICTIVE); - register.accept(SMALL_RESTRICTIVE); - register.accept(NORMAL_RESTRICTIVE); - register.accept(LARGE_RESTRICTIVE); - register.accept(HUGE_RESTRICTIVE); - register.accept(QUADRUPLE_RESTRICTIVE); - register.accept(NONUPLE_RESTRICTIVE); + @Override + public PipeModelRedirector getModel() { + return model; } } From 522c2f9556c14a63ebf0cfc8dd21dadffc7d18f6 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 25 Aug 2024 11:26:37 -0600 Subject: [PATCH 109/157] Fix instances of me being stupid --- .../pipenet/physical/PipeStructureRegistry.java | 14 +++++--------- .../pipenet/physical/tile/PipeTileEntity.java | 1 + .../net/energy/EnergyCapabilityObject.java | 10 +++++++++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java index 3d2b0c9266e..d53fb8b11e8 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java @@ -3,23 +3,21 @@ import gregtech.api.util.GTUtility; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import org.jetbrains.annotations.NotNull; import java.util.Collections; -import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +@SuppressWarnings("unchecked") public final class PipeStructureRegistry { private static final Map, Set> REGISTRY = new Object2ObjectLinkedOpenHashMap<>(); public static void register(@NotNull T structure) { - Set structures = (Set) REGISTRY.get(structure.getClass()); - if (structures == null) { - structures = new LinkedHashSet<>(); - REGISTRY.put(structure.getClass(), structures); - } + Set structures = (Set) REGISTRY.computeIfAbsent(structure.getClass(), + k -> new ObjectLinkedOpenHashSet<>()); structures.add(structure); } @@ -28,8 +26,6 @@ public static void register(@NotNull T structure) { */ public static @NotNull Set getStructures(Class structureClass) { GTUtility.forceInitialization(structureClass); - Set structures = (Set) REGISTRY.get(structureClass); - if (structures == null) return Collections.emptySet(); - return structures; + return (Set) REGISTRY.getOrDefault(structureClass, Collections.emptySet()); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 41e52ec88f6..8b5889ad7ed 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -492,6 +492,7 @@ protected void initialize() { this.listeners.trim(); this.capabilities.trim(); this.netCapabilities.trim(); + updateActiveStatus(null, false); } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 5ad60648ecf..0c901ff05e5 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -69,12 +69,14 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); AbstractNetFlowEdge internalBuffer = this.internalBuffers.get(side); + long bufferOverflowAmperage = 0; if (internalBuffer != null) { long limit = internalBuffer.getFlowLimit(IPredicateTestObject.INSTANCE, net, tick, simulator); if (limit <= 0) { this.transferring = false; return 0; } else if (amperage > limit) { + bufferOverflowAmperage = amperage - limit; amperage = limit; } } @@ -89,7 +91,13 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage } long accepted = amperage - availableAmperage; - if (internalBuffer != null) data.consumeFlowLimit(internalBuffer, node, accepted); + if (internalBuffer != null) { + data.consumeFlowLimit(internalBuffer, node, accepted); + if (bufferOverflowAmperage > 0) { + data.handleOverflow(node, bufferOverflowAmperage); + accepted += bufferOverflowAmperage; + } + } if (!simulate) { EnergyGroupData group = getEnergyData(); if (group != null) { From 1adb2a6ad1dc76cb3425120b93aac222b649fe3a Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 25 Aug 2024 11:58:59 -0600 Subject: [PATCH 110/157] Fix MultiNodeHelper --- .../api/graphnet/MultiNodeHelper.java | 8 +---- .../api/graphnet/logic/NetLogicData.java | 31 +++---------------- .../pipenet/physical/tile/PipeTileEntity.java | 8 +---- 3 files changed, 7 insertions(+), 40 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java index 475085d4175..c0c32ed78f9 100644 --- a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java +++ b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java @@ -85,7 +85,6 @@ public void addNode(@NotNull NetNode node) { public void removeNode(@NotNull NetNode node) { LogicDataHandler removed = handledDatas.remove(node.getNet()); if (removed != null) { - removed.invalidate(); for (NetLogicEntry entry : this.mergedData.getEntries()) { node.getData().removeLogicEntry(entry); entry.unmerge(node); @@ -102,19 +101,14 @@ private void addNewLogicEntry(@NotNull NetLogicEntry entry) { protected class LogicDataHandler implements NetLogicData.ILogicDataListener { public final WeakReference nodeRef; - public final @NotNull NetLogicData.LogicDataListener listener; public final @NotNull NetLogicData data; public LogicDataHandler(@NotNull NetNode node) { this.data = node.getData(); - this.listener = data.createListener(this); + data.addListener(this); this.nodeRef = new WeakReference<>(node); } - public void invalidate() { - this.listener.invalidate(); - } - @Override public void markChanged(NetLogicEntry updatedEntry, boolean removed, boolean fullChange) { if (!fullChange || !updatedEntry.mergedToMultiNodeHelper()) return; diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index 0988f458855..92c11649cf8 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -2,6 +2,8 @@ import gregtech.api.network.IPacket; +import gregtech.api.util.reference.WeakHashSet; + import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -27,7 +29,7 @@ public final class NetLogicData implements INBTSerializable, IPacket // TODO caching logic on simple logics to reduce amount of reduntant creation? private final Object2ObjectOpenHashMap> logicEntrySet; - private final Set listeners = new ObjectOpenHashSet<>(); + private final WeakHashSet listeners = new WeakHashSet<>(); public NetLogicData() { logicEntrySet = new Object2ObjectOpenHashMap<>(4); @@ -155,10 +157,6 @@ public boolean hasLogicEntry(@NotNull NetLogicEntry key) { return new NetLogicData(newLogic); } - public void addListener(LogicDataListener listener) { - this.listeners.add(listener); - } - @Override public NBTTagList serializeNBT() { NBTTagList list = new NBTTagList(); @@ -211,27 +209,8 @@ public void decode(PacketBuffer buf) { } this.logicEntrySet.trim(); } - - public LogicDataListener createListener(ILogicDataListener listener) { - return new LogicDataListener(listener); - } - - public final class LogicDataListener { - - private final ILogicDataListener listener; - - private LogicDataListener(ILogicDataListener listener) { - this.listener = listener; - } - - private void markChanged(NetLogicEntry updatedEntry, boolean removed, boolean fullChange) { - this.listener.markChanged(updatedEntry, removed, fullChange); - } - - // TODO would a weak set be better? - public void invalidate() { - listeners.remove(this); - } + public void addListener(ILogicDataListener listener) { + listeners.add(listener); } @FunctionalInterface diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 8b5889ad7ed..9def4483fae 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -68,7 +68,6 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick public static final int DEFAULT_COLOR = 0xFFFFFFFF; private final Int2ObjectOpenHashMap netLogicDatas = new Int2ObjectOpenHashMap<>(); - private final ObjectOpenHashSet listeners = new ObjectOpenHashSet<>(); // information that is only required for determining graph topology should be stored on the tile entity level, // while information interacted with during graph traversal should be stored on the NetLogicData level. @@ -463,15 +462,13 @@ protected void initialize() { this.netLogicDatas.clear(); this.capabilities.clear(); this.netCapabilities.clear(); - this.listeners.forEach(NetLogicData.LogicDataListener::invalidate); - this.listeners.clear(); boolean firstNode = true; for (WorldPipeNetNode node : PipeBlock.getNodesForTile(this)) { this.addCapabilities(node.getNet().getNewCapabilityObjects(node)); this.netCapabilities.put(node, new PipeCapabilityWrapper(this, node)); int networkID = node.getNet().getNetworkID(); netLogicDatas.put(networkID, node.getData()); - var listener = node.getData().createListener( + node.getData().addListener( (e, r, f) -> writeCustomData(UPDATE_PIPE_LOGIC, buf -> { buf.writeVarInt(networkID); buf.writeString(e.getName()); @@ -481,15 +478,12 @@ protected void initialize() { e.encode(buf, f); } })); - this.listeners.add(listener); - node.getData().addListener(listener); if (firstNode) { firstNode = false; this.temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); } } this.netLogicDatas.trim(); - this.listeners.trim(); this.capabilities.trim(); this.netCapabilities.trim(); updateActiveStatus(null, false); From 134566fcb36f3173c0b3638ef3ba4c24b86aca73 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 25 Aug 2024 15:44:55 -0600 Subject: [PATCH 111/157] Misc improvements & fixes --- .../api/capability/GregtechDataCodes.java | 3 - .../api/graphnet/logic/NetLogicData.java | 14 ++-- .../api/graphnet/pipenet/NodeLossCache.java | 27 +++---- .../api/graphnet/pipenet/NodeLossResult.java | 8 ++- .../pipenet/logic/TemperatureLogic.java | 6 +- .../logic/TemperatureLossFunction.java | 4 +- .../pipenet/physical/block/PipeBlock.java | 2 +- .../pipenet/physical/tile/PipeTileEntity.java | 63 ++++++++++------ .../traverse/AbstractTraverseData.java | 4 ++ .../graphnet/traverse/TraverseHelpers.java | 2 - .../client/particle/GTOverheatParticle.java | 12 ++-- .../renderer/pipe/PipeModelRedirector.java | 3 + .../renderer/pipe/PipeModelRegistry.java | 3 + .../common/covers/CoverFluidRegulator.java | 9 +-- .../common/covers/CoverRoboticArm.java | 9 +-- .../properties/MaterialEnergyProperties.java | 4 +- .../properties/MaterialFluidProperties.java | 2 +- .../net/energy/EnergyCapabilityObject.java | 10 +-- .../net/energy/EnergyTraverseData.java | 72 +++++++++++-------- .../net/fluid/FluidRRTraverseData.java | 2 +- .../pipelike/net/fluid/FluidTraverseData.java | 6 +- .../pipelike/net/item/ItemRRTraverseData.java | 2 +- .../pipelike/net/item/ItemTraverseData.java | 2 +- 23 files changed, 158 insertions(+), 111 deletions(-) diff --git a/src/main/java/gregtech/api/capability/GregtechDataCodes.java b/src/main/java/gregtech/api/capability/GregtechDataCodes.java index 17afacb021b..a511cabec40 100644 --- a/src/main/java/gregtech/api/capability/GregtechDataCodes.java +++ b/src/main/java/gregtech/api/capability/GregtechDataCodes.java @@ -61,15 +61,12 @@ public static int assignId() { public static final int UPDATE_PAINT = assignId(); public static final int UPDATE_CONNECTIONS = assignId(); public static final int SYNC_COVER_IMPLEMENTATION = assignId(); - public static final int UPDATE_PIPE_TYPE = assignId(); - public static final int UPDATE_PIPE_MATERIAL = assignId(); public static final int UPDATE_BLOCKED_CONNECTIONS = assignId(); public static final int UPDATE_FRAME_MATERIAL = assignId(); public static final int UPDATE_COVER_DATA_PIPE = assignId(); public static final int COVER_ATTACHED_PIPE = assignId(); public static final int COVER_REMOVED_PIPE = assignId(); public static final int PIPE_ACTIVE = assignId(); - public static final int CABLE_TEMPERATURE = assignId(); public static final int UPDATE_PIPE_LOGIC = assignId(); // Multiblock implementation update codes diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index 92c11649cf8..3dfce7ee10b 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -1,7 +1,6 @@ package gregtech.api.graphnet.logic; import gregtech.api.network.IPacket; - import gregtech.api.util.reference.WeakHashSet; import net.minecraft.nbt.NBTBase; @@ -13,13 +12,10 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectCollection; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Set; - /** * Note - since the internal map representation encodes keys using {@link IStringSerializable#getName()} on logics, * making a logics class return two different names is a valid way to register multiple instances. @@ -209,8 +205,16 @@ public void decode(PacketBuffer buf) { } this.logicEntrySet.trim(); } - public void addListener(ILogicDataListener listener) { + + /** + * Adds a listener to a weak set which is then notified for as long as it is not collected by the garbage collector. + * + * @param listener the listener. + * @return the listener, for convenience when working with lambdas. + */ + public ILogicDataListener addListener(ILogicDataListener listener) { listeners.add(listener); + return listener; } @FunctionalInterface diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java index 7d5dd25b583..51b03c5cce4 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java @@ -1,6 +1,5 @@ package gregtech.api.graphnet.pipenet; -import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.ITraverseData; import gregtech.api.util.TaskScheduler; @@ -19,22 +18,22 @@ public class NodeLossCache implements Task { private static final WeakHashMap CACHE = new WeakHashMap<>(); - public static void registerLossResult(Key key, NodeLossResult result) { + public static void registerLossResult(Key key, NodeLossResult result, boolean simulating) { NodeLossCache existing = CACHE.get(key.node().getNet()); if (existing == null) { existing = new NodeLossCache(key.node().getNet().getWorld()); CACHE.put(key.node().getNet(), existing); } - existing.registerResult(key, result); + existing.registerResult(key, result, simulating); } - public static @Nullable NodeLossResult getLossResult(Key key) { + public static @Nullable NodeLossResult getLossResult(Key key, boolean simulating) { NodeLossCache existing = CACHE.get(key.node().getNet()); if (existing == null) { existing = new NodeLossCache(key.node().getNet().getWorld()); CACHE.put(key.node().getNet(), existing); } - return existing.getResult(key); + return existing.getResult(key, simulating); } private final Map cache = new Object2ObjectOpenHashMap<>(); @@ -43,32 +42,36 @@ private NodeLossCache(World world) { TaskScheduler.scheduleTask(world, TaskScheduler.weakTask(this)); } - public void registerResult(Key key, NodeLossResult result) { + public void registerResult(Key key, NodeLossResult result, boolean simulating) { + result.simulated = simulating; cache.put(key, result); } - public @Nullable NodeLossResult getResult(Key key) { - return cache.get(key); + public @Nullable NodeLossResult getResult(Key key, boolean simulating) { + NodeLossResult result = cache.get(key); + if (!simulating && result != null && result.simulated) result.simulated = false; + return result; } @Override public boolean run() { if (cache.isEmpty()) return true; for (var result : cache.entrySet()) { + if (result.getValue().simulated) continue; result.getValue().triggerPostAction(result.getKey().node()); } cache.clear(); return true; } - public static Key key(WorldPipeNetNode node, IPredicateTestObject testObject, SimulatorKey simulator) { - return new Key(node, testObject, simulator); + public static Key key(WorldPipeNetNode node, IPredicateTestObject testObject) { + return new Key(node, testObject); } public static Key key(WorldPipeNetNode node, ITraverseData data) { - return new Key(node, data.getTestObject(), data.getSimulatorKey()); + return new Key(node, data.getTestObject()); } @Desugar - public record Key(WorldPipeNetNode node, IPredicateTestObject testObject, SimulatorKey simulator) {} + public record Key(WorldPipeNetNode node, IPredicateTestObject testObject) {} } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java index e5a6b18099b..e3cfd778aaa 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java @@ -16,6 +16,8 @@ public final class NodeLossResult { private final @Nullable Consumer postAction; private final @NotNull ReversibleLossOperator lossFunction; + boolean simulated = true; + public NodeLossResult(@Nullable Consumer postAction, @NotNull ReversibleLossOperator lossFunction) { this.postAction = postAction; @@ -38,10 +40,14 @@ public boolean hasPostAction() { return postAction != null; } - public Consumer getPostAction() { + public @Nullable Consumer getPostAction() { return postAction; } + public NodeLossResult copy() { + return new NodeLossResult(postAction, lossFunction); + } + public void triggerPostAction(WorldPipeNetNode node) { if (postAction == null) return; this.postAction.accept(node); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index bc8bb261f51..fffb0c717d2 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -17,7 +17,6 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -245,6 +244,10 @@ public int getThermalMass() { return thermalMass; } + public long getLastRestorationTick() { + return lastRestorationTick; + } + @Override public boolean mergedToMultiNodeHelper() { return true; @@ -312,7 +315,6 @@ public void encode(PacketBuffer buf, boolean fullChange) { @Override public void decode(PacketBuffer buf, boolean fullChange) { - this.lastRestorationTick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); this.energy = buf.readFloat(); if (fullChange) { this.temperatureMaximum = buf.readVarInt(); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java index e32acca8355..c77d3cd417d 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLossFunction.java @@ -41,7 +41,7 @@ public float restoreTemperature(float energy, int timePassed) { public static TemperatureLossFunction getOrCreateCable(float factor) { TemperatureLossFunction function = CABLE_LOSS_CACHE.get(factor); if (function == null) { - function = new TemperatureLossFunction(EnumLossFunction.WEAK_SCALING, factor, 0.35f); + function = new TemperatureLossFunction(EnumLossFunction.WEAK_SCALING, factor * 10, 0.35f); CABLE_LOSS_CACHE.put(factor, function); } return function; @@ -51,7 +51,7 @@ public static TemperatureLossFunction getOrCreatePipe(float factor) { TemperatureLossFunction function = PIPE_LOSS_CACHE.get(factor); if (function == null) { // since pipes are hollow the exponent is larger - function = new TemperatureLossFunction(EnumLossFunction.WEAK_SCALING, factor, 0.45f); + function = new TemperatureLossFunction(EnumLossFunction.WEAK_SCALING, factor * 10, 0.4f); PIPE_LOSS_CACHE.put(factor, function); } return function; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 816142bbcf9..78b6bd8ba63 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -631,7 +631,7 @@ public int getMetaFromState(@NotNull IBlockState state) { @NotNull BlockPos pos) { PipeTileEntity tile = getTileEntity(worldIn, pos); if (tile == null) return state; - state = writeConnectionMask(state, tile.getConnectionMask()); + state = writeConnectionMask(state, tile.getCoverAdjustedConnectionMask()); return state.withProperty(FRAMED, tile.getFrameMaterial() != null); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 9def4483fae..f6b2b207a07 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -68,6 +68,7 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick public static final int DEFAULT_COLOR = 0xFFFFFFFF; private final Int2ObjectOpenHashMap netLogicDatas = new Int2ObjectOpenHashMap<>(); + private final ObjectOpenHashSet listeners = new ObjectOpenHashSet<>(); // information that is only required for determining graph topology should be stored on the tile entity level, // while information interacted with during graph traversal should be stored on the NetLogicData level. @@ -193,6 +194,17 @@ public byte getConnectionMask() { return connectionMask; } + public byte getCoverAdjustedConnectionMask() { + byte connectionMask = this.connectionMask; + for (EnumFacing facing : EnumFacing.VALUES) { + Cover cover = getCoverHolder().getCoverAtSide(facing); + if (cover != null) { + if (cover.forcePipeRenderConnection()) connectionMask |= 1 << facing.ordinal(); + } + } + return connectionMask; + } + public void setBlocked(EnumFacing facing) { this.blockedMask |= 1 << facing.ordinal(); syncBlocked(); @@ -462,22 +474,17 @@ protected void initialize() { this.netLogicDatas.clear(); this.capabilities.clear(); this.netCapabilities.clear(); + this.listeners.clear(); boolean firstNode = true; for (WorldPipeNetNode node : PipeBlock.getNodesForTile(this)) { this.addCapabilities(node.getNet().getNewCapabilityObjects(node)); this.netCapabilities.put(node, new PipeCapabilityWrapper(this, node)); int networkID = node.getNet().getNetworkID(); netLogicDatas.put(networkID, node.getData()); - node.getData().addListener( - (e, r, f) -> writeCustomData(UPDATE_PIPE_LOGIC, buf -> { - buf.writeVarInt(networkID); - buf.writeString(e.getName()); - buf.writeBoolean(r); - buf.writeBoolean(f); - if (!r) { - e.encode(buf, f); - } - })); + listeners.add(node.getData().addListener((e, r, f) -> writeLogicData(networkID, e, r, f))); + for (NetLogicEntry entry : node.getData().getEntries()) { + writeLogicData(networkID, entry, false, true); + } if (firstNode) { firstNode = false; this.temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); @@ -486,10 +493,23 @@ protected void initialize() { this.netLogicDatas.trim(); this.capabilities.trim(); this.netCapabilities.trim(); + this.listeners.trim(); updateActiveStatus(null, false); } } + private void writeLogicData(int networkID, NetLogicEntry entry, boolean removed, boolean fullChange) { + writeCustomData(UPDATE_PIPE_LOGIC, buf -> { + buf.writeVarInt(networkID); + buf.writeString(entry.getName()); + buf.writeBoolean(removed); + buf.writeBoolean(fullChange); + if (!removed) { + entry.encode(buf, fullChange); + } + }); + } + @Override public @NotNull NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { super.writeToNBT(compound); @@ -577,18 +597,15 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { if (fullChange) { NetLogicEntry logic = NetLogicRegistry.getSupplierErroring(identifier).get(); logic.decode(buf, true); - this.netLogicDatas.compute(networkID, (k, v) -> { - if (v == null) v = new NetLogicData(); - v.setLogicEntry(logic); - return v; - }); + this.netLogicDatas.computeIfAbsent(networkID, k -> new NetLogicData()).setLogicEntry(logic); } else { NetLogicData data = this.netLogicDatas.get(networkID); - if (data != null) { - NetLogicEntry entry = data.getLogicEntryNullable(identifier); - if (entry != null) entry.decode(buf, false); + if (data == null) return; + NetLogicEntry entry = data.getLogicEntryNullable(identifier); + if (entry != null) { + entry.decode(buf, false); data.markLogicEntryAsUpdated(entry, false); - } else return; + } } if (identifier.equals(TemperatureLogic.INSTANCE.getName())) { TemperatureLogic tempLogic = this.netLogicDatas.get(networkID) @@ -717,12 +734,10 @@ public void markAsDirty() { @MustBeInvokedByOverriders public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { byte frameMask = 0; - byte connectionMask = this.connectionMask; for (EnumFacing facing : EnumFacing.VALUES) { Cover cover = getCoverHolder().getCoverAtSide(facing); if (cover != null) { frameMask |= 1 << facing.ordinal(); - if (cover.forcePipeRenderConnection()) connectionMask |= 1 << facing.ordinal(); } } frameMask = (byte) ~frameMask; @@ -735,6 +750,12 @@ public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { .withProperty(CoverRendererPackage.PROPERTY, getCoverHolder().createPackage()); } + @Override + public void scheduleRenderUpdate() { + super.scheduleRenderUpdate(); + if (overheatParticle != null) overheatParticle.updatePipeBoxes(getStructure().getPipeBoxes(this)); + } + public void getCoverBoxes(Consumer consumer) { for (EnumFacing facing : EnumFacing.VALUES) { if (getCoverHolder().hasCover(facing)) { diff --git a/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java index 0b947be53ed..6c4b71f194f 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java @@ -38,6 +38,10 @@ public IPredicateTestObject getTestObject() { return simulator; } + public boolean simulating() { + return simulator != null; + } + @Override public long getQueryTick() { return queryTick; diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index a9a7f8e6a04..0178ce36076 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -127,7 +127,6 @@ D extends ITraverseData> long traverseDumb( for (int i = 0; i < edges.size(); i++) { E edge = edges.get(i); - N sourceNode = nodes.get(i); N targetNode = nodes.get(i + 1); if (targetNode.traverse(data.getQueryTick(), true)) { @@ -453,7 +452,6 @@ P extends INetPath, D extends ITraverseData & IRoundRobinTraverseDat for (int i = 0; i < edges.size(); i++) { E edge = edges.get(i); - N sourceNode = nodes.get(i); N targetNode = nodes.get(i + 1); if (targetNode.traverse(data.getQueryTick(), true)) { diff --git a/src/main/java/gregtech/client/particle/GTOverheatParticle.java b/src/main/java/gregtech/client/particle/GTOverheatParticle.java index 82f8470c41b..02c29c666c4 100644 --- a/src/main/java/gregtech/client/particle/GTOverheatParticle.java +++ b/src/main/java/gregtech/client/particle/GTOverheatParticle.java @@ -19,7 +19,6 @@ import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; -import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -168,14 +167,9 @@ public GTOverheatParticle(@NotNull PipeTileEntity tileEntity, @NotNull Temperatu this.insulated = insulated; } - private int getTemperature() { - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - return temperatureLogic.getTemperature(tick); - } - public void updatePipeBoxes(@NotNull List pipeBoxes) { this.pipeBoxes = pipeBoxes; - pipeBoxes.replaceAll(axisAlignedBB -> axisAlignedBB.expand(0.001, 0.001, 0.001)); + pipeBoxes.replaceAll(axisAlignedBB -> axisAlignedBB.expand(0.003, 0.003, 0.003)); } public void setTemperatureLogic(@NotNull TemperatureLogic logic) { @@ -189,7 +183,9 @@ public void onUpdate() { tileEntity.killOverheatParticle(); return; } - int temperature = getTemperature(); + + // onUpdate is called once per tick + int temperature = temperatureLogic.getTemperature(temperatureLogic.getLastRestorationTick() + 1); if (temperature <= TEMPERATURE_CUTOFF || temperature > temperatureLogic.getTemperatureMaximum()) { setExpired(); diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java b/src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java index 8581b388dc4..e39e2dc27fe 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java @@ -15,6 +15,8 @@ import net.minecraft.util.EnumFacing; import net.minecraft.world.World; import net.minecraftforge.common.property.IExtendedBlockState; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; @@ -25,6 +27,7 @@ import java.util.Optional; import java.util.function.Function; +@SideOnly(Side.CLIENT) public class PipeModelRedirector implements IBakedModel { private final boolean ambientOcclusion; diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java b/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java index f9340a52c49..359fb5125c6 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java @@ -12,12 +12,15 @@ import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.util.ResourceLocation; import net.minecraft.util.registry.IRegistry; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Range; +@SideOnly(Side.CLIENT) public final class PipeModelRegistry { public static final int PIPE_MODEL_COUNT = 7; diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 06b6e0f4815..7ff0df71b54 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -309,8 +309,7 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (contained >= kept) continue; availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, - getSimulatorKey() == null); + (int) Math.min(kept - contained, availableFlow), container, !simulating()); } } return flowReachingDestination - availableFlow; @@ -371,8 +370,7 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (contained >= kept) continue; availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, - getSimulatorKey() == null); + (int) Math.min(kept - contained, availableFlow), container, !simulating()); } } return flowReachingDestination - availableFlow; @@ -405,8 +403,7 @@ public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData= kept) continue; availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, - getSimulatorKey() != null); + (int) Math.min(kept - contained, availableFlow), container, simulating()); } } return flowReachingDestination - availableFlow; @@ -383,8 +382,7 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (contained >= kept) continue; availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, - getSimulatorKey() != null); + (int) Math.min(kept - contained, availableFlow), container, simulating()); } } return flowReachingDestination - availableFlow; @@ -416,8 +414,7 @@ public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData= kept) return 0; availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(pointerFacing)).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, - getSimulatorKey() != null); + (int) Math.min(kept - contained, availableFlow), container, simulating()); } return flowReachingDestination - availableFlow; } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index af7e414b780..9b446b36e04 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -179,7 +179,7 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) - .setLogicEntry(TemperatureLogic.INSTANCE + .mergeLogicEntry(TemperatureLogic.INSTANCE .getWith(TemperatureLossFunction.getOrCreateCable(coolingFactor), materialMeltTemperature, 1, 100 * cable.material(), cable.partialBurnThreshold())); @@ -195,7 +195,7 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) - .setLogicEntry(TemperatureLogic.INSTANCE + .mergeLogicEntry(TemperatureLogic.INSTANCE .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), materialMeltTemperature, 1, 50 * pipe.material(), null)); if (superconductorCriticalTemperature > 0) { diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index 14bd462343c..b77fc8b1d9e 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -184,7 +184,7 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)) .setLogicEntry(FluidContainmentLogic.INSTANCE.getWith(containableStates, containableAttributes, maxFluidTemperature)) - .setLogicEntry(TemperatureLogic.INSTANCE + .mergeLogicEntry(TemperatureLogic.INSTANCE .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), materialMeltTemperature, minFluidTemperature, 50 * pipe.material(), null)); } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 0c901ff05e5..2558f7da51a 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -77,14 +77,14 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage return 0; } else if (amperage > limit) { bufferOverflowAmperage = amperage - limit; - amperage = limit; } } long availableAmperage = amperage; EnergyTraverseData data = new EnergyTraverseData(net, IPredicateTestObject.INSTANCE, simulator, tick, voltage, - tile.getPos(), side); - availableAmperage -= TraverseHelpers.traverseFlood(data, getPaths(data), availableAmperage); + tile.getPos(), side, bufferOverflowAmperage); + availableAmperage -= TraverseHelpers.traverseFlood(data, getPaths(data), + availableAmperage - bufferOverflowAmperage); if (availableAmperage > 0) { availableAmperage -= TraverseHelpers.traverseDumb(data, getPaths(data), data::handleOverflow, availableAmperage); @@ -92,7 +92,9 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage long accepted = amperage - availableAmperage; if (internalBuffer != null) { - data.consumeFlowLimit(internalBuffer, node, accepted); + data.resetPathVoltage(); + bufferOverflowAmperage = data.calculateActualBufferOverflow(bufferOverflowAmperage); + data.consumeFlowLimit(internalBuffer, node, accepted - bufferOverflowAmperage); if (bufferOverflowAmperage > 0) { data.handleOverflow(node, bufferOverflowAmperage); accepted += bufferOverflowAmperage; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index 875278dae18..fd3fc1ca5bd 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -22,43 +22,46 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; -import java.util.function.Supplier; - public class EnergyTraverseData extends AbstractTraverseData { private final Object2ObjectOpenHashMap overVoltageInformation; private final long startVoltage; private long pathVoltage; + private long bufferOverflow; private final BlockPos sourcePos; private final EnumFacing inputFacing; public EnergyTraverseData(IGraphNet net, IPredicateTestObject testObject, SimulatorKey simulator, long queryTick, - long startVoltage, BlockPos sourcePos, EnumFacing inputFacing) { + long startVoltage, BlockPos sourcePos, EnumFacing inputFacing, long bufferOverflow) { super(net, testObject, simulator, queryTick); this.overVoltageInformation = new Object2ObjectOpenHashMap<>(); this.startVoltage = startVoltage; this.sourcePos = sourcePos; this.inputFacing = inputFacing; + this.bufferOverflow = bufferOverflow; } @Override public boolean prepareForPathWalk(@NotNull FlowWorldPipeNetPath path, long flow) { if (flow <= 0) return true; - this.pathVoltage = startVoltage; + resetPathVoltage(); this.overVoltageInformation.clear(); this.overVoltageInformation.trim(10); return false; } + public void resetPathVoltage() { + this.pathVoltage = startVoltage; + } + @Override public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, long flowReachingNode) { VoltageLimitLogic limitLogic = node.getData().getLogicEntryNullable(VoltageLimitLogic.INSTANCE); if (limitLogic != null) { long voltage = limitLogic.getValue(); - if (voltage < pathVoltage) overVoltageInformation.put(node, - new OverVoltageInformation(voltage, flowReachingNode)); + if (voltage < pathVoltage) overVoltageInformation.put(node, new OverVoltageInformation(voltage)); } TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); if (!node.getData().getLogicEntryDefaultable(SuperconductorLogic.INSTANCE) @@ -68,7 +71,7 @@ public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, lon } NodeLossCache.Key key = NodeLossCache.key(node, this); - NodeLossResult result = NodeLossCache.getLossResult(key); + NodeLossResult result = NodeLossCache.getLossResult(key, simulating()); if (result != null) { return result.getLossFunction(); } else { @@ -76,25 +79,40 @@ public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, lon if (result == null) { return ReversibleLossOperator.IDENTITY; } - if (result.hasPostAction()) NodeLossCache.registerLossResult(key, result); + if (result.hasPostAction()) NodeLossCache.registerLossResult(key, result, simulating()); return result.getLossFunction(); } } public void handleOverflow(@NotNull WorldPipeNetNode node, long overflow) { - TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); - if (logic != null) { - // this occurs after finalization but before path reset. - logic.applyThermalEnergy(calculateHeatA(overflow, pathVoltage), getQueryTick()); + if (bufferOverflow > 0) { + long difference = bufferOverflow - overflow; + if (difference < 0) { + overflow -= bufferOverflow; + bufferOverflow = 0; + } else { + bufferOverflow -= overflow; + return; + } + } + if (overflow > 0) { + TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + if (logic != null) { + // this occurs after finalization but before path reset. + logic.applyThermalEnergy(calculateHeatA(overflow, pathVoltage), getQueryTick()); + } } } + public long calculateActualBufferOverflow(long startingOverflow) { + return startingOverflow - bufferOverflow; + } + @Override public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { this.pathVoltage = (long) GTUtility.geometricMean(pathVoltage, overVoltageInformation.values().stream().filter(o -> o.voltageCap < this.pathVoltage) .mapToDouble(o -> (double) o.voltageCap).toArray()); - overVoltageInformation.forEach((k, v) -> v.doHeating(k, pathVoltage, getQueryTick())); long availableFlow = flowReachingDestination; for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && @@ -106,11 +124,11 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl if (container != null) { availableFlow -= IEnergyTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(pathVoltage, availableFlow, container, - capability.getKey(), getSimulatorKey() != null); + capability.getKey(), simulating()); } } long accepted = flowReachingDestination - availableFlow; - if (getSimulatorKey() == null && destination.getGroupUnsafe() != null && + if (!simulating() && destination.getGroupUnsafe() != null && destination.getGroupSafe().getData() instanceof EnergyGroupData data) { data.addEnergyOutPerSec(accepted * pathVoltage, getQueryTick()); } @@ -121,7 +139,11 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { super.consumeFlowLimit(edge, targetNode, consumption); - if (consumption > 0) recordFlow(targetNode, consumption); + if (consumption > 0 && !simulating()) { + recordFlow(targetNode, consumption); + OverVoltageInformation info = overVoltageInformation.get((WorldPipeNetNode) targetNode); + if (info != null) info.doHeating((WorldPipeNetNode) targetNode, pathVoltage, getQueryTick(), consumption); + } } private void recordFlow(@NotNull NetNode node, long amperes) { @@ -134,30 +156,22 @@ private void recordFlow(@NotNull NetNode node, long amperes) { } private static int calculateHeatV(long amperage, long voltage, long maxVoltage) { - return (int) (amperage * (Math.log1p(Math.log((double) voltage / maxVoltage)) * 45 + 36.5)); + return (int) (amperage * (Math.log1p(4 * Math.log((double) voltage / maxVoltage)) * 85 + 36)); } private static int calculateHeatA(long amperage, long voltage) { - return (int) (amperage * (Math.log1p(Math.log((double) voltage)) * 45 + 36.5)); + return (int) (amperage * (Math.log1p(4 * Math.log1p(Math.log((double) voltage))) * 85 + 36)); } - protected static class OverVoltageInformation implements Supplier { + protected static class OverVoltageInformation { public final long voltageCap; - private final long amperage; - - public OverVoltageInformation(long voltageCap, long amperage) { + public OverVoltageInformation(long voltageCap) { this.voltageCap = voltageCap; - this.amperage = amperage; - } - - @Override - public Long get() { - return voltageCap; } - public void doHeating(WorldPipeNetNode node, long finalVoltage, long tick) { + public void doHeating(WorldPipeNetNode node, long finalVoltage, long tick, long amperage) { TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); if (logic != null) { logic.applyThermalEnergy(calculateHeatV(amperage, finalVoltage, voltageCap), tick); diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java index 260c4de33d4..92d424c395c 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java @@ -55,7 +55,7 @@ public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData Date: Tue, 27 Aug 2024 15:11:42 -0600 Subject: [PATCH 112/157] Split of world handling & world pos handling --- .../api/graphnet/pipenet/WorldPipeNet.java | 4 +- .../graphnet/pipenet/WorldPipeNetNode.java | 4 +- .../api/graphnet/worldnet/WorldNet.java | 25 ---------- .../api/graphnet/worldnet/WorldPosNet.java | 49 +++++++++++++++++++ ...WorldNetNode.java => WorldPosNetNode.java} | 10 ++-- 5 files changed, 58 insertions(+), 34 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java rename src/main/java/gregtech/api/graphnet/worldnet/{WorldNetNode.java => WorldPosNetNode.java} (76%) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 09c1de55427..56502dacb1f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -10,7 +10,7 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.EdgePredicate; -import gregtech.api.graphnet.worldnet.WorldNet; +import gregtech.api.graphnet.worldnet.WorldPosNet; import gregtech.api.util.IDirtyNotifiable; import gregtech.api.util.reference.WeakHashSet; @@ -34,7 +34,7 @@ import java.util.function.Function; import java.util.stream.Stream; -public abstract class WorldPipeNet extends WorldNet { +public abstract class WorldPipeNet extends WorldPosNet { public static final int MULTI_NET_TIMEOUT = 10; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java index 97a364f8912..98f2d8962b0 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java @@ -3,7 +3,7 @@ import gregtech.api.graphnet.MultiNodeHelper; import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.worldnet.WorldNetNode; +import gregtech.api.graphnet.worldnet.WorldPosNetNode; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; @@ -14,7 +14,7 @@ import java.lang.ref.WeakReference; -public final class WorldPipeNetNode extends WorldNetNode { +public final class WorldPipeNetNode extends WorldPosNetNode { private static final PipeTileEntity FALLBACK = new PipeTileEntity(); diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java index 3a513cc1259..8f3a944eff8 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -14,7 +14,6 @@ import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.storage.WorldSavedData; @@ -56,26 +55,12 @@ public Iterator getPaths(NetNode node, IPredicateTestObject return backer.getPaths(node, 0, GenericGraphNetPath.MAPPER, testObject, simulator, queryTick); } - @NotNull - public WorldNetNode getOrCreateNode(@NotNull BlockPos pos) { - WorldNetNode node = getNode(pos); - if (node != null) return node; - node = getNewNode(); - node.setPos(pos); - addNode(node); - return node; - } - @Override public void addNode(@NotNull NetNode node) { nodeClassCheck(node); this.backer.addNode(node); } - public @Nullable WorldNetNode getNode(@NotNull BlockPos equivalencyData) { - return (WorldNetNode) getNode((Object) equivalencyData); - } - @Override public @Nullable NetNode getNode(@NotNull Object equivalencyData) { return backer.getNode(equivalencyData); @@ -140,14 +125,4 @@ public void readFromNBT(@NotNull NBTTagCompound nbt) { public GraphNetBacker getBacker() { return backer; } - - @Override - public Class getNodeClass() { - return WorldNetNode.class; - } - - @Override - public @NotNull WorldNetNode getNewNode() { - return new WorldNetNode(this); - } } diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java new file mode 100644 index 00000000000..cfcd4433355 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java @@ -0,0 +1,49 @@ +package gregtech.api.graphnet.worldnet; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.alg.AlgorithmBuilder; +import gregtech.api.graphnet.graph.INetGraph; + +import net.minecraft.util.math.BlockPos; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Function; + +public abstract class WorldPosNet extends WorldNet { + + public WorldPosNet(String name, @NotNull Function graphBuilder, + AlgorithmBuilder... algorithmBuilders) { + super(name, graphBuilder, algorithmBuilders); + } + + public WorldPosNet(String name, boolean directed, AlgorithmBuilder... algorithmBuilders) { + super(name, directed, algorithmBuilders); + } + + @NotNull + public WorldPosNetNode getOrCreateNode(@NotNull BlockPos pos) { + WorldPosNetNode node = getNode(pos); + if (node != null) return node; + node = getNewNode(); + node.setPos(pos); + addNode(node); + return node; + } + + public @Nullable WorldPosNetNode getNode(@NotNull BlockPos equivalencyData) { + return (WorldPosNetNode) getNode((Object) equivalencyData); + } + + @Override + public Class getNodeClass() { + return WorldPosNetNode.class; + } + + @Override + public @NotNull WorldPosNetNode getNewNode() { + return new WorldPosNetNode(this); + } +} diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNetNode.java similarity index 76% rename from src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java rename to src/main/java/gregtech/api/graphnet/worldnet/WorldPosNetNode.java index 904a13c88be..d6dfc872cda 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNetNode.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNetNode.java @@ -7,20 +7,20 @@ import org.jetbrains.annotations.NotNull; -public class WorldNetNode extends NetNode { +public class WorldPosNetNode extends NetNode { private BlockPos pos; - public WorldNetNode(WorldNet net) { + public WorldPosNetNode(WorldPosNet net) { super(net); } @Override - public @NotNull WorldNet getNet() { - return (WorldNet) super.getNet(); + public @NotNull WorldPosNet getNet() { + return (WorldPosNet) super.getNet(); } - public WorldNetNode setPos(BlockPos pos) { + public WorldPosNetNode setPos(BlockPos pos) { this.pos = pos; return this; } From dcb9587a8bffbcc79784ddf55894fe8f15feba9b Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 29 Aug 2024 13:33:23 -0600 Subject: [PATCH 113/157] Reference tweaks --- .../reference/ExpiringReferenceHashSet.java | 114 ------------ .../reference/RegeneratingSoftReference.java | 44 +++++ .../api/util/reference/SoftHashSet.java | 46 ----- .../api/util/reference/WeakHashSet.java | 169 +++++++++++++----- .../renderer/pipe/PipeModelRedirector.java | 2 +- .../renderer/pipe/PipeModelRegistry.java | 2 +- .../renderer/pipe/cache/ColorQuadCache.java | 16 +- .../MetaTileEntityComputationHatch.java | 6 - .../MetaTileEntityOpticalDataHatch.java | 6 - 9 files changed, 182 insertions(+), 223 deletions(-) delete mode 100644 src/main/java/gregtech/api/util/reference/ExpiringReferenceHashSet.java create mode 100644 src/main/java/gregtech/api/util/reference/RegeneratingSoftReference.java delete mode 100644 src/main/java/gregtech/api/util/reference/SoftHashSet.java diff --git a/src/main/java/gregtech/api/util/reference/ExpiringReferenceHashSet.java b/src/main/java/gregtech/api/util/reference/ExpiringReferenceHashSet.java deleted file mode 100644 index d0be91f036c..00000000000 --- a/src/main/java/gregtech/api/util/reference/ExpiringReferenceHashSet.java +++ /dev/null @@ -1,114 +0,0 @@ -package gregtech.api.util.reference; - -import it.unimi.dsi.fastutil.objects.AbstractObjectIterator; -import it.unimi.dsi.fastutil.objects.AbstractObjectSet; -import it.unimi.dsi.fastutil.objects.ObjectIterator; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.Nullable; - -public abstract class ExpiringReferenceHashSet extends AbstractObjectSet { - - private final ObjectOpenHashSet> backer = new ObjectOpenHashSet<>(); - - @Override - public int size() { - return backer.size(); - } - - @Override - public boolean isEmpty() { - return backer.isEmpty(); - } - - @Override - public boolean contains(Object o) { - // noinspection unchecked - return backer.contains(wrapObject((T) o)); - } - - @Override - public ObjectIterator iterator() { - return new SetIterator(); - } - - @Override - public boolean add(T t) { - return backer.add(wrapObject(t)); - } - - public void clearStaleEntries() { - // iteration automatically removes stale entries. - // noinspection StatementWithEmptyBody - for (T ignored : this); - } - - /** - * Clears stale entries and then performs {@link ObjectOpenHashSet#trim()} - */ - public void trim() { - clearStaleEntries(); - backer.trim(); - } - - /** - * Clears stale entries and then performs {@link ObjectOpenHashSet#trim(int)} - */ - public void trim(final int n) { - clearStaleEntries(); - backer.trim(n); - } - - protected abstract ExpiringReference wrapObject(T obj); - - /** - * Implementations must override equals() and hashCode() with calls to their referenced object. - * If expired, return false or 0. - */ - protected interface ExpiringReference { - - @Nullable - T get(); - - default boolean expired() { - return get() == null; - } - } - - protected class SetIterator extends AbstractObjectIterator { - - protected final ObjectIterator> backer = ExpiringReferenceHashSet.this.backer.iterator(); - - protected T next; - - @Override - public boolean hasNext() { - if (!backer.hasNext()) return false; - if (this.next == null) computeNext(); - return this.next != null; - } - - @Override - public T next() { - if (this.next == null) computeNext(); - T next = this.next; - this.next = null; - return next; - } - - protected void computeNext() { - while (true) { - ExpiringReference ref = backer.next(); - this.next = ref.get(); - if (ref.expired()) { - backer.remove(); - } else break; - if (!backer.hasNext()) break; - } - } - - @Override - public void remove() { - backer.remove(); - } - } -} diff --git a/src/main/java/gregtech/api/util/reference/RegeneratingSoftReference.java b/src/main/java/gregtech/api/util/reference/RegeneratingSoftReference.java new file mode 100644 index 00000000000..6f6cc8f9e2f --- /dev/null +++ b/src/main/java/gregtech/api/util/reference/RegeneratingSoftReference.java @@ -0,0 +1,44 @@ +package gregtech.api.util.reference; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.SoftReference; +import java.util.function.Supplier; + +public class RegeneratingSoftReference implements Supplier { + + private final @Nullable ReferenceQueue q; + private final @NotNull Supplier regenerator; + private @NotNull SoftReference reference; + + public RegeneratingSoftReference(@NotNull T initialReference, @NotNull Supplier regenerator, + @Nullable ReferenceQueue q) { + this.q = q; + this.reference = new SoftReference<>(initialReference, q); + this.regenerator = regenerator; + } + + public RegeneratingSoftReference(@NotNull Supplier regenerator, @Nullable ReferenceQueue q) { + this(regenerator.get(), regenerator, q); + } + + public RegeneratingSoftReference(@NotNull T initialReference, @NotNull Supplier regenerator) { + this(initialReference, regenerator, null); + } + + public RegeneratingSoftReference(@NotNull Supplier regenerator) { + this(regenerator.get(), regenerator); + } + + @Override + public T get() { + T fetch = reference.get(); + if (fetch == null) { + fetch = regenerator.get(); + reference = new SoftReference<>(fetch, q); + } + return fetch; + } +} diff --git a/src/main/java/gregtech/api/util/reference/SoftHashSet.java b/src/main/java/gregtech/api/util/reference/SoftHashSet.java deleted file mode 100644 index a585188754f..00000000000 --- a/src/main/java/gregtech/api/util/reference/SoftHashSet.java +++ /dev/null @@ -1,46 +0,0 @@ -package gregtech.api.util.reference; - -import java.lang.ref.SoftReference; -import java.util.Objects; - -public class SoftHashSet extends ExpiringReferenceHashSet { - - @Override - protected ExpiringReference wrapObject(T obj) { - return new Reference(obj); - } - - protected class Reference extends SoftReference implements ExpiringReference { - - public Reference(T referent) { - super(referent); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - Reference that; - try { - // noinspection unchecked - that = (Reference) obj; - } catch (ClassCastException e) { - return false; - } - - T contained = this.get(); - T other = that.get(); - if (this.expired() || that.expired()) return false; - return Objects.equals(contained, other); - } - - @Override - public int hashCode() { - T contained = this.get(); - if (contained == null) { - return 0; - } - return contained.hashCode(); - } - } -} diff --git a/src/main/java/gregtech/api/util/reference/WeakHashSet.java b/src/main/java/gregtech/api/util/reference/WeakHashSet.java index 110cb559f2f..2a3dfa62d08 100644 --- a/src/main/java/gregtech/api/util/reference/WeakHashSet.java +++ b/src/main/java/gregtech/api/util/reference/WeakHashSet.java @@ -1,46 +1,135 @@ package gregtech.api.util.reference; -import java.lang.ref.WeakReference; +import org.jetbrains.annotations.NotNull; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; import java.util.Objects; +import java.util.Set; +import java.util.Spliterator; +import java.util.WeakHashMap; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Stream; + +/** + * Replica of {@link java.util.Collections.SetFromMap} for {@link WeakHashMap} to allow for greater type specificity + * than the {@link java.util.Set} interface. + */ +public class WeakHashSet extends AbstractSet { + + private final WeakHashMap m = new WeakHashMap<>(); + + private final transient Set s = m.keySet(); + + @Override + public void clear() { + m.clear(); + } + + @Override + public int size() { + return m.size(); + } + + @Override + public boolean isEmpty() { + return m.isEmpty(); + } + + // TODO access WeakHashMap#getEntry somehow + // public E get(Object o) { + // } + + @SuppressWarnings("SuspiciousMethodCalls") + @Override + public boolean contains(Object o) { + return m.containsKey(o); + } + + @Override + public boolean remove(Object o) { + return m.remove(o) != null; + } + + @Override + public boolean add(E e) { + return m.put(e, null) == null; + } + + @Override + public Iterator iterator() { + return s.iterator(); + } + + @Override + public Object[] toArray() { + return s.toArray(); + } + + @Override + public T[] toArray(T @NotNull [] a) { + return s.toArray(a); + } -public class WeakHashSet extends ExpiringReferenceHashSet { - - @Override - protected ExpiringReference wrapObject(T obj) { - return new Reference(obj); - } - - protected class Reference extends WeakReference implements ExpiringReference { - - public Reference(T referent) { - super(referent); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - Reference that; - try { - // noinspection unchecked - that = (Reference) obj; - } catch (ClassCastException e) { - return false; - } - - T contained = this.get(); - T other = that.get(); - if (this.expired() || that.expired()) return false; - return Objects.equals(contained, other); - } - - @Override - public int hashCode() { - T contained = this.get(); - if (contained == null || this.expired()) { - return 0; - } - return contained.hashCode(); - } + @Override + public String toString() { + return s.toString(); + } + + @Override + public int hashCode() { + return s.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + WeakHashSet that = (WeakHashSet) o; + return Objects.equals(s, that.s); + } + + @Override + public boolean containsAll(@NotNull Collection c) { + return s.containsAll(c); + } + + @Override + public boolean removeAll(Collection c) { + return s.removeAll(c); + } + + @Override + public boolean retainAll(@NotNull Collection c) { + return s.retainAll(c); + } + // addAll is the only inherited implementation + + @Override + public void forEach(Consumer action) { + s.forEach(action); + } + + @Override + public boolean removeIf(Predicate filter) { + return s.removeIf(filter); + } + + @Override + public Spliterator spliterator() { + return s.spliterator(); + } + + @Override + public Stream stream() { + return s.stream(); + } + + @Override + public Stream parallelStream() { + return s.parallelStream(); } } diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java b/src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java index e39e2dc27fe..09fdd98556e 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModelRedirector.java @@ -100,7 +100,7 @@ public ModelResourceLocation getLoc() { } @FunctionalInterface - public interface Supplier { + public interface ModelRedirectorSupplier { PipeModelRedirector create(ModelResourceLocation loc, MaterialModelSupplier supplier, Function stackMaterialFunction); diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java b/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java index 359fb5125c6..cb38d59fae2 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java @@ -108,7 +108,7 @@ public static void registerModels(@NotNull IRegistry { PipeMaterialBlock pipe = PipeMaterialBlock.getBlockFromItem(stack); diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java index 82b9740d775..e77b38dfb52 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java @@ -1,5 +1,6 @@ package gregtech.client.renderer.pipe.cache; +import gregtech.api.util.reference.RegeneratingSoftReference; import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; @@ -7,35 +8,32 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.List; +import java.util.Map; @SideOnly(Side.CLIENT) public final class ColorQuadCache { - // TODO dynamic cache growth & collapse - private static final int CACHE_LIMIT = 20; - private final List prototypes; - private final Object2ObjectLinkedOpenHashMap> cache; + private final RegeneratingSoftReference>> cache; public ColorQuadCache(List prototypes) { this.prototypes = prototypes; - this.cache = new Object2ObjectLinkedOpenHashMap<>(); + this.cache = new RegeneratingSoftReference<>(Object2ObjectOpenHashMap::new); } public List getQuads(ColorData data) { - List existing = cache.getAndMoveToFirst(data); + List existing = cache.get().get(data); if (existing == null) { existing = new ObjectArrayList<>(); for (RecolorableBakedQuad quad : prototypes) { existing.add(quad.withColor(data)); } - cache.put(data, existing); - if (cache.size() > CACHE_LIMIT) cache.removeLast(); + cache.get().put(data, existing); } return existing; } diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java index a95a2501969..cc2d9763311 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityComputationHatch.java @@ -50,12 +50,6 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { return new MetaTileEntityComputationHatch(metaTileEntityId, isTransmitter); } - @Override - public void update() { - super.update(); - if (getOffsetTimer() % 20 == 0) recentQueries.trim(); - } - @Override public boolean isTransmitter() { return this.isTransmitter; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java index 2785e96795a..ce2f1165b1f 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java @@ -48,12 +48,6 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { return new MetaTileEntityOpticalDataHatch(metaTileEntityId, this.isTransmitter); } - @Override - public void update() { - super.update(); - if (getOffsetTimer() % 20 == 0) recentQueries.trim(); - } - @Override protected boolean openGUIOnRightClick() { return false; From 689b20e7635fa76490f1e065c7562b2d3c796b0b Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 31 Aug 2024 09:43:26 -0600 Subject: [PATCH 114/157] Annotation --- src/main/java/gregtech/api/util/reference/WeakHashSet.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/gregtech/api/util/reference/WeakHashSet.java b/src/main/java/gregtech/api/util/reference/WeakHashSet.java index 2a3dfa62d08..5be61764723 100644 --- a/src/main/java/gregtech/api/util/reference/WeakHashSet.java +++ b/src/main/java/gregtech/api/util/reference/WeakHashSet.java @@ -17,6 +17,7 @@ * Replica of {@link java.util.Collections.SetFromMap} for {@link WeakHashMap} to allow for greater type specificity * than the {@link java.util.Set} interface. */ +@SuppressWarnings("JavadocReference") public class WeakHashSet extends AbstractSet { private final WeakHashMap m = new WeakHashMap<>(); From b8aa223c2b5aaa68e0f78aa1ff39b8a36cd8720c Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 4 Sep 2024 12:33:06 -0600 Subject: [PATCH 115/157] Misc fixes --- .../java/gregtech/api/graphnet/NetGroup.java | 1 + .../DynamicWeightsShortestPathsAlgorithm.java | 5 +++-- .../graphnet/alg/ShortestPathsAlgorithm.java | 4 ++-- .../gregtech/api/graphnet/path/INetPath.java | 5 ----- .../predicate/test/ItemTestObject.java | 8 +++++-- .../renderer/pipe/cache/ColorQuadCache.java | 12 ++++++---- .../pipe/cover/CoverRendererBuilder.java | 9 ++++---- .../renderer/pipe/quad/PipeQuadHelper.java | 22 +++++++++---------- .../client/renderer/pipe/quad/UVMapper.java | 13 ++++++----- .../gregtech/common/ToolEventHandlers.java | 8 +++---- 10 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/NetGroup.java b/src/main/java/gregtech/api/graphnet/NetGroup.java index 1c1a7d1f507..7b6f5d292d3 100644 --- a/src/main/java/gregtech/api/graphnet/NetGroup.java +++ b/src/main/java/gregtech/api/graphnet/NetGroup.java @@ -134,6 +134,7 @@ public void splitNode(NetNode source) { NetNode temp; while (i.hasNext()) { temp = i.next(); + if (temp == source) continue; targetGroup.add(temp); // if we find a target node in our search, remove it from the list targets.remove(temp); diff --git a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java index 17b502d51ca..09b851e8f90 100644 --- a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java @@ -34,7 +34,7 @@ public DynamicWeightsShortestPathsAlgorithm(IGraphNet net, boolean recomputeEver public > IteratorFactory getPathsIteratorFactory(GraphVertex source, NetPathMapper remapper) { Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream().filter(NetNode::isActive) - .map(n -> n.wrapper).filter(node -> !source.equals(node)).collect(Collectors.toSet()); + .map(n -> n.wrapper).filter(node -> !(source == node) && graph.containsVertex(node)).collect(Collectors.toSet()); return (graph, testObject, simulator, queryTick) -> { if (recomputeEveryCall) graph.prepareForAlgorithmRun(testObject, simulator, queryTick); return new LimitedIterator<>(source, searchSpace, remapper); @@ -89,7 +89,8 @@ private void calculateNext() { private boolean isUnique(Path path) { for (Path other : visited) { - if (path.matches(other)) return false; + if (path.getOrderedNodes().equals(other.getOrderedNodes()) && + path.getOrderedEdges().equals(other.getOrderedEdges())) return false; } return true; } diff --git a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java index 1b5971882f9..9c757b275cc 100644 --- a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java @@ -37,8 +37,8 @@ public ShortestPathsAlgorithm(IGraphNet net, boolean recomputeEveryCall) { return SimpleIteratorFactories.fromSingleton(path); } - Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream() - .filter(NetNode::isActive).map(n -> n.wrapper).collect(Collectors.toSet()); + Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream().filter(NetNode::isActive) + .map(n -> n.wrapper).filter(node -> !source.equals(node) && graph.containsVertex(node)).collect(Collectors.toSet()); Set singleton = Collections.singleton(source); if (recomputeEveryCall) { return (graph1, testObject, simulator, queryTick) -> { diff --git a/src/main/java/gregtech/api/graphnet/path/INetPath.java b/src/main/java/gregtech/api/graphnet/path/INetPath.java index 3c0da1e701a..95407135b19 100644 --- a/src/main/java/gregtech/api/graphnet/path/INetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/INetPath.java @@ -29,11 +29,6 @@ default N getTargetNode() { double getWeight(); - default boolean matches(@NotNull INetPath other) { - return WEIGHT_COMPARATOR.compare(getWeight(), other.getWeight()) == 0 && - getOrderedNodes().equals(other.getOrderedNodes()) && getOrderedEdges().equals(other.getOrderedEdges()); - } - NetLogicData getUnifiedNodeData(); @Nullable diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java index 4fa2f5b0ee1..f2cdd566ac2 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java @@ -31,13 +31,17 @@ public ItemTestObject(@NotNull ItemStack stack) { @Override @Contract(" -> new") public ItemStack recombine() { - return new ItemStack(item, 1, meta, tag); + ItemStack stack = new ItemStack(item, 1, meta); + stack.setTagCompound(tag.copy()); + return stack; } @Contract("_ -> new") public ItemStack recombine(int amount) { assert amount <= getStackLimit() && amount > 0; - return new ItemStack(item, amount, meta, tag); + ItemStack stack = new ItemStack(item, amount, meta); + stack.setTagCompound(tag.copy()); + return stack; } @Override diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java index e77b38dfb52..711b100cfa8 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java @@ -4,6 +4,8 @@ import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; + import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -19,21 +21,23 @@ public final class ColorQuadCache { private final List prototypes; - private final RegeneratingSoftReference>> cache; + private final Object2ObjectLinkedOpenHashMap> cache; + public ColorQuadCache(List prototypes) { this.prototypes = prototypes; - this.cache = new RegeneratingSoftReference<>(Object2ObjectOpenHashMap::new); + this.cache = new Object2ObjectLinkedOpenHashMap<>(); } public List getQuads(ColorData data) { - List existing = cache.get().get(data); + List existing = cache.getAndMoveToFirst(data); if (existing == null) { existing = new ObjectArrayList<>(); for (RecolorableBakedQuad quad : prototypes) { existing.add(quad.withColor(data)); } - cache.get().put(data, existing); + cache.put(data, existing); + if (cache.size() > 20) cache.removeLast(); } return existing; } diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java index a46534f3929..b56172f509c 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java @@ -49,7 +49,7 @@ public class CoverRendererBuilder { private static final EnumMap> OVERLAY_BOXES_2 = new EnumMap<>( EnumFacing.class); - private static final UVMapper defaultMapper = UVMapper.standard(0); + private static final UVMapper defaultMapper = UVMapper.standard(180); static { for (EnumFacing facing : EnumFacing.VALUES) { @@ -72,19 +72,18 @@ public class CoverRendererBuilder { public static ColorQuadCache buildPlates(SpriteInformation sprite) { List quads = new ObjectArrayList<>(); - UVMapper mapper = UVMapper.standard(0); for (EnumFacing facing : EnumFacing.VALUES) { - PLATE_COORDS.put(facing, buildPlates(quads, facing, mapper, sprite)); + PLATE_COORDS.put(facing, buildPlates(quads, facing, sprite)); } return new ColorQuadCache(quads); } protected static SubListAddress buildPlates(List quads, EnumFacing facing, - UVMapper mapper, SpriteInformation sprite) { + SpriteInformation sprite) { int start = quads.size(); Pair box = PLATE_BOXES.get(facing); for (EnumFacing dir : EnumFacing.values()) { - quads.add(QuadHelper.buildQuad(dir, box, mapper, sprite)); + quads.add(QuadHelper.buildQuad(dir, box, CoverRendererBuilder.defaultMapper, sprite)); } return new SubListAddress(start, quads.size()); } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java index 6f13eb6a301..36eee59fe53 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -102,24 +102,22 @@ public List visitTube(EnumFacing facing, int overlayLayer) Pair box = sideBoxesList.get(overlayLayer).get(facing); switch (facing.getAxis()) { case X -> { - UVMapper mapper = UVMapper.standard(0); - list.add(visitQuad(EnumFacing.UP, box, mapper)); - list.add(visitQuad(EnumFacing.DOWN, box, mapper)); - list.add(visitQuad(EnumFacing.SOUTH, box, mapper)); - list.add(visitQuad(EnumFacing.NORTH, box, UVMapper.standard(180))); + list.add(visitQuad(EnumFacing.UP, box, UVMapper.standard(0))); + list.add(visitQuad(EnumFacing.DOWN, box, UVMapper.standard(0))); + list.add(visitQuad(EnumFacing.SOUTH, box, UVMapper.standard(0))); + list.add(visitQuad(EnumFacing.NORTH, box, UVMapper.standard(0))); } case Y -> { - UVMapper mapper = UVMapper.standard(0); - list.add(visitQuad(EnumFacing.EAST, box, UVMapper.standard(270))); - list.add(visitQuad(EnumFacing.WEST, box, UVMapper.standard(270))); - list.add(visitQuad(EnumFacing.SOUTH, box, mapper)); - list.add(visitQuad(EnumFacing.NORTH, box, mapper)); + list.add(visitQuad(EnumFacing.EAST, box, UVMapper.standard(90))); + list.add(visitQuad(EnumFacing.WEST, box, UVMapper.standard(90))); + list.add(visitQuad(EnumFacing.SOUTH, box, UVMapper.standard(0))); + list.add(visitQuad(EnumFacing.NORTH, box, UVMapper.standard(0))); } case Z -> { - list.add(visitQuad(EnumFacing.UP, box, UVMapper.standard(180))); + list.add(visitQuad(EnumFacing.UP, box, UVMapper.standard(0))); list.add(visitQuad(EnumFacing.DOWN, box, UVMapper.standard(0))); list.add(visitQuad(EnumFacing.EAST, box, UVMapper.standard(270))); - list.add(visitQuad(EnumFacing.WEST, box, UVMapper.standard(90))); + list.add(visitQuad(EnumFacing.WEST, box, UVMapper.standard(270))); } } return list; diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java index 1fdb61f8870..0d4f25684fd 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java @@ -1,5 +1,6 @@ package gregtech.client.renderer.pipe.quad; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.client.renderer.block.model.BlockFaceUV; import net.minecraft.util.EnumFacing; import net.minecraftforge.fml.relauncher.Side; @@ -12,16 +13,18 @@ @SideOnly(Side.CLIENT) public interface UVMapper { + Int2ObjectOpenHashMap CACHE = new Int2ObjectOpenHashMap<>(); + static UVMapper standard(int rot) { - return (normal, box) -> { + return CACHE.computeIfAbsent(rot, (r) -> (normal, box) -> { Vector3f small = box.getLeft(); Vector3f large = box.getRight(); return switch (normal.getAxis()) { - case X -> new BlockFaceUV(new float[] { small.y, large.z, large.y, small.z }, rot); - case Y -> new BlockFaceUV(new float[] { small.x, large.z, large.x, small.z }, rot); - case Z -> new BlockFaceUV(new float[] { small.x, large.y, large.x, small.y }, rot); + case X -> new BlockFaceUV(new float[] { small.y, large.z, large.y, small.z }, r); + case Y -> new BlockFaceUV(new float[] { small.x, large.z, large.x, small.z }, r); + case Z -> new BlockFaceUV(new float[] { small.x, large.y, large.x, small.y }, r); }; - }; + }); } BlockFaceUV map(EnumFacing normal, Pair box); diff --git a/src/main/java/gregtech/common/ToolEventHandlers.java b/src/main/java/gregtech/common/ToolEventHandlers.java index 8a9b771cd23..5f86dfa1128 100644 --- a/src/main/java/gregtech/common/ToolEventHandlers.java +++ b/src/main/java/gregtech/common/ToolEventHandlers.java @@ -220,7 +220,7 @@ public static void onDrawHighlightEvent(@NotNull DrawBlockHighlightEvent event) boolean sneaking = player.isSneaking(); // Grid overlays - if (shouldRenderGridOverlays(state, tile, stack, player.getHeldItemOffhand(), sneaking) && + if (shouldRenderGridOverlays(player, pos, state, tile, stack, player.getHeldItemOffhand(), sneaking) && renderGridOverlays(player, pos, state, event.getTarget().sideHit, tile, event.getPartialTicks())) { event.setCanceled(true); return; @@ -300,11 +300,11 @@ private static void postRenderDamagedBlocks() { } @SideOnly(Side.CLIENT) - private static boolean shouldRenderGridOverlays(@NotNull IBlockState state, @Nullable TileEntity tile, + private static boolean shouldRenderGridOverlays(@NotNull EntityPlayer player, @NotNull BlockPos pos, + @NotNull IBlockState state, @Nullable TileEntity tile, ItemStack mainHand, ItemStack offHand, boolean isSneaking) { if (state.getBlock() instanceof PipeBlock pipe) { - if (isSneaking && - (mainHand.isEmpty() || mainHand.getItem().getClass() == Item.getItemFromBlock(pipe).getClass())) { + if (pipe.hasPipeCollisionChangingItem(player.world, pos, player)) { return true; } else { Set mainToolClasses = mainHand.getItem().getToolClasses(mainHand); From 40950ccf6ab19617dd8ee7ee0ae0ab8a34a3682f Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 4 Sep 2024 14:33:17 -0600 Subject: [PATCH 116/157] Actually fix quad UVs --- .../DynamicWeightsShortestPathsAlgorithm.java | 6 +++-- .../graphnet/alg/ShortestPathsAlgorithm.java | 3 ++- .../gregtech/api/graphnet/path/INetPath.java | 1 - .../pipenet/physical/block/PipeBlock.java | 2 +- .../renderer/pipe/cache/ColorQuadCache.java | 7 +----- .../pipe/cover/CoverRendererBuilder.java | 2 +- .../renderer/pipe/quad/PipeQuadHelper.java | 12 ++++----- .../client/renderer/pipe/quad/UVMapper.java | 25 ++++++++++++++----- 8 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java index 09b851e8f90..d474101d6d2 100644 --- a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java @@ -34,7 +34,8 @@ public DynamicWeightsShortestPathsAlgorithm(IGraphNet net, boolean recomputeEver public > IteratorFactory getPathsIteratorFactory(GraphVertex source, NetPathMapper remapper) { Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream().filter(NetNode::isActive) - .map(n -> n.wrapper).filter(node -> !(source == node) && graph.containsVertex(node)).collect(Collectors.toSet()); + .map(n -> n.wrapper).filter(node -> !(source == node) && graph.containsVertex(node)) + .collect(Collectors.toSet()); return (graph, testObject, simulator, queryTick) -> { if (recomputeEveryCall) graph.prepareForAlgorithmRun(testObject, simulator, queryTick); return new LimitedIterator<>(source, searchSpace, remapper); @@ -90,7 +91,8 @@ private void calculateNext() { private boolean isUnique(Path path) { for (Path other : visited) { if (path.getOrderedNodes().equals(other.getOrderedNodes()) && - path.getOrderedEdges().equals(other.getOrderedEdges())) return false; + path.getOrderedEdges().equals(other.getOrderedEdges())) + return false; } return true; } diff --git a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java index 9c757b275cc..0e70d04b2da 100644 --- a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java @@ -38,7 +38,8 @@ public ShortestPathsAlgorithm(IGraphNet net, boolean recomputeEveryCall) { } Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream().filter(NetNode::isActive) - .map(n -> n.wrapper).filter(node -> !source.equals(node) && graph.containsVertex(node)).collect(Collectors.toSet()); + .map(n -> n.wrapper).filter(node -> !source.equals(node) && graph.containsVertex(node)) + .collect(Collectors.toSet()); Set singleton = Collections.singleton(source); if (recomputeEveryCall) { return (graph1, testObject, simulator, queryTick) -> { diff --git a/src/main/java/gregtech/api/graphnet/path/INetPath.java b/src/main/java/gregtech/api/graphnet/path/INetPath.java index 95407135b19..8b369110058 100644 --- a/src/main/java/gregtech/api/graphnet/path/INetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/INetPath.java @@ -4,7 +4,6 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.logic.NetLogicData; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.alg.util.ToleranceDoubleComparator; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 78b6bd8ba63..4d47843b823 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -164,7 +164,7 @@ public boolean onBlockActivated(@NotNull World worldIn, @NotNull BlockPos pos, @ PipeCoverHolder coverable = tile.getCoverHolder(); Cover cover = coverable.getCoverAtSide(facing); if (cover != null) { - if (ToolHelper.isTool(item, ToolClasses.SCREWDRIVER)) { + if (ToolHelper.isTool(item, ToolClasses.SCREWDRIVER) || (item.isEmpty() && playerIn.isSneaking())) { EnumActionResult result = cover.onScrewdriverClick(playerIn, hand, trace); if (result != EnumActionResult.PASS) { if (result == EnumActionResult.SUCCESS) { diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java index 711b100cfa8..e22a3ef1493 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java @@ -1,20 +1,16 @@ package gregtech.client.renderer.pipe.cache; -import gregtech.api.util.reference.RegeneratingSoftReference; import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; - import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.List; -import java.util.Map; @SideOnly(Side.CLIENT) public final class ColorQuadCache { @@ -23,7 +19,6 @@ public final class ColorQuadCache { private final Object2ObjectLinkedOpenHashMap> cache; - public ColorQuadCache(List prototypes) { this.prototypes = prototypes; this.cache = new Object2ObjectLinkedOpenHashMap<>(); diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java index b56172f509c..fa31dd8240a 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java @@ -49,7 +49,7 @@ public class CoverRendererBuilder { private static final EnumMap> OVERLAY_BOXES_2 = new EnumMap<>( EnumFacing.class); - private static final UVMapper defaultMapper = UVMapper.standard(180); + private static final UVMapper defaultMapper = UVMapper.standard(0); static { for (EnumFacing facing : EnumFacing.VALUES) { diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java index 36eee59fe53..8feb60e09e4 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -105,19 +105,19 @@ public List visitTube(EnumFacing facing, int overlayLayer) list.add(visitQuad(EnumFacing.UP, box, UVMapper.standard(0))); list.add(visitQuad(EnumFacing.DOWN, box, UVMapper.standard(0))); list.add(visitQuad(EnumFacing.SOUTH, box, UVMapper.standard(0))); - list.add(visitQuad(EnumFacing.NORTH, box, UVMapper.standard(0))); + list.add(visitQuad(EnumFacing.NORTH, box, UVMapper.flipped(0))); } case Y -> { - list.add(visitQuad(EnumFacing.EAST, box, UVMapper.standard(90))); - list.add(visitQuad(EnumFacing.WEST, box, UVMapper.standard(90))); + list.add(visitQuad(EnumFacing.EAST, box, UVMapper.standard(0))); + list.add(visitQuad(EnumFacing.WEST, box, UVMapper.standard(0))); list.add(visitQuad(EnumFacing.SOUTH, box, UVMapper.standard(0))); list.add(visitQuad(EnumFacing.NORTH, box, UVMapper.standard(0))); } case Z -> { - list.add(visitQuad(EnumFacing.UP, box, UVMapper.standard(0))); + list.add(visitQuad(EnumFacing.UP, box, UVMapper.flipped(0))); list.add(visitQuad(EnumFacing.DOWN, box, UVMapper.standard(0))); - list.add(visitQuad(EnumFacing.EAST, box, UVMapper.standard(270))); - list.add(visitQuad(EnumFacing.WEST, box, UVMapper.standard(270))); + list.add(visitQuad(EnumFacing.EAST, box, UVMapper.flipped(0))); + list.add(visitQuad(EnumFacing.WEST, box, UVMapper.standard(0))); } } return list; diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java index 0d4f25684fd..b9f0923be59 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/UVMapper.java @@ -1,11 +1,11 @@ package gregtech.client.renderer.pipe.quad; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.client.renderer.block.model.BlockFaceUV; import net.minecraft.util.EnumFacing; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.util.vector.Vector3f; @@ -13,16 +13,29 @@ @SideOnly(Side.CLIENT) public interface UVMapper { - Int2ObjectOpenHashMap CACHE = new Int2ObjectOpenHashMap<>(); + Int2ObjectArrayMap STANDARD = new Int2ObjectArrayMap<>(4); + Int2ObjectArrayMap FLIPPED = new Int2ObjectArrayMap<>(4); static UVMapper standard(int rot) { - return CACHE.computeIfAbsent(rot, (r) -> (normal, box) -> { + return FLIPPED.computeIfAbsent(rot, (r) -> (normal, box) -> { Vector3f small = box.getLeft(); Vector3f large = box.getRight(); return switch (normal.getAxis()) { - case X -> new BlockFaceUV(new float[] { small.y, large.z, large.y, small.z }, r); - case Y -> new BlockFaceUV(new float[] { small.x, large.z, large.x, small.z }, r); - case Z -> new BlockFaceUV(new float[] { small.x, large.y, large.x, small.y }, r); + case X -> new BlockFaceUV(new float[] { small.z, 16 - large.y, large.z, 16 - small.y }, r); + case Y -> new BlockFaceUV(new float[] { small.x, 16 - large.z, large.x, 16 - small.z }, r); + case Z -> new BlockFaceUV(new float[] { small.x, 16 - large.y, large.x, 16 - small.y }, r); + }; + }); + } + + static UVMapper flipped(int rot) { + return STANDARD.computeIfAbsent(rot, (r) -> (normal, box) -> { + Vector3f small = box.getLeft(); + Vector3f large = box.getRight(); + return switch (normal.getAxis()) { + case X -> new BlockFaceUV(new float[] { 16 - large.z, small.y, 16 - small.z, large.y }, r); + case Y -> new BlockFaceUV(new float[] { 16 - large.x, small.z, 16 - small.x, large.z }, r); + case Z -> new BlockFaceUV(new float[] { 16 - large.x, small.y, 16 - small.x, large.y }, r); }; }); } From 8a210b39a3bea0f2724e74eb3fd55df679893284 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 4 Sep 2024 15:28:24 -0600 Subject: [PATCH 117/157] Make quad recoloring smarter --- .../renderer/pipe/cache/ColorQuadCache.java | 4 +- .../client/renderer/pipe/quad/ColorData.java | 12 +- .../renderer/pipe/quad/PipeQuadHelper.java | 25 +-- .../client/renderer/pipe/quad/QuadHelper.java | 13 +- .../pipe/quad/RecolorableBakedQuad.java | 177 +++--------------- .../gregtech/common/blocks/MetaBlocks.java | 21 +++ 6 files changed, 79 insertions(+), 173 deletions(-) diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java index e22a3ef1493..a16dea437a4 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java @@ -25,14 +25,14 @@ public ColorQuadCache(List prototypes) { } public List getQuads(ColorData data) { - List existing = cache.getAndMoveToFirst(data); + List existing = cache.get(data); if (existing == null) { existing = new ObjectArrayList<>(); for (RecolorableBakedQuad quad : prototypes) { existing.add(quad.withColor(data)); } cache.put(data, existing); - if (cache.size() > 20) cache.removeLast(); +// if (cache.size() > 20) cache.removeLast(); } return existing; } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java b/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java index d28907b6272..da2cb1c089b 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java @@ -5,6 +5,16 @@ import com.github.bsideup.jabel.Desugar; +import java.util.Arrays; + @Desugar @SideOnly(Side.CLIENT) -public record ColorData(int... colorsARGB) {} +public record ColorData(int... colorsARGB) { + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (ColorData) obj; + return Arrays.equals(this.colorsARGB, that.colorsARGB); + } +} diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java index 8feb60e09e4..1cbba015b1f 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/PipeQuadHelper.java @@ -10,6 +10,7 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; import org.lwjgl.util.vector.Vector3f; import java.util.EnumMap; @@ -59,7 +60,7 @@ public int getLayerCount() { } private void generateBox(float xS, float xL, float yS, float yL, float zS, float zL, - OverlayLayerDefinition definition) { + @NotNull OverlayLayerDefinition definition) { coreBoxList.add(definition.computeBox(null, xS, yS, zS, xL, yL, zL)); EnumMap> sideBoxes = new EnumMap<>(EnumFacing.class); sideBoxes.put(EnumFacing.DOWN, definition.computeBox(EnumFacing.DOWN, xS, 0, zS, xL, yS, zL)); @@ -71,13 +72,15 @@ private void generateBox(float xS, float xL, float yS, float yL, float zS, float sideBoxesList.add(sideBoxes); } - public static PipeQuadHelper create(float thickness, double x, double y, double z) { + @Contract("_, _, _, _ -> new") + public static @NotNull PipeQuadHelper create(float thickness, double x, double y, double z) { float small = 0.5f - thickness / 2; float large = 0.5f + thickness / 2; return new PipeQuadHelper((float) x, (float) y, (float) z, small, large); } - public static PipeQuadHelper create(float thickness) { + @Contract("_ -> new") + public static @NotNull PipeQuadHelper create(float thickness) { return create(thickness, 0, 0, 0); } @@ -85,19 +88,19 @@ public void setTargetSprite(SpriteInformation sprite) { this.targetSprite = sprite; } - public RecolorableBakedQuad visitCore(EnumFacing facing) { + public @NotNull RecolorableBakedQuad visitCore(EnumFacing facing) { return visitCore(facing, 0); } - public RecolorableBakedQuad visitCore(EnumFacing facing, int overlayLayer) { + public @NotNull RecolorableBakedQuad visitCore(EnumFacing facing, int overlayLayer) { return visitQuad(facing, coreBoxList.get(overlayLayer), UVMapper.standard(0)); } - public List visitTube(EnumFacing facing) { + public @NotNull List visitTube(EnumFacing facing) { return visitTube(facing, 0); } - public List visitTube(EnumFacing facing, int overlayLayer) { + public @NotNull List visitTube(EnumFacing facing, int overlayLayer) { List list = new ObjectArrayList<>(); Pair box = sideBoxesList.get(overlayLayer).get(facing); switch (facing.getAxis()) { @@ -123,19 +126,19 @@ public List visitTube(EnumFacing facing, int overlayLayer) return list; } - public RecolorableBakedQuad visitCapper(EnumFacing facing) { + public @NotNull RecolorableBakedQuad visitCapper(EnumFacing facing) { return visitCapper(facing, 0); } - public RecolorableBakedQuad visitCapper(EnumFacing facing, int overlayLayer) { + public @NotNull RecolorableBakedQuad visitCapper(EnumFacing facing, int overlayLayer) { return visitQuad(facing, sideBoxesList.get(overlayLayer).get(facing), UVMapper.standard(0)); } - public RecolorableBakedQuad visitQuad(EnumFacing normal, Pair box, UVMapper uv) { + public @NotNull RecolorableBakedQuad visitQuad(EnumFacing normal, Pair box, UVMapper uv) { return QuadHelper.buildQuad(normal, box, uv, targetSprite); } - public static List createFrame(TextureAtlasSprite sprite) { + public static @NotNull List createFrame(TextureAtlasSprite sprite) { PipeQuadHelper helper = PipeQuadHelper.create(0.998f).initialize(); helper.setTargetSprite(new SpriteInformation(sprite, 0)); List list = new ObjectArrayList<>(); diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java index 03502642fec..25e1d01e1ed 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java @@ -26,19 +26,16 @@ public final class QuadHelper { private QuadHelper() {} - public static RecolorableBakedQuad buildQuad(EnumFacing normal, Pair box, - UVMapper uv, SpriteInformation targetSprite) { + public static @NotNull RecolorableBakedQuad buildQuad(EnumFacing normal, Pair box, + @NotNull UVMapper uv, @NotNull SpriteInformation targetSprite) { BlockPartFace face = new BlockPartFace(null, -1, targetSprite.sprite().getIconName(), uv.map(normal, box)); BakedQuad quad = BAKERY.makeBakedQuad(box.getLeft(), box.getRight(), face, targetSprite.sprite(), normal, ModelRotation.X0_Y0, null, false, true); - RecolorableBakedQuad.Builder builder = new RecolorableBakedQuad.Builder(quad.getFormat()); - builder.setTexture(targetSprite); - quad.pipe(builder); - return builder.build(); + return new RecolorableBakedQuad(quad, targetSprite); } - public static BakedQuad buildQuad(EnumFacing normal, Pair box, - UVMapper uv, TextureAtlasSprite targetSprite) { + public static @NotNull BakedQuad buildQuad(EnumFacing normal, Pair box, + @NotNull UVMapper uv, @NotNull TextureAtlasSprite targetSprite) { BlockPartFace face = new BlockPartFace(null, -1, targetSprite.getIconName(), uv.map(normal, box)); return BAKERY.makeBakedQuad(box.getLeft(), box.getRight(), face, targetSprite, normal, ModelRotation.X0_Y0, null, false, true); diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java index ffcdfbda141..315f00d6c0e 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java @@ -1,7 +1,10 @@ package gregtech.client.renderer.pipe.quad; +import gregtech.api.util.reference.WeakHashSet; import gregtech.client.renderer.pipe.util.SpriteInformation; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.VertexFormat; @@ -15,164 +18,36 @@ import org.jetbrains.annotations.NotNull; @SideOnly(Side.CLIENT) -public class RecolorableBakedQuad extends UnpackedBakedQuad { +public class RecolorableBakedQuad extends BakedQuad { + private final Int2ObjectOpenHashMap cache; private final SpriteInformation spriteInformation; - public RecolorableBakedQuad(float[][][] unpackedData, int tint, EnumFacing orientation, - SpriteInformation texture, boolean applyDiffuseLighting, VertexFormat format) { - super(unpackedData, tint, orientation, texture.sprite(), applyDiffuseLighting, format); - this.spriteInformation = texture; + /** + * Create a new recolorable quad based off of a baked quad prototype. + * @param prototype the prototype. + * @param spriteInformation the sprite information of this baked quad. + */ + public RecolorableBakedQuad(BakedQuad prototype, SpriteInformation spriteInformation) { + this(prototype, prototype.getTintIndex(), spriteInformation, new Int2ObjectOpenHashMap<>()); + } + + protected RecolorableBakedQuad(BakedQuad prototype, int tintIndex, + SpriteInformation spriteInformation, Int2ObjectOpenHashMap cache) { + super(prototype.vertexData, tintIndex, prototype.getFace(), spriteInformation.sprite(), + prototype.shouldApplyDiffuseLighting(), prototype.getFormat()); + this.spriteInformation = spriteInformation; + this.cache = cache; } + /** + * Get a recolorable quad based off of this quad but aligned with the given color data. + * @param data the color data. + * @return a quad colored based on the color data. + */ public RecolorableBakedQuad withColor(ColorData data) { if (!spriteInformation.colorable()) return this; int argb = data.colorsARGB()[spriteInformation.colorID()]; - - float[][][] newData = new float[4][format.getElementCount()][]; - - float a = ((argb >> 24) & 0xFF) / 255f; // alpha - float r = ((argb >> 16) & 0xFF) / 255f; // red - float g = ((argb >> 8) & 0xFF) / 255f; // green - float b = ((argb) & 0xFF) / 255f; // blue - float[] array = new float[] { r, g, b, a }; - for (int v = 0; v < 4; v++) { - for (int e = 0; e < format.getElementCount(); e++) { - if (format.getElement(e).getUsage() == VertexFormatElement.EnumUsage.COLOR) { - newData[v][e] = array; - } else { - newData[v][e] = unpackedData[v][e]; - } - } - } - return new RecolorableBakedQuad(newData, this.tintIndex, this.face, this.spriteInformation, - this.applyDiffuseLighting, this.format); - } - - public static RecolorableBakedQuad.Builder of(BakedQuad quad) { - Builder builder = new Builder(quad.getFormat()); - quad.pipe(builder); - return builder; - } - - public static class Builder implements IVertexConsumer { - - private final VertexFormat format; - private final float[][][] unpackedData; - private int tint = -1; - private EnumFacing orientation; - private SpriteInformation texture; - private boolean applyDiffuseLighting = true; - - private int vertices = 0; - private int elements = 0; - private boolean full = false; - private boolean contractUVs = false; - - public Builder(VertexFormat format) { - this.format = format; - unpackedData = new float[4][format.getElementCount()][4]; - } - - public @NotNull VertexFormat getVertexFormat() { - return format; - } - - public void setContractUVs(boolean value) { - this.contractUVs = value; - } - - public void setQuadTint(int tint) { - this.tint = tint; - } - - public void setQuadOrientation(@NotNull EnumFacing orientation) { - this.orientation = orientation; - } - - public void setTexture(@NotNull SpriteInformation texture) { - this.texture = texture; - } - - @Override - public void setTexture(@NotNull TextureAtlasSprite texture) {} - - public void setApplyDiffuseLighting(boolean diffuse) { - this.applyDiffuseLighting = diffuse; - } - - public void put(int element, float @NotNull... data) { - for (int i = 0; i < 4; i++) { - if (i < data.length) { - unpackedData[vertices][element][i] = data[i]; - } else { - unpackedData[vertices][element][i] = 0; - } - } - elements++; - if (elements == format.getElementCount()) { - vertices++; - elements = 0; - } - if (vertices == 4) { - full = true; - } - } - - public RecolorableBakedQuad build() { - if (!full) { - throw new IllegalStateException("not enough data"); - } - if (texture == null) { - throw new IllegalStateException("texture not set"); - } - if (contractUVs) { - float tX = texture.sprite().getIconWidth() / (texture.sprite().getMaxU() - texture.sprite().getMinU()); - float tY = texture.sprite().getIconHeight() / (texture.sprite().getMaxV() - texture.sprite().getMinV()); - float tS = Math.max(tX, tY); - float ep = 1f / (tS * 0x100); - int uve = 0; - while (uve < format.getElementCount()) { - VertexFormatElement e = format.getElement(uve); - if (e.getUsage() == VertexFormatElement.EnumUsage.UV && e.getIndex() == 0) { - break; - } - uve++; - } - if (uve == format.getElementCount()) { - throw new IllegalStateException("Can't contract UVs: format doesn't contain UVs"); - } - float[] uvc = new float[4]; - for (int v = 0; v < 4; v++) { - for (int i = 0; i < 4; i++) { - uvc[i] += unpackedData[v][uve][i] / 4; - } - } - for (int v = 0; v < 4; v++) { - for (int i = 0; i < 4; i++) { - float uo = unpackedData[v][uve][i]; - float eps = 1f / 0x100; - float un = uo * (1 - eps) + uvc[i] * eps; - float ud = uo - un; - float aud = ud; - if (aud < 0) aud = -aud; - if (aud < ep) // not moving a fraction of a pixel - { - float udc = uo - uvc[i]; - if (udc < 0) udc = -udc; - if (udc < 2 * ep) // center is closer than 2 fractions of a pixel, don't move too close - { - un = (uo + uvc[i]) / 2; - } else // move at least by a fraction - { - un = uo + (ud < 0 ? ep : -ep); - } - } - unpackedData[v][uve][i] = un; - } - } - } - return new RecolorableBakedQuad(unpackedData, tint, orientation, texture, applyDiffuseLighting, format); - } + return cache.computeIfAbsent(argb, (c) -> new RecolorableBakedQuad(this, c, this.spriteInformation, this.cache)); } } diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 71fb8cfe750..09efea4eebc 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -4,6 +4,7 @@ import gregtech.api.GregTechAPI; import gregtech.api.block.machines.BlockMachine; import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; +import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; @@ -25,6 +26,7 @@ import gregtech.client.model.modelfactories.BakedModelHandler; import gregtech.client.renderer.handler.MetaTileEntityRenderer; import gregtech.client.renderer.handler.MetaTileEntityTESR; +import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.common.ConfigHolder; import gregtech.common.blocks.explosive.BlockITNT; import gregtech.common.blocks.explosive.BlockPowderbarrel; @@ -68,6 +70,8 @@ import net.minecraft.client.renderer.block.statemap.IStateMapper; import net.minecraft.client.renderer.block.statemap.StateMapperBase; import net.minecraft.client.renderer.color.BlockColors; +import net.minecraft.client.renderer.color.IBlockColor; +import net.minecraft.client.renderer.color.IItemColor; import net.minecraft.client.renderer.color.ItemColors; import net.minecraft.init.Blocks; import net.minecraft.item.EnumDyeColor; @@ -76,6 +80,7 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fluids.BlockFluidBase; import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.registry.GameRegistry; @@ -623,6 +628,22 @@ public static void registerColors() { itemColors.registerItemColorHandler((s, i) -> block.getGtMaterial(s).getMaterialRGB(), block); } + IBlockColor pipeBlockColor = (s, w, p, i) -> i; + IItemColor pipeItemColor = (s, i) -> i; + for (MaterialRegistry registry : GregTechAPI.materialManager.getRegistries()) { + MaterialPipeBlock[] pipes = MATERIAL_PIPES.get(registry.getModid()); + blockColors.registerBlockColorHandler(pipeBlockColor, pipes); + itemColors.registerItemColorHandler(pipeItemColor, pipes); + + CableBlock[] cables = CABLES.get(registry.getModid()); + blockColors.registerBlockColorHandler(pipeBlockColor, cables); + itemColors.registerItemColorHandler(pipeItemColor, cables); + } + blockColors.registerBlockColorHandler(pipeBlockColor, OPTICAL_PIPES); + itemColors.registerItemColorHandler(pipeItemColor, OPTICAL_PIPES); + blockColors.registerBlockColorHandler(pipeBlockColor, LASER_PIPES); + itemColors.registerItemColorHandler(pipeItemColor, LASER_PIPES); + for (BlockFrame block : FRAME_BLOCKS) { blockColors.registerBlockColorHandler((s, w, p, i) -> block.getGtMaterial(s).getMaterialRGB(), block); itemColors.registerItemColorHandler((s, i) -> block.getGtMaterial(s).getMaterialRGB(), block); From 65d0051248dd81157ed05291d5d50ba7ed814fb2 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 4 Sep 2024 15:28:39 -0600 Subject: [PATCH 118/157] spotless --- .../renderer/pipe/cache/ColorQuadCache.java | 2 +- .../client/renderer/pipe/quad/ColorData.java | 1 + .../client/renderer/pipe/quad/QuadHelper.java | 3 ++- .../pipe/quad/RecolorableBakedQuad.java | 21 +++++++------------ .../gregtech/common/blocks/MetaBlocks.java | 3 --- 5 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java index a16dea437a4..4795aae2d26 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/ColorQuadCache.java @@ -32,7 +32,7 @@ public List getQuads(ColorData data) { existing.add(quad.withColor(data)); } cache.put(data, existing); -// if (cache.size() > 20) cache.removeLast(); + // if (cache.size() > 20) cache.removeLast(); } return existing; } diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java b/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java index da2cb1c089b..1862e3122f5 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/ColorData.java @@ -10,6 +10,7 @@ @Desugar @SideOnly(Side.CLIENT) public record ColorData(int... colorsARGB) { + @Override public boolean equals(Object obj) { if (obj == this) return true; diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java b/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java index 25e1d01e1ed..468f6c0bdbf 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/QuadHelper.java @@ -27,7 +27,8 @@ public final class QuadHelper { private QuadHelper() {} public static @NotNull RecolorableBakedQuad buildQuad(EnumFacing normal, Pair box, - @NotNull UVMapper uv, @NotNull SpriteInformation targetSprite) { + @NotNull UVMapper uv, + @NotNull SpriteInformation targetSprite) { BlockPartFace face = new BlockPartFace(null, -1, targetSprite.sprite().getIconName(), uv.map(normal, box)); BakedQuad quad = BAKERY.makeBakedQuad(box.getLeft(), box.getRight(), face, targetSprite.sprite(), normal, ModelRotation.X0_Y0, null, false, true); diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java index 315f00d6c0e..45890a8ecda 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java @@ -1,21 +1,12 @@ package gregtech.client.renderer.pipe.quad; -import gregtech.api.util.reference.WeakHashSet; import gregtech.client.renderer.pipe.util.SpriteInformation; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - import net.minecraft.client.renderer.block.model.BakedQuad; -import net.minecraft.client.renderer.texture.TextureAtlasSprite; -import net.minecraft.client.renderer.vertex.VertexFormat; -import net.minecraft.client.renderer.vertex.VertexFormatElement; -import net.minecraft.util.EnumFacing; -import net.minecraftforge.client.model.pipeline.IVertexConsumer; -import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import org.jetbrains.annotations.NotNull; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; @SideOnly(Side.CLIENT) public class RecolorableBakedQuad extends BakedQuad { @@ -25,7 +16,8 @@ public class RecolorableBakedQuad extends BakedQuad { /** * Create a new recolorable quad based off of a baked quad prototype. - * @param prototype the prototype. + * + * @param prototype the prototype. * @param spriteInformation the sprite information of this baked quad. */ public RecolorableBakedQuad(BakedQuad prototype, SpriteInformation spriteInformation) { @@ -33,7 +25,8 @@ public RecolorableBakedQuad(BakedQuad prototype, SpriteInformation spriteInforma } protected RecolorableBakedQuad(BakedQuad prototype, int tintIndex, - SpriteInformation spriteInformation, Int2ObjectOpenHashMap cache) { + SpriteInformation spriteInformation, + Int2ObjectOpenHashMap cache) { super(prototype.vertexData, tintIndex, prototype.getFace(), spriteInformation.sprite(), prototype.shouldApplyDiffuseLighting(), prototype.getFormat()); this.spriteInformation = spriteInformation; @@ -42,12 +35,14 @@ protected RecolorableBakedQuad(BakedQuad prototype, int tintIndex, /** * Get a recolorable quad based off of this quad but aligned with the given color data. + * * @param data the color data. * @return a quad colored based on the color data. */ public RecolorableBakedQuad withColor(ColorData data) { if (!spriteInformation.colorable()) return this; int argb = data.colorsARGB()[spriteInformation.colorID()]; - return cache.computeIfAbsent(argb, (c) -> new RecolorableBakedQuad(this, c, this.spriteInformation, this.cache)); + return cache.computeIfAbsent(argb, + (c) -> new RecolorableBakedQuad(this, c, this.spriteInformation, this.cache)); } } diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index 09efea4eebc..a92b72d72ba 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -4,7 +4,6 @@ import gregtech.api.GregTechAPI; import gregtech.api.block.machines.BlockMachine; import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; -import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; @@ -26,7 +25,6 @@ import gregtech.client.model.modelfactories.BakedModelHandler; import gregtech.client.renderer.handler.MetaTileEntityRenderer; import gregtech.client.renderer.handler.MetaTileEntityTESR; -import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.common.ConfigHolder; import gregtech.common.blocks.explosive.BlockITNT; import gregtech.common.blocks.explosive.BlockPowderbarrel; @@ -80,7 +78,6 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.property.IExtendedBlockState; import net.minecraftforge.fluids.BlockFluidBase; import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.registry.GameRegistry; From 40b1cb7857670d30b113b306e871fb47a67714ba Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 4 Sep 2024 18:43:06 -0600 Subject: [PATCH 119/157] me when I don't null check --- .../api/graphnet/predicate/test/FluidTestObject.java | 2 +- .../api/graphnet/predicate/test/ItemTestObject.java | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java index bf49a7392e7..34b84597210 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/FluidTestObject.java @@ -14,7 +14,7 @@ public final class FluidTestObject implements IPredicateTestObject, Predicate { public final Fluid fluid; - public final NBTTagCompound tag; + public final @Nullable NBTTagCompound tag; private final int hash; diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java index f2cdd566ac2..74a44e4a3b8 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Objects; import java.util.function.Predicate; @@ -14,7 +15,7 @@ public class ItemTestObject implements IPredicateTestObject, Predicate new") public ItemStack recombine() { ItemStack stack = new ItemStack(item, 1, meta); - stack.setTagCompound(tag.copy()); + if (tag != null) stack.setTagCompound(tag.copy()); return stack; } @@ -40,7 +41,7 @@ public ItemStack recombine() { public ItemStack recombine(int amount) { assert amount <= getStackLimit() && amount > 0; ItemStack stack = new ItemStack(item, amount, meta); - stack.setTagCompound(tag.copy()); + if (tag != null) stack.setTagCompound(tag.copy()); return stack; } From e37a1b26e9924b2c0d4277345f3d4ed4024c6b7b Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 4 Sep 2024 18:55:42 -0600 Subject: [PATCH 120/157] Fix a minor mistake --- .../client/renderer/pipe/PipeModelRegistry.java | 14 ++++++++------ .../renderer/pipe/util/MaterialModelOverride.java | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java b/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java index cb38d59fae2..6ee2553cd5e 100644 --- a/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java +++ b/src/main/java/gregtech/client/renderer/pipe/PipeModelRegistry.java @@ -18,6 +18,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Range; @SideOnly(Side.CLIENT) @@ -137,13 +138,14 @@ private static void initPipes() { array[4] = new PipeModel(Textures.PIPE_HUGE, Textures.PIPE_SIDE, false); array[5] = new PipeModel(Textures.PIPE_QUADRUPLE, Textures.PIPE_SIDE, false); array[6] = new PipeModel(Textures.PIPE_NONUPLE, Textures.PIPE_SIDE, false); - PIPE_OVERRIDES.add(new MaterialModelOverride.StandardOverride<>(array, m -> true)); + PIPE_OVERRIDES.addAndMoveToLast(new MaterialModelOverride.StandardOverride<>(array, m -> true)); array = new PipeModel[PIPE_MODEL_COUNT]; array[1] = new PipeModel(Textures.PIPE_SMALL_WOOD, Textures.PIPE_SIDE_WOOD, false); array[2] = new PipeModel(Textures.PIPE_NORMAL_WOOD, Textures.PIPE_SIDE_WOOD, false); array[3] = new PipeModel(Textures.PIPE_LARGE_WOOD, Textures.PIPE_SIDE_WOOD, false); - registerPipeOverride(new MaterialModelOverride.StandardOverride<>(array, m -> m.hasProperty(PropertyKey.WOOD))); + registerPipeOverride( + new MaterialModelOverride.StandardOverride<>(array, m -> m != null && m.hasProperty(PropertyKey.WOOD))); array = new PipeModel[PIPE_MODEL_COUNT]; array[0] = new PipeModel(Textures.PIPE_TINY, Textures.PIPE_SIDE, true); @@ -153,7 +155,7 @@ private static void initPipes() { array[4] = new PipeModel(Textures.PIPE_HUGE, Textures.PIPE_SIDE, true); array[5] = new PipeModel(Textures.PIPE_QUADRUPLE, Textures.PIPE_SIDE, true); array[6] = new PipeModel(Textures.PIPE_NONUPLE, Textures.PIPE_SIDE, true); - PIPE_RESTRICTIVE_OVERRIDES.add(new MaterialModelOverride.StandardOverride<>(array, m -> true)); + PIPE_RESTRICTIVE_OVERRIDES.addAndMoveToLast(new MaterialModelOverride.StandardOverride<>(array, m -> true)); ResourceLocation loc = GTUtility.gregtechId("block/pipe_material"); for (int i = 0; i < PIPE_MODEL_COUNT; i++) { @@ -164,7 +166,7 @@ private static void initPipes() { } } - private static PipeModel getOrCachePipeModel(Material m, int i) { + private static PipeModel getOrCachePipeModel(@Nullable Material m, int i) { if (m == null) return PIPE_OVERRIDES.last().getModel(null, i); PipeModel[] cached = PIPE.computeIfAbsent(m, k -> new PipeModel[PIPE_MODEL_COUNT]); PipeModel selected = cached[i]; @@ -201,7 +203,7 @@ private static void initCables() { } array[i] = new CableModel(Textures.INSULATION[i - 1], Textures.INSULATION_FULL); } - CABLE_OVERRIDES.add(new MaterialModelOverride.StandardOverride<>(array, m -> true)); + CABLE_OVERRIDES.addAndMoveToLast(new MaterialModelOverride.StandardOverride<>(array, m -> true)); ResourceLocation loc = GTUtility.gregtechId("block/cable"); for (int i = 0; i < CABLE_MODEL_COUNT; i++) { @@ -210,7 +212,7 @@ private static void initCables() { } } - private static CableModel getOrCacheCableModel(Material m, int i) { + private static CableModel getOrCacheCableModel(@Nullable Material m, int i) { if (m == null) return CABLE_OVERRIDES.last().getModel(null, i); CableModel[] cached = CABLE.computeIfAbsent(m, k -> new CableModel[CABLE_MODEL_COUNT]); CableModel selected = cached[i]; diff --git a/src/main/java/gregtech/client/renderer/pipe/util/MaterialModelOverride.java b/src/main/java/gregtech/client/renderer/pipe/util/MaterialModelOverride.java index 8d080b924a6..6b4838856e1 100644 --- a/src/main/java/gregtech/client/renderer/pipe/util/MaterialModelOverride.java +++ b/src/main/java/gregtech/client/renderer/pipe/util/MaterialModelOverride.java @@ -16,12 +16,12 @@ public interface MaterialModelOverride> { @Desugar record StandardOverride> (@NotNull T[] models, - @NotNull Predicate predicate) + @NotNull Predicate<@Nullable Material> predicate) implements MaterialModelOverride { @Override public @Nullable T getModel(Material material, int i) { - if (material == null || !predicate.test(material)) return null; + if (!predicate.test(material)) return null; else return models[i]; } } From 7848291a4176f9539df0ec9cb1cd4645d38b2e63 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 4 Sep 2024 21:17:04 -0600 Subject: [PATCH 121/157] Fix misc stuff --- .../pipenet/physical/IPipeStructure.java | 4 +-- .../traverse/IEqualizableTraverseData.java | 12 ++++++++ .../graphnet/traverse/TraverseHelpers.java | 2 +- .../java/gregtech/api/util/GTUtility.java | 4 +-- .../common/covers/CoverFluidRegulator.java | 17 ++++++----- .../common/covers/CoverRoboticArm.java | 17 ++++++----- .../net/fluid/FluidEQTraverseData.java | 21 ++++++++++++++ .../pipelike/net/item/ItemEQTraverseData.java | 21 ++++++++++++++ .../java/gregtech/api/util/GTUtilityTest.java | 28 +++++++++++++++++++ 9 files changed, 107 insertions(+), 19 deletions(-) create mode 100644 src/test/java/gregtech/api/util/GTUtilityTest.java diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java index e047314f99a..9e2170b466c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeStructure.java @@ -38,11 +38,11 @@ default boolean canConnectTo(EnumFacing side, byte connectionMask) { default List getPipeBoxes(@NotNull PipeTileEntity tileContext) { List pipeBoxes = new ObjectArrayList<>(); float thickness = getRenderThickness(); - if ((tileContext.getConnectionMask() & 63) < 63) { + if ((tileContext.getCoverAdjustedConnectionMask() & 63) < 63) { pipeBoxes.add(getSideBox(null, thickness)); } for (EnumFacing facing : EnumFacing.VALUES) { - if (tileContext.isConnected(facing)) + if (tileContext.isConnectedCoverAdjusted(facing)) pipeBoxes.add(getSideBox(facing, thickness)); } return pipeBoxes; diff --git a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java index ecc8cac2b04..50edd683349 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java @@ -20,4 +20,16 @@ public interface IEqualizableTraverseData> long traverseEqualDistribution( if (pathFlow <= 0) continue pathloop; } - long accepted = data.finalizeAtDestination(nodes.get(nodes.size() - 1), pathFlow); + long accepted = data.finalizeAtDestination(nodes.get(nodes.size() - 1), pathFlow, entry.getIntValue()); if (!simulate) pathTraverseCalls.forEach(Runnable::run); availableFlow -= stack.consumeWithEndValue(accepted); diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 73b3f841a04..ea08d84c411 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -925,10 +925,10 @@ public static long binarySearch(long minValue, long maxValue, LongPredicate test if (test.test(middle) ^ !ascending) { maxValue = middle; } else { - minValue = maxValue; + minValue = middle; } } - return ascending ? maxValue : minValue; + return test.test(ascending ? minValue : maxValue) ^ ascending ? maxValue : minValue; } public static int[] convertARGBtoArray(int argb) { diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 7ff0df71b54..cfce81f24c3 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -353,10 +353,13 @@ protected void compute(@NotNull WorldPipeNetNode destination) { } @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { - long availableFlow = flowReachingDestination; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + public long finalizeAtDestination(@NotNull WorldPipeNetNode node, long flowReachingNode, + int expectedDestinations) { + long availableFlow = flowReachingNode; + long flowPerDestination = flowReachingNode / expectedDestinations; + if (flowPerDestination == 0) return 0; + for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { + if (GTUtility.arePosEqual(node.getEquivalencyData(), sourcePos) && capability.getKey() == inputFacing) continue; // anti insert-to-our-source logic @@ -368,12 +371,12 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl assert getFluidFilter() != null; int kept = getFluidFilter().getTransferLimit(getTestObject().recombine()); if (contained >= kept) continue; - availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + availableFlow -= IFluidTransferController.CONTROL.get(node.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, !simulating()); + (int) Math.min(kept - contained, flowPerDestination), container, !simulating()); } } - return flowReachingDestination - availableFlow; + return flowReachingNode - availableFlow; } } diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index c43dc53ed04..f4692d3a689 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -365,10 +365,13 @@ protected void compute(@NotNull WorldPipeNetNode destination) { } @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { - long availableFlow = flowReachingDestination; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && + public long finalizeAtDestination(@NotNull WorldPipeNetNode node, long flowReachingNode, + int expectedDestinations) { + long availableFlow = flowReachingNode; + long flowPerDestination = flowReachingNode / expectedDestinations; + if (flowPerDestination == 0) return 0; + for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { + if (GTUtility.arePosEqual(node.getEquivalencyData(), sourcePos) && capability.getKey() == inputFacing) continue; // anti insert-to-our-source logic @@ -380,12 +383,12 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl assert getItemFilter() != null; int kept = getItemFilter().getTransferLimit(getTestObject().recombine()); if (contained >= kept) continue; - availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + availableFlow = IItemTransferController.CONTROL.get(node.getTileEntity().getCoverHolder() .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, simulating()); + (int) Math.min(kept - contained, flowPerDestination), container, simulating()); } } - return flowReachingDestination - availableFlow; + return flowReachingNode - availableFlow; } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java index ae4c42299d9..5f11c9d878d 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java @@ -63,4 +63,25 @@ public boolean shouldSkipPath(@NotNull FlowWorldPipeNetPath path) { public long getMaxFlowToLeastDestination(@NotNull WorldPipeNetNode destination) { return maxMinFlow; } + + @Override + public long finalizeAtDestination(@NotNull WorldPipeNetNode node, long flowReachingNode, int expectedDestinations) { + long availableFlow = flowReachingNode; + long flowPerDestination = flowReachingNode / expectedDestinations; + if (flowPerDestination == 0) return 0; + for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { + if (GTUtility.arePosEqual(node.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IFluidHandler container = capability.getValue() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + availableFlow -= IFluidTransferController.CONTROL.get(node.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + (int) Math.min(Integer.MAX_VALUE, flowPerDestination), container, !simulating()); + } + } + return flowReachingNode - availableFlow; + } } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java index 2caa35f7371..6f8246a7a66 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java @@ -63,4 +63,25 @@ public boolean shouldSkipPath(@NotNull FlowWorldPipeNetPath path) { public long getMaxFlowToLeastDestination(@NotNull WorldPipeNetNode destination) { return maxMinFlow; } + + @Override + public long finalizeAtDestination(@NotNull WorldPipeNetNode node, long flowReachingNode, int expectedDestinations) { + long availableFlow = flowReachingNode; + long flowPerDestination = flowReachingNode / expectedDestinations; + if (flowPerDestination == 0) return 0; + for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { + if (GTUtility.arePosEqual(node.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IItemHandler container = capability.getValue() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); + if (container != null) { + availableFlow = IItemTransferController.CONTROL.get(node.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), + (int) Math.min(Integer.MAX_VALUE, flowPerDestination), container, simulating()); + } + } + return flowReachingNode - availableFlow; + } } diff --git a/src/test/java/gregtech/api/util/GTUtilityTest.java b/src/test/java/gregtech/api/util/GTUtilityTest.java new file mode 100644 index 00000000000..b2bc0520559 --- /dev/null +++ b/src/test/java/gregtech/api/util/GTUtilityTest.java @@ -0,0 +1,28 @@ +package gregtech.api.util; + +import org.junit.jupiter.api.Test; + +public class GTUtilityTest { + + @Test + public void binarySearchTest() { + for (int i = 0; i < 1000; i++) { + int finalI = i; + + long result = GTUtility.binarySearch(0, 10000, l -> l >= finalI, true); + + if (result != finalI) { + throw new AssertionError("Got " + result + " when desiring " + finalI); + } + } + for (int i = 0; i < 1000; i++) { + int finalI = i; + + long result = GTUtility.binarySearch(0, 10000, l -> l <= finalI, false); + + if (result != finalI) { + throw new AssertionError("Got " + result + " when desiring " + finalI); + } + } + } +} From ff72f205941f94fcb5f8b5bb99affe2006543a72 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Wed, 4 Sep 2024 21:41:17 -0600 Subject: [PATCH 122/157] More fixes --- .../DynamicWeightsShortestPathsAlgorithm.java | 1 + .../java/gregtech/client/ClientProxy.java | 2 ++ .../renderer/pipe/AbstractPipeModel.java | 23 ++++++++++++++----- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java index d474101d6d2..381268fb87f 100644 --- a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java @@ -80,6 +80,7 @@ private void calculateNext() { next = remapper.map(source); return; } + searchSpace.removeIf(vertex -> !graph.containsVertex(vertex)); ManyToManyShortestPaths paths = getManyToManyPaths(Collections.singleton(source), searchSpace); Optional next = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) diff --git a/src/main/java/gregtech/client/ClientProxy.java b/src/main/java/gregtech/client/ClientProxy.java index 46b5f50081a..aa204495aa5 100644 --- a/src/main/java/gregtech/client/ClientProxy.java +++ b/src/main/java/gregtech/client/ClientProxy.java @@ -15,6 +15,7 @@ import gregtech.client.model.customtexture.MetadataSectionCTM; import gregtech.client.renderer.handler.FacadeRenderer; import gregtech.client.renderer.handler.MetaTileEntityRenderer; +import gregtech.client.renderer.pipe.AbstractPipeModel; import gregtech.client.renderer.pipe.PipeModelRegistry; import gregtech.client.utils.ItemRenderCompat; import gregtech.client.utils.TooltipHelper; @@ -108,6 +109,7 @@ public static void registerColors() { @SubscribeEvent public static void registerBakedModels(ModelBakeEvent event) { + AbstractPipeModel.invalidateCaches(); PipeModelRegistry.registerModels(event.getModelRegistry()); } diff --git a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java index ed7cfb09e27..0310cf2b38f 100644 --- a/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java +++ b/src/main/java/gregtech/client/renderer/pipe/AbstractPipeModel.java @@ -8,6 +8,7 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.info.MaterialIconType; import gregtech.api.util.GTUtility; +import gregtech.api.util.reference.WeakHashSet; import gregtech.client.renderer.pipe.cache.ColorQuadCache; import gregtech.client.renderer.pipe.cache.StructureQuadCache; import gregtech.client.renderer.pipe.cover.CoverRendererPackage; @@ -55,7 +56,21 @@ public abstract class AbstractPipeModel { public static final UnlistedPropertyMaterial MATERIAL_PROPERTY = new UnlistedPropertyMaterial("material"); protected final Object2ObjectOpenHashMap frameCache = new Object2ObjectOpenHashMap<>(); - protected final Object2ObjectOpenHashMap pipeCache = new Object2ObjectOpenHashMap<>(); + protected final Object2ObjectOpenHashMap pipeCache; + + protected static final WeakHashSet> PIPE_CACHES = new WeakHashSet<>(); + + public static void invalidateCaches() { + for (var cache : PIPE_CACHES) { + cache.clear(); + cache.trim(16); + } + } + + public AbstractPipeModel() { + pipeCache = new Object2ObjectOpenHashMap<>(); + PIPE_CACHES.add(pipeCache); + } public @NotNull List getQuads(IExtendedBlockState state, EnumFacing side, long rand) { if (side == null) { @@ -108,11 +123,7 @@ protected static int safeInt(@Nullable Integer integer) { @Nullable Material frameMaterial, byte frameMask, byte coverMask) { List quads = new ObjectArrayList<>(); - StructureQuadCache cache = pipeCache.get(key); - if (cache == null) { - cache = constructForKey(key); - pipeCache.put(key, cache); - } + StructureQuadCache cache = pipeCache.computeIfAbsent(key, this::constructForKey); cache.addToList(quads, connectionMask, closedMask, blockedMask, data, coverMask); From 9e9d0a290a446ce2b93ca85c03a2989d176f1927 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 5 Sep 2024 13:07:35 -0600 Subject: [PATCH 123/157] More fixes yey --- .../pipenet/physical/block/PipeBlock.java | 26 ++++++++++++++----- .../physical/block/PipeMaterialBlock.java | 10 ------- .../physical/tile/PipeMaterialTileEntity.java | 5 ++++ .../pipenet/physical/tile/PipeTileEntity.java | 20 ++++++++++++++ .../renderer/pipe/AbstractPipeModel.java | 3 ++- .../pipe/cover/CoverRendererBuilder.java | 20 +++++++++----- .../gregtech/common/covers/CoverConveyor.java | 4 +-- .../gregtech/common/covers/CoverPump.java | 4 +-- .../common/covers/CoverRoboticArm.java | 4 +-- 9 files changed, 66 insertions(+), 30 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 4d47843b823..6c44f286252 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -122,15 +122,19 @@ public void doPlacementLogic(PipeTileEntity tile, EnumFacing placedBlockSearchSi if (neighbor instanceof PipeTileEntity other) { // first check -- does the other tile have a cover that would prevent connection Cover cover = other.getCoverHolder().getCoverAtSide(facing.getOpposite()); - if (cover != null && !cover.canPipePassThrough()) continue; + if (cover != null && !cover.canPipePassThrough()) { + // first check extended -- connect visually if the cover visually connects + if (cover.forcePipeRenderConnection() && (facing == placedBlockSearchSide || + !ConfigHolder.machines.gt6StylePipesCables)) + connectTile(tile, null, facing); + } // second check -- connect to matching mark pipes if side matches or config allows. - if (tile.getPaintingColor() == other.getPaintingColor() && (facing == placedBlockSearchSide || + else if (tile.getPaintingColor() == other.getPaintingColor() && (facing == placedBlockSearchSide || !ConfigHolder.machines.gt6StylePipesCables)) { - if (coverCheck(tile, other, facing)) connectTile(tile, other, facing); - continue; - } + if (coverCheck(tile, other, facing)) connectTile(tile, other, facing); + } // third check -- connect to pipes with an open connection, no matter the mark status. - if (other.isConnected(facing.getOpposite())) { + else if (other.isConnected(facing.getOpposite())) { if (coverCheck(tile, other, facing)) connectTile(tile, other, facing); } } else if (facing == placedBlockSearchSide) { @@ -550,7 +554,7 @@ public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, En if (entity instanceof EntityPlayer player) { return hasPipeCollisionChangingItem(world, pos, player.getHeldItemMainhand()) || hasPipeCollisionChangingItem(world, pos, player.getHeldItemOffhand()) || - entity.isSneaking() && isHoldingPipe(player); + entity.isSneaking() && (isHoldingPipe(player) || player.getHeldItemMainhand().isEmpty()); } return false; } @@ -569,6 +573,14 @@ public static PipeBlock getBlockFromItem(@NotNull ItemStack stack) { else return null; } + @Override + public @NotNull ItemStack getPickBlock(@NotNull IBlockState state, @NotNull RayTraceResult target, + @NotNull World world, @NotNull BlockPos pos, @NotNull EntityPlayer player) { + PipeTileEntity tile = getTileEntity(world, pos); + if (tile != null) return tile.getPickItem(target, player); + return super.getPickBlock(state, target, world, pos, player); + } + public boolean hasPipeCollisionChangingItem(IBlockAccess world, BlockPos pos, ItemStack stack) { if (isPipeTool(stack)) return true; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index 88ac5ebb8ca..fa8bdfb99e4 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -18,12 +18,10 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.creativetab.CreativeTabs; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; @@ -60,14 +58,6 @@ public void getSubBlocks(@NotNull CreativeTabs itemIn, @NotNull NonNullList quads, @NotNull CoverRendererPackage int matColor = GTUtility.convertRGBtoARGB(material.getMaterialRGB()); if (color == 0 || color == matColor) { // unpainted - color = 0xFFFFFFFF; + color = ConfigHolder.client.defaultPaintingColor; } } } diff --git a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java index fa31dd8240a..2083f0b7afd 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java +++ b/src/main/java/gregtech/client/renderer/pipe/cover/CoverRendererBuilder.java @@ -1,6 +1,5 @@ package gregtech.client.renderer.pipe.cover; -import gregtech.api.GTValues; import gregtech.api.cover.CoverUtil; import gregtech.client.renderer.pipe.cache.ColorQuadCache; import gregtech.client.renderer.pipe.cache.SubListAddress; @@ -39,7 +38,7 @@ public class CoverRendererBuilder { private static final float OVERLAY_DIST_1 = 0.003f; private static final float OVERLAY_DIST_2 = 0.006f; - private static final ColorQuadCache PLATE_QUADS; + private static final ColorQuadCache[] PLATE_QUADS; private static final EnumMap PLATE_COORDS = new EnumMap<>(EnumFacing.class); public static final EnumMap PLATE_AABBS = new EnumMap<>(EnumFacing.class); @@ -63,11 +62,15 @@ public class CoverRendererBuilder { OVERLAY_BOXES_2.put(value.getKey(), QuadHelper.fullOverlay(value.getKey(), value.getValue(), OVERLAY_DIST_2)); } - PLATE_QUADS = buildPlates(new SpriteInformation(defaultPlateSprite(), 0)); + PLATE_QUADS = new ColorQuadCache[Textures.VOLTAGE_CASINGS.length]; + for (int i = 0; i < Textures.VOLTAGE_CASINGS.length; i++) { + if (Textures.VOLTAGE_CASINGS[i] == null) break; + PLATE_QUADS[i] = buildPlates(new SpriteInformation(plateSprite(i), 0)); + } } - private static @NotNull TextureAtlasSprite defaultPlateSprite() { - return Textures.VOLTAGE_CASINGS[GTValues.LV].getSpriteOnSide(SimpleSidedCubeRenderer.RenderSide.SIDE); + private static @NotNull TextureAtlasSprite plateSprite(int i) { + return Textures.VOLTAGE_CASINGS[i].getSpriteOnSide(SimpleSidedCubeRenderer.RenderSide.SIDE); } public static ColorQuadCache buildPlates(SpriteInformation sprite) { @@ -100,7 +103,7 @@ protected static void addPlates(List quads, List plateQuad protected UVMapper mapper = defaultMapper; protected UVMapper mapperEmissive = defaultMapper; - protected ColorQuadCache plateQuads = PLATE_QUADS; + protected ColorQuadCache plateQuads = PLATE_QUADS[1]; public CoverRendererBuilder(@NotNull SimpleOverlayRenderer overlay) { this(overlay.getSprite(), overlay.getSpriteEmissive()); @@ -126,6 +129,11 @@ public CoverRendererBuilder setPlateQuads(ColorQuadCache cache) { return this; } + public CoverRendererBuilder setPlateQuads(int index) { + this.plateQuads = PLATE_QUADS[index]; + return this; + } + protected static List getPlates(EnumFacing facing, ColorData data, ColorQuadCache plateQuads) { return PLATE_COORDS.get(facing).getSublist(plateQuads.getQuads(data)); } diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 0b3bb887a4f..9f75843b327 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -717,11 +717,11 @@ public void readFromNBT(@NotNull NBTTagCompound tagCompound) { @Override protected CoverRenderer buildRenderer() { - return new CoverRendererBuilder(Textures.CONVEYOR_OVERLAY).build(); + return new CoverRendererBuilder(Textures.CONVEYOR_OVERLAY).setPlateQuads(tier).build(); } protected CoverRenderer buildRendererInverted() { - return new CoverRendererBuilder(Textures.CONVEYOR_OVERLAY_INVERTED).build(); + return new CoverRendererBuilder(Textures.CONVEYOR_OVERLAY_INVERTED).setPlateQuads(tier).build(); } @Override diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index ff9ffbc9dbf..d58745651d9 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -563,11 +563,11 @@ public void renderCover(@NotNull CCRenderState renderState, @NotNull Matrix4 tra @Override protected CoverRenderer buildRenderer() { - return new CoverRendererBuilder(Textures.PUMP_OVERLAY).build(); + return new CoverRendererBuilder(Textures.PUMP_OVERLAY).setPlateQuads(tier).build(); } protected CoverRenderer buildRendererInverted() { - return new CoverRendererBuilder(Textures.PUMP_OVERLAY_INVERTED).build(); + return new CoverRendererBuilder(Textures.PUMP_OVERLAY_INVERTED).setPlateQuads(tier).build(); } @Override diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index f4692d3a689..decce3ad0fc 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -71,12 +71,12 @@ public void renderCover(CCRenderState renderState, Matrix4 translation, IVertexO @Override protected CoverRenderer buildRenderer() { - return new CoverRendererBuilder(Textures.ARM_OVERLAY).build(); + return new CoverRendererBuilder(Textures.ARM_OVERLAY).setPlateQuads(tier).build(); } @Override protected CoverRenderer buildRendererInverted() { - return new CoverRendererBuilder(Textures.ARM_OVERLAY_INVERTED).build(); + return new CoverRendererBuilder(Textures.ARM_OVERLAY_INVERTED).setPlateQuads(tier).build(); } @Override From 4b453f9697737c79ff316ab3974b6bbd3a1ca323 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 5 Sep 2024 18:17:44 -0600 Subject: [PATCH 124/157] Accumulated fixes & TOP improvements --- .../logic/AbstractTransientLogicData.java | 34 +++++ .../api/graphnet/logic/NetLogicData.java | 5 +- .../api/graphnet/logic/NetLogicEntry.java | 2 - .../pipenet/physical/block/PipeBlock.java | 12 +- .../physical/block/PipeMaterialBlock.java | 7 +- .../pipenet/physical/tile/PipeTileEntity.java | 7 + .../items/behaviors/TricorderBehavior.java | 4 +- .../pipelike/block/laser/LaserPipeBlock.java | 6 +- .../block/optical/OpticalPipeBlock.java | 6 +- .../properties/MaterialFluidProperties.java | 4 + .../properties/MaterialItemProperties.java | 4 + .../pipelike/net/energy/EnergyFlowLogic.java | 36 +---- .../net/fluid/FluidCapabilityObject.java | 2 + .../pipelike/net/fluid/FluidFlowLogic.java | 63 +++++++++ .../pipelike/net/fluid/FluidTraverseData.java | 28 ++-- .../pipelike/net/fluid/WorldFluidNet.java | 2 +- .../pipelike/net/item/ItemFlowLogic.java | 63 +++++++++ .../pipelike/net/item/ItemTraverseData.java | 19 +++ .../pipelike/net/item/WorldItemNet.java | 2 +- .../theoneprobe/TheOneProbeModule.java | 1 + .../provider/PipeTileInfoProvider.java | 128 ++++++++++++++++++ .../resources/assets/gregtech/lang/en_us.lang | 5 + 22 files changed, 375 insertions(+), 65 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/logic/AbstractTransientLogicData.java create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java create mode 100644 src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java create mode 100644 src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractTransientLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractTransientLogicData.java new file mode 100644 index 00000000000..16ff72a13f2 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractTransientLogicData.java @@ -0,0 +1,34 @@ +package gregtech.api.graphnet.logic; + +import net.minecraft.nbt.NBTBase; +import net.minecraft.network.PacketBuffer; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class AbstractTransientLogicData> + extends NetLogicEntry { + + protected AbstractTransientLogicData(@NotNull String name) { + super(name); + } + + @Override + public final void deserializeNBT(NBTBase nbt) {} + + @Override + public final @Nullable NBTBase serializeNBT() { + return null; + } + + @Override + public boolean shouldEncode() { + return false; + } + + @Override + public void encode(PacketBuffer buf, boolean fullChange) {} + + @Override + public void decode(PacketBuffer buf, boolean fullChange) {} +} diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index 3dfce7ee10b..e68c8499867 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -157,10 +157,11 @@ public boolean hasLogicEntry(@NotNull NetLogicEntry key) { public NBTTagList serializeNBT() { NBTTagList list = new NBTTagList(); for (NetLogicEntry entry : getEntries()) { + NBTBase nbt = entry.serializeNBT(); + if (nbt == null) continue; NBTTagCompound tag = new NBTTagCompound(); tag.setString("Name", entry.getName()); - NBTBase nbt = entry.serializeNBT(); - if (nbt != null) tag.setTag("Tag", nbt); + tag.setTag("Tag", nbt); list.appendTag(tag); } return list; diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java index e0cfd1e78c1..78fd8f77fb5 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java @@ -99,8 +99,6 @@ public T cast(NetLogicEntry entry) { /** * Controls whether this {@link NetLogicEntry} will be synced to the client or not. - * - * @return */ public boolean shouldEncode() { return true; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 6c44f286252..ae89c270dbf 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -371,20 +371,12 @@ protected boolean allowsBlocking() { public static Collection getNodesForTile(PipeTileEntity tile) { assert !tile.getWorld().isRemote; - return tile.getBlockType().getHandler(tile.getWorld(), tile.getPos()) + return tile.getBlockType().getHandler(tile) .getOrCreateFromNets(tile.getWorld(), tile.getPos(), tile.getStructure()); } - @Override - public void breakBlock(@NotNull World worldIn, @NotNull BlockPos pos, @NotNull IBlockState state) { - super.breakBlock(worldIn, pos, state); - if (!worldIn.isRemote) { - getHandler(worldIn, pos).removeFromNets(worldIn, pos, getStructure()); - } - } - @NotNull - protected abstract IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos); + public abstract IPipeNetNodeHandler getHandler(PipeTileEntity tileContext); @NotNull protected abstract IPipeNetNodeHandler getHandler(@NotNull ItemStack stack); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index fa8bdfb99e4..80e8557e9a2 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -74,10 +74,9 @@ public Material getMaterialForStack(@NotNull ItemStack stack) { } @Override - protected @NotNull IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos) { - PipeMaterialTileEntity tile = getTileEntity(world, pos); - if (tile != null) return tile.getMaterial().getProperty(PropertyKey.PIPENET_PROPERTIES); - else return Materials.Aluminium.getProperty(PropertyKey.PIPENET_PROPERTIES); + @NotNull + public IPipeNetNodeHandler getHandler(PipeTileEntity tileContext) { + return ((PipeMaterialTileEntity) tileContext).getMaterial().getProperty(PropertyKey.PIPENET_PROPERTIES); } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index ec9416bc745..ec4fa0ea5bb 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -57,6 +57,7 @@ import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; import java.util.EnumMap; import java.util.List; @@ -122,6 +123,8 @@ public void validate() { @Override public void invalidate() { super.invalidate(); + if (!getWorld().isRemote) getBlockType().getHandler(this) + .removeFromNets(this.getWorld(), this.getPos(), this.getStructure()); // TODO I hate this so much can someone please make it so that covers go through getDrops()? getCoverHolder().dropAllCovers(); } @@ -460,6 +463,10 @@ public NetLogicData getNetLogicData(int networkID) { return netLogicDatas.get(networkID); } + public @UnmodifiableView Int2ObjectOpenHashMap getNetLogicDatas() { + return netLogicDatas; + } + @Override public @NotNull PipeBlock getBlockType() { return (PipeBlock) super.getBlockType(); diff --git a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java index 719a3ada31a..260a1c788ce 100644 --- a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java @@ -286,12 +286,12 @@ else if (metaTileEntity instanceof IDataInfoProvider) int cumulativeCount = 0; long cumulativeVoltage = 0; long cumulativeAmperage = 0; - for (var memory : data.getLogicEntryDefaultable(EnergyFlowLogic.INSTANCE).getMemory().entrySet()) { + for (var memory : data.getLogicEntryDefaultable(EnergyFlowLogic.INSTANCE).getMemory().values()) { cumulativeCount++; int count = 0; double voltage = 0; long amperage = 0; - for (EnergyFlowData flow : memory.getValue()) { + for (EnergyFlowData flow : memory) { count++; long prev = amperage; amperage += flow.amperage(); diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java index b2982c286e0..23d279fda32 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserPipeBlock.java @@ -2,13 +2,12 @@ import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.physical.block.PipeActivableBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.toolitem.ToolClasses; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.pipelike.handlers.LaserNetHandler; import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockAccess; import org.jetbrains.annotations.NotNull; @@ -35,7 +34,8 @@ protected boolean allowsBlocking() { } @Override - protected @NotNull IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos) { + @NotNull + public IPipeNetNodeHandler getHandler(PipeTileEntity tileContext) { return LaserNetHandler.INSTANCE; } diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java index 8ce692697a2..74bb6a82836 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalPipeBlock.java @@ -2,13 +2,12 @@ import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.physical.block.PipeActivableBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.toolitem.ToolClasses; import gregtech.common.creativetab.GTCreativeTabs; import gregtech.common.pipelike.handlers.OpticalNetHandler; import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockAccess; import org.jetbrains.annotations.NotNull; @@ -35,7 +34,8 @@ protected boolean allowsBlocking() { } @Override - protected @NotNull IPipeNetNodeHandler getHandler(IBlockAccess world, BlockPos pos) { + @NotNull + public IPipeNetNodeHandler getHandler(PipeTileEntity tileContext) { return OpticalNetHandler.INSTANCE; } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index b77fc8b1d9e..2e43fe07d9e 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -5,6 +5,7 @@ import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; @@ -187,6 +188,9 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { .mergeLogicEntry(TemperatureLogic.INSTANCE .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), materialMeltTemperature, minFluidTemperature, 50 * pipe.material(), null)); + if (pipe.channelCount() > 1) { + data.setLogicEntry(ChannelCountLogic.INSTANCE.getWith(pipe.channelCount())); + } } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index d33d65023ea..e0f35222408 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -1,6 +1,7 @@ package gregtech.common.pipelike.handlers.properties; import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; @@ -84,6 +85,9 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { long throughput = baseItemsPer5Ticks * pipe.material(); data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(getFlowPriority(structure))) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)); + if (pipe.channelCount() > 1) { + data.setLogicEntry(ChannelCountLogic.INSTANCE.getWith(pipe.channelCount())); + } } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java index fdb5769892a..97ee3c93eb2 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java @@ -1,9 +1,8 @@ package gregtech.common.pipelike.net.energy; -import gregtech.api.graphnet.logic.NetLogicEntry; +import gregtech.api.graphnet.logic.AbstractTransientLogicData; -import net.minecraft.nbt.NBTTagByte; -import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.common.FMLCommonHandler; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; @@ -13,11 +12,11 @@ import java.util.Collections; import java.util.List; -public class EnergyFlowLogic extends NetLogicEntry { +public class EnergyFlowLogic extends AbstractTransientLogicData { public static final EnergyFlowLogic INSTANCE = new EnergyFlowLogic(); - private static final int MEMORY_TICKS = 10; + public static final int MEMORY_TICKS = 10; private final Long2ObjectOpenHashMap> memory = new Long2ObjectOpenHashMap<>(); @@ -26,20 +25,18 @@ protected EnergyFlowLogic() { } public @NotNull Long2ObjectOpenHashMap> getMemory() { + updateMemory(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); return memory; } public @NotNull List getFlow(long tick) { + updateMemory(tick); return memory.getOrDefault(tick, Collections.emptyList()); } public void recordFlow(long tick, EnergyFlowData flow) { updateMemory(tick); - memory.compute(tick, (k, v) -> { - if (v == null) v = new ObjectArrayList<>(); - v.add(flow); - return v; - }); + memory.computeIfAbsent(tick, k -> new ObjectArrayList<>()).add(flow); } private void updateMemory(long tick) { @@ -52,27 +49,8 @@ private void updateMemory(long tick) { } } - @Override - public NBTTagByte serializeNBT() { - return new NBTTagByte((byte) 0); - } - - @Override - public void deserializeNBT(NBTTagByte nbt) {} - @Override public @NotNull EnergyFlowLogic getNew() { return new EnergyFlowLogic(); } - - @Override - public boolean shouldEncode() { - return false; - } - - @Override - public void encode(PacketBuffer buf, boolean fullChange) {} - - @Override - public void decode(PacketBuffer buf, boolean fullChange) {} } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index c3ef8072e92..485c5bbf169 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -85,7 +85,9 @@ public Capability[] getCapabilities() { @Override public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { + if (facing == null) return null; // hard override to prevent TOP from displaying a tank. if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { + // noinspection ConstantValue return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(facing == null ? this : wrappers.get(facing)); } return null; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java new file mode 100644 index 00000000000..6c7b10455c3 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java @@ -0,0 +1,63 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.graphnet.logic.AbstractTransientLogicData; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fml.common.FMLCommonHandler; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class FluidFlowLogic extends AbstractTransientLogicData { + + public static final FluidFlowLogic INSTANCE = new FluidFlowLogic(); + + public static final int MEMORY_TICKS = 10; + + private final Long2ObjectOpenHashMap> memory = new Long2ObjectOpenHashMap<>(); + private FluidStack last; + + protected FluidFlowLogic() { + super("FluidFlow"); + } + + public @NotNull Long2ObjectOpenHashMap> getMemory() { + updateMemory(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); + return memory; + } + + public @NotNull List getFlow(long tick) { + updateMemory(tick); + return memory.getOrDefault(tick, Collections.emptyList()); + } + + public void recordFlow(long tick, FluidStack flow) { + updateMemory(tick); + memory.computeIfAbsent(tick, k -> new ObjectArrayList<>()).add(flow); + last = flow; + } + + public FluidStack getLast() { + return last; + } + + private void updateMemory(long tick) { + var iter = memory.long2ObjectEntrySet().fastIterator(); + while (iter.hasNext()) { + Long2ObjectMap.Entry> entry = iter.next(); + if (entry.getLongKey() + MEMORY_TICKS < tick) { + iter.remove(); + } + } + } + + @Override + public @NotNull FluidFlowLogic getNew() { + return new FluidFlowLogic(); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index 8ba0b338b19..3b591b2e9a7 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -166,14 +166,26 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { super.consumeFlowLimit(edge, targetNode, consumption); - TemperatureLogic temperatureLogic = targetNode.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); - if (temperatureLogic != null) { - FluidContainmentLogic containmentLogic = targetNode.getData() - .getLogicEntryDefaultable(FluidContainmentLogic.INSTANCE); - boolean overMax = fluidTemp > containmentLogic.getMaximumTemperature() && - !(state == FluidState.PLASMA && containmentLogic.contains(FluidState.PLASMA)); - temperatureLogic.moveTowardsTemperature(fluidTemp, - getQueryTick(), consumption * TEMPERATURE_EFFECT, !overMax); + if (consumption > 0 && !simulating()) { + recordFlow(targetNode, consumption); + TemperatureLogic temperatureLogic = targetNode.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + if (temperatureLogic != null) { + FluidContainmentLogic containmentLogic = targetNode.getData() + .getLogicEntryDefaultable(FluidContainmentLogic.INSTANCE); + boolean overMax = fluidTemp > containmentLogic.getMaximumTemperature() && + !(state == FluidState.PLASMA && containmentLogic.contains(FluidState.PLASMA)); + temperatureLogic.moveTowardsTemperature(fluidTemp, + getQueryTick(), consumption * TEMPERATURE_EFFECT, !overMax); + } + } + } + + private void recordFlow(@NotNull NetNode node, long flow) { + FluidFlowLogic logic = node.getData().getLogicEntryNullable(FluidFlowLogic.INSTANCE); + if (logic == null) { + logic = FluidFlowLogic.INSTANCE.getNew(); + node.getData().setLogicEntry(logic); } + logic.recordFlow(getQueryTick(), getTestObject().recombine(GTUtility.safeCastLongToInt(flow))); } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 66e43f04014..75423e3d62a 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -46,7 +46,7 @@ public class WorldFluidNet extends WorldPipeNet implements FlowWorldPipeNetPath. } public WorldFluidNet(String name) { - super(name, false, DynamicWeightsShortestPathsAlgorithm::new); + super(name, true, DynamicWeightsShortestPathsAlgorithm::new); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java new file mode 100644 index 00000000000..068abe32267 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java @@ -0,0 +1,63 @@ +package gregtech.common.pipelike.net.item; + +import gregtech.api.graphnet.logic.AbstractTransientLogicData; + +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.common.FMLCommonHandler; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +public class ItemFlowLogic extends AbstractTransientLogicData { + + public static final ItemFlowLogic INSTANCE = new ItemFlowLogic(); + + public static final int MEMORY_TICKS = 10; + + private final Long2ObjectOpenHashMap> memory = new Long2ObjectOpenHashMap<>(); + private ItemStack last; + + protected ItemFlowLogic() { + super("ItemFlow"); + } + + public @NotNull Long2ObjectOpenHashMap> getMemory() { + updateMemory(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); + return memory; + } + + public @NotNull List getFlow(long tick) { + updateMemory(tick); + return memory.getOrDefault(tick, Collections.emptyList()); + } + + public void recordFlow(long tick, ItemStack flow) { + updateMemory(tick); + memory.computeIfAbsent(tick, k -> new ObjectArrayList<>()).add(flow); + last = flow; + } + + public ItemStack getLast() { + return last; + } + + private void updateMemory(long tick) { + var iter = memory.long2ObjectEntrySet().fastIterator(); + while (iter.hasNext()) { + Long2ObjectMap.Entry> entry = iter.next(); + if (entry.getLongKey() + MEMORY_TICKS < tick) { + iter.remove(); + } + } + } + + @Override + public @NotNull ItemFlowLogic getNew() { + return new ItemFlowLogic(); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java index cfd764086ea..41e654894f1 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java @@ -1,6 +1,8 @@ package gregtech.common.pipelike.net.item; import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; @@ -61,4 +63,21 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl } return flowReachingDestination - availableFlow; } + + @Override + public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { + super.consumeFlowLimit(edge, targetNode, consumption); + if (consumption > 0 && !simulating()) { + recordFlow(targetNode, consumption); + } + } + + private void recordFlow(@NotNull NetNode node, long flow) { + ItemFlowLogic logic = node.getData().getLogicEntryNullable(ItemFlowLogic.INSTANCE); + if (logic == null) { + logic = ItemFlowLogic.INSTANCE.getNew(); + node.getData().setLogicEntry(logic); + } + logic.recordFlow(getQueryTick(), getTestObject().recombine(GTUtility.safeCastLongToInt(flow))); + } } diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index ba3843ab923..39e92b08ad2 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -46,7 +46,7 @@ public class WorldItemNet extends WorldPipeNet implements FlowWorldPipeNetPath.P } public WorldItemNet(String name) { - super(name, false, DynamicWeightsShortestPathsAlgorithm::new); + super(name, true, DynamicWeightsShortestPathsAlgorithm::new); } @Override diff --git a/src/main/java/gregtech/integration/theoneprobe/TheOneProbeModule.java b/src/main/java/gregtech/integration/theoneprobe/TheOneProbeModule.java index 8b64c066cc9..0ec291cf5c8 100644 --- a/src/main/java/gregtech/integration/theoneprobe/TheOneProbeModule.java +++ b/src/main/java/gregtech/integration/theoneprobe/TheOneProbeModule.java @@ -43,6 +43,7 @@ public void init(FMLInitializationEvent event) { oneProbe.registerProvider(new LampInfoProvider()); oneProbe.registerProvider(new LDPipeProvider()); oneProbe.registerProvider(new LaserContainerInfoProvider()); + oneProbe.registerProvider(new PipeTileInfoProvider()); // Dev environment debug providers oneProbe.registerProvider(new DebugPipeNetInfoProvider()); diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java new file mode 100644 index 00000000000..292a3c1a95b --- /dev/null +++ b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java @@ -0,0 +1,128 @@ +package gregtech.integration.theoneprobe.provider; + +import gregtech.api.GTValues; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.common.pipelike.net.energy.EnergyFlowData; +import gregtech.common.pipelike.net.energy.EnergyFlowLogic; +import gregtech.common.pipelike.net.fluid.FluidFlowLogic; +import gregtech.common.pipelike.net.item.ItemFlowLogic; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; + +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import mcjty.theoneprobe.api.ElementAlignment; +import mcjty.theoneprobe.api.IProbeHitData; +import mcjty.theoneprobe.api.IProbeInfo; +import mcjty.theoneprobe.api.IProbeInfoProvider; +import mcjty.theoneprobe.api.ProbeMode; +import mcjty.theoneprobe.api.TextStyleClass; + +public class PipeTileInfoProvider implements IProbeInfoProvider { + + @Override + public String getID() { + return GTValues.MODID + ":pipe_tile_provider"; + } + + @Override + public void addProbeInfo(ProbeMode probeMode, IProbeInfo iProbeInfo, EntityPlayer entityPlayer, World world, + IBlockState iBlockState, IProbeHitData iProbeHitData) { + if (iBlockState.getBlock() instanceof PipeBlock pipe) { + PipeTileEntity tile = pipe.getTileEntity(world, iProbeHitData.getPos()); + if (tile != null) { + for (NetLogicData data : tile.getNetLogicDatas().values()) { + EnergyFlowLogic energy = data.getLogicEntryNullable(EnergyFlowLogic.INSTANCE); + if (energy != null) { + addEnergyFlowInformation(probeMode, iProbeInfo, entityPlayer, iProbeHitData, energy); + } + FluidFlowLogic fluid = data.getLogicEntryNullable(FluidFlowLogic.INSTANCE); + if (fluid != null) { + addFluidFlowInformation(probeMode, iProbeInfo, entityPlayer, iProbeHitData, fluid); + } + ItemFlowLogic item = data.getLogicEntryNullable(ItemFlowLogic.INSTANCE); + if (item != null) { + addItemFlowInformation(probeMode, iProbeInfo, entityPlayer, iProbeHitData, item); + } + } + } + } + } + + private void addEnergyFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, EntityPlayer entityPlayer, + IProbeHitData iProbeHitData, EnergyFlowLogic logic) { + long cumulativeVoltage = 0; + long cumulativeAmperage = 0; + for (var memory : logic.getMemory().values()) { + int count = 0; + double voltage = 0; + long amperage = 0; + for (EnergyFlowData flow : memory) { + count++; + long prev = amperage; + amperage += flow.amperage(); + // weighted average + voltage = voltage * prev / amperage + (double) (flow.voltage() * flow.amperage()) / amperage; + } + if (count != 0) { + cumulativeVoltage += voltage / count; + cumulativeAmperage += amperage / count; + } + } + iProbeInfo.text(TextStyleClass.INFO + "{*gregtech.top.pipe.voltage*} " + TextStyleClass.INFOIMP + + cumulativeVoltage / EnergyFlowLogic.MEMORY_TICKS); + iProbeInfo.text(TextStyleClass.INFO + "{*gregtech.top.pipe.amperage*} " + TextStyleClass.INFOIMP + + cumulativeAmperage / EnergyFlowLogic.MEMORY_TICKS); + } + + private void addFluidFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, EntityPlayer entityPlayer, + IProbeHitData iProbeHitData, FluidFlowLogic logic) { + iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) + .text(TextStyleClass.INFO + "{*gregtech.top.pipe.fluid_last*}") + .icon(logic.getLast().getFluid().getStill(logic.getLast()), -1, -1, 14, 14) + .text(logic.getLast().getLocalizedName()); + + Object2IntOpenHashMap counts = new Object2IntOpenHashMap<>(); + for (var memory : logic.getMemory().values()) { + for (FluidStack stack : memory) { + counts.merge(new FluidTestObject(stack), stack.amount, Integer::sum); + } + } + + for (var entry : counts.object2IntEntrySet()) { + FluidStack stack = entry.getKey().recombine(); + iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) + .icon(stack.getFluid().getStill(stack), -1, -1, 14, 14) + .text(entry.getIntValue() * 20 / FluidFlowLogic.MEMORY_TICKS + " L/s " + stack.getLocalizedName()); + } + } + + private void addItemFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, EntityPlayer entityPlayer, + IProbeHitData iProbeHitData, ItemFlowLogic logic) { + iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) + .text(TextStyleClass.INFO + "{*gregtech.top.pipe.item_last*}") + .item(logic.getLast()) + .text(logic.getLast().getDisplayName()); + + Object2IntOpenHashMap counts = new Object2IntOpenHashMap<>(); + for (var memory : logic.getMemory().values()) { + for (ItemStack stack : memory) { + counts.merge(new ItemTestObject(stack), stack.getCount(), Integer::sum); + } + } + + for (var entry : counts.object2IntEntrySet()) { + ItemStack stack = entry.getKey().recombine(); + iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) + .item(stack) + .text(entry.getIntValue() * 20 / ItemFlowLogic.MEMORY_TICKS + " /s " + stack.getDisplayName()); + } + } +} diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index f9eb22e1362..7a70a1bcd37 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -104,6 +104,11 @@ gregtech.top.ld_pipe_output=Output gregtech.top.ld_pipe_input_endpoint=Input Endpoint: gregtech.top.ld_pipe_output_endpoint=Output Endpoint: +gregtech.top.pipe.voltage=Average Voltage/s: +gregtech.top.pipe.amperage=Average Amperage/s: +gregtech.top.pipe.fluid_last=Last Fluid: +gregtech.top.pipe.item_last=Last Item: + option.gregtech.block_ore=Ore Blocks option.gregtech.controllable=Controllable Machines option.gregtech.converter=Energy Converters From 0a9d473f0c20f0df7dcb79e8c08ce1472476392d Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 5 Sep 2024 21:04:00 -0600 Subject: [PATCH 125/157] Improve TOP formatting --- .../provider/PipeTileInfoProvider.java | 38 ++++++++++++------- .../resources/assets/gregtech/lang/en_us.lang | 3 +- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java index 292a3c1a95b..4a4321b6e1a 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java @@ -6,12 +6,15 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.util.GTUtility; +import gregtech.api.util.TextFormattingUtil; import gregtech.common.pipelike.net.energy.EnergyFlowData; import gregtech.common.pipelike.net.energy.EnergyFlowLogic; import gregtech.common.pipelike.net.fluid.FluidFlowLogic; import gregtech.common.pipelike.net.item.ItemFlowLogic; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.world.World; @@ -76,18 +79,21 @@ private void addEnergyFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo cumulativeAmperage += amperage / count; } } - iProbeInfo.text(TextStyleClass.INFO + "{*gregtech.top.pipe.voltage*} " + TextStyleClass.INFOIMP + - cumulativeVoltage / EnergyFlowLogic.MEMORY_TICKS); - iProbeInfo.text(TextStyleClass.INFO + "{*gregtech.top.pipe.amperage*} " + TextStyleClass.INFOIMP + - cumulativeAmperage / EnergyFlowLogic.MEMORY_TICKS); + long v = cumulativeVoltage / EnergyFlowLogic.MEMORY_TICKS; + String voltage = TextFormattingUtil.formatNumbers(v); + String amperage = TextFormattingUtil.formatNumbers(cumulativeAmperage / EnergyFlowLogic.MEMORY_TICKS); + String tier = GTValues.VNF[GTUtility.getTierByVoltage(v)]; + iProbeInfo.text(I18n.format("gregtech.top.pipe.energy", voltage, tier, amperage)); } private void addFluidFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, EntityPlayer entityPlayer, IProbeHitData iProbeHitData, FluidFlowLogic logic) { - iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) - .text(TextStyleClass.INFO + "{*gregtech.top.pipe.fluid_last*}") - .icon(logic.getLast().getFluid().getStill(logic.getLast()), -1, -1, 14, 14) - .text(logic.getLast().getLocalizedName()); + if (logic.getMemory().isEmpty()) { + iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) + .text(TextStyleClass.INFO + "{*gregtech.top.pipe.fluid_last*} ") + .icon(logic.getLast().getFluid().getStill(logic.getLast()), -1, -1, 14, 14) + .text(" " + logic.getLast().getLocalizedName()); + } Object2IntOpenHashMap counts = new Object2IntOpenHashMap<>(); for (var memory : logic.getMemory().values()) { @@ -98,18 +104,21 @@ private void addFluidFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, for (var entry : counts.object2IntEntrySet()) { FluidStack stack = entry.getKey().recombine(); + String value = TextFormattingUtil.formatNumbers(entry.getIntValue() * 20L / FluidFlowLogic.MEMORY_TICKS); iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) .icon(stack.getFluid().getStill(stack), -1, -1, 14, 14) - .text(entry.getIntValue() * 20 / FluidFlowLogic.MEMORY_TICKS + " L/s " + stack.getLocalizedName()); + .text(" " + value + " L/s " + stack.getLocalizedName()); } } private void addItemFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, EntityPlayer entityPlayer, IProbeHitData iProbeHitData, ItemFlowLogic logic) { - iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) - .text(TextStyleClass.INFO + "{*gregtech.top.pipe.item_last*}") - .item(logic.getLast()) - .text(logic.getLast().getDisplayName()); + if (logic.getMemory().isEmpty()) { + iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) + .text(TextStyleClass.INFO + "{*gregtech.top.pipe.item_last*} ") + .item(logic.getLast()) + .text(" " + logic.getLast().getDisplayName()); + } Object2IntOpenHashMap counts = new Object2IntOpenHashMap<>(); for (var memory : logic.getMemory().values()) { @@ -120,9 +129,10 @@ private void addItemFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, for (var entry : counts.object2IntEntrySet()) { ItemStack stack = entry.getKey().recombine(); + String value = TextFormattingUtil.formatNumbers(entry.getIntValue() * 20L / ItemFlowLogic.MEMORY_TICKS); iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) .item(stack) - .text(entry.getIntValue() * 20 / ItemFlowLogic.MEMORY_TICKS + " /s " + stack.getDisplayName()); + .text(" " + value + " /s " + stack.getDisplayName()); } } } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 7a70a1bcd37..77719d91ea8 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -104,8 +104,7 @@ gregtech.top.ld_pipe_output=Output gregtech.top.ld_pipe_input_endpoint=Input Endpoint: gregtech.top.ld_pipe_output_endpoint=Output Endpoint: -gregtech.top.pipe.voltage=Average Voltage/s: -gregtech.top.pipe.amperage=Average Amperage/s: +gregtech.top.pipe.energy=Avg. Energy: §a%s EU/t §f(%s§f) @ §a%sA gregtech.top.pipe.fluid_last=Last Fluid: gregtech.top.pipe.item_last=Last Item: From 44d0214aad9140c22238ed001459fe22169e97ac Mon Sep 17 00:00:00 2001 From: M-W-K Date: Thu, 5 Sep 2024 21:40:13 -0600 Subject: [PATCH 126/157] Tooltip names --- .../pipelike/handlers/properties/MaterialFluidProperties.java | 1 + .../pipelike/handlers/properties/MaterialItemProperties.java | 1 + .../theoneprobe/provider/PipeTileInfoProvider.java | 4 ++-- src/main/resources/assets/gregtech/lang/en_us.lang | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index 2e43fe07d9e..c147952b5e7 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -150,6 +150,7 @@ public MaterialPropertyKey getKey() { @Override public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn, IPipeMaterialStructure structure) { + tooltip.add(I18n.format("gregtech.fluid_pipe")); tooltip.add(I18n.format("gregtech.universal.tooltip.fluid_transfer_rate", getThroughput(structure))); tooltip.add(I18n.format("gregtech.fluid_pipe.max_temperature", getMaxFluidTemperature())); tooltip.add(I18n.format("gregtech.fluid_pipe.min_temperature", getMinFluidTemperature())); diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index e0f35222408..d301ae68e71 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -50,6 +50,7 @@ public MaterialPropertyKey getKey() { @Override public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn, IPipeMaterialStructure structure) { + tooltip.add(I18n.format("gregtech.item_pipe")); if (baseItemsPer5Ticks % 16 != 0) { tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate", baseItemsPer5Ticks * 4)); diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java index 4a4321b6e1a..cfc462dc69d 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java @@ -107,7 +107,7 @@ private void addFluidFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, String value = TextFormattingUtil.formatNumbers(entry.getIntValue() * 20L / FluidFlowLogic.MEMORY_TICKS); iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) .icon(stack.getFluid().getStill(stack), -1, -1, 14, 14) - .text(" " + value + " L/s " + stack.getLocalizedName()); + .text(" §b" + value + " L/s §f" + stack.getLocalizedName()); } } @@ -132,7 +132,7 @@ private void addItemFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, String value = TextFormattingUtil.formatNumbers(entry.getIntValue() * 20L / ItemFlowLogic.MEMORY_TICKS); iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) .item(stack) - .text(" " + value + " /s " + stack.getDisplayName()); + .text(" §b" + value + " /s §f" + stack.getDisplayName()); } } } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 77719d91ea8..e1e8b2d74ca 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -5593,6 +5593,8 @@ gregtech.fluid_pipe.acid_proof=§6Can handle Acids gregtech.fluid_pipe.plasma_proof=§6Can handle all Plasmas gregtech.fluid_pipe.not_gas_proof=§4Gases may leak! +gregtech.fluid_pipe=§dFluid Pipe +gregtech.item_pipe=§dItem Pipe gregtech.fluid_pipe.priority=§9Priority: §f%s gregtech.item_pipe.priority=§9Priority: §f%s From df73818024fb0768a2da82407a5de5adb6672dba Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 6 Sep 2024 10:54:47 -0600 Subject: [PATCH 127/157] Unconductive pipes & fix some temperature stuff --- .../api/graphnet/pipenet/logic/TemperatureLogic.java | 3 +-- .../pipenet/physical/tile/PipeTileEntity.java | 1 + .../handlers/properties/MaterialEnergyProperties.java | 11 +++++++---- .../pipelike/net/energy/EnergyTraverseData.java | 4 ++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index fffb0c717d2..7088e5f329c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -165,12 +165,11 @@ public void moveTowardsTemperature(int temperature, long tick, float mult, boole float thermalEnergy = mult * (temperature - temp); if (noParticle) { float thermalMax = this.thermalMass * (GTOverheatParticle.TEMPERATURE_CUTOFF - DEFAULT_TEMPERATURE); - if (thermalMax > this.energy) return; if (thermalEnergy + this.energy > thermalMax) { thermalEnergy = thermalMax - this.energy; } } - if (thermalEnergy > 0) applyThermalEnergy(thermalEnergy, tick); + applyThermalEnergy(thermalEnergy, tick); } public int getTemperature(long tick) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index ec4fa0ea5bb..a93a34a33ab 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -125,6 +125,7 @@ public void invalidate() { super.invalidate(); if (!getWorld().isRemote) getBlockType().getHandler(this) .removeFromNets(this.getWorld(), this.getPos(), this.getStructure()); + else killOverheatParticle(); // TODO I hate this so much can someone please make it so that covers go through getDrops()? getCoverHolder().dropAllCovers(); } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 9b446b36e04..323c0e3f0ac 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -48,6 +48,8 @@ public final class MaterialEnergyProperties implements PipeNetProperties.IPipeNe public static final MaterialPropertyKey KEY = new MaterialPropertyKey<>( "EnergyProperties"); + private static final int MINIMUM_MELT_TEMPERATURE = 1500; + private final long voltageLimit; private final long amperageLimit; private int materialMeltTemperature; @@ -141,13 +143,14 @@ public static int computeMaterialMeltTemperature(@NotNull MaterialProperties pro if (fluid == null) { FluidBuilder builder = prop.getQueuedBuilder(FluidStorageKeys.LIQUID); if (builder != null) { - return builder.getDeterminedTemperature(properties.getMaterial(), FluidStorageKeys.LIQUID); + return Math.max(MINIMUM_MELT_TEMPERATURE, + builder.getDeterminedTemperature(properties.getMaterial(), FluidStorageKeys.LIQUID)); } } else { - return fluid.getTemperature(); + return Math.max(MINIMUM_MELT_TEMPERATURE, fluid.getTemperature()); } } - return 3000; + return MINIMUM_MELT_TEMPERATURE; } @Override @@ -244,6 +247,6 @@ public boolean generatesStructure(IPipeStructure structure) { @Override public boolean supportsStructure(IPipeStructure structure) { - return structure instanceof CableStructure || structure instanceof MaterialPipeStructure; + return structure instanceof CableStructure /* || structure instanceof MaterialPipeStructure */; } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index fd3fc1ca5bd..5af122e013f 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -156,11 +156,11 @@ private void recordFlow(@NotNull NetNode node, long amperes) { } private static int calculateHeatV(long amperage, long voltage, long maxVoltage) { - return (int) (amperage * (Math.log1p(4 * Math.log((double) voltage / maxVoltage)) * 85 + 36)); + return (int) (amperage * (Math.log1p((double) voltage / maxVoltage) * 85 + 36)); } private static int calculateHeatA(long amperage, long voltage) { - return (int) (amperage * (Math.log1p(4 * Math.log1p(Math.log((double) voltage))) * 85 + 36)); + return (int) (amperage * (Math.log1p(Math.log(voltage)) * 85 + 36)); } protected static class OverVoltageInformation { From 65094e72d6663f5c12ba8a5cc77c71487da69e9d Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+techlord22@users.noreply.github.com> Date: Fri, 6 Sep 2024 13:28:26 -0400 Subject: [PATCH 128/157] FluidStackElement for TOP --- .../element/FluidStackElement.java | 83 +++++++++++++++++++ .../provider/PipeTileInfoProvider.java | 6 +- 2 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 src/main/java/gregtech/integration/theoneprobe/element/FluidStackElement.java diff --git a/src/main/java/gregtech/integration/theoneprobe/element/FluidStackElement.java b/src/main/java/gregtech/integration/theoneprobe/element/FluidStackElement.java new file mode 100644 index 00000000000..ca77962d1d8 --- /dev/null +++ b/src/main/java/gregtech/integration/theoneprobe/element/FluidStackElement.java @@ -0,0 +1,83 @@ +package gregtech.integration.theoneprobe.element; + +import gregtech.client.utils.RenderUtil; + +import io.netty.buffer.ByteBuf; +import mcjty.theoneprobe.TheOneProbe; +import mcjty.theoneprobe.api.IElement; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.util.ResourceLocation; + +import net.minecraftforge.fluids.FluidStack; + +import org.jetbrains.annotations.NotNull; + +import java.nio.charset.StandardCharsets; + +public class FluidStackElement implements IElement { + + private static final int ID = TheOneProbe.theOneProbeImp.registerElementFactory(FluidStackElement::new); + + private final String location; + private final int color; + + private TextureAtlasSprite sprite = null; + + public FluidStackElement(@NotNull FluidStack stack) { + this(stack.getFluid().getStill(stack), stack.getFluid().getColor(stack)); + } + + public FluidStackElement(@NotNull ResourceLocation location, int color) { + this.location = location.toString(); + this.color = color; + } + + public FluidStackElement(@NotNull ByteBuf buf) { + byte[] bytes = new byte[buf.readInt()]; + buf.readBytes(bytes); + this.location = new String(bytes, StandardCharsets.UTF_8); + this.color = buf.readInt(); + } + + @Override + public void render(int x, int y) { + if (sprite == null) { + sprite = Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(location); + } + + GlStateManager.enableBlend(); + Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE); + + RenderUtil.setGlColorFromInt(color, 0xFF); + RenderUtil.drawFluidTexture(x, y, sprite, 0, 0, 0); + + GlStateManager.disableBlend(); + } + + @Override + public int getWidth() { + return 16; + } + + @Override + public int getHeight() { + return 16; + } + + @Override + public void toBytes(@NotNull ByteBuf buf) { + byte[] bytes = location.getBytes(StandardCharsets.UTF_8); + buf.writeInt(bytes.length); + buf.writeBytes(bytes); + buf.writeInt(color); + } + + @Override + public int getID() { + return ID; + } +} diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java index cfc462dc69d..041bf564e28 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java @@ -13,6 +13,8 @@ import gregtech.common.pipelike.net.fluid.FluidFlowLogic; import gregtech.common.pipelike.net.item.ItemFlowLogic; +import gregtech.integration.theoneprobe.element.FluidStackElement; + import net.minecraft.block.state.IBlockState; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; @@ -91,7 +93,7 @@ private void addFluidFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, if (logic.getMemory().isEmpty()) { iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) .text(TextStyleClass.INFO + "{*gregtech.top.pipe.fluid_last*} ") - .icon(logic.getLast().getFluid().getStill(logic.getLast()), -1, -1, 14, 14) + .element(new FluidStackElement(logic.getLast())) .text(" " + logic.getLast().getLocalizedName()); } @@ -106,7 +108,7 @@ private void addFluidFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, FluidStack stack = entry.getKey().recombine(); String value = TextFormattingUtil.formatNumbers(entry.getIntValue() * 20L / FluidFlowLogic.MEMORY_TICKS); iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) - .icon(stack.getFluid().getStill(stack), -1, -1, 14, 14) + .element(new FluidStackElement(stack)) .text(" §b" + value + " L/s §f" + stack.getLocalizedName()); } } From eb8cba2fd010a8b85e6a636d589443ef9fbbd18e Mon Sep 17 00:00:00 2001 From: M-W-K Date: Fri, 6 Sep 2024 15:34:07 -0600 Subject: [PATCH 129/157] Fix issues with cable burning & more --- .../api/capability/GregtechDataCodes.java | 1 + .../api/graphnet/logic/NetLogicData.java | 1 + .../graphnet/pipenet/IPipeNetNodeHandler.java | 22 +++++ .../pipenet/logic/TemperatureLogic.java | 23 ++++-- .../physical/tile/PipeMaterialTileEntity.java | 2 +- .../pipenet/physical/tile/PipeTileEntity.java | 37 ++++++--- .../pipenet/traverse/FlowManagerMap.java | 20 +++++ .../pipenet/traverse/ITileFlowManager.java | 14 ++++ .../traverse/LocalTransferInformation.java | 8 ++ .../items/behaviors/TricorderBehavior.java | 16 +--- .../pipelike/block/cable/CableBlock.java | 24 ++++++ .../properties/MaterialEnergyProperties.java | 14 +++- .../properties/MaterialFluidProperties.java | 7 +- .../net/energy/EnergyTraverseData.java | 80 +++++++++++++++---- .../element/FluidStackElement.java | 8 +- .../provider/PipeTileInfoProvider.java | 13 ++- 16 files changed, 227 insertions(+), 63 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/ITileFlowManager.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/LocalTransferInformation.java diff --git a/src/main/java/gregtech/api/capability/GregtechDataCodes.java b/src/main/java/gregtech/api/capability/GregtechDataCodes.java index a511cabec40..e8dff884f30 100644 --- a/src/main/java/gregtech/api/capability/GregtechDataCodes.java +++ b/src/main/java/gregtech/api/capability/GregtechDataCodes.java @@ -58,6 +58,7 @@ public static int assignId() { public static final int UPDATE_FACADE_STACK = assignId(); // Pipe implementation update codes + public static final int SYNC_EVERYTHING = assignId(); public static final int UPDATE_PAINT = assignId(); public static final int UPDATE_CONNECTIONS = assignId(); public static final int SYNC_COVER_IMPLEMENTATION = assignId(); diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index e68c8499867..45ea851cbee 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -176,6 +176,7 @@ public void deserializeNBT(NBTTagList nbt) { if (entry == null) entry = NetLogicRegistry.getSupplierNotNull(key).get(); if (entry == null) continue; entry.deserializeNBTNaive(tag.getTag("Tag")); + this.logicEntrySet.put(key, entry); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java index 61a10f222ad..4e2eac6d798 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.Collections; import java.util.List; public interface IPipeNetNodeHandler { @@ -25,4 +26,25 @@ public interface IPipeNetNodeHandler { void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn, IPipeStructure structure); + + IPipeNetNodeHandler EMPTY = new IPipeNetNodeHandler() { + + @Override + public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, + IPipeStructure structure) { + return Collections.emptyList(); + } + + @Override + public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { + return Collections.emptyList(); + } + + @Override + public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) {} + + @Override + public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, + @NotNull ITooltipFlag flagIn, IPipeStructure structure) {} + }; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index 7088e5f329c..222d48ed0e7 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -18,6 +18,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -80,6 +81,16 @@ public TemperatureLogic getWith(@NotNull TemperatureLossFunction temperatureRest .setFunctionPriority(functionPriority); } + @Contract("_ -> this") + public TemperatureLogic setInitialThermalEnergy(float energy) { + this.energy = energy; + return this; + } + + public float getThermalEnergy() { + return energy; + } + @Override public void registerToMultiNodeHelper(MultiNodeHelper helper) { this.isMultiNodeHelper = true; @@ -179,13 +190,13 @@ public int getTemperature(long tick) { private void restoreTemperature(long tick) { long timePassed = tick - lastRestorationTick; - this.lastRestorationTick = tick; - float energy = this.energy; - if (timePassed != 0) { - if (timePassed >= Integer.MAX_VALUE || timePassed < 0) { + // sometimes the tick time randomly warps backward for no explicable reason, on both server and client. + if (timePassed > 0) { + float energy = this.energy; + this.lastRestorationTick = tick; + if (timePassed >= Integer.MAX_VALUE) { this.energy = 0; - } else this.energy = temperatureLossFunction - .restoreTemperature(energy, (int) timePassed); + } else this.energy = temperatureLossFunction.restoreTemperature(energy, (int) timePassed); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java index 0d25b5b8a72..77bfa7ff728 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeMaterialTileEntity.java @@ -23,7 +23,7 @@ public class PipeMaterialTileEntity extends PipeTileEntity { private Material material; @Override - protected void initialize() { + public void initialize() { // prevent initialization when we don't know our material; // this specifically happens right after we have been // placed and placedBy() has yet to be called. diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index a93a34a33ab..b020373a3ba 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -54,6 +54,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -301,9 +302,13 @@ public void onLoad() { initialize(); // since we're an instance of ITickable, we're automatically added to the tickable list just before this exact // moment. - // it would theoretically be a micro optimization to just pop the last tile from the tickable list, but that's - // not guaranteed. - if (!this.isTicking()) this.getWorld().tickableTileEntities.remove(this); + if (!this.isTicking()) { + // check the last tile first to see if it's us, otherwise fallback to default. + List tickables = this.getWorld().tickableTileEntities; + TileEntity last = tickables.get(tickables.size() - 1); + if (last == this) tickables.remove(tickables.size() - 1); + else tickables.remove(this); + } } public void removeTicker(ITickable ticker) { @@ -479,13 +484,16 @@ public void setWorld(@NotNull World worldIn) { super.setWorld(worldIn); } - protected void initialize() { + /** + * DO NOT CALL UNLESS YOU KNOW WHAT YOU ARE DOING + */ + @ApiStatus.Internal + public void initialize() { if (!getWorld().isRemote) { this.netLogicDatas.clear(); this.capabilities.clear(); this.netCapabilities.clear(); this.listeners.clear(); - boolean firstNode = true; for (WorldPipeNetNode node : PipeBlock.getNodesForTile(this)) { this.addCapabilities(node.getNet().getNewCapabilityObjects(node)); this.netCapabilities.put(node, new PipeCapabilityWrapper(this, node)); @@ -495,9 +503,10 @@ protected void initialize() { for (NetLogicEntry entry : node.getData().getEntries()) { writeLogicData(networkID, entry, false, true); } - if (firstNode) { - firstNode = false; - this.temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + if (this.temperatureLogic == null) { + TemperatureLogic candidate = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + if (candidate != null) + updateTemperatureLogic(candidate); } } this.netLogicDatas.trim(); @@ -505,6 +514,8 @@ protected void initialize() { this.netCapabilities.trim(); this.listeners.trim(); updateActiveStatus(null, false); + } else { + getBlockType(); // ensure block is cached on client for later reference } } @@ -554,6 +565,10 @@ protected Material decodeMaterialFromBuffer(@NotNull PacketBuffer buf) { return GregTechAPI.materialManager.getRegistry(buf.readVarInt()).getObjectById(buf.readInt()); } + public void forceFullSync() { + writeCustomData(SYNC_EVERYTHING, this::writeInitialSyncData); + } + @Override public void writeInitialSyncData(@NotNull PacketBuffer buf) { buf.writeByte(connectionMask); @@ -594,7 +609,10 @@ public void receiveInitialSyncData(@NotNull PacketBuffer buf) { @Override public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { - if (discriminator == UPDATE_PIPE_LOGIC) { + if (discriminator == SYNC_EVERYTHING) { + receiveInitialSyncData(buf); + scheduleRenderUpdate(); + } else if (discriminator == UPDATE_PIPE_LOGIC) { // extra check just to make sure we don't affect actual net data with our writes if (world.isRemote) { int networkID = buf.readVarInt(); @@ -647,6 +665,7 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { // particle // public void updateTemperatureLogic(@NotNull TemperatureLogic logic) { + this.temperatureLogic = logic; if (overheatParticle == null || !overheatParticle.isAlive()) { long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); int temp = logic.getTemperature(tick); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java new file mode 100644 index 00000000000..fe5d31b2a6a --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java @@ -0,0 +1,20 @@ +package gregtech.api.graphnet.pipenet.traverse; + +import gregtech.api.graphnet.pipenet.WorldPipeNetNode; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import java.util.function.Function; + +public class FlowManagerMap extends Object2ObjectOpenHashMap { + + private final Function newSupplier; + + public FlowManagerMap(Function newSupplier) { + this.newSupplier = newSupplier; + } + + public ITileFlowManager access(WorldPipeNetNode node) { + return computeIfAbsent(node, newSupplier); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/ITileFlowManager.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/ITileFlowManager.java new file mode 100644 index 00000000000..ae41ecc7af3 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/ITileFlowManager.java @@ -0,0 +1,14 @@ +package gregtech.api.graphnet.pipenet.traverse; + +public interface ITileFlowManager { + + default boolean canAcceptFlow() { + return getMaximumFlow() > 0; + } + + long getMaximumFlow(); + + void reportAttemptingFlow(long flow); + + long acceptFlow(long flow); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/LocalTransferInformation.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/LocalTransferInformation.java new file mode 100644 index 00000000000..e81dea469ae --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/LocalTransferInformation.java @@ -0,0 +1,8 @@ +package gregtech.api.graphnet.pipenet.traverse; + +import net.minecraft.util.EnumFacing; + +import com.github.bsideup.jabel.Desugar; + +@Desugar +public record LocalTransferInformation (EnumFacing facing, T controller, C container) {} diff --git a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java index 260a1c788ce..4463cd723b0 100644 --- a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java @@ -283,30 +283,22 @@ else if (metaTileEntity instanceof IDataInfoProvider) } NetLogicData data = pipeTile.getNetLogicData(WorldEnergyNet.getWorldNet(world).getNetworkID()); if (data != null) { - int cumulativeCount = 0; long cumulativeVoltage = 0; long cumulativeAmperage = 0; for (var memory : data.getLogicEntryDefaultable(EnergyFlowLogic.INSTANCE).getMemory().values()) { - cumulativeCount++; - int count = 0; double voltage = 0; long amperage = 0; for (EnergyFlowData flow : memory) { - count++; long prev = amperage; amperage += flow.amperage(); // weighted average voltage = voltage * prev / amperage + (double) (flow.voltage() * flow.amperage()) / amperage; } - if (count != 0) { - cumulativeVoltage += voltage / count; - cumulativeAmperage += amperage / count; - } - } - if (cumulativeCount != 0) { - cumulativeVoltage /= cumulativeCount; - cumulativeAmperage /= cumulativeCount; + cumulativeVoltage += voltage; + cumulativeAmperage += amperage; } + cumulativeVoltage /= EnergyFlowLogic.MEMORY_TICKS; + cumulativeAmperage /= EnergyFlowLogic.MEMORY_TICKS; list.add(new TextComponentTranslation("behavior.tricorder.eut_per_sec", new TextComponentTranslation(TextFormattingUtil.formatNumbers(cumulativeVoltage)) .setStyle(new Style().setColor(TextFormatting.RED)))); diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index b7bfe5bc47a..81dd17b170f 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -1,9 +1,11 @@ package gregtech.common.pipelike.block.cable; import gregtech.api.damagesources.DamageSources; +import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; +import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.items.toolitem.ToolClasses; import gregtech.api.unification.material.registry.MaterialRegistry; @@ -19,6 +21,8 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -32,6 +36,8 @@ public class CableBlock extends PipeMaterialBlock implements IBurnable { private static final Map> CACHE = new Object2ObjectOpenHashMap<>(); + private static final ThreadLocal RELOCATING_TILE = ThreadLocal.withInitial(() -> Boolean.FALSE); + public CableBlock(CableStructure structure, MaterialRegistry registry) { super(structure, registry); CACHE.compute(registry, (k, v) -> { @@ -62,9 +68,27 @@ public void partialBurn(IBlockState state, World world, BlockPos pos) { CableStructure structure = getStructure(); if (structure.partialBurnStructure() != null) { CableBlock newBlock = CACHE.get(registry).get(structure.partialBurnStructure()); + PipeMaterialTileEntity tileOld = getTileEntity(world, pos); + RELOCATING_TILE.set(Boolean.TRUE); // noinspection deprecation world.setBlockState(pos, newBlock.getStateFromMeta(this.getMetaFromState(state))); + RELOCATING_TILE.set(Boolean.FALSE); + TileEntity tileNew = world.getTileEntity(pos); + if (tileOld != null && tileNew instanceof PipeTileEntity pipeTile) { + pipeTile.deserializeNBT(tileOld.writeToNBT(new NBTTagCompound())); + pipeTile.initialize(); + pipeTile.forceFullSync(); + } + } + } + + @Override + public @NotNull IPipeNetNodeHandler getHandler(PipeTileEntity tileContext) { + if (RELOCATING_TILE.get()) { + // prevent node removal when relocating tile + return IPipeNetNodeHandler.EMPTY; } + return super.getHandler(tileContext); } @Override diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 323c0e3f0ac..bf2b3825119 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -178,14 +178,17 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { boolean insulated = cable.partialBurnStructure() != null; // insulated cables cool down half as fast float coolingFactor = (float) (Math.sqrt(cable.material()) / (insulated ? 8 : 4)); + TemperatureLogic existing = data.getLogicEntryNullable(TemperatureLogic.INSTANCE); + float energy = existing == null ? 0 : existing.getThermalEnergy(); data.setLogicEntry(VoltageLossLogic.INSTANCE.getWith(loss)) .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) - .mergeLogicEntry(TemperatureLogic.INSTANCE + .setLogicEntry(TemperatureLogic.INSTANCE .getWith(TemperatureLossFunction.getOrCreateCable(coolingFactor), materialMeltTemperature, 1, - 100 * cable.material(), cable.partialBurnThreshold())); + 100 * cable.material(), cable.partialBurnThreshold()) + .setInitialThermalEnergy(energy)); if (superconductorCriticalTemperature > 0) { data.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorCriticalTemperature)); } @@ -194,13 +197,16 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { if (amperage == 0) return; // skip pipes that are too small long loss = getLoss(structure); float coolingFactor = (float) Math.sqrt((double) pipe.material() / (4 + pipe.channelCount())); + TemperatureLogic existing = data.getLogicEntryNullable(TemperatureLogic.INSTANCE); + float energy = existing == null ? 0 : existing.getThermalEnergy(); data.setLogicEntry(VoltageLossLogic.INSTANCE.getWith(loss)) .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) - .mergeLogicEntry(TemperatureLogic.INSTANCE + .setLogicEntry(TemperatureLogic.INSTANCE .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), materialMeltTemperature, 1, - 50 * pipe.material(), null)); + 50 * pipe.material(), null) + .setInitialThermalEnergy(energy)); if (superconductorCriticalTemperature > 0) { data.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorCriticalTemperature)); } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index c147952b5e7..91c99c55a6b 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -182,13 +182,16 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { if (structure instanceof MaterialPipeStructure pipe) { long throughput = getThroughput(structure); float coolingFactor = (float) Math.sqrt((double) pipe.material() / (4 + pipe.channelCount())); + TemperatureLogic existing = data.getLogicEntryNullable(TemperatureLogic.INSTANCE); + float energy = existing == null ? 0 : existing.getThermalEnergy(); data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(getFlowPriority(structure))) .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)) .setLogicEntry(FluidContainmentLogic.INSTANCE.getWith(containableStates, containableAttributes, maxFluidTemperature)) - .mergeLogicEntry(TemperatureLogic.INSTANCE + .setLogicEntry(TemperatureLogic.INSTANCE .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), materialMeltTemperature, - minFluidTemperature, 50 * pipe.material(), null)); + minFluidTemperature, 50 * pipe.material(), null) + .setInitialThermalEnergy(energy)); if (pipe.channelCount() > 1) { data.setLogicEntry(ChannelCountLogic.INSTANCE.getWith(pipe.channelCount())); } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index 5af122e013f..2571c072a94 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -11,6 +11,9 @@ import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.traverse.FlowManagerMap; +import gregtech.api.graphnet.pipenet.traverse.ITileFlowManager; +import gregtech.api.graphnet.pipenet.traverse.LocalTransferInformation; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.AbstractTraverseData; import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; @@ -19,6 +22,7 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; @@ -26,6 +30,8 @@ public class EnergyTraverseData extends AbstractTraverseData overVoltageInformation; + protected final FlowManagerMap managers = new FlowManagerMap(EnergyFlowManager::new); + private final long startVoltage; private long pathVoltage; private long bufferOverflow; @@ -45,8 +51,9 @@ public EnergyTraverseData(IGraphNet net, IPredicateTestObject testObject, Simula @Override public boolean prepareForPathWalk(@NotNull FlowWorldPipeNetPath path, long flow) { - if (flow <= 0) return true; resetPathVoltage(); + if (flow <= 0 || !managers.access(path.getTargetNode()).canAcceptFlow()) return true; + managers.access(path.getTargetNode()).reportAttemptingFlow(flow); this.overVoltageInformation.clear(); this.overVoltageInformation.trim(10); return false; @@ -113,21 +120,7 @@ public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long fl this.pathVoltage = (long) GTUtility.geometricMean(pathVoltage, overVoltageInformation.values().stream().filter(o -> o.voltageCap < this.pathVoltage) .mapToDouble(o -> (double) o.voltageCap).toArray()); - long availableFlow = flowReachingDestination; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IEnergyContainer container = capability.getValue() - .getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, capability.getKey().getOpposite()); - if (container != null) { - availableFlow -= IEnergyTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(pathVoltage, availableFlow, container, - capability.getKey(), simulating()); - } - } - long accepted = flowReachingDestination - availableFlow; + long accepted = managers.access(destination).acceptFlow(flowReachingDestination); if (!simulating() && destination.getGroupUnsafe() != null && destination.getGroupSafe().getData() instanceof EnergyGroupData data) { data.addEnergyOutPerSec(accepted * pathVoltage, getQueryTick()); @@ -178,4 +171,59 @@ public void doHeating(WorldPipeNetNode node, long finalVoltage, long tick, long } } } + + protected class EnergyFlowManager extends + Object2LongOpenHashMap> + implements ITileFlowManager { + + public EnergyFlowManager(@NotNull WorldPipeNetNode node) { + for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { + if (GTUtility.arePosEqual(node.getEquivalencyData(), sourcePos) && + capability.getKey() == inputFacing) + continue; // anti insert-to-our-source logic + + IEnergyContainer container = capability.getValue() + .getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, + capability.getKey().getOpposite()); + if (container != null) { + IEnergyTransferController controller = IEnergyTransferController.CONTROL.get(node.getTileEntity() + .getCoverHolder().getCoverAtSide(capability.getKey())); + this.put(new LocalTransferInformation<>(capability.getKey(), controller, container), + controller.insertToHandler(pathVoltage, Long.MAX_VALUE, container, capability.getKey(), + true)); + } + } + } + + @Override + public long getMaximumFlow() { + long sum = 0; + for (long l : this.values()) { + sum += l; + } + return sum; + } + + @Override + public void reportAttemptingFlow(long flow) { + for (var entry : this.entrySet()) { + entry.setValue(Math.max(entry.getValue() - flow, 0)); + } + } + + @Override + public long acceptFlow(long flow) { + long availableFlow = flow; + var iter = this.entrySet().iterator(); + while (iter.hasNext()) { + var entry = iter.next(); + var info = entry.getKey(); + long accepted = info.controller().insertToHandler(pathVoltage, availableFlow, info.container(), + info.facing(), simulating()); + if (entry.getValue() == 0) iter.remove(); + availableFlow -= accepted; + } + return flow - availableFlow; + } + } } diff --git a/src/main/java/gregtech/integration/theoneprobe/element/FluidStackElement.java b/src/main/java/gregtech/integration/theoneprobe/element/FluidStackElement.java index ca77962d1d8..44b9c4e16d4 100644 --- a/src/main/java/gregtech/integration/theoneprobe/element/FluidStackElement.java +++ b/src/main/java/gregtech/integration/theoneprobe/element/FluidStackElement.java @@ -2,18 +2,16 @@ import gregtech.client.utils.RenderUtil; -import io.netty.buffer.ByteBuf; -import mcjty.theoneprobe.TheOneProbe; -import mcjty.theoneprobe.api.IElement; - import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.util.ResourceLocation; - import net.minecraftforge.fluids.FluidStack; +import io.netty.buffer.ByteBuf; +import mcjty.theoneprobe.TheOneProbe; +import mcjty.theoneprobe.api.IElement; import org.jetbrains.annotations.NotNull; import java.nio.charset.StandardCharsets; diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java index 041bf564e28..990ebbf46ad 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java @@ -12,7 +12,6 @@ import gregtech.common.pipelike.net.energy.EnergyFlowLogic; import gregtech.common.pipelike.net.fluid.FluidFlowLogic; import gregtech.common.pipelike.net.item.ItemFlowLogic; - import gregtech.integration.theoneprobe.element.FluidStackElement; import net.minecraft.block.state.IBlockState; @@ -66,20 +65,16 @@ private void addEnergyFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo long cumulativeVoltage = 0; long cumulativeAmperage = 0; for (var memory : logic.getMemory().values()) { - int count = 0; double voltage = 0; long amperage = 0; for (EnergyFlowData flow : memory) { - count++; long prev = amperage; amperage += flow.amperage(); // weighted average voltage = voltage * prev / amperage + (double) (flow.voltage() * flow.amperage()) / amperage; } - if (count != 0) { - cumulativeVoltage += voltage / count; - cumulativeAmperage += amperage / count; - } + cumulativeVoltage += voltage; + cumulativeAmperage += amperage; } long v = cumulativeVoltage / EnergyFlowLogic.MEMORY_TICKS; String voltage = TextFormattingUtil.formatNumbers(v); @@ -116,9 +111,11 @@ private void addFluidFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, private void addItemFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, EntityPlayer entityPlayer, IProbeHitData iProbeHitData, ItemFlowLogic logic) { if (logic.getMemory().isEmpty()) { + ItemStack countlessLast = logic.getLast().copy(); + countlessLast.setCount(1); iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) .text(TextStyleClass.INFO + "{*gregtech.top.pipe.item_last*} ") - .item(logic.getLast()) + .item(countlessLast) .text(" " + logic.getLast().getDisplayName()); } From b1e37c5488a250e9edfc9c26756b75f14a858d1d Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 7 Sep 2024 10:42:53 -0600 Subject: [PATCH 130/157] Me when I don't test something --- .../material/properties/PipeNetProperties.java | 8 -------- .../common/pipelike/net/optical/DataCapabilityObject.java | 5 ++++- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index c1a48b7a643..f453f88e42f 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -102,14 +102,6 @@ public void verifyProperty(MaterialProperties properties) { } } - protected static final class MaterialPropertyComparator implements Comparator { - - @Override - public int compare(IPipeNetMaterialProperty o1, IPipeNetMaterialProperty o2) { - return 0; - } - } - public interface IPipeNetMaterialProperty extends IMaterialProperty { @Nullable diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index d0ecd136e62..fbbf91ca474 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -10,6 +10,7 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.util.reference.WeakHashSet; import gregtech.common.pipelike.net.SlowActiveWalker; import net.minecraft.util.EnumFacing; @@ -27,6 +28,8 @@ public class DataCapabilityObject implements IPipeCapabilityObject, IDataAccess private @Nullable PipeTileEntity tile; + private final WeakHashSet recentQueries = new WeakHashSet<>(); + public DataCapabilityObject(@NotNull N net) { this.net = net; } @@ -42,7 +45,7 @@ public void setTile(@Nullable PipeTileEntity tile) { @Override public boolean accessData(@NotNull DataQueryObject queryObject) { - if (tile == null) return false; + if (tile == null || !recentQueries.add(queryObject)) return false; for (Iterator it = getPaths(); it.hasNext();) { BasicWorldPipeNetPath path = it.next(); From fc8094d196ee5cd05e80f226f8da13f9d1cac2b1 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 7 Sep 2024 11:38:25 -0600 Subject: [PATCH 131/157] anti insert-to-our-source logic --- .../net/optical/DataCapabilityObject.java | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index fbbf91ca474..749a0ab3483 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -10,6 +10,7 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.util.GTUtility; import gregtech.api.util.reference.WeakHashSet; import gregtech.common.pipelike.net.SlowActiveWalker; @@ -20,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.EnumMap; import java.util.Iterator; public class DataCapabilityObject implements IPipeCapabilityObject, IDataAccess { @@ -28,10 +30,15 @@ public class DataCapabilityObject implements IPipeCapabilityObject, IDataAccess private @Nullable PipeTileEntity tile; + private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); + private final WeakHashSet recentQueries = new WeakHashSet<>(); public DataCapabilityObject(@NotNull N net) { this.net = net; + for (EnumFacing facing : EnumFacing.VALUES) { + wrappers.put(facing, new Wrapper(facing)); + } } private BasicWorldPipeNetPath.Provider getProvider() { @@ -45,12 +52,19 @@ public void setTile(@Nullable PipeTileEntity tile) { @Override public boolean accessData(@NotNull DataQueryObject queryObject) { + return accessData(queryObject, null); + } + + private boolean accessData(@NotNull DataQueryObject queryObject, @Nullable EnumFacing facing) { if (tile == null || !recentQueries.add(queryObject)) return false; for (Iterator it = getPaths(); it.hasNext();) { BasicWorldPipeNetPath path = it.next(); WorldPipeNetNode destination = path.getTargetNode(); for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (GTUtility.arePosEqual(destination.getEquivalencyData(), tile.getPos()) && + capability.getKey() == facing) + continue; // anti insert-to-our-source logic IDataAccess access = capability.getValue() .getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, capability.getKey().getOpposite()); @@ -89,8 +103,32 @@ public Capability[] getCapabilities() { @Override public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { if (capability == GregtechTileCapabilities.CAPABILITY_DATA_ACCESS) { - return GregtechTileCapabilities.CAPABILITY_DATA_ACCESS.cast(this); + return GregtechTileCapabilities.CAPABILITY_DATA_ACCESS.cast(facing == null ? this : wrappers.get(facing)); } return null; } + + protected class Wrapper implements IDataAccess { + + private final EnumFacing facing; + + public Wrapper(EnumFacing facing) { + this.facing = facing; + } + + @Override + public boolean accessData(@NotNull DataQueryObject queryObject) { + return DataCapabilityObject.this.accessData(queryObject, facing); + } + + @Override + public @NotNull DataAccessFormat getFormat() { + return DataCapabilityObject.this.getFormat(); + } + + @Override + public boolean supportsQuery(@NotNull DataQueryObject queryObject) { + return DataCapabilityObject.this.supportsQuery(queryObject); + } + } } From 620f73f2687d0a58ec37237da5c21fb75146e73a Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 7 Sep 2024 11:50:13 -0600 Subject: [PATCH 132/157] Fix weak sets --- src/main/java/gregtech/api/util/reference/WeakHashSet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/util/reference/WeakHashSet.java b/src/main/java/gregtech/api/util/reference/WeakHashSet.java index 5be61764723..84afea9bebf 100644 --- a/src/main/java/gregtech/api/util/reference/WeakHashSet.java +++ b/src/main/java/gregtech/api/util/reference/WeakHashSet.java @@ -56,7 +56,7 @@ public boolean remove(Object o) { @Override public boolean add(E e) { - return m.put(e, null) == null; + return m.put(e, Boolean.TRUE) == null; } @Override From a7e6e804f864f0a88f76ec942fe52d639bbc85aa Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 7 Sep 2024 12:31:34 -0600 Subject: [PATCH 133/157] Refactory data query logic --- .../api/capability/data/IDataAccess.java | 13 ++++++------ .../data/query/DataQueryObject.java | 20 +++++++++++++++++++ .../electric/MetaTileEntityAssemblyLine.java | 5 ++--- .../MetaTileEntityComputationHatch.java | 6 +----- .../MetaTileEntityDataAccessHatch.java | 1 - .../MetaTileEntityOpticalDataHatch.java | 6 +----- .../net/optical/DataCapabilityObject.java | 5 +---- .../optical/IOpticalTransferController.java | 3 ++- 8 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/main/java/gregtech/api/capability/data/IDataAccess.java b/src/main/java/gregtech/api/capability/data/IDataAccess.java index 67b6a9a507b..e9c19ef50a0 100644 --- a/src/main/java/gregtech/api/capability/data/IDataAccess.java +++ b/src/main/java/gregtech/api/capability/data/IDataAccess.java @@ -10,8 +10,7 @@ public interface IDataAccess { /** * Queries this {@link IDataAccess} with the specified query. * - * @param queryObject the object representing the query. Can be cached in a - * {@link gregtech.api.util.reference.WeakHashSet} in order to prevent endless recursion. + * @param queryObject the object representing the query. * @return if the query has been cancelled */ boolean accessData(@NotNull DataQueryObject queryObject); @@ -42,10 +41,12 @@ static boolean accessData(@NotNull Iterable accesses, boolean walk = false; boolean cancelled = false; for (IDataAccess access : accesses) { - query.setShouldTriggerWalker(false); - cancelled = access.accessData(query); - if (!walk) walk = query.shouldTriggerWalker(); - if (cancelled) break; + if (query.traverseTo(access)) { + query.setShouldTriggerWalker(false); + cancelled = access.accessData(query); + if (!walk) walk = query.shouldTriggerWalker(); + if (cancelled) break; + } } query.setShouldTriggerWalker(walk); return cancelled; diff --git a/src/main/java/gregtech/api/capability/data/query/DataQueryObject.java b/src/main/java/gregtech/api/capability/data/query/DataQueryObject.java index 68a5666b562..f12f8ec2e1b 100644 --- a/src/main/java/gregtech/api/capability/data/query/DataQueryObject.java +++ b/src/main/java/gregtech/api/capability/data/query/DataQueryObject.java @@ -1,6 +1,11 @@ package gregtech.api.capability.data.query; +import gregtech.api.capability.data.IDataAccess; + +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public abstract class DataQueryObject { @@ -10,6 +15,8 @@ public abstract class DataQueryObject { private boolean shouldTriggerWalker = false; + private final ReferenceOpenHashSet visited = new ReferenceOpenHashSet<>(); + public DataQueryObject() { this.id = ID++; } @@ -22,6 +29,19 @@ public boolean shouldTriggerWalker() { return shouldTriggerWalker; } + /** + * Used to tell this query when it passes through a location during traversal, + * know if the location supports this query, + * and know if this query has already visited the location. + * + * @param location the location next on traversal + * @return whether the location is not null, supports this query, and has not yet been visited. + */ + @Contract("null -> false") + public final boolean traverseTo(@Nullable IDataAccess location) { + return location != null && location.supportsQuery(this) && this.visited.add(location); + } + @NotNull public abstract DataQueryFormat getFormat(); diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java index f770d007fe1..1c68940bf95 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityAssemblyLine.java @@ -374,10 +374,9 @@ private static boolean isRecipeAvailable(@NotNull Iterable recentQueries = new WeakHashSet<>(); - public MetaTileEntityComputationHatch(ResourceLocation metaTileEntityId, boolean isTransmitter) { super(metaTileEntityId, GTValues.ZPM); this.isTransmitter = isTransmitter; @@ -57,7 +54,6 @@ public boolean isTransmitter() { @Override public boolean accessData(@NotNull DataQueryObject queryObject) { - if (!supportsQuery(queryObject) || !recentQueries.add(queryObject)) return false; if (isAttachedToMultiBlock()) { if (isTransmitter()) { MultiblockControllerBase controller = getController(); @@ -79,7 +75,7 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { IDataAccess cap = tileEntity.getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, getFrontFacing().getOpposite()); - return cap != null && cap.accessData(queryObject); + if (queryObject.traverseTo(cap)) return cap.accessData(queryObject); } } return false; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java index 338b86fd2a3..0751c00296d 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityDataAccessHatch.java @@ -151,7 +151,6 @@ private void rebuildData(boolean isDataBank) { @Override public boolean accessData(@NotNull DataQueryObject queryObject) { - if (!supportsQuery(queryObject)) return false; if (queryObject instanceof RecipeDataQuery query) { if (isCreative || recipes.contains(query.getRecipe())) { query.setFound(); diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java index ce2f1165b1f..b443cf2f9b3 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityOpticalDataHatch.java @@ -11,7 +11,6 @@ import gregtech.api.metatileentity.multiblock.IMultiblockAbilityPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.metatileentity.multiblock.MultiblockControllerBase; -import gregtech.api.util.reference.WeakHashSet; import gregtech.client.renderer.texture.Textures; import net.minecraft.client.resources.I18n; @@ -34,8 +33,6 @@ public class MetaTileEntityOpticalDataHatch extends MetaTileEntityMultiblockNoti IMultiblockAbilityPart, IStandardDataAccess { - private final WeakHashSet recentQueries = new WeakHashSet<>(); - private final boolean isTransmitter; public MetaTileEntityOpticalDataHatch(ResourceLocation metaTileEntityId, boolean isTransmitter) { @@ -63,7 +60,6 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, @Override public boolean accessData(@NotNull DataQueryObject queryObject) { - if (!supportsQuery(queryObject) || !recentQueries.add(queryObject)) return false; if (isAttachedToMultiBlock()) { if (isTransmitter()) { MultiblockControllerBase controller = getController(); @@ -82,7 +78,7 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { if (tileEntity == null) return false; IDataAccess cap = tileEntity.getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, getFrontFacing().getOpposite()); - return cap != null && cap.accessData(queryObject); + if (queryObject.traverseTo(cap)) return cap.accessData(queryObject); } } return false; diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index 749a0ab3483..a19fc657675 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -11,7 +11,6 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.util.GTUtility; -import gregtech.api.util.reference.WeakHashSet; import gregtech.common.pipelike.net.SlowActiveWalker; import net.minecraft.util.EnumFacing; @@ -32,8 +31,6 @@ public class DataCapabilityObject implements IPipeCapabilityObject, IDataAccess private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); - private final WeakHashSet recentQueries = new WeakHashSet<>(); - public DataCapabilityObject(@NotNull N net) { this.net = net; for (EnumFacing facing : EnumFacing.VALUES) { @@ -56,7 +53,7 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { } private boolean accessData(@NotNull DataQueryObject queryObject, @Nullable EnumFacing facing) { - if (tile == null || !recentQueries.add(queryObject)) return false; + if (tile == null) return false; for (Iterator it = getPaths(); it.hasNext();) { BasicWorldPipeNetPath path = it.next(); diff --git a/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java b/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java index d44f58cbd00..94da6f4ce10 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java @@ -39,6 +39,7 @@ public boolean queryHandler(DataQueryObject query, IDataAccess handler) { * @return whether the request should be cancelled */ default boolean queryHandler(DataQueryObject query, IDataAccess handler) { - return handler.accessData(query); + if (query.traverseTo(handler)) return handler.accessData(query); + else return false; } } From 40986a033b6e60fb14894ffa298e9be49e44e02e Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 7 Sep 2024 15:06:14 -0600 Subject: [PATCH 134/157] Move things with filters onto the net level --- .../api/graphnet/pipenet/WorldPipeNet.java | 9 ++- .../gregtech/common/covers/CoverConveyor.java | 5 ++ .../common/covers/CoverFluidRegulator.java | 71 +++++++++---------- .../gregtech/common/covers/CoverPump.java | 5 ++ .../common/covers/CoverRoboticArm.java | 71 ++++++++++--------- .../gregtech/common/covers/CoverShutter.java | 3 +- 6 files changed, 91 insertions(+), 73 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 56502dacb1f..77941262d02 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -9,10 +9,12 @@ import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.graphnet.pipenet.predicate.BlockedPredicate; import gregtech.api.graphnet.predicate.EdgePredicate; import gregtech.api.graphnet.worldnet.WorldPosNet; import gregtech.api.util.IDirtyNotifiable; import gregtech.api.util.reference.WeakHashSet; +import gregtech.common.covers.CoverShutter; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -129,7 +131,12 @@ protected boolean predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode * @param a the cover on the source of the edge * @param b the cover on the sink of the edge */ - protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) {} + protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { + if (a instanceof CoverShutter aS && aS.isWorkingEnabled() || + b instanceof CoverShutter bS && bS.isWorkingEnabled()) { + edge.getPredicateHandler().setPredicate(BlockedPredicate.INSTANCE); + } + } public abstract Capability[] getTargetCapabilities(); diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 9f75843b327..1b2ea5b14c2 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -789,4 +789,9 @@ public ItemStack extractItem(int slot, int amount, boolean simulate) { return super.extractItem(slot, amount, simulate); } } + + @Override + public boolean canPipePassThrough() { + return true; + } } diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index cfce81f24c3..9e86937858a 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -37,7 +37,6 @@ import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.function.IntUnaryOperator; @@ -189,41 +188,41 @@ protected ParentWidget createUI(ModularPanel mainPanel, PanelSyncManager sync .setTextColor(Color.WHITE.darker(1)))); } - @Override - public int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, - boolean doFill) { - if (pumpMode == PumpMode.EXPORT) { - if (transferMode == TransferMode.KEEP_EXACT) { - int contained = computeContained(destHandler, testObject); - assert getFluidFilter() != null; - int keep = getFluidFilter().getTransferLimit(testObject.recombine()); - if (contained >= keep) return 0; - return super.insertToHandler(testObject, Math.min(keep - contained, amount), destHandler, doFill); - } else if (transferMode == TransferMode.TRANSFER_EXACT) { - assert getFluidFilter() != null; - int required = getFluidFilter().getTransferLimit(testObject.recombine()); - if (amount < required) return 0; - return super.insertToHandler(testObject, required, destHandler, doFill); - } - } - return super.insertToHandler(testObject, amount, destHandler, doFill); - } - - @Override - public @Nullable FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, - IFluidHandler sourceHandler, boolean doDrain) { - if (pumpMode == PumpMode.IMPORT) { - // TODO should extraction instead be ignored for transfer exact? - if (transferMode == TransferMode.TRANSFER_EXACT) { - assert getFluidFilter() != null; - int required = testObject == null ? getFluidFilter().getTransferSize() : - getFluidFilter().getTransferLimit(testObject.recombine()); - if (amount < required) return null; - else amount = required; - } - } - return super.extractFromHandler(testObject, amount, sourceHandler, doDrain); - } + // @Override + // public int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, + // boolean doFill) { + // if (pumpMode == PumpMode.EXPORT) { + // if (transferMode == TransferMode.KEEP_EXACT) { + // int contained = computeContained(destHandler, testObject); + // assert getFluidFilter() != null; + // int keep = getFluidFilter().getTransferLimit(testObject.recombine()); + // if (contained >= keep) return 0; + // return super.insertToHandler(testObject, Math.min(keep - contained, amount), destHandler, doFill); + // } else if (transferMode == TransferMode.TRANSFER_EXACT) { + // assert getFluidFilter() != null; + // int required = getFluidFilter().getTransferLimit(testObject.recombine()); + // if (amount < required) return 0; + // return super.insertToHandler(testObject, required, destHandler, doFill); + // } + // } + // return super.insertToHandler(testObject, amount, destHandler, doFill); + // } + // + // @Override + // public @Nullable FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, + // IFluidHandler sourceHandler, boolean doDrain) { + // if (pumpMode == PumpMode.IMPORT) { + // // should extraction instead be ignored for transfer exact? + // if (transferMode == TransferMode.TRANSFER_EXACT) { + // assert getFluidFilter() != null; + // int required = testObject == null ? getFluidFilter().getTransferSize() : + // getFluidFilter().getTransferLimit(testObject.recombine()); + // if (amount < required) return null; + // else amount = required; + // } + // } + // return super.extractFromHandler(testObject, amount, sourceHandler, doDrain); + // } @Override public int getMaxTransferRate() { diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index d58745651d9..e0ec083f81f 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -754,4 +754,9 @@ public FluidStack drain(int maxDrain, boolean doDrain) { return super.drain(maxDrain, doDrain); } } + + @Override + public boolean canPipePassThrough() { + return true; + } } diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index decce3ad0fc..911ce54bf6d 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -210,41 +210,42 @@ protected ParentWidget createUI(ModularPanel mainPanel, PanelSyncManager .setTextColor(Color.WHITE.darker(1)))); } - @Override - public int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, - boolean simulate) { - if (conveyorMode == ConveyorMode.EXPORT) { - if (transferMode == TransferMode.KEEP_EXACT) { - int contained = computeContained(destHandler, testObject); - assert getItemFilter() != null; - int keep = getItemFilter().getTransferLimit(testObject.recombine()); - if (contained >= keep) return amount; - int allowed = Math.min(keep - contained, amount); - return (amount - allowed) + super.insertToHandler(testObject, allowed, destHandler, simulate); - } else if (transferMode == TransferMode.TRANSFER_EXACT) { - assert getItemFilter() != null; - int required = getItemFilter().getTransferLimit(testObject.recombine()); - if (amount < required) return amount; - return (amount - required) + super.insertToHandler(testObject, required, destHandler, simulate); - } - } - return super.insertToHandler(testObject, amount, destHandler, simulate); - } - - @Override - public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler sourceHandler, - boolean simulate) { - if (conveyorMode == ConveyorMode.IMPORT) { - // TODO should extraction instead be ignored for transfer exact? - if (transferMode == TransferMode.TRANSFER_EXACT) { - assert getItemFilter() != null; - int required = getItemFilter().getTransferLimit(testObject.recombine()); - if (amount < required) return 0; - else amount = required; - } - } - return super.extractFromHandler(testObject, amount, sourceHandler, simulate); - } + // @Override + // public int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, + // boolean simulate) { + // if (conveyorMode == ConveyorMode.EXPORT) { + // if (transferMode == TransferMode.KEEP_EXACT) { + // int contained = computeContained(destHandler, testObject); + // assert getItemFilter() != null; + // int keep = getItemFilter().getTransferLimit(testObject.recombine()); + // if (contained >= keep) return amount; + // int allowed = Math.min(keep - contained, amount); + // return (amount - allowed) + super.insertToHandler(testObject, allowed, destHandler, simulate); + // } else if (transferMode == TransferMode.TRANSFER_EXACT) { + // assert getItemFilter() != null; + // int required = getItemFilter().getTransferLimit(testObject.recombine()); + // if (amount < required) return amount; + // return (amount - required) + super.insertToHandler(testObject, required, destHandler, simulate); + // } + // } + // return super.insertToHandler(testObject, amount, destHandler, simulate); + // } + // + // @Override + // public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler + // sourceHandler, + // boolean simulate) { + // if (conveyorMode == ConveyorMode.IMPORT) { + // // should extraction instead be ignored for transfer exact? + // if (transferMode == TransferMode.TRANSFER_EXACT) { + // assert getItemFilter() != null; + // int required = getItemFilter().getTransferLimit(testObject.recombine()); + // if (amount < required) return 0; + // else amount = required; + // } + // } + // return super.extractFromHandler(testObject, amount, sourceHandler, simulate); + // } @Override protected int getMaxStackSize() { diff --git a/src/main/java/gregtech/common/covers/CoverShutter.java b/src/main/java/gregtech/common/covers/CoverShutter.java index c79c939e50f..2f2a29d409a 100644 --- a/src/main/java/gregtech/common/covers/CoverShutter.java +++ b/src/main/java/gregtech/common/covers/CoverShutter.java @@ -80,7 +80,8 @@ public boolean forcePipeRenderConnection() { @Override public boolean canPipePassThrough() { - return !isWorkingAllowed; + // isWorkingAllowed restriction is applied during edge predication + return true; } @Override From b9abfbbee0131deb2af9d4b469b2ec72f1b89b83 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 7 Sep 2024 15:46:47 -0600 Subject: [PATCH 135/157] Tentative datafix edge rebuilding system --- .../pipenet/physical/tile/PipeTileEntity.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index b020373a3ba..533c7272896 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -74,6 +74,9 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick private final Int2ObjectOpenHashMap netLogicDatas = new Int2ObjectOpenHashMap<>(); private final ObjectOpenHashSet listeners = new ObjectOpenHashSet<>(); + // this tile was loaded from datafixed NBT and needs to initialize its connections + private boolean legacy; + // information that is only required for determining graph topology should be stored on the tile entity level, // while information interacted with during graph traversal should be stored on the NetLogicData level. @@ -509,6 +512,13 @@ public void initialize() { updateTemperatureLogic(candidate); } } + if (this.legacy) { + for (EnumFacing facing : EnumFacing.VALUES) { + if (this.isConnected(facing)) + PipeBlock.connectTile(this, this.getPipeNeighbor(facing, false), facing); + } + this.legacy = false; + } this.netLogicDatas.trim(); this.capabilities.trim(); this.netCapabilities.trim(); @@ -538,6 +548,7 @@ private void writeLogicData(int networkID, NetLogicEntry entry, boolean re compound.setByte("RenderMask", renderMask); compound.setByte("BlockedMask", blockedMask); compound.setInteger("Paint", paintingColor); + if (legacy) compound.setBoolean("Legacy", true); if (frameMaterial != null) compound.setString("Frame", frameMaterial.getRegistryName()); compound.setTag("Covers", getCoverHolder().serializeNBT()); return compound; @@ -550,6 +561,7 @@ public void readFromNBT(@NotNull NBTTagCompound compound) { renderMask = compound.getByte("RenderMask"); blockedMask = compound.getByte("BlockedMask"); paintingColor = compound.getInteger("Paint"); + legacy = compound.getBoolean("Legacy"); if (compound.hasKey("Frame")) this.frameMaterial = GregTechAPI.materialManager.getMaterial(compound.getString("Frame")); else this.frameMaterial = null; From c9fc15e96b89e02391b52f71bf27e2bdbd75bab8 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 7 Sep 2024 15:58:05 -0600 Subject: [PATCH 136/157] Prevent endless recursion on datafix --- .../pipenet/physical/tile/PipeTileEntity.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 533c7272896..c0e11255400 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -43,6 +43,7 @@ import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; import net.minecraft.world.WorldServer; +import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.property.IExtendedBlockState; @@ -513,10 +514,17 @@ public void initialize() { } } if (this.legacy) { + BlockPos.PooledMutableBlockPos mutablePos = BlockPos.PooledMutableBlockPos.retain(); for (EnumFacing facing : EnumFacing.VALUES) { - if (this.isConnected(facing)) - PipeBlock.connectTile(this, this.getPipeNeighbor(facing, false), facing); + if (this.isConnected(facing)) { + mutablePos.setPos(this.getPos().offset(facing)); + TileEntity candidate = getWorld().getChunk(mutablePos) + .getTileEntity(mutablePos, Chunk.EnumCreateEntityType.CHECK); + if (candidate instanceof PipeTileEntity pipe) + PipeBlock.connectTile(this, pipe, facing); + } } + mutablePos.release(); this.legacy = false; } this.netLogicDatas.trim(); From ea3a84a484631358f966170b63ba6be13497c855 Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+techlord22@users.noreply.github.com> Date: Sat, 7 Sep 2024 22:29:19 -0400 Subject: [PATCH 137/157] data fixers --- .../gregtech/common/blocks/MetaBlocks.java | 2 +- .../java/gregtech/datafix/GTDataFixers.java | 7 + .../java/gregtech/datafix/GTDataVersion.java | 6 +- .../migration/impl/MigrateMTEBlockTE.java | 12 - .../migration/impl/MigratePipeBlockTE.java | 214 ++++++++++++++++++ .../migration/impl/MigratePipeItems.java | 44 ++++ .../datafix/util/DataFixConstants.java | 15 ++ 7 files changed, 286 insertions(+), 14 deletions(-) create mode 100644 src/main/java/gregtech/datafix/migration/impl/MigratePipeBlockTE.java create mode 100644 src/main/java/gregtech/datafix/migration/impl/MigratePipeItems.java diff --git a/src/main/java/gregtech/common/blocks/MetaBlocks.java b/src/main/java/gregtech/common/blocks/MetaBlocks.java index a92b72d72ba..f809549aec3 100644 --- a/src/main/java/gregtech/common/blocks/MetaBlocks.java +++ b/src/main/java/gregtech/common/blocks/MetaBlocks.java @@ -437,7 +437,7 @@ public static void registerTileEntity() { GameRegistry.registerTileEntity(MetaTileEntityHolder.class, gregtechId("machine")); GameRegistry.registerTileEntity(PipeTileEntity.class, gregtechId("pipe")); GameRegistry.registerTileEntity(PipeMaterialTileEntity.class, gregtechId("material_pipe")); - GameRegistry.registerTileEntity(PipeActivableTileEntity.class, gregtechId("activable_pipe")); + GameRegistry.registerTileEntity(PipeActivableTileEntity.class, gregtechId("activatable_pipe")); } @SideOnly(Side.CLIENT) diff --git a/src/main/java/gregtech/datafix/GTDataFixers.java b/src/main/java/gregtech/datafix/GTDataFixers.java index ea8efe93388..09476a561db 100644 --- a/src/main/java/gregtech/datafix/GTDataFixers.java +++ b/src/main/java/gregtech/datafix/GTDataFixers.java @@ -4,6 +4,8 @@ import gregtech.api.GregTechAPI; import gregtech.datafix.migration.impl.MigrateMTEBlockTE; import gregtech.datafix.migration.impl.MigrateMTEItems; +import gregtech.datafix.migration.impl.MigratePipeBlockTE; +import gregtech.datafix.migration.impl.MigratePipeItems; import gregtech.datafix.migration.lib.MTERegistriesMigrator; import gregtech.datafix.walker.WalkItemStackLike; @@ -58,6 +60,11 @@ private static void registerFixes(@NotNull GTDataVersion version, @NotNull ModFi fixer.registerFix(GTFixType.ITEM_STACK_LIKE, new MigrateMTEItems(migrator)); fixer.registerFix(FixTypes.CHUNK, new MigrateMTEBlockTE(migrator)); } + case V2_POST_PIPES -> { + int v = GTDataVersion.V2_POST_PIPES.ordinal(); + fixer.registerFix(GTFixType.ITEM_STACK_LIKE, new MigratePipeItems(v)); + fixer.registerFix(FixTypes.CHUNK, new MigratePipeBlockTE(v)); + } default -> {} } } diff --git a/src/main/java/gregtech/datafix/GTDataVersion.java b/src/main/java/gregtech/datafix/GTDataVersion.java index e077b5ed729..8d9c14d4fae 100644 --- a/src/main/java/gregtech/datafix/GTDataVersion.java +++ b/src/main/java/gregtech/datafix/GTDataVersion.java @@ -14,7 +14,11 @@ public enum GTDataVersion { /** * Version of data after multiple MTE registries were possible */ - V1_POST_MTE; + V1_POST_MTE, + /** + * Version of data after pipes utilized JGraphT + */ + V2_POST_PIPES; static final @NotNull GTDataVersion @NotNull [] VALUES = values(); diff --git a/src/main/java/gregtech/datafix/migration/impl/MigrateMTEBlockTE.java b/src/main/java/gregtech/datafix/migration/impl/MigrateMTEBlockTE.java index f5a2443168d..432ad6752f2 100644 --- a/src/main/java/gregtech/datafix/migration/impl/MigrateMTEBlockTE.java +++ b/src/main/java/gregtech/datafix/migration/impl/MigrateMTEBlockTE.java @@ -27,18 +27,6 @@ public class MigrateMTEBlockTE implements IFixableData { private static final String META_ID = "MetaId"; private static final String META_TILE_ENTITY = "MetaTileEntity"; - private static final String X = "x"; - private static final String Y = "y"; - private static final String Z = "z"; - private static final String X_POS = "xPos"; - private static final String Z_POS = "zPos"; - private static final String CHUNK_SECTION_Y = "Y"; - private static final String CHUNK_SECTION_BLOCKS = "Blocks"; - private static final String CHUNK_SECTION_DATA = "Data"; - private static final String CHUNK_SECTION_ADD = "Add"; - - private static final int BLOCKS_PER_SECTION = 4096; - private final MTEMigrator migrator; public MigrateMTEBlockTE(@NotNull MTEMigrator migrator) { diff --git a/src/main/java/gregtech/datafix/migration/impl/MigratePipeBlockTE.java b/src/main/java/gregtech/datafix/migration/impl/MigratePipeBlockTE.java new file mode 100644 index 00000000000..7af08652812 --- /dev/null +++ b/src/main/java/gregtech/datafix/migration/impl/MigratePipeBlockTE.java @@ -0,0 +1,214 @@ +package gregtech.datafix.migration.impl; + +import gregtech.api.util.GTLog; +import gregtech.common.pipelike.block.pipe.MaterialPipeStructure; +import gregtech.datafix.GTDataFixers; + +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.datafix.IFixableData; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.NibbleArray; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.registries.GameData; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +import static gregtech.datafix.util.DataFixConstants.*; + +public class MigratePipeBlockTE implements IFixableData { + + private static final String PIPE_BLOCK_TAG = "PipeBlock"; + private static final String PIPE_TYPE_TAG = "PipeType"; + + private final int version; + + public MigratePipeBlockTE(int version) { + this.version = version; + } + + @Override + public int getFixVersion() { + return version; + } + + @Override + public @NotNull NBTTagCompound fixTagCompound(@NotNull NBTTagCompound compound) { + if (!compound.hasKey(LEVEL_TAG, Constants.NBT.TAG_COMPOUND)) { + return compound; + } + + NBTTagCompound level = compound.getCompoundTag(LEVEL_TAG); + processChunkSections(level, gatherTEs(level)); + return compound; + } + + /** + * @param level the level tag + * @return the TEs in the level + */ + private static @NotNull Map gatherTEs(@NotNull NBTTagCompound level) { + Map tileEntityIds = new Object2ObjectOpenHashMap<>(); + NBTTagList tileEntityTagList = level.getTagList(TILE_ENTITIES_TAG, Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < tileEntityTagList.tagCount(); i++) { + NBTTagCompound tileEntityTag = tileEntityTagList.getCompoundTagAt(i); + if (tileEntityTag.hasKey(PIPE_BLOCK_TAG, Constants.NBT.TAG_STRING) && + tileEntityTag.hasKey(PIPE_TYPE_TAG, Constants.NBT.TAG_INT)) { + BlockPos pos = new BlockPos(tileEntityTag.getInteger(X), tileEntityTag.getInteger(Y), + tileEntityTag.getInteger(Z)); + ResourceLocation blockId = fixTileEntityTag(tileEntityTag); + tileEntityIds.put(pos, blockId); + } + } + return tileEntityIds; + } + + private static @NotNull ResourceLocation fixTileEntityTag(@NotNull NBTTagCompound tag) { + ResourceLocation fixedTileEntityId = fixTileEntityId(new ResourceLocation(tag.getString(TILE_ENTITY_ID))); + if (fixedTileEntityId != null) { + tag.setString(TILE_ENTITY_ID, fixedTileEntityId.toString()); + } + + ResourceLocation blockRegistryName = new ResourceLocation(tag.getString(PIPE_BLOCK_TAG)); + ResourceLocation fixedBlockRegistryName = fixBlockRegistryName(blockRegistryName); + if (fixedBlockRegistryName == null) { + GTDataFixers.LOGGER.warn("Cannot find pipe structure for PipeType: {}", blockRegistryName); + return blockRegistryName; + } else { + blockRegistryName = fixedBlockRegistryName; + } + tag.setByte("ConnectionMask", (byte) tag.getInteger("Connections")); + tag.setByte("BlockedMask", (byte) tag.getInteger("BlockedConnections")); + if (tag.hasKey("InsulationColor", Constants.NBT.TAG_INT)) { + tag.setInteger("Paint", tag.getInteger("InsulationColor")); + } else { + tag.setInteger("Paint", -1); + } + GTLog.logger.fatal("PAINING COLOR: {}", tag.getInteger("Paint")); + tag.setString("Frame", tag.getString("FrameMaterial")); + tag.setBoolean("Legacy", true); + + if (tag.hasKey("PipeMaterial")) { + tag.setString("Material", tag.getString("PipeMaterial")); + } + + // the "Fluids" key is discarded for fluid pipes + + return blockRegistryName; + } + + private static @Nullable ResourceLocation fixTileEntityId(@NotNull ResourceLocation id) { + String value = switch (id.getPath()) { + case "cable", "fluid_pipe", "fluid_pipe_active", "item_pipe" -> "material_pipe"; + case "optical_pipe", "laser_pipe" -> "activatable_pipe"; + default -> null; + }; + + if (value == null) { + GTDataFixers.LOGGER.warn("Cannot find pipe tile class for id: {}", id); + return null; + } + + return new ResourceLocation(id.getNamespace(), value); + } + + public static @Nullable ResourceLocation fixBlockRegistryName(@NotNull ResourceLocation name) { + String value = name.getPath(); + if (value.startsWith("wire_") || value.startsWith("cable_") || value.startsWith("laser_pipe_") || + value.startsWith("optical_pipe_")) { + // unchanged values + return name; + } + + value = switch (value) { + case "fluid_pipe_tiny" -> MaterialPipeStructure.TINY.getName(); + case "fluid_pipe_small", "item_pipe_small" -> MaterialPipeStructure.SMALL.getName(); + case "fluid_pipe_normal", "item_pipe_normal" -> MaterialPipeStructure.NORMAL.getName(); + case "fluid_pipe_large", "item_pipe_large" -> MaterialPipeStructure.LARGE.getName(); + case "fluid_pipe_huge", "item_pipe_huge" -> MaterialPipeStructure.HUGE.getName(); + case "fluid_pipe_quadruple" -> MaterialPipeStructure.QUADRUPLE.getName(); + case "fluid_pipe_nonuple" -> MaterialPipeStructure.NONUPLE.getName(); + case "item_pipe_small_restrictive" -> MaterialPipeStructure.SMALL_RESTRICTIVE.getName(); + case "item_pipe_normal_restrictive" -> MaterialPipeStructure.NORMAL_RESTRICTIVE.getName(); + case "item_pipe_large_restrictive" -> MaterialPipeStructure.LARGE_RESTRICTIVE.getName(); + case "item_pipe_huge_restrictive" -> MaterialPipeStructure.HUGE_RESTRICTIVE.getName(); + default -> null; + }; + + if (value == null) { + return null; + } + + return new ResourceLocation(name.getNamespace(), value); + } + + /** + * Processes the chunk sections to remap blocks. + * + * @param level the level tag + * @param blockIds the Blocks present in the chunk section + */ + private static void processChunkSections(@NotNull NBTTagCompound level, + @NotNull Map blockIds) { + if (blockIds.isEmpty()) { + return; + } + + var blockStateIDMap = GameData.getBlockStateIDMap(); + ChunkPos chunkPos = new ChunkPos(level.getInteger(X_POS), level.getInteger(Z_POS)); + NBTTagList sectionTagList = level.getTagList(SECTIONS, Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < sectionTagList.tagCount(); i++) { + NBTTagCompound chunkSectionTag = sectionTagList.getCompoundTagAt(i); + + int sectionY = chunkSectionTag.getByte(CHUNK_SECTION_Y); + byte[] blockIDs = chunkSectionTag.getByteArray(CHUNK_SECTION_BLOCKS); + NibbleArray blockData = new NibbleArray(chunkSectionTag.getByteArray(CHUNK_SECTION_DATA)); + NibbleArray extendedIDs = chunkSectionTag.hasKey(CHUNK_SECTION_ADD, Constants.NBT.TAG_BYTE_ARRAY) ? + new NibbleArray(chunkSectionTag.getByteArray(CHUNK_SECTION_ADD)) : null; + for (int j = 0; j < BLOCKS_PER_SECTION; j++) { + int x = j & 0x0F; + int y = j >> 8 & 0x0F; + int z = j >> 4 & 0x0F; + + BlockPos pos = chunkPos.getBlock(x, sectionY << 4 | y, z); + ResourceLocation blockId = blockIds.get(pos); + if (blockId == null) { + continue; + } + + Block block = Block.REGISTRY.getObject(blockId); + if (block == Blocks.AIR) { + continue; + } + + int newStateID = blockStateIDMap.get(block.getDefaultState()); + byte newBlockID = (byte) (newStateID >> 4 & 0xFF); + byte newBlockIDExt = (byte) (newStateID >> 12 & 0x0F); + byte newBlockData = (byte) (newStateID & 0x0F); + + blockIDs[j] = newBlockID; + if (newBlockIDExt != 0) { + if (extendedIDs == null) { + extendedIDs = new NibbleArray(); + } + extendedIDs.set(x, y, z, newBlockIDExt); + } + blockData.set(x, y, z, newBlockData); + } + + chunkSectionTag.setByteArray(CHUNK_SECTION_BLOCKS, blockIDs); + chunkSectionTag.setByteArray(CHUNK_SECTION_DATA, blockData.getData()); + if (extendedIDs != null) { + chunkSectionTag.setByteArray(CHUNK_SECTION_ADD, extendedIDs.getData()); + } + } + } +} diff --git a/src/main/java/gregtech/datafix/migration/impl/MigratePipeItems.java b/src/main/java/gregtech/datafix/migration/impl/MigratePipeItems.java new file mode 100644 index 00000000000..9aea4091795 --- /dev/null +++ b/src/main/java/gregtech/datafix/migration/impl/MigratePipeItems.java @@ -0,0 +1,44 @@ +package gregtech.datafix.migration.impl; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.datafix.IFixableData; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static gregtech.datafix.util.DataFixConstants.*; + +public class MigratePipeItems implements IFixableData { + + private final int version; + + public MigratePipeItems(int version) { + this.version = version; + } + + @Override + public int getFixVersion() { + return version; + } + + @Override + public @NotNull NBTTagCompound fixTagCompound(@NotNull NBTTagCompound compound) { + final String id = compound.getString(ITEM_ID); + if (id.isEmpty()) { + return compound; + } + + ResourceLocation itemBlockId = new ResourceLocation(id); + ResourceLocation fixedName = fixItemName(itemBlockId); + if (fixedName != null) { + compound.setString(ITEM_ID, fixedName.toString()); + } + + return compound; + } + + private static @Nullable ResourceLocation fixItemName(@NotNull ResourceLocation itemBlockId) { + return MigratePipeBlockTE.fixBlockRegistryName(itemBlockId); + } +} diff --git a/src/main/java/gregtech/datafix/util/DataFixConstants.java b/src/main/java/gregtech/datafix/util/DataFixConstants.java index 83f374add07..6ea7529cc7c 100644 --- a/src/main/java/gregtech/datafix/util/DataFixConstants.java +++ b/src/main/java/gregtech/datafix/util/DataFixConstants.java @@ -10,5 +10,20 @@ public final class DataFixConstants { public static final String ITEM_COUNT = "Count"; public static final String ITEM_DAMAGE = "Damage"; + public static final String X_POS = "xPos"; + public static final String Z_POS = "zPos"; + public static final String X = "x"; + public static final String Y = "y"; + public static final String Z = "z"; + + public static final String CHUNK_SECTION_Y = "Y"; + public static final String CHUNK_SECTION_BLOCKS = "Blocks"; + public static final String CHUNK_SECTION_DATA = "Data"; + public static final String CHUNK_SECTION_ADD = "Add"; + + public static final int BLOCKS_PER_SECTION = 4096; + + public static final String TILE_ENTITY_ID = "id"; + private DataFixConstants() {} } From 90d40b65f7b2cc7aec3ba8347d197040b7b8fa04 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sat, 7 Sep 2024 21:20:20 -0600 Subject: [PATCH 138/157] Tiny fixes --- .../client/renderer/pipe/quad/RecolorableBakedQuad.java | 2 +- .../gregtech/datafix/migration/impl/MigratePipeBlockTE.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java index 45890a8ecda..b275af86ae4 100644 --- a/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java +++ b/src/main/java/gregtech/client/renderer/pipe/quad/RecolorableBakedQuad.java @@ -27,7 +27,7 @@ public RecolorableBakedQuad(BakedQuad prototype, SpriteInformation spriteInforma protected RecolorableBakedQuad(BakedQuad prototype, int tintIndex, SpriteInformation spriteInformation, Int2ObjectOpenHashMap cache) { - super(prototype.vertexData, tintIndex, prototype.getFace(), spriteInformation.sprite(), + super(prototype.getVertexData(), tintIndex, prototype.getFace(), spriteInformation.sprite(), prototype.shouldApplyDiffuseLighting(), prototype.getFormat()); this.spriteInformation = spriteInformation; this.cache = cache; diff --git a/src/main/java/gregtech/datafix/migration/impl/MigratePipeBlockTE.java b/src/main/java/gregtech/datafix/migration/impl/MigratePipeBlockTE.java index 7af08652812..6d68a896bec 100644 --- a/src/main/java/gregtech/datafix/migration/impl/MigratePipeBlockTE.java +++ b/src/main/java/gregtech/datafix/migration/impl/MigratePipeBlockTE.java @@ -1,6 +1,5 @@ package gregtech.datafix.migration.impl; -import gregtech.api.util.GTLog; import gregtech.common.pipelike.block.pipe.MaterialPipeStructure; import gregtech.datafix.GTDataFixers; @@ -92,7 +91,6 @@ public int getFixVersion() { } else { tag.setInteger("Paint", -1); } - GTLog.logger.fatal("PAINING COLOR: {}", tag.getInteger("Paint")); tag.setString("Frame", tag.getString("FrameMaterial")); tag.setBoolean("Legacy", true); From 6440b0c89708c9ac51f885c455a1f60732bf2199 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Sun, 8 Sep 2024 22:24:21 -0600 Subject: [PATCH 139/157] min length tubes --- .../renderer/pipe/cache/BlockableSQC.java | 21 +++++++++++++++++-- .../renderer/pipe/cache/RestrictiveSQC.java | 9 ++++---- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java index fea9003c5ad..3f759abcb6b 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/BlockableSQC.java @@ -12,7 +12,10 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.apache.commons.lang3.tuple.ImmutablePair; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.util.vector.Vector3f; import java.util.EnumMap; import java.util.List; @@ -34,13 +37,27 @@ protected BlockableSQC(PipeQuadHelper helper, SpriteInformation endTex, SpriteIn public static @NotNull BlockableSQC create(PipeQuadHelper helper, SpriteInformation endTex, SpriteInformation sideTex, SpriteInformation blockedTex) { - helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, - OVERLAY_DIST_1)); + helper.initialize((facing, x1, y1, z1, x2, y2, z2) -> minLengthTube(facing, x1, y1, z1, x2, y2, z2, + OVERLAY_DIST_1, 4)); BlockableSQC cache = new BlockableSQC(helper, endTex, sideTex, blockedTex); cache.buildPrototype(); return cache; } + public static ImmutablePair minLengthTube(@Nullable EnumFacing facing, float x1, float y1, + float z1, float x2, + float y2, float z2, float g, float minLength) { + if (facing == null) return QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, g); + return switch (facing) { + case UP -> QuadHelper.tubeOverlay(facing, x1, Math.min(y1, y2 - minLength), z1, x2, y2, z2, g); + case DOWN -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, Math.max(y2, y1 + minLength), z2, g); + case EAST -> QuadHelper.tubeOverlay(facing, Math.min(x1, x2 - minLength), y1, z1, x2, y2, z2, g); + case WEST -> QuadHelper.tubeOverlay(facing, x1, y1, z1, Math.max(x2, x1 + minLength), y2, z2, g); + case SOUTH -> QuadHelper.tubeOverlay(facing, x1, y1, Math.min(z1, z2 - minLength), x2, y2, z2, g); + case NORTH -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, Math.max(z2, z1 + minLength), g); + }; + } + @Override protected List buildPrototypeInternal() { List quads = super.buildPrototypeInternal(); diff --git a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java index 91a08988745..8d986a0323e 100644 --- a/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java +++ b/src/main/java/gregtech/client/renderer/pipe/cache/RestrictiveSQC.java @@ -3,7 +3,6 @@ import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.quad.ColorData; import gregtech.client.renderer.pipe.quad.PipeQuadHelper; -import gregtech.client.renderer.pipe.quad.QuadHelper; import gregtech.client.renderer.pipe.quad.RecolorableBakedQuad; import gregtech.client.renderer.pipe.util.SpriteInformation; @@ -36,10 +35,10 @@ protected RestrictiveSQC(PipeQuadHelper helper, SpriteInformation endTex, Sprite SpriteInformation sideTex, SpriteInformation blockedTex, SpriteInformation restrictiveTex) { helper.initialize( - (facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, - OVERLAY_DIST_2), - (facing, x1, y1, z1, x2, y2, z2) -> QuadHelper.tubeOverlay(facing, x1, y1, z1, x2, y2, z2, - OVERLAY_DIST_1)); + (facing, x1, y1, z1, x2, y2, z2) -> minLengthTube(facing, x1, y1, z1, x2, y2, z2, + OVERLAY_DIST_2, 4), + (facing, x1, y1, z1, x2, y2, z2) -> minLengthTube(facing, x1, y1, z1, x2, y2, z2, + OVERLAY_DIST_1, 2)); RestrictiveSQC sqc = new RestrictiveSQC(helper, endTex, sideTex, blockedTex, restrictiveTex); sqc.buildPrototype(); return sqc; From e36a45e5f40d31c543cc4fe3629bfdf7914fac25 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 9 Sep 2024 09:52:49 -0600 Subject: [PATCH 140/157] Fix tests --- .../api/metatileentity/multiblock/FuelMultiblockController.java | 2 +- .../multiblock/RecipeMapMultiblockController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/FuelMultiblockController.java b/src/main/java/gregtech/api/metatileentity/multiblock/FuelMultiblockController.java index 790a150ec0c..907869d534d 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/FuelMultiblockController.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/FuelMultiblockController.java @@ -36,7 +36,7 @@ protected void initializeAbilities() { super.initializeAbilities(); List outputEnergy = new ArrayList<>(getAbilities(MultiblockAbility.OUTPUT_ENERGY)); outputEnergy.addAll(getAbilities(MultiblockAbility.SUBSTATION_OUTPUT_ENERGY)); - outputEnergy.addAll(getAbilities(MultiblockAbility.OUTPUT_LASER)); + outputEnergy.addAll(getAbilities(MultiblockAbility.LASER_TRANSMISSION)); this.energyContainer = new EnergyContainerList(outputEnergy); } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapMultiblockController.java b/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapMultiblockController.java index 4949074c91a..3e9afb6a9e9 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapMultiblockController.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapMultiblockController.java @@ -127,7 +127,7 @@ protected void initializeAbilities() { List inputEnergy = new ArrayList<>(getAbilities(MultiblockAbility.INPUT_ENERGY)); inputEnergy.addAll(getAbilities(MultiblockAbility.SUBSTATION_INPUT_ENERGY)); - inputEnergy.addAll(getAbilities(MultiblockAbility.INPUT_LASER)); + inputEnergy.addAll(getAbilities(MultiblockAbility.LASER_RECEPTION)); this.energyContainer = new EnergyContainerList(inputEnergy); } From 1d787a8c97be240a45193f452d0e57f4bb393a42 Mon Sep 17 00:00:00 2001 From: M-W-K Date: Mon, 9 Sep 2024 13:45:29 -0600 Subject: [PATCH 141/157] Laser mirror cable recipe --- .../api/unification/material/Materials.java | 1 + .../material/materials/ElementMaterials.java | 2 +- .../materials/FirstDegreeMaterials.java | 9 ++- .../java/gregtech/common/items/MetaItem1.java | 3 + .../java/gregtech/common/items/MetaItems.java | 3 + .../loaders/recipe/ComputerRecipes.java | 55 ++++++++++++++---- .../loaders/recipe/MiscRecipeLoader.java | 16 +++++ .../resources/assets/gregtech/lang/en_us.lang | 4 ++ .../item/metaitems/laser_reflector.json | 6 ++ .../ultrasmooth_borosilicate_glass.json | 6 ++ .../items/metaitems/laser_reflector.png | Bin 0 -> 275 bytes .../ultrasmooth_borosilicate_glass.png | Bin 0 -> 444 bytes 12 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/laser_reflector.json create mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/ultrasmooth_borosilicate_glass.json create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/laser_reflector.png create mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/ultrasmooth_borosilicate_glass.png diff --git a/src/main/java/gregtech/api/unification/material/Materials.java b/src/main/java/gregtech/api/unification/material/Materials.java index 30174ce8f44..954afd4c44c 100644 --- a/src/main/java/gregtech/api/unification/material/Materials.java +++ b/src/main/java/gregtech/api/unification/material/Materials.java @@ -477,6 +477,7 @@ public static void register() { public static Material HafniumTetrachloride; public static Material Zircaloy4; public static Material Inconel718; + public static Material TitaniumDioxide; /** * Organic chemistry diff --git a/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java b/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java index 687790f7cd1..04e96d79250 100644 --- a/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java @@ -831,7 +831,7 @@ public static void register() { .ingot(3).fluid() .color(0xDCA0F0).iconSet(METALLIC) .flags(EXT2_METAL, GENERATE_DOUBLE_PLATE, GENERATE_ROTOR, GENERATE_SMALL_GEAR, GENERATE_GEAR, - GENERATE_FRAME) + GENERATE_FRAME, GENERATE_FOIL) .element(Elements.Ti) .toolStats(ToolProperty.Builder.of(8.0F, 6.0F, 1536, 3) .enchantability(14).build()) diff --git a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java index f457551a10e..0fc31ccd400 100644 --- a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java @@ -885,7 +885,7 @@ public static void register() { SiliconDioxide = new Material.Builder(356, gregtechId("silicon_dioxide")) .dust(1) .color(0xC8C8C8).iconSet(QUARTZ) - .flags(NO_SMASHING, NO_SMELTING) + .flags(NO_SMASHING, NO_SMELTING, GENERATE_FOIL) .components(Silicon, 1, Oxygen, 2) .build(); @@ -1591,5 +1591,12 @@ public static void register() { .dust(1) .color(0x8B0000).iconSet(SAND) .build(); + + TitaniumDioxide = new Material.Builder(453, gregtechId("titanium_dioxide")) + .dust(1) + .color(0xF8C8C8).iconSet(QUARTZ) + .flags(NO_SMASHING, NO_SMELTING, GENERATE_FOIL) + .components(Titanium, 1, Oxygen, 2) + .build(); } } diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index ecfc26873f6..eb080bdc5dd 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -1162,5 +1162,8 @@ public void registerSubItems() { MULTIBLOCK_BUILDER = addItem(1004, "tool.multiblock_builder").addComponents(new MultiblockBuilderBehavior()) .setMaxStackSize(1); + + ULTRASMOOTH_BOROSILICATE = addItem(1005, "ultrasmooth_borosilicate_glass"); + LASER_REFLECTOR = addItem(1006, "laser_reflector"); } } diff --git a/src/main/java/gregtech/common/items/MetaItems.java b/src/main/java/gregtech/common/items/MetaItems.java index 303588e6dc8..05cd911fbdc 100644 --- a/src/main/java/gregtech/common/items/MetaItems.java +++ b/src/main/java/gregtech/common/items/MetaItems.java @@ -564,6 +564,9 @@ private MetaItems() {} public static MetaItem.MetaValueItem MULTIBLOCK_BUILDER; + public static MetaItem.MetaValueItem ULTRASMOOTH_BOROSILICATE; + public static MetaItem.MetaValueItem LASER_REFLECTOR; + private static final List orePrefixes = new ArrayList<>(); static { diff --git a/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java b/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java index de8cb2d3e2e..c4aee00cf42 100644 --- a/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java @@ -11,8 +11,7 @@ import net.minecraft.item.ItemStack; import static gregtech.api.GTValues.*; -import static gregtech.api.recipes.RecipeMaps.ASSEMBLER_RECIPES; -import static gregtech.api.recipes.RecipeMaps.ASSEMBLY_LINE_RECIPES; +import static gregtech.api.recipes.RecipeMaps.*; import static gregtech.api.unification.material.Materials.*; import static gregtech.api.unification.ore.OrePrefix.*; import static gregtech.common.blocks.MetaBlocks.*; @@ -313,13 +312,49 @@ public static void init() { .cleanroom(CleanroomType.CLEANROOM) .duration(100).EUt(VA[IV]).buildAndRegister(); - // ASSEMBLER_RECIPES.recipeBuilder() - // .input(LASER_PIPES[0], 2) - // .input(foil, Silver, 2) - // .input(NEUTRON_REFLECTOR) - // .fluidInputs(Polytetrafluoroethylene.getFluid(L)) - // .output(LASER_PIPES[1]) - // .cleanroom(CleanroomType.CLEANROOM) - // .duration(150).EUt(VA[IV]).buildAndRegister(); + AUTOCLAVE_RECIPES.recipeBuilder() + .input(dust, BorosilicateGlass, 5) + .fluidInputs(Water.getFluid(1000)) + .output(ULTRASMOOTH_BOROSILICATE) + .duration(3000).EUt(VA[IV]).buildAndRegister(); + + AUTOCLAVE_RECIPES.recipeBuilder() + .input(dust, BorosilicateGlass, 5) + .fluidInputs(DistilledWater.getFluid(1000)) + .output(ULTRASMOOTH_BOROSILICATE) + .duration(2000).EUt(VA[IV]).buildAndRegister(); + + ASSEMBLER_RECIPES.recipeBuilder() + .notConsumable(EMITTER_ZPM) + .input(foil, TitaniumDioxide, 3) + .input(foil, SiliconDioxide, 3) + .input(ULTRASMOOTH_BOROSILICATE) + .fluidInputs(Oxygen.getPlasma(85)) + .output(LASER_REFLECTOR) + .cleanroom(CleanroomType.CLEANROOM) + .duration(10000).EUt(VA[LuV]).buildAndRegister(); + + ASSEMBLER_RECIPES.recipeBuilder() + .notConsumable(EMITTER_UV) + .input(foil, Titanium) + .input(foil, Silicon) + .input(ULTRASMOOTH_BOROSILICATE) + .fluidInputs(Oxygen.getPlasma(1085)) + .output(LASER_REFLECTOR) + .cleanroom(CleanroomType.CLEANROOM) + .duration(1000).EUt(VA[ZPM]).buildAndRegister(); + + ASSEMBLY_LINE_RECIPES.recipeBuilder() + .input(LASER_REFLECTOR) + .input(lens, NetherStar, 2) + .input(stick, Duranium, 6) + .input(ELECTRIC_PUMP_ZPM) + .input(foil, Osmiridium, 5) + .fluidInputs(Polytetrafluoroethylene.getFluid(L * 3), + NaquadahAlloy.getFluid(L * 32)) + .output(LASER_PIPES[1]) + .cleanroom(CleanroomType.CLEANROOM) + .stationResearch(s -> s.researchStack(LASER_REFLECTOR.getStackForm()).EUt(VA[ZPM]).CWUt(32)) + .duration(350).EUt(VA[ZPM]).buildAndRegister(); } } diff --git a/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java index fb3b3173dc4..cdfbecd0e84 100644 --- a/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java @@ -507,5 +507,21 @@ public static void init() { .input(ring, Steel, 2) .output(STEEL_MINECART_WHEELS) .duration(60).EUt(20).buildAndRegister(); + + CHEMICAL_RECIPES.recipeBuilder() + .input(dust, Titanium) + .fluidInputs(Oxygen.getFluid(2000)) + .output(dust, TitaniumDioxide, 3) + .duration(100).EUt(60).buildAndRegister(); + + COMPRESSOR_RECIPES.recipeBuilder() + .input(dustSmall, SiliconDioxide) + .output(foil, SiliconDioxide) + .duration(200).EUt(1).buildAndRegister(); + + COMPRESSOR_RECIPES.recipeBuilder() + .input(dustSmall, TitaniumDioxide) + .output(foil, TitaniumDioxide) + .duration(200).EUt(1).buildAndRegister(); } } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index c1b487bd2ce..58eb43fdd99 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -1188,6 +1188,9 @@ metaitem.fertilizer.name=Fertilizer metaitem.blacklight.name=Blacklight metaitem.blacklight.tooltip=Long-Wave §dUltraviolet§7 light source +metaitem.ultrasmooth_borosilicate_glass.name=Ultrasmooth Borosilicate Glass +metaitem.laser_reflector.name=Dielectric Laser Mirror + gui.widget.incrementButton.default_tooltip=Hold Shift, Ctrl or both to change the amount gui.widget.recipeProgressWidget.default_tooltip=Show Recipes @@ -1838,6 +1841,7 @@ gregtech.material.hafnia=Hafnia gregtech.material.hafnium_tetrachloride=Hafnium Tetrachloride gregtech.material.zircaloy_4=Zircaloy-4 gregtech.material.inconel_718=Inconel-718 +gregtech.material.titanium_dioxide=Titanium Dioxide # Organic Chemistry Materials diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/laser_reflector.json b/src/main/resources/assets/gregtech/models/item/metaitems/laser_reflector.json new file mode 100644 index 00000000000..44bac8e3c2d --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/laser_reflector.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/laser_reflector" + } +} diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/ultrasmooth_borosilicate_glass.json b/src/main/resources/assets/gregtech/models/item/metaitems/ultrasmooth_borosilicate_glass.json new file mode 100644 index 00000000000..9dbdc65b105 --- /dev/null +++ b/src/main/resources/assets/gregtech/models/item/metaitems/ultrasmooth_borosilicate_glass.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "gregtech:items/metaitems/ultrasmooth_borosilicate_glass" + } +} diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/laser_reflector.png b/src/main/resources/assets/gregtech/textures/items/metaitems/laser_reflector.png new file mode 100644 index 0000000000000000000000000000000000000000..d31178c3c636c42975830873f2aae83c98c29607 GIT binary patch literal 275 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkEsO-Y4_$GQa3h^|M=hN*y45juT(6ba_N1yi7|h& z&Ry3dD;-^C{gP%7)D@OUzQ&oA#j)_FL$+?m36TY5>o&4olh0)it72R;Jv8i|z|(%9 PTNylE{an^LB{Ts5+(2Kd literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/ultrasmooth_borosilicate_glass.png b/src/main/resources/assets/gregtech/textures/items/metaitems/ultrasmooth_borosilicate_glass.png new file mode 100644 index 0000000000000000000000000000000000000000..df916b8685b05c322060752663d43309021de3a2 GIT binary patch literal 444 zcmV;t0YmPx$bV)=(R5(wiQ_V`lKoI^Wy-A-y(jY#71r=Hmv_3;T+VtJptNI9PP9jt`hG}1qGXt*=$ooS}Zt+WFa%(-)so~Ec)j>Y5;fRkcj|hpm%usCqb>@_A%t%{s}(6 zzi|Kj0DwU(Itgb7b-why zUjYFCLp+gqGG7=Im8=06hkV@bKu;&&dBK#+LxkiOj|fSupd(#ZApTv?wM;pPg&CMT zf>E5c)=-hgz`ro+D;BB%5*~qz1Z@!#rJ-M91m{5&pgIgVIT!MU#jbVwmSQ%`O8*rF z0?=x?Ca}fo%o41CG)>Lj$g&JNiV^rL6i7pZfNjr3`ktC4G$aEHB*Q9F82J6tdU+UL zjo5Aptz8dJUdS(Agl2OKSvG@;Vhk*MEyP7s!|M@?USf%#;qG{4jM`qHWvm Date: Mon, 9 Sep 2024 17:49:12 -0600 Subject: [PATCH 142/157] Fix material tree --- .../jei/basic/MaterialTreeCategory.java | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/main/java/gregtech/integration/jei/basic/MaterialTreeCategory.java b/src/main/java/gregtech/integration/jei/basic/MaterialTreeCategory.java index 16a26032f73..d379ffb2e27 100644 --- a/src/main/java/gregtech/integration/jei/basic/MaterialTreeCategory.java +++ b/src/main/java/gregtech/integration/jei/basic/MaterialTreeCategory.java @@ -60,18 +60,17 @@ public class MaterialTreeCategory extends BasicRecipeCategory frameGt drawArrow(minecraft, "d7r25u6", 62, 103, itemExists.get(9) && itemExists.get(13)); // stick -> bolt - drawArrow(minecraft, "d7r50u6", 62, 103, itemExists.get(9) && itemExists.get(18)); + drawArrow(minecraft, "d7r50u6", 62, 103, itemExists.get(9) && itemExists.get(17)); // stick -> gear - drawArrow(minecraft, "d7r50d7", 62, 103, itemExists.get(9) && itemExists.get(19)); + drawArrow(minecraft, "d7r50d7", 62, 103, itemExists.get(9) && itemExists.get(18)); // stick -> stickLong - drawArrow(minecraft, "d7r75u6", 62, 103, itemExists.get(9) && itemExists.get(22)); + drawArrow(minecraft, "d7r75u6", 62, 103, itemExists.get(9) && itemExists.get(21)); // stick -> gearSmall - drawArrow(minecraft, "d7r75d7", 62, 103, itemExists.get(9) && itemExists.get(23)); + drawArrow(minecraft, "d7r75d7", 62, 103, itemExists.get(9) && itemExists.get(22)); // stick -> springSmall - drawArrow(minecraft, "d7r87u46r4", 62, 61, itemExists.get(9) && itemExists.get(25)); + drawArrow(minecraft, "d7r87u46r4", 62, 61, itemExists.get(9) && itemExists.get(24)); // stick -> ring - drawArrow(minecraft, "d7r87u22r4", 62, 85, itemExists.get(9) && itemExists.get(26)); + drawArrow(minecraft, "d7r87u22r4", 62, 85, itemExists.get(9) && itemExists.get(25)); // nugget -> round drawArrow(minecraft, "r7", 72, 123, itemExists.get(10) && itemExists.get(14)); - // plate -> pipeNormalFluid/pipeNormalItem + // plate -> pipeNormal drawArrow(minecraft, "u7r25d6", 62, 140, itemExists.get(11) && - (itemExists.get(15) || itemExists.get(16))); + (itemExists.get(15))); // plate -> gear - drawArrow(minecraft, "u7r50u5", 62, 135, itemExists.get(11) && itemExists.get(19)); + drawArrow(minecraft, "u7r50u5", 62, 135, itemExists.get(11) && itemExists.get(18)); // plate -> plateDouble - drawArrow(minecraft, "u7r50d6", 62, 140, itemExists.get(11) && itemExists.get(20)); + drawArrow(minecraft, "u7r50d6", 62, 140, itemExists.get(11) && itemExists.get(19)); // plate -> gearSmall - drawArrow(minecraft, "u7r75u5", 62, 135, itemExists.get(11) && itemExists.get(23)); + drawArrow(minecraft, "u7r75u5", 62, 135, itemExists.get(11) && itemExists.get(22)); // plate -> plateDense - drawArrow(minecraft, "u7r75d6", 62, 140, itemExists.get(11) && itemExists.get(24)); + drawArrow(minecraft, "u7r75d6", 62, 140, itemExists.get(11) && itemExists.get(23)); // plate -> lens - drawArrow(minecraft, "u7r87u8r4", 62, 130, itemExists.get(11) && itemExists.get(27)); + drawArrow(minecraft, "u7r87u8r4", 62, 130, itemExists.get(11) && itemExists.get(26)); // plate -> foil - drawArrow(minecraft, "u7r87d15r4", 62, 140, itemExists.get(11) && itemExists.get(28)); + drawArrow(minecraft, "u7r87d15r4", 62, 140, itemExists.get(11) && itemExists.get(27)); // bolt -> screw - drawArrow(minecraft, "u12", 110, 73, itemExists.get(18) && itemExists.get(17)); + drawArrow(minecraft, "u12", 110, 73, itemExists.get(17) && itemExists.get(16)); // stickLong -> spring - drawArrow(minecraft, "u12", 135, 73, itemExists.get(22) && itemExists.get(21)); + drawArrow(minecraft, "u12", 135, 73, itemExists.get(21) && itemExists.get(20)); // material info rendering int linesDrawn = 0; From 3eb827646dda42c22590720af7da5654c5766f71 Mon Sep 17 00:00:00 2001 From: TechLord22 <37029404+techlord22@users.noreply.github.com> Date: Mon, 9 Sep 2024 19:35:38 -0400 Subject: [PATCH 143/157] recipe adjustments --- .../api/unification/material/Materials.java | 1 - .../material/materials/ElementMaterials.java | 4 +- .../materials/FirstDegreeMaterials.java | 9 +-- .../materials/SecondDegreeMaterials.java | 2 +- .../api/unification/ore/OrePrefix.java | 1 - .../java/gregtech/common/items/MetaItem1.java | 3 +- .../java/gregtech/common/items/MetaItems.java | 1 - .../loaders/recipe/ComputerRecipes.java | 52 +++++------------- .../loaders/recipe/MiscRecipeLoader.java | 16 ------ .../ultrasmooth_borosilicate_glass.json | 6 -- .../items/metaitems/laser_reflector.png | Bin 275 -> 326 bytes .../ultrasmooth_borosilicate_glass.png | Bin 444 -> 0 bytes 12 files changed, 20 insertions(+), 75 deletions(-) delete mode 100644 src/main/resources/assets/gregtech/models/item/metaitems/ultrasmooth_borosilicate_glass.json delete mode 100644 src/main/resources/assets/gregtech/textures/items/metaitems/ultrasmooth_borosilicate_glass.png diff --git a/src/main/java/gregtech/api/unification/material/Materials.java b/src/main/java/gregtech/api/unification/material/Materials.java index 954afd4c44c..30174ce8f44 100644 --- a/src/main/java/gregtech/api/unification/material/Materials.java +++ b/src/main/java/gregtech/api/unification/material/Materials.java @@ -477,7 +477,6 @@ public static void register() { public static Material HafniumTetrachloride; public static Material Zircaloy4; public static Material Inconel718; - public static Material TitaniumDioxide; /** * Organic chemistry diff --git a/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java b/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java index 04e96d79250..5a28aa3e4ef 100644 --- a/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java @@ -91,7 +91,7 @@ public static void register() { .liquid(new FluidBuilder().temperature(1560)) .ore() .color(0x64B464).iconSet(METALLIC) - .flags(STD_METAL, GENERATE_DOUBLE_PLATE) + .flags(STD_METAL, GENERATE_DOUBLE_PLATE, GENERATE_FOIL) .element(Elements.Be) .build(); @@ -1001,7 +1001,7 @@ public static void register() { Trinium = new Material.Builder(130, gregtechId("trinium")) .ingot(7).fluid() .color(0x9973BD).iconSet(SHINY) - .flags(GENERATE_FOIL, GENERATE_BOLT_SCREW, GENERATE_GEAR) + .flags(GENERATE_FOIL, GENERATE_BOLT_SCREW, GENERATE_GEAR, GENERATE_FRAME) .element(Elements.Ke) .cableProperties(V[ZPM], 6, 4) .blast(b -> b diff --git a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java index 0fc31ccd400..f457551a10e 100644 --- a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java @@ -885,7 +885,7 @@ public static void register() { SiliconDioxide = new Material.Builder(356, gregtechId("silicon_dioxide")) .dust(1) .color(0xC8C8C8).iconSet(QUARTZ) - .flags(NO_SMASHING, NO_SMELTING, GENERATE_FOIL) + .flags(NO_SMASHING, NO_SMELTING) .components(Silicon, 1, Oxygen, 2) .build(); @@ -1591,12 +1591,5 @@ public static void register() { .dust(1) .color(0x8B0000).iconSet(SAND) .build(); - - TitaniumDioxide = new Material.Builder(453, gregtechId("titanium_dioxide")) - .dust(1) - .color(0xF8C8C8).iconSet(QUARTZ) - .flags(NO_SMASHING, NO_SMELTING, GENERATE_FOIL) - .components(Titanium, 1, Oxygen, 2) - .build(); } } diff --git a/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java index 27403478bcd..94d9cef3cd6 100644 --- a/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/SecondDegreeMaterials.java @@ -307,7 +307,7 @@ public static void register() { .ingot(1) .liquid(new FluidBuilder().temperature(1921)) .color(0xE6F3E6).iconSet(SHINY) - .flags(GENERATE_FINE_WIRE, GENERATE_PLATE) + .flags(GENERATE_FINE_WIRE, GENERATE_PLATE, NO_SMASHING) .components(Boron, 1, SiliconDioxide, 7) .build(); diff --git a/src/main/java/gregtech/api/unification/ore/OrePrefix.java b/src/main/java/gregtech/api/unification/ore/OrePrefix.java index 4e0dbfe7589..845738e6de7 100644 --- a/src/main/java/gregtech/api/unification/ore/OrePrefix.java +++ b/src/main/java/gregtech/api/unification/ore/OrePrefix.java @@ -467,7 +467,6 @@ public static void init() { cableGtOctal.addSecondaryMaterial(new MaterialStack(Materials.Rubber, plate.materialAmount * 3)); cableGtHex.addSecondaryMaterial(new MaterialStack(Materials.Rubber, plate.materialAmount * 5)); - plate.setIgnored(Materials.BorosilicateGlass); foil.setIgnored(Materials.BorosilicateGlass); dustSmall.setIgnored(Materials.Lapotron); diff --git a/src/main/java/gregtech/common/items/MetaItem1.java b/src/main/java/gregtech/common/items/MetaItem1.java index eb080bdc5dd..f4cb969a4e0 100644 --- a/src/main/java/gregtech/common/items/MetaItem1.java +++ b/src/main/java/gregtech/common/items/MetaItem1.java @@ -1163,7 +1163,6 @@ public void registerSubItems() { MULTIBLOCK_BUILDER = addItem(1004, "tool.multiblock_builder").addComponents(new MultiblockBuilderBehavior()) .setMaxStackSize(1); - ULTRASMOOTH_BOROSILICATE = addItem(1005, "ultrasmooth_borosilicate_glass"); - LASER_REFLECTOR = addItem(1006, "laser_reflector"); + LASER_REFLECTOR = addItem(1005, "laser_reflector"); } } diff --git a/src/main/java/gregtech/common/items/MetaItems.java b/src/main/java/gregtech/common/items/MetaItems.java index 05cd911fbdc..fa74ea23fc0 100644 --- a/src/main/java/gregtech/common/items/MetaItems.java +++ b/src/main/java/gregtech/common/items/MetaItems.java @@ -564,7 +564,6 @@ private MetaItems() {} public static MetaItem.MetaValueItem MULTIBLOCK_BUILDER; - public static MetaItem.MetaValueItem ULTRASMOOTH_BOROSILICATE; public static MetaItem.MetaValueItem LASER_REFLECTOR; private static final List orePrefixes = new ArrayList<>(); diff --git a/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java b/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java index c4aee00cf42..e7632ca92a7 100644 --- a/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java +++ b/src/main/java/gregtech/loaders/recipe/ComputerRecipes.java @@ -312,49 +312,27 @@ public static void init() { .cleanroom(CleanroomType.CLEANROOM) .duration(100).EUt(VA[IV]).buildAndRegister(); - AUTOCLAVE_RECIPES.recipeBuilder() - .input(dust, BorosilicateGlass, 5) - .fluidInputs(Water.getFluid(1000)) - .output(ULTRASMOOTH_BOROSILICATE) - .duration(3000).EUt(VA[IV]).buildAndRegister(); - - AUTOCLAVE_RECIPES.recipeBuilder() - .input(dust, BorosilicateGlass, 5) - .fluidInputs(DistilledWater.getFluid(1000)) - .output(ULTRASMOOTH_BOROSILICATE) - .duration(2000).EUt(VA[IV]).buildAndRegister(); - - ASSEMBLER_RECIPES.recipeBuilder() - .notConsumable(EMITTER_ZPM) - .input(foil, TitaniumDioxide, 3) - .input(foil, SiliconDioxide, 3) - .input(ULTRASMOOTH_BOROSILICATE) - .fluidInputs(Oxygen.getPlasma(85)) + FORMING_PRESS_RECIPES.recipeBuilder() + .input(plate, BorosilicateGlass) + .input(foil, Titanium, 12) + .input(foil, Silicon, 12) + .input(foil, Tantalum, 12) + .input(foil, Zinc, 12) + .input(foil, Beryllium, 12) .output(LASER_REFLECTOR) .cleanroom(CleanroomType.CLEANROOM) - .duration(10000).EUt(VA[LuV]).buildAndRegister(); - - ASSEMBLER_RECIPES.recipeBuilder() - .notConsumable(EMITTER_UV) - .input(foil, Titanium) - .input(foil, Silicon) - .input(ULTRASMOOTH_BOROSILICATE) - .fluidInputs(Oxygen.getPlasma(1085)) - .output(LASER_REFLECTOR) - .cleanroom(CleanroomType.CLEANROOM) - .duration(1000).EUt(VA[ZPM]).buildAndRegister(); + .duration(200).EUt(VA[LuV]).buildAndRegister(); ASSEMBLY_LINE_RECIPES.recipeBuilder() + .input(frameGt, Trinium) + .input(LASER_PIPES[0], 2) .input(LASER_REFLECTOR) .input(lens, NetherStar, 2) - .input(stick, Duranium, 6) - .input(ELECTRIC_PUMP_ZPM) - .input(foil, Osmiridium, 5) - .fluidInputs(Polytetrafluoroethylene.getFluid(L * 3), - NaquadahAlloy.getFluid(L * 32)) + .input(foil, Osmiridium, 20) + .fluidInputs(Polybenzimidazole.getFluid(L)) .output(LASER_PIPES[1]) - .cleanroom(CleanroomType.CLEANROOM) - .stationResearch(s -> s.researchStack(LASER_REFLECTOR.getStackForm()).EUt(VA[ZPM]).CWUt(32)) - .duration(350).EUt(VA[ZPM]).buildAndRegister(); + .scannerResearch(b -> b.researchStack(new ItemStack(LASER_PIPES[0])) + .EUt(VA[IV])) + .duration(200).EUt(VA[LuV]).buildAndRegister(); } } diff --git a/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java b/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java index cdfbecd0e84..fb3b3173dc4 100644 --- a/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java +++ b/src/main/java/gregtech/loaders/recipe/MiscRecipeLoader.java @@ -507,21 +507,5 @@ public static void init() { .input(ring, Steel, 2) .output(STEEL_MINECART_WHEELS) .duration(60).EUt(20).buildAndRegister(); - - CHEMICAL_RECIPES.recipeBuilder() - .input(dust, Titanium) - .fluidInputs(Oxygen.getFluid(2000)) - .output(dust, TitaniumDioxide, 3) - .duration(100).EUt(60).buildAndRegister(); - - COMPRESSOR_RECIPES.recipeBuilder() - .input(dustSmall, SiliconDioxide) - .output(foil, SiliconDioxide) - .duration(200).EUt(1).buildAndRegister(); - - COMPRESSOR_RECIPES.recipeBuilder() - .input(dustSmall, TitaniumDioxide) - .output(foil, TitaniumDioxide) - .duration(200).EUt(1).buildAndRegister(); } } diff --git a/src/main/resources/assets/gregtech/models/item/metaitems/ultrasmooth_borosilicate_glass.json b/src/main/resources/assets/gregtech/models/item/metaitems/ultrasmooth_borosilicate_glass.json deleted file mode 100644 index 9dbdc65b105..00000000000 --- a/src/main/resources/assets/gregtech/models/item/metaitems/ultrasmooth_borosilicate_glass.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "item/generated", - "textures": { - "layer0": "gregtech:items/metaitems/ultrasmooth_borosilicate_glass" - } -} diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/laser_reflector.png b/src/main/resources/assets/gregtech/textures/items/metaitems/laser_reflector.png index d31178c3c636c42975830873f2aae83c98c29607..a5d80897d0e67b3036d86ade48575a8d82b840f7 100644 GIT binary patch delta 300 zcmV+{0n`4I0>%Q6BYy!6NklvIbSQ`^G)qyL+?*g+ z1sbUgwPYzue2*V-mi^0$q7b|+%jo;}q^a;yRZ`b=^eUWx0wF}uG>sTz#9ABO7#r_+ zOF~rKwyj*dPWrx=VHl#{!nq4~yd@z3$U@*aj^ZXK-uvKpnSY#%cYujG01(qBrIHQ7 z{FvprEV2aW43Mg5jrnXKT0Z?!GFcI-0iqh-h&i;8=lKrcqeu-H&`$tKHvr0_Jj$e8 z%0>u?Gi}ixZPM-rpb!ScpcohevQiB|?iesJ2eAV58wn(vej`-@)^Gd@z!b7B(z-`sfJw`qT zZQ;`sO-}=b7I?ZihFF|lJK36#S&_%(Y}Yj7h?1CA;bKv%)8Y#X9d~9P>bfs9>FgAb z&l3NyRL=Y0!frF=oqSSHxXSZ6zob5x@olg!To8AWTjRM6Lnp_c?_S?ORtM|4urM&B z#hDkT-J5qv-Pkz(rT5(?#{9`TcU_OHbaa{ZOPWDYS6CwX8fR7( t$HJQq*}5GkL>82-+sJlJK9@PHigC^K(6D;~Py0c>^K|udS?83{1OO>GT`d3r diff --git a/src/main/resources/assets/gregtech/textures/items/metaitems/ultrasmooth_borosilicate_glass.png b/src/main/resources/assets/gregtech/textures/items/metaitems/ultrasmooth_borosilicate_glass.png deleted file mode 100644 index df916b8685b05c322060752663d43309021de3a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 444 zcmV;t0YmPx$bV)=(R5(wiQ_V`lKoI^Wy-A-y(jY#71r=Hmv_3;T+VtJptNI9PP9jt`hG}1qGXt*=$ooS}Zt+WFa%(-)so~Ec)j>Y5;fRkcj|hpm%usCqb>@_A%t%{s}(6 zzi|Kj0DwU(Itgb7b-why zUjYFCLp+gqGG7=Im8=06hkV@bKu;&&dBK#+LxkiOj|fSupd(#ZApTv?wM;pPg&CMT zf>E5c)=-hgz`ro+D;BB%5*~qz1Z@!#rJ-M91m{5&pgIgVIT!MU#jbVwmSQ%`O8*rF z0?=x?Ca}fo%o41CG)>Lj$g&JNiV^rL6i7pZfNjr3`ktC4G$aEHB*Q9F82J6tdU+UL zjo5Aptz8dJUdS(Agl2OKSvG@;Vhk*MEyP7s!|M@?USf%#;qG{4jM`qHWvm Date: Mon, 9 Sep 2024 20:21:04 -0400 Subject: [PATCH 144/157] tooltip improvements and cleanup --- .../api/capability/IPropertyFluidFilter.java | 29 +++++-------------- .../pipenet/physical/block/PipeBlock.java | 2 +- .../gregtech/api/items/metaitem/MetaItem.java | 2 +- .../materials/FirstDegreeMaterials.java | 18 ++++++------ .../storage/MetaTileEntityDrum.java | 16 ++++------ .../properties/MaterialEnergyProperties.java | 8 +++-- .../properties/MaterialFluidProperties.java | 5 ++-- .../properties/MaterialItemProperties.java | 2 +- .../resources/assets/gregtech/lang/en_us.lang | 9 +++--- .../resources/assets/gregtech/lang/ja_jp.lang | 2 +- .../resources/assets/gregtech/lang/ru_ru.lang | 2 +- .../resources/assets/gregtech/lang/zh_cn.lang | 2 +- 12 files changed, 40 insertions(+), 57 deletions(-) diff --git a/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java b/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java index 2f1ad999eaf..17a671b58ad 100644 --- a/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java +++ b/src/main/java/gregtech/api/capability/IPropertyFluidFilter.java @@ -3,7 +3,6 @@ import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.AttributedFluid; import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.client.utils.TooltipHelper; import net.minecraft.client.resources.I18n; import net.minecraftforge.fluids.Fluid; @@ -70,27 +69,15 @@ default int getPriority() { /** * Append tooltips about containment info * - * @param tooltip the tooltip to append to - * @param showToolsInfo if the "hold shift" line should mention tool info - * @param showTemperatureInfo if the temperature information should be displayed + * @param tooltip the tooltip to append to */ - default void appendTooltips(@NotNull List tooltip, boolean showToolsInfo, boolean showTemperatureInfo) { - if (TooltipHelper.isShiftDown()) { - if (showTemperatureInfo) { - tooltip.add(I18n.format("gregtech.fluid_pipe.max_temperature", getMaxFluidTemperature())); - tooltip.add(I18n.format("gregtech.fluid_pipe.min_temperature", getMinFluidTemperature())); - } - if (isGasProof()) tooltip.add(I18n.format("gregtech.fluid_pipe.gas_proof")); - else tooltip.add(I18n.format("gregtech.fluid_pipe.not_gas_proof")); - if (isPlasmaProof()) tooltip.add(I18n.format("gregtech.fluid_pipe.plasma_proof")); - getContainedAttributes().forEach(a -> a.appendContainerTooltips(tooltip)); - } else if (isGasProof() || isPlasmaProof() || !getContainedAttributes().isEmpty()) { - if (showToolsInfo) { - tooltip.add(I18n.format("gregtech.tooltip.tool_fluid_hold_shift")); - } else { - tooltip.add(I18n.format("gregtech.tooltip.fluid_pipe_hold_shift")); - } - } + default void appendTooltips(@NotNull List tooltip) { + tooltip.add(I18n.format("gregtech.fluid_pipe.max_temperature", getMaxFluidTemperature())); + tooltip.add(I18n.format("gregtech.fluid_pipe.min_temperature", getMinFluidTemperature())); + if (isGasProof()) tooltip.add(I18n.format("gregtech.fluid_pipe.gas_proof")); + else tooltip.add(I18n.format("gregtech.fluid_pipe.not_gas_proof")); + if (isPlasmaProof()) tooltip.add(I18n.format("gregtech.fluid_pipe.plasma_proof")); + getContainedAttributes().forEach(a -> a.appendContainerTooltips(tooltip)); } /** diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index ae89c270dbf..b66bd683e1b 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -386,11 +386,11 @@ public static Collection getNodesForTile(PipeTileEntity tile) @Override public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn) { + getHandler(stack).addInformation(stack, worldIn, tooltip, flagIn, getStructure()); if (getStructure() instanceof IPipeChanneledStructure channeledStructure) { if (channeledStructure.getChannelCount() > 1) tooltip.add(I18n.format("gregtech.pipe.channels", channeledStructure.getChannelCount())); } - getHandler(stack).addInformation(stack, worldIn, tooltip, flagIn, getStructure()); if (TooltipHelper.isShiftDown()) { tooltip.add(I18n.format(getConnectLangKey())); tooltip.add(I18n.format("gregtech.tool_action.screwdriver.access_covers")); diff --git a/src/main/java/gregtech/api/items/metaitem/MetaItem.java b/src/main/java/gregtech/api/items/metaitem/MetaItem.java index a17559b05b2..12a715fd7e2 100644 --- a/src/main/java/gregtech/api/items/metaitem/MetaItem.java +++ b/src/main/java/gregtech/api/items/metaitem/MetaItem.java @@ -641,7 +641,7 @@ public void addInformation(@NotNull ItemStack itemStack, @Nullable World worldIn if (fluidHandler instanceof IFilteredFluidContainer filtered && filtered.getFilter() instanceof IPropertyFluidFilter propertyFilter) { - propertyFilter.appendTooltips(lines, false, true); + propertyFilter.appendTooltips(lines); } } diff --git a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java index f457551a10e..614f772b8ff 100644 --- a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java @@ -1341,7 +1341,7 @@ public static void register() { .color(0xE1B454).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Manganese, 1, Phosphorus, 1) - .cableProperties(GTValues.V[GTValues.LV], 2, GTValues.V[GTValues.ULV], 500) + .cableProperties(GTValues.V[GTValues.LV], 2, GTValues.V[GTValues.ULV], Integer.MAX_VALUE) .blast(1200, GasTier.LOW) .build(); @@ -1351,7 +1351,7 @@ public static void register() { .color(0x331900).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Magnesium, 1, Boron, 2) - .cableProperties(GTValues.V[GTValues.MV], 4, GTValues.V[GTValues.LV], 500) + .cableProperties(GTValues.V[GTValues.MV], 4, GTValues.V[GTValues.LV], Integer.MAX_VALUE) .blast(b -> b .temp(2500, GasTier.LOW) .blastStats(VA[HV], 1000) @@ -1364,7 +1364,7 @@ public static void register() { .color(0x555555).iconSet(SHINY) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Mercury, 1, Barium, 2, Calcium, 2, Copper, 3, Oxygen, 8) - .cableProperties(GTValues.V[GTValues.HV], 4, GTValues.V[GTValues.MV], 500) + .cableProperties(GTValues.V[GTValues.HV], 4, GTValues.V[GTValues.MV], Integer.MAX_VALUE) .blast(b -> b .temp(3300, GasTier.LOW) .blastStats(VA[HV], 1500) @@ -1377,7 +1377,7 @@ public static void register() { .color(0x008700).iconSet(SHINY) .flags(DECOMPOSITION_BY_CENTRIFUGING) .components(Uranium, 1, Platinum, 3) - .cableProperties(GTValues.V[GTValues.EV], 6, GTValues.V[GTValues.HV], 500) + .cableProperties(GTValues.V[GTValues.EV], 6, GTValues.V[GTValues.HV], Integer.MAX_VALUE) .blast(b -> b .temp(4400, GasTier.MID) .blastStats(VA[EV], 1000) @@ -1390,7 +1390,7 @@ public static void register() { .color(0x330033).iconSet(SHINY) .flags(DECOMPOSITION_BY_CENTRIFUGING) .components(Samarium, 1, Iron, 1, Arsenic, 1, Oxygen, 1) - .cableProperties(GTValues.V[GTValues.IV], 6, GTValues.V[GTValues.EV], 500) + .cableProperties(GTValues.V[GTValues.IV], 6, GTValues.V[GTValues.EV], Integer.MAX_VALUE) .blast(b -> b .temp(5200, GasTier.MID) .blastStats(VA[EV], 1500) @@ -1403,7 +1403,7 @@ public static void register() { .color(0x994C00).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING, GENERATE_FINE_WIRE) .components(Indium, 4, Tin, 2, Barium, 2, Titanium, 1, Copper, 7, Oxygen, 14) - .cableProperties(GTValues.V[GTValues.LuV], 8, GTValues.V[GTValues.IV], 500) + .cableProperties(GTValues.V[GTValues.LuV], 8, GTValues.V[GTValues.IV], Integer.MAX_VALUE) .blast(b -> b .temp(6000, GasTier.HIGH) .blastStats(VA[IV], 1000) @@ -1416,7 +1416,7 @@ public static void register() { .color(0x0A0A0A) .flags(DECOMPOSITION_BY_CENTRIFUGING, GENERATE_FINE_WIRE) .components(Uranium, 1, Rhodium, 1, Naquadah, 2) - .cableProperties(GTValues.V[GTValues.ZPM], 8, GTValues.V[LuV], 500) + .cableProperties(GTValues.V[GTValues.ZPM], 8, GTValues.V[LuV], Integer.MAX_VALUE) .blast(b -> b .temp(9000, GasTier.HIGH) .blastStats(VA[IV], 1500) @@ -1430,7 +1430,7 @@ public static void register() { .color(0x7D9673).iconSet(METALLIC) .flags(DECOMPOSITION_BY_CENTRIFUGING, GENERATE_FINE_WIRE) .components(NaquadahEnriched, 4, Trinium, 3, Europium, 2, Duranium, 1) - .cableProperties(GTValues.V[GTValues.UV], 16, GTValues.V[GTValues.ZPM], 500) + .cableProperties(GTValues.V[GTValues.UV], 16, GTValues.V[GTValues.ZPM], Integer.MAX_VALUE) .blast(b -> b .temp(9900, GasTier.HIGH) .blastStats(VA[LuV], 1200) @@ -1444,7 +1444,7 @@ public static void register() { .color(0xFFFFFF).iconSet(BRIGHT) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Ruthenium, 1, Trinium, 2, Americium, 1, Neutronium, 2, Oxygen, 8) - .cableProperties(GTValues.V[GTValues.UHV], 24, GTValues.V[GTValues.UV], 500) + .cableProperties(GTValues.V[GTValues.UHV], 24, GTValues.V[GTValues.UV], Integer.MAX_VALUE) .blast(b -> b .temp(10800, GasTier.HIGHER) .blastStats(VA[ZPM], 1000) diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java index e5c5ec252ad..431fbb81347 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityDrum.java @@ -11,7 +11,6 @@ import gregtech.api.unification.material.properties.PropertyKey; import gregtech.api.util.GTUtility; import gregtech.client.renderer.texture.Textures; -import gregtech.client.utils.TooltipHelper; import gregtech.common.pipelike.handlers.properties.MaterialFluidProperties; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -278,13 +277,7 @@ public int getDefaultPaintingColor() { @SideOnly(Side.CLIENT) public void addInformation(ItemStack stack, @Nullable World player, List tooltip, boolean advanced) { tooltip.add(I18n.format("gregtech.universal.tooltip.fluid_storage_capacity", tankSize)); - this.fluidFilter.appendTooltips(tooltip, true, true); - - if (TooltipHelper.isShiftDown()) { - tooltip.add(I18n.format("gregtech.tool_action.screwdriver.access_covers")); - tooltip.add(I18n.format("gregtech.tool_action.screwdriver.auto_output_down")); - tooltip.add(I18n.format("gregtech.tool_action.crowbar")); - } + this.fluidFilter.appendTooltips(tooltip); NBTTagCompound tagCompound = stack.getTagCompound(); if (tagCompound != null && tagCompound.hasKey("Fluid", Constants.NBT.TAG_COMPOUND)) { @@ -295,10 +288,11 @@ public void addInformation(ItemStack stack, @Nullable World player, List } } - // Override this so that we can control the "Hold SHIFT" tooltip manually @Override - public boolean showToolUsages() { - return false; + public void addToolUsages(ItemStack stack, @Nullable World world, List tooltip, boolean advanced) { + tooltip.add(I18n.format("gregtech.tool_action.screwdriver.access_covers")); + tooltip.add(I18n.format("gregtech.tool_action.screwdriver.auto_output_down")); + tooltip.add(I18n.format("gregtech.tool_action.crowbar")); } @Override diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index bf2b3825119..9b20e0e3960 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -116,9 +116,13 @@ public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull Lis tooltip.add(I18n.format("gregtech.cable.superconductor", GTValues.VN[tier])); tooltip.add(I18n.format("gregtech.cable.voltage", voltageLimit, GTValues.VNF[tier])); tooltip.add(I18n.format("gregtech.cable.amperage", getAmperage(structure))); - tooltip.add(I18n.format("gregtech.cable.loss_per_block", getLoss(structure))); - if (isSuperconductor()) + + long loss = isSuperconductor() && superconductorCriticalTemperature == Integer.MAX_VALUE ? 0 : + getLoss(structure); + tooltip.add(I18n.format("gregtech.cable.loss_per_block", loss)); + if (isSuperconductor() && superconductorCriticalTemperature != Integer.MAX_VALUE) { tooltip.add(I18n.format("gregtech.cable.superconductor_loss", superconductorCriticalTemperature)); + } } @Override diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index 91c99c55a6b..c71d820b373 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -152,10 +152,9 @@ public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull Lis @NotNull ITooltipFlag flagIn, IPipeMaterialStructure structure) { tooltip.add(I18n.format("gregtech.fluid_pipe")); tooltip.add(I18n.format("gregtech.universal.tooltip.fluid_transfer_rate", getThroughput(structure))); - tooltip.add(I18n.format("gregtech.fluid_pipe.max_temperature", getMaxFluidTemperature())); - tooltip.add(I18n.format("gregtech.fluid_pipe.min_temperature", getMinFluidTemperature())); - tooltip.add(I18n.format("gregtech.fluid_pipe.priority", + tooltip.add(I18n.format("gregtech.pipe.priority", TextFormattingUtil.formatNumbers(getFlowPriority(structure)))); + appendTooltips(tooltip); } @Override diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index d301ae68e71..f9d0dac25b7 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -58,7 +58,7 @@ public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull Lis tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate_stacks", baseItemsPer5Ticks / 16)); } - tooltip.add(I18n.format("gregtech.item_pipe.priority", + tooltip.add(I18n.format("gregtech.pipe.priority", TextFormattingUtil.formatNumbers(getFlowPriority(structure)))); } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 58eb43fdd99..2ba1def719c 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -5589,12 +5589,13 @@ gregtech.item_filter.footer=§eClick with item to override gregtech.cable.voltage=§aMax Voltage: §f%,d §f(%s§f) gregtech.cable.amperage=§eMax Amperage: §f%,d gregtech.cable.loss_per_block=§cLoss/Meter/Ampere: §f%,d§f EU-Volt -gregtech.cable.superconductor_loss=§cLoss is set to §f0§c under critical temperature §f%,d§f K +gregtech.cable.superconductor_loss=§cLoss is §f0§c under critical temperature §f%,d§f K gregtech.cable.superconductor=§d%s Superconductor -gregtech.fluid_pipe.max_temperature=§cTemperature Limit: §f%,d K -gregtech.fluid_pipe.min_temperature=§6Can handle fluids at or above §f%,d K +gregtech.fluid_pipe.max_temperature=§cMax Temperature: §f%,d K +gregtech.fluid_pipe.min_temperature=§bMin Temperature: §f%,d K gregtech.pipe.channels=§eChannels: §f%d +gregtech.pipe.priority=§9Priority: §f%s gregtech.fluid_pipe.gas_proof=§6Can handle Gases gregtech.fluid_pipe.acid_proof=§6Can handle Acids gregtech.fluid_pipe.plasma_proof=§6Can handle all Plasmas @@ -5602,8 +5603,6 @@ gregtech.fluid_pipe.not_gas_proof=§4Gases may leak! gregtech.fluid_pipe=§dFluid Pipe gregtech.item_pipe=§dItem Pipe -gregtech.fluid_pipe.priority=§9Priority: §f%s -gregtech.item_pipe.priority=§9Priority: §f%s gregtech.multiblock.work_paused=Work Paused. gregtech.multiblock.running=Running perfectly. diff --git a/src/main/resources/assets/gregtech/lang/ja_jp.lang b/src/main/resources/assets/gregtech/lang/ja_jp.lang index e4024638d3f..f2031f3ea7b 100644 --- a/src/main/resources/assets/gregtech/lang/ja_jp.lang +++ b/src/main/resources/assets/gregtech/lang/ja_jp.lang @@ -5505,7 +5505,7 @@ gregtech.fluid_pipe.cryo_proof=§6極低温の液体を運搬可能 gregtech.fluid_pipe.plasma_proof=§6全てのプラズマを運搬可能 gregtech.fluid_pipe.not_gas_proof=§4気体を密封できない! -gregtech.item_pipe.priority=§9優先度: %d +gregtech.pipe.priority=§9優先度: %d gregtech.multiblock.work_paused=一時停止中 gregtech.multiblock.running=完璧に動作中 diff --git a/src/main/resources/assets/gregtech/lang/ru_ru.lang b/src/main/resources/assets/gregtech/lang/ru_ru.lang index f8bfe1a7604..1a6d1cc4cb1 100644 --- a/src/main/resources/assets/gregtech/lang/ru_ru.lang +++ b/src/main/resources/assets/gregtech/lang/ru_ru.lang @@ -4910,7 +4910,7 @@ gregtech.fluid_pipe.gas_proof=§6Может хранить газы gregtech.fluid_pipe.acid_proof=§6Может хранить кислоты gregtech.fluid_pipe.cryo_proof=§6Может хранить криогенику gregtech.fluid_pipe.not_gas_proof=§4Возможна утечка газов! -gregtech.item_pipe.priority=§9Приоритет: §f%,d +gregtech.pipe.priority=§9Приоритет: §f%,d gregtech.multiblock.work_paused=Работа приостановлена. gregtech.multiblock.running=Работает отлично. gregtech.multiblock.idling=Холостой ход. diff --git a/src/main/resources/assets/gregtech/lang/zh_cn.lang b/src/main/resources/assets/gregtech/lang/zh_cn.lang index fb68f3d3bf2..8f5418c7ff7 100644 --- a/src/main/resources/assets/gregtech/lang/zh_cn.lang +++ b/src/main/resources/assets/gregtech/lang/zh_cn.lang @@ -5577,7 +5577,7 @@ gregtech.fluid_pipe.cryo_proof=§6可传输低温物质 gregtech.fluid_pipe.plasma_proof=§6可传输所有等离子体 gregtech.fluid_pipe.not_gas_proof=§4气体可能泄漏! -gregtech.item_pipe.priority=§9优先级:§f%,d +gregtech.pipe.priority=§9优先级:§f%,d gregtech.multiblock.work_paused=暂停。 gregtech.multiblock.running=运行正常。 From 659162ac05e6d93a4704ed4e8aecadb9667bfdde Mon Sep 17 00:00:00 2001 From: M-W-K Date: Tue, 10 Sep 2024 15:59:02 -0600 Subject: [PATCH 145/157] Logic types & event-driven registration --- .../java/gregtech/api/graphnet/IGraphNet.java | 2 +- .../api/graphnet/MultiNodeHelper.java | 4 +- .../graphnet/edge/AbstractNetFlowEdge.java | 4 +- .../logic/AbstractDoubleLogicData.java | 31 +++- .../graphnet/logic/AbstractIntLogicData.java | 31 +++- .../graphnet/logic/AbstractLongLogicData.java | 31 +++- .../logic/AbstractTransientLogicData.java | 5 - .../api/graphnet/logic/ChannelCountLogic.java | 13 +- .../graphnet/logic/MultiNetCountLogic.java | 24 --- .../api/graphnet/logic/NetLogicData.java | 124 +++++++-------- .../api/graphnet/logic/NetLogicEntry.java | 17 +- .../logic/NetLogicRegistrationEvent.java | 22 +++ .../api/graphnet/logic/NetLogicRegistry.java | 84 ++++++++-- .../api/graphnet/logic/NetLogicType.java | 47 ++++++ .../api/graphnet/logic/ThroughputLogic.java | 13 +- .../api/graphnet/logic/WeightFactorLogic.java | 15 +- .../graphnet/path/GenericGraphNetPath.java | 2 +- .../pipenet/BasicWorldPipeNetPath.java | 2 +- .../pipenet/FlowWorldPipeNetPath.java | 2 +- .../api/graphnet/pipenet/WorldPipeNet.java | 5 +- .../logic/EdgeCoverReferenceLogic.java | 146 ------------------ .../pipenet/logic/TemperatureLogic.java | 84 +++++----- .../PipeStructureRegistrationEvent.java | 25 +++ .../physical/PipeStructureRegistry.java | 24 ++- .../pipenet/physical/tile/PipeTileEntity.java | 37 ++--- .../pipenet/predicate/BlockedPredicate.java | 14 +- .../pipenet/predicate/FilterPredicate.java | 15 +- .../api/graphnet/predicate/EdgePredicate.java | 18 +-- .../predicate/EdgePredicateHandler.java | 36 ++--- .../NetPredicateRegistrationEvent.java | 22 +++ .../predicate/NetPredicateRegistry.java | 84 ++++++++-- .../graphnet/predicate/NetPredicateType.java | 47 ++++++ .../api/graphnet/servernet/ServerNet.java | 4 +- .../api/graphnet/worldnet/WorldNet.java | 4 +- .../java/gregtech/api/util/GTUtility.java | 2 +- .../java/gregtech/common/CommonProxy.java | 49 ++++++ .../items/behaviors/TricorderBehavior.java | 2 +- .../pipelike/block/cable/CableBlock.java | 4 +- .../pipelike/block/cable/CableStructure.java | 29 ++-- .../pipelike/block/laser/LaserStructure.java | 15 +- .../block/optical/OpticalStructure.java | 13 +- .../block/pipe/MaterialPipeStructure.java | 31 ++-- .../properties/MaterialEnergyProperties.java | 28 ++-- .../properties/MaterialFluidProperties.java | 12 +- .../properties/MaterialItemProperties.java | 6 +- .../net/energy/EnergyCapabilityObject.java | 4 +- .../pipelike/net/energy/EnergyFlowLogic.java | 15 +- .../net/energy/EnergyTraverseData.java | 16 +- .../net/energy/SuperconductorLogic.java | 14 +- .../net/energy/VoltageLimitLogic.java | 12 +- .../pipelike/net/energy/VoltageLossLogic.java | 14 +- .../net/fluid/FluidCapabilityObject.java | 2 +- .../net/fluid/FluidContainmentLogic.java | 48 +++--- .../pipelike/net/fluid/FluidFlowLogic.java | 15 +- .../pipelike/net/fluid/FluidTraverseData.java | 12 +- .../pipelike/net/fluid/WorldFluidNet.java | 10 +- .../pipelike/net/item/ItemFlowLogic.java | 15 +- .../pipelike/net/item/ItemTraverseData.java | 4 +- .../pipelike/net/item/WorldItemNet.java | 10 +- src/main/java/gregtech/core/CoreModule.java | 1 + .../provider/PipeTileInfoProvider.java | 6 +- .../resources/assets/gregtech/lang/en_us.lang | 2 + 62 files changed, 793 insertions(+), 636 deletions(-) delete mode 100644 src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/NetLogicRegistrationEvent.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/NetLogicType.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistrationEvent.java create mode 100644 src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistrationEvent.java create mode 100644 src/main/java/gregtech/api/graphnet/predicate/NetPredicateType.java diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index 42f9dd65d2b..c8d58446a9d 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -125,7 +125,7 @@ default AbstractGroupData getBlankGroupData() { */ @NotNull default NetLogicData getDefaultNodeData() { - return new NetLogicData().setLogicEntry(WeightFactorLogic.INSTANCE.getWith(1)); + return new NetLogicData().setLogicEntry(WeightFactorLogic.TYPE.getWith(1)); } /** diff --git a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java index c0c32ed78f9..7db90c646ad 100644 --- a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java +++ b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java @@ -66,7 +66,7 @@ public void addNode(@NotNull NetNode node) { List> toSet = new ObjectArrayList<>(); for (NetLogicEntry entry : node.getData().getEntries()) { if (entry.mergedToMultiNodeHelper()) { - NetLogicEntry existing = mergedData.getLogicEntryNullable(entry); + NetLogicEntry existing = mergedData.getLogicEntryNullable(entry.getType()); if (existing != null) { existing.merge(node, entry); // don't put it into the data yet because we're currently iterating through the data's entries. @@ -114,7 +114,7 @@ public void markChanged(NetLogicEntry updatedEntry, boolean removed, boole if (!fullChange || !updatedEntry.mergedToMultiNodeHelper()) return; NetNode node = nodeRef.get(); if (node == null) return; - NetLogicEntry existing = mergedData.getLogicEntryNullable(updatedEntry); + NetLogicEntry existing = mergedData.getLogicEntryNullable(updatedEntry.getType()); if (removed) { if (existing != null) mergedData.removeLogicEntry(existing); } else { diff --git a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java index f0385f11d16..1ea0158b368 100644 --- a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java @@ -50,11 +50,11 @@ protected AbstractChannelsHolder getChannels(@Nullable SimulatorKey simulator) { } protected int getChannelCount() { - return getData().getLogicEntryDefaultable(ChannelCountLogic.INSTANCE).getValue(); + return getData().getLogicEntryDefaultable(ChannelCountLogic.TYPE).getValue(); } public long getThroughput() { - return getData().getLogicEntryDefaultable(ThroughputLogic.INSTANCE).getValue(); + return getData().getLogicEntryDefaultable(ThroughputLogic.TYPE).getValue(); } public long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick, diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java index 68785c1516d..9633ad7e13e 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractDoubleLogicData.java @@ -2,20 +2,21 @@ import net.minecraft.nbt.NBTTagDouble; import net.minecraft.network.PacketBuffer; +import net.minecraft.util.ResourceLocation; import org.jetbrains.annotations.NotNull; +import java.util.function.Supplier; + public abstract class AbstractDoubleLogicData> extends NetLogicEntry { private double value; - protected AbstractDoubleLogicData(@NotNull String name) { - super(name); - } + protected AbstractDoubleLogicData() {} - public T getWith(double value) { - return getNew().setValue(value); + protected AbstractDoubleLogicData(double init) { + this.value = init; } protected T setValue(double value) { @@ -46,4 +47,24 @@ public void encode(PacketBuffer buf, boolean fullChange) { public void decode(PacketBuffer buf, boolean fullChange) { this.value = buf.readDouble(); } + + @Override + public abstract @NotNull DoubleLogicType getType(); + + public static class DoubleLogicType> extends NetLogicType { + + public DoubleLogicType(@NotNull ResourceLocation name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + super(name, supplier, defaultable); + } + + public DoubleLogicType(@NotNull String namespace, @NotNull String name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + super(namespace, name, supplier, defaultable); + } + + public T getWith(double value) { + return getNew().setValue(value); + } + } } diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java index d71c8e00b54..57f793f0944 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractIntLogicData.java @@ -2,19 +2,20 @@ import net.minecraft.nbt.NBTTagInt; import net.minecraft.network.PacketBuffer; +import net.minecraft.util.ResourceLocation; import org.jetbrains.annotations.NotNull; +import java.util.function.Supplier; + public abstract class AbstractIntLogicData> extends NetLogicEntry { private int value; - protected AbstractIntLogicData(@NotNull String name) { - super(name); - } + protected AbstractIntLogicData() {} - public T getWith(int value) { - return getNew().setValue(value); + protected AbstractIntLogicData(int init) { + this.value = init; } protected T setValue(int value) { @@ -45,4 +46,24 @@ public void encode(PacketBuffer buf, boolean fullChange) { public void decode(PacketBuffer buf, boolean fullChange) { this.value = buf.readVarInt(); } + + @Override + public abstract @NotNull IntLogicType getType(); + + public static class IntLogicType> extends NetLogicType { + + public IntLogicType(@NotNull ResourceLocation name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + super(name, supplier, defaultable); + } + + public IntLogicType(@NotNull String namespace, @NotNull String name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + super(namespace, name, supplier, defaultable); + } + + public T getWith(int value) { + return getNew().setValue(value); + } + } } diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java index 07773f1a978..4f241937a92 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractLongLogicData.java @@ -2,22 +2,17 @@ import net.minecraft.nbt.NBTTagLong; import net.minecraft.network.PacketBuffer; +import net.minecraft.util.ResourceLocation; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import java.util.function.Supplier; + public abstract class AbstractLongLogicData> extends NetLogicEntry { private long value; - protected AbstractLongLogicData(@NotNull String name) { - super(name); - } - - public T getWith(long value) { - return getNew().setValue(value); - } - @Contract("_ -> this") public T setValue(long value) { this.value = value; @@ -47,4 +42,24 @@ public void encode(PacketBuffer buf, boolean fullChange) { public void decode(PacketBuffer buf, boolean fullChange) { this.value = buf.readVarLong(); } + + @Override + public abstract @NotNull LongLogicType getType(); + + public static class LongLogicType> extends NetLogicType { + + public LongLogicType(@NotNull ResourceLocation name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + super(name, supplier, defaultable); + } + + public LongLogicType(@NotNull String namespace, @NotNull String name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + super(namespace, name, supplier, defaultable); + } + + public T getWith(long value) { + return getNew().setValue(value); + } + } } diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractTransientLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractTransientLogicData.java index 16ff72a13f2..392409d8c5a 100644 --- a/src/main/java/gregtech/api/graphnet/logic/AbstractTransientLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractTransientLogicData.java @@ -3,16 +3,11 @@ import net.minecraft.nbt.NBTBase; import net.minecraft.network.PacketBuffer; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public abstract class AbstractTransientLogicData> extends NetLogicEntry { - protected AbstractTransientLogicData(@NotNull String name) { - super(name); - } - @Override public final void deserializeNBT(NBTBase nbt) {} diff --git a/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java b/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java index 65420e09c84..c3f1a1280f2 100644 --- a/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/ChannelCountLogic.java @@ -1,18 +1,17 @@ package gregtech.api.graphnet.logic; +import gregtech.api.GTValues; + import org.jetbrains.annotations.NotNull; public final class ChannelCountLogic extends AbstractIntLogicData { - public static final ChannelCountLogic INSTANCE = new ChannelCountLogic().setValue(1); - - public ChannelCountLogic() { - super("ChannelCount"); - } + public static final IntLogicType TYPE = new IntLogicType<>(GTValues.MODID, "ChannelCount", + ChannelCountLogic::new, new ChannelCountLogic().setValue(1)); @Override - public @NotNull ChannelCountLogic getNew() { - return new ChannelCountLogic(); + public @NotNull IntLogicType getType() { + return TYPE; } @Override diff --git a/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java b/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java deleted file mode 100644 index ec0d40cc1a2..00000000000 --- a/src/main/java/gregtech/api/graphnet/logic/MultiNetCountLogic.java +++ /dev/null @@ -1,24 +0,0 @@ -package gregtech.api.graphnet.logic; - -import org.jetbrains.annotations.NotNull; - -public final class MultiNetCountLogic extends AbstractIntLogicData { - - public static final MultiNetCountLogic INSTANCE = new MultiNetCountLogic().setValue(1); - - public MultiNetCountLogic() { - super("MultiNetCount"); - } - - @Override - public @NotNull MultiNetCountLogic getNew() { - return new MultiNetCountLogic(); - } - - @Override - public MultiNetCountLogic union(NetLogicEntry other) { - if (other instanceof MultiNetCountLogic l) { - return this.getValue() < l.getValue() ? this : l; - } else return this; - } -} diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java index 45ea851cbee..36523ee2581 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicData.java @@ -7,7 +7,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.network.PacketBuffer; -import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -16,14 +15,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -/** - * Note - since the internal map representation encodes keys using {@link IStringSerializable#getName()} on logics, - * making a logics class return two different names is a valid way to register multiple instances. - */ public final class NetLogicData implements INBTSerializable, IPacket, INetLogicEntryListener { - // TODO caching logic on simple logics to reduce amount of reduntant creation? - private final Object2ObjectOpenHashMap> logicEntrySet; + private final Object2ObjectOpenHashMap, NetLogicEntry> logicEntrySet; private final WeakHashSet listeners = new WeakHashSet<>(); @@ -31,7 +25,7 @@ public NetLogicData() { logicEntrySet = new Object2ObjectOpenHashMap<>(4); } - private NetLogicData(Object2ObjectOpenHashMap> logicEntrySet) { + private NetLogicData(Object2ObjectOpenHashMap, NetLogicEntry> logicEntrySet) { this.logicEntrySet = logicEntrySet; } @@ -40,7 +34,7 @@ private NetLogicData(Object2ObjectOpenHashMap> logic * nothing happens if an entry is already present. */ public NetLogicData mergeLogicEntry(NetLogicEntry entry) { - NetLogicEntry current = logicEntrySet.get(entry.getName()); + NetLogicEntry current = logicEntrySet.get(entry.getType()); if (current == null) return setLogicEntry(entry); if (entry.getClass().isInstance(current)) { @@ -52,7 +46,7 @@ public NetLogicData mergeLogicEntry(NetLogicEntry entry) { public NetLogicData setLogicEntry(NetLogicEntry entry) { entry.registerToNetLogicData(this); - logicEntrySet.put(entry.getName(), entry); + logicEntrySet.put(entry.getType(), entry); this.markLogicEntryAsUpdated(entry, true); return this; } @@ -69,12 +63,12 @@ public void clearData() { logicEntrySet.trim(4); } - public NetLogicData removeLogicEntry(@NotNull NetLogicEntry key) { - return removeLogicEntry(key.getName()); + public NetLogicData removeLogicEntry(@NotNull NetLogicEntry entry) { + return removeLogicEntry(entry.getType()); } - public NetLogicData removeLogicEntry(@NotNull String key) { - NetLogicEntry entry = logicEntrySet.remove(key); + public NetLogicData removeLogicEntry(@NotNull NetLogicType type) { + NetLogicEntry entry = logicEntrySet.remove(type); if (entry != null) { entry.deregisterFromNetLogicData(this); this.listeners.forEach(l -> l.markChanged(entry, true, true)); @@ -88,36 +82,18 @@ public void markLogicEntryAsUpdated(NetLogicEntry entry, boolean fullChang this.listeners.forEach(l -> l.markChanged(entry, false, fullChange)); } - public boolean hasLogicEntry(@NotNull String key) { - return logicEntrySet.containsKey(key); - } - - public boolean hasLogicEntry(@NotNull NetLogicEntry key) { - return logicEntrySet.containsKey(key.getName()); + public boolean hasLogicEntry(@NotNull NetLogicType type) { + return logicEntrySet.containsKey(type); } @Nullable - public NetLogicEntry getLogicEntryNullable(@NotNull String key) { - return logicEntrySet.get(key); - } - - @Nullable - public > T getLogicEntryNullable(@NotNull T key) { - try { - return (T) logicEntrySet.get(key.getName()); - } catch (ClassCastException ignored) { - return null; - } + public > T getLogicEntryNullable(@NotNull NetLogicType type) { + return type.cast(logicEntrySet.get(type)); } @NotNull - public > T getLogicEntryDefaultable(@NotNull T key) { - try { - T returnable = (T) logicEntrySet.get(key.getName()); - return returnable == null ? key : returnable; - } catch (ClassCastException ignored) { - return key; - } + public > T getLogicEntryDefaultable(@NotNull NetLogicType type) { + return type.cast(logicEntrySet.getOrDefault(type, type.getDefault())); } @Contract("null, null -> null; !null, _ -> new; _, !null -> new") @@ -129,10 +105,10 @@ public boolean hasLogicEntry(@NotNull NetLogicEntry key) { @Contract("_, _ -> new") public static @NotNull NetLogicData union(@NotNull NetLogicData sourceData, @Nullable NetLogicData targetData) { - Object2ObjectOpenHashMap> newLogic = new Object2ObjectOpenHashMap<>( + Object2ObjectOpenHashMap, NetLogicEntry> newLogic = new Object2ObjectOpenHashMap<>( sourceData.logicEntrySet); if (targetData != null) { - for (String key : newLogic.keySet()) { + for (NetLogicType key : newLogic.keySet()) { newLogic.computeIfPresent(key, (k, v) -> v.union(targetData.logicEntrySet.get(k))); } targetData.logicEntrySet.forEach((key, value) -> newLogic.computeIfAbsent(key, k -> value.union(null))); @@ -142,10 +118,10 @@ public boolean hasLogicEntry(@NotNull NetLogicEntry key) { @Contract("_, _ -> new") public static @NotNull NetLogicData union(@NotNull NetLogicData first, @NotNull NetLogicData... others) { - Object2ObjectOpenHashMap> newLogic = new Object2ObjectOpenHashMap<>( + Object2ObjectOpenHashMap, NetLogicEntry> newLogic = new Object2ObjectOpenHashMap<>( first.logicEntrySet); for (NetLogicData other : others) { - for (String key : newLogic.keySet()) { + for (NetLogicType key : newLogic.keySet()) { newLogic.computeIfPresent(key, (k, v) -> v.union(other.logicEntrySet.get(k))); } other.logicEntrySet.forEach((key, value) -> newLogic.computeIfAbsent(key, k -> value.union(null))); @@ -160,7 +136,7 @@ public NBTTagList serializeNBT() { NBTBase nbt = entry.serializeNBT(); if (nbt == null) continue; NBTTagCompound tag = new NBTTagCompound(); - tag.setString("Name", entry.getName()); + tag.setString("Type", entry.getType().getName()); tag.setTag("Tag", nbt); list.appendTag(tag); } @@ -171,25 +147,24 @@ public NBTTagList serializeNBT() { public void deserializeNBT(NBTTagList nbt) { for (int i = 0; i < nbt.tagCount(); i++) { NBTTagCompound tag = nbt.getCompoundTagAt(i); - String key = tag.getString("Name"); - NetLogicEntry entry = this.logicEntrySet.get(key); - if (entry == null) entry = NetLogicRegistry.getSupplierNotNull(key).get(); - if (entry == null) continue; + NetLogicType type = NetLogicRegistry.getTypeNullable(tag.getString("Type")); + if (type == null) continue; + NetLogicEntry entry = this.logicEntrySet.get(type); + if (entry == null) entry = type.getNew(); entry.deserializeNBTNaive(tag.getTag("Tag")); - this.logicEntrySet.put(key, entry); + this.logicEntrySet.put(type, entry); } } @Override public void encode(PacketBuffer buf) { - buf.writeVarInt(getEntries().size()); + int count = 0; for (NetLogicEntry entry : getEntries()) { - if (entry.shouldEncode()) { - buf.writeString(entry.getName()); - entry.encode(buf, true); - } else { - buf.writeString(""); - } + if (entry.shouldEncode()) count++; + } + buf.writeVarInt(count); + for (NetLogicEntry entry : getEntries()) { + if (entry.shouldEncode()) writeEntry(buf, entry, true); } } @@ -198,16 +173,43 @@ public void decode(PacketBuffer buf) { this.logicEntrySet.clear(); int entryCount = buf.readVarInt(); for (int i = 0; i < entryCount; i++) { - String name = buf.readString(255); - if (name.equals("")) continue; - NetLogicEntry existing = NetLogicRegistry.getSupplierErroring(name).get(); - existing.registerToNetLogicData(this); - existing.decode(buf); - this.logicEntrySet.put(name, existing); + readEntry(buf); } this.logicEntrySet.trim(); } + public static void writeEntry(@NotNull PacketBuffer buf, @NotNull NetLogicEntry entry, boolean fullChange) { + buf.writeVarInt(NetLogicRegistry.getNetworkID(entry)); + buf.writeBoolean(fullChange); + entry.encode(buf, fullChange); + } + + /** + * @return the net logic entry decoded to. + */ + @Nullable + public NetLogicEntry readEntry(@NotNull PacketBuffer buf) { + int id = buf.readVarInt(); + boolean fullChange = buf.readBoolean(); + NetLogicType type = NetLogicRegistry.getType(id); + NetLogicEntry existing = this.getLogicEntryNullable(type); + boolean add = false; + if (existing == null) { + // never partially decode into a new entry + if (!fullChange) return null; + existing = type.getNew(); + add = true; + } + try { + existing.decode(buf, fullChange); + } catch (Exception ignored) { + NetLogicRegistry.throwDecodingError(); + } + // make sure to add after decoding, so we don't notify listeners with an empty logic entry + if (add) this.setLogicEntry(existing); + return existing; + } + /** * Adds a listener to a weak set which is then notified for as long as it is not collected by the garbage collector. * diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java index 78fd8f77fb5..83957c55068 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java @@ -7,7 +7,6 @@ import net.minecraft.nbt.NBTBase; import net.minecraft.network.PacketBuffer; -import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; import org.jetbrains.annotations.NotNull; @@ -18,19 +17,9 @@ * {@link #union(NetLogicEntry)} behavior. */ public abstract class NetLogicEntry, N extends NBTBase> - implements INBTSerializable, IStringSerializable, IPacket { + implements INBTSerializable, IPacket { - private final @NotNull String name; - - protected NetLogicEntry(@NotNull String name) { - this.name = name; - NetLogicRegistry.register(this); - } - - @Override - public final @NotNull String getName() { - return name; - } + public abstract @NotNull NetLogicType getType(); public void deserializeNBTNaive(@Nullable NBTBase nbt) { if (nbt != null) deserializeNBT((N) nbt); @@ -91,8 +80,6 @@ public void registerToNetLogicData(NetLogicData data) {} public void deregisterFromNetLogicData(NetLogicData data) {} - public abstract @NotNull T getNew(); - public T cast(NetLogicEntry entry) { return (T) entry; } diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistrationEvent.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistrationEvent.java new file mode 100644 index 00000000000..28409b6ee87 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistrationEvent.java @@ -0,0 +1,22 @@ +package gregtech.api.graphnet.logic; + +import net.minecraftforge.fml.common.eventhandler.Event; + +import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; + +import java.util.Comparator; + +public final class NetLogicRegistrationEvent extends Event { + + private final ObjectRBTreeSet> gather = new ObjectRBTreeSet<>( + Comparator.comparing(NetLogicType::getName)); + + public void accept(NetLogicType type) { + if (!gather.add(type)) + throw new IllegalStateException("Detected a name collision during Net Logic registration!"); + } + + ObjectRBTreeSet> getGather() { + return gather; + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java index 98dc76b57bf..ed07079e990 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java @@ -1,36 +1,90 @@ package gregtech.api.graphnet.logic; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.client.Minecraft; +import net.minecraft.util.IntIdentityHashBiMap; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.relauncher.Side; + +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Map; -import java.util.function.Supplier; +import java.util.Set; public final class NetLogicRegistry { - private static final Map>> REGISTRY = new Object2ObjectOpenHashMap<>(); + private static final Int2ObjectArrayMap> REGISTRY; + + private static final IntIdentityHashBiMap NAMES_TO_NETWORK_IDS; + + static { + NetLogicRegistrationEvent event = new NetLogicRegistrationEvent(); + MinecraftForge.EVENT_BUS.post(event); + Set> gather = event.getGather(); + NAMES_TO_NETWORK_IDS = new IntIdentityHashBiMap<>(gather.size()); + REGISTRY = new Int2ObjectArrayMap<>(gather.size()); + int id = 1; + for (NetLogicType type : gather) { + NAMES_TO_NETWORK_IDS.put(type.getName(), id); + REGISTRY.put(id, type); + id++; + } + } + + public static String getName(int networkID) { + return NAMES_TO_NETWORK_IDS.get(networkID); + } + + public static int getNetworkID(@NotNull String name) { + return NAMES_TO_NETWORK_IDS.getId(name); + } + + public static int getNetworkID(@NotNull NetLogicType type) { + return getNetworkID(type.getName()); + } + + public static int getNetworkID(@NotNull NetLogicEntry entry) { + return getNetworkID(entry.getType()); + } - static void register(NetLogicEntry entry) { - REGISTRY.putIfAbsent(entry.getName(), entry::getNew); + public static @Nullable NetLogicType getTypeNullable(int networkID) { + return REGISTRY.get(networkID); } - public static @Nullable Supplier<@NotNull NetLogicEntry> getSupplierNullable(String name) { - return REGISTRY.get(name); + public static @Nullable NetLogicType getTypeNullable(@NotNull String name) { + return getTypeNullable(getNetworkID(name)); } - public static @NotNull Supplier<@Nullable NetLogicEntry> getSupplierNotNull(String name) { - return REGISTRY.getOrDefault(name, () -> null); + public static @NotNull NetLogicType getType(int networkID) { + NetLogicType type = REGISTRY.get(networkID); + if (type == null) throwNonexistenceError(); + assert type != null; + return type; } - public static @NotNull Supplier<@NotNull NetLogicEntry> getSupplierErroring(String name) { - Supplier> supplier = REGISTRY.get(name); - if (supplier == null) throwNonexistenceError(); - return supplier; + public static @NotNull NetLogicType getType(@NotNull String name) { + return getType(getNetworkID(name)); } public static void throwNonexistenceError() { - throw new RuntimeException("Could not find a matching supplier for an encoded NetLogicEntry. " + + if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) disconnect(); + throw new RuntimeException("Could not find the type of an encoded NetLogicEntry. " + "This suggests that the server and client have different GT versions or modifications."); } + + public static void throwDecodingError() { + if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) disconnect(); + throw new RuntimeException("Failed to decode an encoded NetLogicEntry. " + + "This suggests that the server and client have different GT versions or modifications."); + } + + private static void disconnect() { + if (Minecraft.getMinecraft().getConnection() != null) + Minecraft.getMinecraft().getConnection() + .onDisconnect(new TextComponentTranslation("gregtech.universal.netlogicdisconnect")); + } + + private NetLogicRegistry() {} } diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicType.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicType.java new file mode 100644 index 00000000000..7c3c2363f46 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicType.java @@ -0,0 +1,47 @@ +package gregtech.api.graphnet.logic; + +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.ResourceLocation; + +import org.jetbrains.annotations.NotNull; + +import java.util.function.Supplier; + +public class NetLogicType> implements IStringSerializable { + + private final @NotNull String name; + private final @NotNull Supplier<@NotNull T> supplier; + private final @NotNull T defaultable; + + public NetLogicType(@NotNull ResourceLocation name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + this.name = name.toString(); + this.supplier = supplier; + this.defaultable = defaultable; + } + + public NetLogicType(@NotNull String namespace, @NotNull String name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + this.name = namespace + ":" + name; + this.supplier = supplier; + this.defaultable = defaultable; + } + + @SuppressWarnings("unchecked") + public T cast(NetLogicEntry entry) { + return (T) entry; + } + + public final @NotNull T getNew() { + return supplier.get(); + } + + public final @NotNull T getDefault() { + return defaultable; + } + + @Override + public final @NotNull String getName() { + return name; + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java b/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java index 6d6f47ce1a2..9ea1caa9c1d 100644 --- a/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/ThroughputLogic.java @@ -1,18 +1,17 @@ package gregtech.api.graphnet.logic; +import gregtech.api.GTValues; + import org.jetbrains.annotations.NotNull; public final class ThroughputLogic extends AbstractLongLogicData { - public static final ThroughputLogic INSTANCE = new ThroughputLogic().setValue(0); - - private ThroughputLogic() { - super("Throughput"); - } + public static final LongLogicType TYPE = new LongLogicType<>(GTValues.MODID, "Throughput", + ThroughputLogic::new, new ThroughputLogic()); @Override - public @NotNull ThroughputLogic getNew() { - return new ThroughputLogic(); + public @NotNull LongLogicType getType() { + return TYPE; } @Override diff --git a/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java index 7ebcfb12121..b2cdafb3d75 100644 --- a/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java @@ -1,24 +1,23 @@ package gregtech.api.graphnet.logic; +import gregtech.api.GTValues; + import org.jetbrains.annotations.NotNull; public final class WeightFactorLogic extends AbstractDoubleLogicData { - public static final WeightFactorLogic INSTANCE = new WeightFactorLogic().setValue(0.1d); - - private WeightFactorLogic() { - super("WeightFactor"); - } + public static final DoubleLogicType TYPE = new DoubleLogicType<>(GTValues.MODID, "WeightFactor", + WeightFactorLogic::new, new WeightFactorLogic().setValue(0.1)); @Override - public @NotNull WeightFactorLogic getNew() { - return new WeightFactorLogic(); + public @NotNull DoubleLogicType getType() { + return TYPE; } @Override public WeightFactorLogic union(NetLogicEntry other) { if (other instanceof WeightFactorLogic l) { - return getWith(this.getValue() + l.getValue()); + return TYPE.getWith(this.getValue() + l.getValue()); } else return this; } } diff --git a/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java b/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java index 86ffe4000ea..7d0088f58dc 100644 --- a/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java @@ -24,7 +24,7 @@ public class GenericGraphNetPath extends AbstractNetPath { public GenericGraphNetPath(GraphVertex vertex) { this(Collections.singletonList(vertex), Collections.emptyList(), - vertex.wrapped.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue()); + vertex.wrapped.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue()); } public GenericGraphNetPath(List vertices, List edges, double weight) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java index 833f0e65a7b..b310f8748d5 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java @@ -24,7 +24,7 @@ public class BasicWorldPipeNetPath extends AbstractNetPath vertices, List edges, double weight) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java index c583e24be02..67e35007938 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java @@ -24,7 +24,7 @@ public class FlowWorldPipeNetPath extends AbstractNetPath vertices, List edges, double weight) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 77941262d02..d11d5338d2e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -11,6 +11,7 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.pipenet.predicate.BlockedPredicate; import gregtech.api.graphnet.predicate.EdgePredicate; +import gregtech.api.graphnet.predicate.NetPredicateType; import gregtech.api.graphnet.worldnet.WorldPosNet; import gregtech.api.util.IDirtyNotifiable; import gregtech.api.util.reference.WeakHashSet; @@ -101,7 +102,7 @@ protected void updatePredicationInternal(@NotNull WorldPipeNetNode node, @NotNul protected boolean predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode source, @Nullable Cover coverSource, @NotNull WorldPipeNetNode target, @Nullable Cover coverTarget) { - Map> prevValue = new Object2ObjectOpenHashMap<>( + Map, EdgePredicate> prevValue = new Object2ObjectOpenHashMap<>( edge.getPredicateHandler().getPredicateSet()); edge.getPredicateHandler().clearPredicates(); coverPredication(edge, coverSource, coverTarget); @@ -134,7 +135,7 @@ protected boolean predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { if (a instanceof CoverShutter aS && aS.isWorkingEnabled() || b instanceof CoverShutter bS && bS.isWorkingEnabled()) { - edge.getPredicateHandler().setPredicate(BlockedPredicate.INSTANCE); + edge.getPredicateHandler().setPredicate(BlockedPredicate.TYPE.getNew()); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java deleted file mode 100644 index bba5d655887..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/EdgeCoverReferenceLogic.java +++ /dev/null @@ -1,146 +0,0 @@ -package gregtech.api.graphnet.pipenet.logic; - -import gregtech.api.cover.Cover; -import gregtech.api.graphnet.logic.NetLogicEntry; -import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.util.DimensionFacingPos; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.network.PacketBuffer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.common.DimensionManager; - -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.ref.WeakReference; - -public final class EdgeCoverReferenceLogic extends NetLogicEntry { - - public static final EdgeCoverReferenceLogic INSTANCE = new EdgeCoverReferenceLogic(); - - @Nullable - private WeakReference coverSource; - private DimensionFacingPos coverSourcePos; - @Nullable - private WeakReference coverTarget; - private DimensionFacingPos coverTargetPos; - - public EdgeCoverReferenceLogic() { - super("EdgeCoverReference"); - } - - @Contract("_,_ -> this") - public EdgeCoverReferenceLogic coverSource(@NotNull DimensionFacingPos pos, @NotNull Cover cover) { - this.coverSource = new WeakReference<>(cover); - this.coverSourcePos = pos; - return this; - } - - @Contract("_,_ -> this") - public EdgeCoverReferenceLogic coverTarget(@NotNull DimensionFacingPos pos, @NotNull Cover cover) { - this.coverTarget = new WeakReference<>(cover); - this.coverTargetPos = pos; - return this; - } - - private @Nullable Cover getSource() { - if (coverSource == null) return null; - Cover ref = coverSource.get(); - if (ref == null) { - World world = DimensionManager.getWorld(coverSourcePos.getDimension()); - if (world == null || !world.isBlockLoaded(coverSourcePos.getPos())) return null; - - TileEntity tile = world.getTileEntity(coverSourcePos.getPos()); - if (tile instanceof PipeTileEntity pipe) { - Cover cover = pipe.getCoverHolder().getCoverAtSide(coverSourcePos.getFacing()); - if (cover != null) { - this.coverSource = new WeakReference<>(cover); - return cover; - } else { - // the cover doesn't exist, which makes no sense since we have a reference to its location but - // whatever - this.coverSource = null; - return null; - } - } else { - // the pipe doesn't exist, which makes no sense since the edge holding us exists but whatever - this.coverSource = null; - return null; - } - } else { - return ref; - } - } - - private @Nullable Cover getTarget() { - if (coverTarget == null) return null; - Cover ref = coverTarget.get(); - if (ref == null) { - World world = DimensionManager.getWorld(coverTargetPos.getDimension()); - if (world == null || !world.isBlockLoaded(coverTargetPos.getPos())) return null; - - TileEntity tile = world.getTileEntity(coverTargetPos.getPos()); - if (tile instanceof PipeTileEntity pipe) { - Cover cover = pipe.getCoverHolder().getCoverAtSide(coverTargetPos.getFacing()); - if (cover != null) { - this.coverTarget = new WeakReference<>(cover); - return cover; - } else { - // the cover doesn't exist, which makes no sense since we have a reference to its location but - // whatever - this.coverTarget = null; - return null; - } - } else { - // the pipe doesn't exist, which makes no sense since the edge holding us exists but whatever - this.coverTarget = null; - return null; - } - } else { - return ref; - } - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tag = new NBTTagCompound(); - tag.setLong("SourcePos", coverSourcePos.getPos().toLong()); - tag.setByte("SourceFacing", (byte) coverSourcePos.getFacing().ordinal()); - tag.setInteger("SourceDim", coverSourcePos.getDimension()); - tag.setLong("TargetPos", coverTargetPos.getPos().toLong()); - tag.setByte("TargetFacing", (byte) coverTargetPos.getFacing().ordinal()); - tag.setInteger("TargetDim", coverTargetPos.getDimension()); - return tag; - } - - @Override - public void deserializeNBT(NBTTagCompound nbt) { - this.coverSourcePos = new DimensionFacingPos(BlockPos.fromLong(nbt.getLong("SourcePos")), - EnumFacing.VALUES[nbt.getByte("SourceFacing")], nbt.getInteger("SourceDim")); - this.coverSource = new WeakReference<>(null); - this.coverTargetPos = new DimensionFacingPos(BlockPos.fromLong(nbt.getLong("TargetPos")), - EnumFacing.VALUES[nbt.getByte("TargetFacing")], nbt.getInteger("TargetDim")); - this.coverTarget = coverSource; - } - - @Override - public @NotNull EdgeCoverReferenceLogic getNew() { - return new EdgeCoverReferenceLogic(); - } - - @Override - public boolean shouldEncode() { - return false; - } - - @Override - public void encode(PacketBuffer buf, boolean fullChange) {} - - @Override - public void decode(PacketBuffer buf, boolean fullChange) {} -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index 222d48ed0e7..e9a23fe0197 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -1,10 +1,12 @@ package gregtech.api.graphnet.pipenet.logic; +import gregtech.api.GTValues; import gregtech.api.graphnet.MultiNodeHelper; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.logic.INetLogicEntryListener; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; +import gregtech.api.graphnet.logic.NetLogicType; import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.IFreezable; @@ -26,7 +28,7 @@ public final class TemperatureLogic extends NetLogicEntry { - public static final TemperatureLogic INSTANCE = new TemperatureLogic(); + public static final TemperatureLogicType TYPE = new TemperatureLogicType(); public static final int DEFAULT_TEMPERATURE = 298; @@ -43,42 +45,9 @@ public final class TemperatureLogic extends NetLogicEntry this") @@ -337,4 +306,45 @@ public void decode(PacketBuffer buf, boolean fullChange) { else this.partialBurnTemperature = null; } } + + public static class TemperatureLogicType extends NetLogicType { + + public TemperatureLogicType() { + super(GTValues.MODID, "Temperature", TemperatureLogic::new, new TemperatureLogic()); + } + + public TemperatureLogic getWith(@NotNull TemperatureLossFunction temperatureRestorationFunction, + int temperatureMaximum) { + return getWith(temperatureRestorationFunction, temperatureMaximum, 1); + } + + public TemperatureLogic getWith(@NotNull TemperatureLossFunction temperatureRestorationFunction, + int temperatureMaximum, int temperatureMinimum) { + return getWith(temperatureRestorationFunction, temperatureMaximum, temperatureMinimum, 1000); + } + + public TemperatureLogic getWith(@NotNull TemperatureLossFunction temperatureRestorationFunction, + int temperatureMaximum, int temperatureMinimum, int thermalMass) { + return getWith(temperatureRestorationFunction, temperatureMaximum, temperatureMinimum, thermalMass, 0); + } + + public TemperatureLogic getWith(@NotNull TemperatureLossFunction temperatureRestorationFunction, + int temperatureMaximum, int temperatureMinimum, int thermalMass, + @Nullable Integer partialBurnTemperature) { + return getWith(temperatureRestorationFunction, temperatureMaximum, temperatureMinimum, thermalMass, + partialBurnTemperature, 0); + } + + public TemperatureLogic getWith(@NotNull TemperatureLossFunction temperatureRestorationFunction, + int temperatureMaximum, int temperatureMinimum, int thermalMass, + @Nullable Integer partialBurnTemperature, int functionPriority) { + return getNew() + .setRestorationFunction(temperatureRestorationFunction) + .setTemperatureMaximum(temperatureMaximum) + .setTemperatureMinimum(temperatureMinimum) + .setThermalMass(thermalMass) + .setPartialBurnTemperature(partialBurnTemperature) + .setFunctionPriority(functionPriority); + } + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistrationEvent.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistrationEvent.java new file mode 100644 index 00000000000..7dd084900f2 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistrationEvent.java @@ -0,0 +1,25 @@ +package gregtech.api.graphnet.pipenet.physical; + +import net.minecraftforge.fml.common.eventhandler.Event; + +import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.Set; + +public final class PipeStructureRegistrationEvent extends Event { + + private final Map, Set> registry = new Object2ObjectLinkedOpenHashMap<>(); + + public void register(@NotNull T structure) { + Set structures = (Set) registry.computeIfAbsent(structure.getClass(), + k -> new ObjectLinkedOpenHashSet<>()); + structures.add(structure); + } + + Map, Set> getRegistry() { + return registry; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java index d53fb8b11e8..3743ca0cca6 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/PipeStructureRegistry.java @@ -1,31 +1,25 @@ package gregtech.api.graphnet.pipenet.physical; -import gregtech.api.util.GTUtility; +import net.minecraftforge.common.MinecraftForge; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.UnmodifiableView; import java.util.Collections; import java.util.Map; import java.util.Set; -@SuppressWarnings("unchecked") public final class PipeStructureRegistry { - private static final Map, Set> REGISTRY = new Object2ObjectLinkedOpenHashMap<>(); + private static final Map, Set> REGISTRY = fireEvent(); - public static void register(@NotNull T structure) { - Set structures = (Set) REGISTRY.computeIfAbsent(structure.getClass(), - k -> new ObjectLinkedOpenHashSet<>()); - structures.add(structure); + public static @NotNull @UnmodifiableView Set getStructures(Class structureClass) { + return (Set) REGISTRY.getOrDefault(structureClass, Collections.emptySet()); } - /** - * Do not modify the returned set. - */ - public static @NotNull Set getStructures(Class structureClass) { - GTUtility.forceInitialization(structureClass); - return (Set) REGISTRY.getOrDefault(structureClass, Collections.emptySet()); + private static Map, Set> fireEvent() { + PipeStructureRegistrationEvent event = new PipeStructureRegistrationEvent(); + MinecraftForge.EVENT_BUS.post(event); + return event.getRegistry(); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index c0e11255400..fd45187ec12 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -7,6 +7,7 @@ import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.NetLogicRegistry; +import gregtech.api.graphnet.logic.NetLogicType; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; @@ -508,7 +509,7 @@ public void initialize() { writeLogicData(networkID, entry, false, true); } if (this.temperatureLogic == null) { - TemperatureLogic candidate = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + TemperatureLogic candidate = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); if (candidate != null) updateTemperatureLogic(candidate); } @@ -540,12 +541,9 @@ public void initialize() { private void writeLogicData(int networkID, NetLogicEntry entry, boolean removed, boolean fullChange) { writeCustomData(UPDATE_PIPE_LOGIC, buf -> { buf.writeVarInt(networkID); - buf.writeString(entry.getName()); buf.writeBoolean(removed); - buf.writeBoolean(fullChange); - if (!removed) { - entry.encode(buf, fullChange); - } + if (removed) buf.writeVarInt(NetLogicRegistry.getNetworkID(entry.getType())); + else NetLogicData.writeEntry(buf, entry, fullChange); }); } @@ -636,29 +634,16 @@ public void receiveCustomData(int discriminator, @NotNull PacketBuffer buf) { // extra check just to make sure we don't affect actual net data with our writes if (world.isRemote) { int networkID = buf.readVarInt(); - String identifier = buf.readString(255); boolean removed = buf.readBoolean(); - boolean fullChange = buf.readBoolean(); if (removed) { - this.netLogicDatas.computeIfPresent(networkID, (k, v) -> v.removeLogicEntry(identifier)); + NetLogicType type = NetLogicRegistry.getType(buf.readVarInt()); + NetLogicData data = this.netLogicDatas.get(networkID); + if (data != null) data.removeLogicEntry(type); } else { - if (fullChange) { - NetLogicEntry logic = NetLogicRegistry.getSupplierErroring(identifier).get(); - logic.decode(buf, true); - this.netLogicDatas.computeIfAbsent(networkID, k -> new NetLogicData()).setLogicEntry(logic); - } else { - NetLogicData data = this.netLogicDatas.get(networkID); - if (data == null) return; - NetLogicEntry entry = data.getLogicEntryNullable(identifier); - if (entry != null) { - entry.decode(buf, false); - data.markLogicEntryAsUpdated(entry, false); - } - } - if (identifier.equals(TemperatureLogic.INSTANCE.getName())) { - TemperatureLogic tempLogic = this.netLogicDatas.get(networkID) - .getLogicEntryNullable(TemperatureLogic.INSTANCE); - if (tempLogic != null) updateTemperatureLogic(tempLogic); + NetLogicData data = this.netLogicDatas.computeIfAbsent(networkID, i -> new NetLogicData()); + NetLogicEntry read = data.readEntry(buf); + if (read instanceof TemperatureLogic tempLogic) { + updateTemperatureLogic(tempLogic); } } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java b/src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java index 9ac2199ac92..22f58bc582b 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/predicate/BlockedPredicate.java @@ -1,6 +1,8 @@ package gregtech.api.graphnet.pipenet.predicate; +import gregtech.api.GTValues; import gregtech.api.graphnet.predicate.EdgePredicate; +import gregtech.api.graphnet.predicate.NetPredicateType; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTTagByte; @@ -9,16 +11,14 @@ public final class BlockedPredicate extends EdgePredicate { - public static final BlockedPredicate INSTANCE = new BlockedPredicate(); + private static final BlockedPredicate INSTANCE = new BlockedPredicate(); - private BlockedPredicate() { - super("Blocked"); - } + public static final NetPredicateType TYPE = new NetPredicateType<>(GTValues.MODID, "Blocked", + () -> INSTANCE, INSTANCE); @Override - @Deprecated - public @NotNull BlockedPredicate getNew() { - return INSTANCE; + public @NotNull NetPredicateType getType() { + return TYPE; } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java b/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java index c37ee85c253..308c8534e53 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/predicate/FilterPredicate.java @@ -1,6 +1,8 @@ package gregtech.api.graphnet.pipenet.predicate; +import gregtech.api.GTValues; import gregtech.api.graphnet.predicate.EdgePredicate; +import gregtech.api.graphnet.predicate.NetPredicateType; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.common.covers.filter.BaseFilterContainer; @@ -14,13 +16,15 @@ public final class FilterPredicate extends EdgePredicate { - public static final FilterPredicate INSTANCE = new FilterPredicate(); + public static final NetPredicateType TYPE = new NetPredicateType<>(GTValues.MODID, "Filter", + FilterPredicate::new, new FilterPredicate()); private @Nullable BaseFilterContainer sourceFilter; private @Nullable BaseFilterContainer targetFilter; - private FilterPredicate() { - super("FluidFilter"); + @Override + public @NotNull NetPredicateType getType() { + return TYPE; } public void setSourceFilter(@Nullable BaseFilterContainer sourceFilter) { @@ -56,11 +60,6 @@ public boolean andy() { return true; } - @Override - public @NotNull FilterPredicate getNew() { - return new FilterPredicate(); - } - @Override public boolean test(IPredicateTestObject object) { Object test = object.recombine(); diff --git a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java index 0f67a5e3828..142c8119f21 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java +++ b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicate.java @@ -3,7 +3,6 @@ import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTBase; -import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; import org.jetbrains.annotations.NotNull; @@ -14,19 +13,9 @@ * {@link #union(EdgePredicate)} behavior. */ public abstract class EdgePredicate, N extends NBTBase> - implements INBTSerializable, IStringSerializable { + implements INBTSerializable { - private final @NotNull String name; - - public EdgePredicate(@NotNull String name) { - this.name = name; - NetPredicateRegistry.register(this); - } - - @Override - public final @NotNull String getName() { - return name; - } + public abstract @NotNull NetPredicateType getType(); public void deserializeNBTNaive(NBTBase nbt) { deserializeNBT((N) nbt); @@ -41,9 +30,6 @@ public void deserializeNBTNaive(NBTBase nbt) { */ public abstract boolean andy(); - @NotNull - public abstract T getNew(); - public abstract boolean test(IPredicateTestObject object); /** diff --git a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java index affd03080a7..990805dbc57 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java +++ b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java @@ -4,7 +4,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.IStringSerializable; import net.minecraftforge.common.util.INBTSerializable; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -13,13 +12,9 @@ import java.util.Map; import java.util.function.Predicate; -/** - * Note - since the internal map representation encodes keys using {@link IStringSerializable#getName()} on predicates, - * making a predicate class return two different names is a valid way to register multiple instances. - */ public final class EdgePredicateHandler implements INBTSerializable, Predicate { - private final Map> predicateSet; + private final Map, EdgePredicate> predicateSet; public EdgePredicateHandler() { predicateSet = new Object2ObjectOpenHashMap<>(); @@ -30,7 +25,7 @@ public EdgePredicateHandler() { * nothing happens if a predicate is already present. */ public EdgePredicateHandler mergePredicate(@NotNull EdgePredicate predicate) { - EdgePredicate current = predicateSet.get(predicate.getName()); + EdgePredicate current = predicateSet.get(predicate.getType()); if (current == null) return setPredicate(predicate); if (predicate.getClass().isInstance(current)) { @@ -43,30 +38,30 @@ public EdgePredicateHandler mergePredicate(@NotNull EdgePredicate predicat /** * Do not modify the returned value */ - public Map> getPredicateSet() { + public Map, EdgePredicate> getPredicateSet() { return predicateSet; } public EdgePredicateHandler setPredicate(@NotNull EdgePredicate predicate) { - predicateSet.put(predicate.getName(), predicate); + predicateSet.put(predicate.getType(), predicate); return this; } public EdgePredicateHandler removePredicate(@NotNull EdgePredicate predicate) { - return removePredicate(predicate.getName()); + return removePredicate(predicate.getType()); } - public EdgePredicateHandler removePredicate(String key) { - predicateSet.remove(key); + public EdgePredicateHandler removePredicate(@NotNull NetPredicateType type) { + predicateSet.remove(type); return this; } public boolean hasPredicate(@NotNull EdgePredicate predicate) { - return predicateSet.containsKey(predicate.getName()); + return hasPredicate(predicate.getType()); } - public boolean hasPredicate(String key) { - return predicateSet.containsKey(key); + public boolean hasPredicate(@NotNull NetPredicateType type) { + return predicateSet.containsKey(type); } public void clearPredicates() { @@ -97,7 +92,7 @@ public NBTTagList serializeNBT() { for (EdgePredicate entry : predicateSet.values()) { NBTTagCompound tag = new NBTTagCompound(); tag.setTag("Tag", entry.serializeNBT()); - tag.setString("Name", entry.getName()); + tag.setString("Type", entry.getType().getName()); list.appendTag(tag); } return list; @@ -107,10 +102,11 @@ public NBTTagList serializeNBT() { public void deserializeNBT(NBTTagList nbt) { for (int i = 0; i < nbt.tagCount(); i++) { NBTTagCompound tag = nbt.getCompoundTagAt(i); - String key = tag.getString("Name"); - EdgePredicate entry = this.predicateSet.get(key); - if (entry == null) entry = NetPredicateRegistry.getSupplierNotNull(key).get(); - if (entry == null) continue; + NetPredicateType type = NetPredicateRegistry.getType(tag.getString("Type")); + EdgePredicate entry = this.predicateSet.get(type); + if (entry == null) { + entry = type.getNew(); + } entry.deserializeNBTNaive(tag.getTag("Tag")); } } diff --git a/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistrationEvent.java b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistrationEvent.java new file mode 100644 index 00000000000..e6be519c722 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistrationEvent.java @@ -0,0 +1,22 @@ +package gregtech.api.graphnet.predicate; + +import net.minecraftforge.fml.common.eventhandler.Event; + +import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; + +import java.util.Comparator; + +public final class NetPredicateRegistrationEvent extends Event { + + private final ObjectRBTreeSet> gather = new ObjectRBTreeSet<>( + Comparator.comparing(NetPredicateType::getName)); + + public void accept(NetPredicateType type) { + if (!gather.add(type)) + throw new IllegalStateException("Detected a name collision during Net Predicate registration!"); + } + + ObjectRBTreeSet> getGather() { + return gather; + } +} diff --git a/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java index df5429d7a2e..46715e6f34c 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java +++ b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java @@ -1,36 +1,90 @@ package gregtech.api.graphnet.predicate; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.client.Minecraft; +import net.minecraft.util.IntIdentityHashBiMap; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.relauncher.Side; + +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Map; -import java.util.function.Supplier; +import java.util.Set; public final class NetPredicateRegistry { - private static final Map>> REGISTRY = new Object2ObjectOpenHashMap<>(); + private static final Int2ObjectArrayMap> REGISTRY; + + private static final IntIdentityHashBiMap NAMES_TO_NETWORK_IDS; + + static { + NetPredicateRegistrationEvent event = new NetPredicateRegistrationEvent(); + MinecraftForge.EVENT_BUS.post(event); + Set> gather = event.getGather(); + NAMES_TO_NETWORK_IDS = new IntIdentityHashBiMap<>(gather.size()); + REGISTRY = new Int2ObjectArrayMap<>(gather.size()); + int id = 1; + for (NetPredicateType type : gather) { + NAMES_TO_NETWORK_IDS.put(type.getName(), id); + REGISTRY.put(id, type); + id++; + } + } + + public static String getName(int networkID) { + return NAMES_TO_NETWORK_IDS.get(networkID); + } + + public static int getNetworkID(@NotNull String name) { + return NAMES_TO_NETWORK_IDS.getId(name); + } + + public static int getNetworkID(@NotNull NetPredicateType type) { + return getNetworkID(type.getName()); + } + + public static int getNetworkID(@NotNull EdgePredicate entry) { + return getNetworkID(entry.getType()); + } - static void register(@NotNull EdgePredicate predicate) { - REGISTRY.putIfAbsent(predicate.getName(), predicate::getNew); + public static @Nullable NetPredicateType getTypeNullable(int networkID) { + return REGISTRY.get(networkID); } - public static @Nullable Supplier<@NotNull EdgePredicate> getSupplierNullable(String name) { - return REGISTRY.get(name); + public static @Nullable NetPredicateType getTypeNullable(@NotNull String name) { + return getTypeNullable(getNetworkID(name)); } - public static @NotNull Supplier<@Nullable EdgePredicate> getSupplierNotNull(String name) { - return REGISTRY.getOrDefault(name, () -> null); + public static @NotNull NetPredicateType getType(int networkID) { + NetPredicateType type = REGISTRY.get(networkID); + if (type == null) throwNonexistenceError(); + assert type != null; + return type; } - public static @NotNull Supplier> getSupplierErroring(String name) { - Supplier> supplier = REGISTRY.get(name); - if (supplier == null) throwNonexistenceError(); - return supplier; + public static @NotNull NetPredicateType getType(@NotNull String name) { + return getType(getNetworkID(name)); } public static void throwNonexistenceError() { - throw new RuntimeException("Could not find a matching supplier for an encoded EdgePredicate. " + + if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) disconnect(); + throw new RuntimeException("Could not find the type of an encoded EdgePredicate. " + "This suggests that the server and client have different GT versions or modifications."); } + + public static void throwDecodingError() { + if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) disconnect(); + throw new RuntimeException("Failed to decode an encoded EdgePredicate. " + + "This suggests that the server and client have different GT versions or modifications."); + } + + private static void disconnect() { + if (Minecraft.getMinecraft().getConnection() != null) + Minecraft.getMinecraft().getConnection() + .onDisconnect(new TextComponentTranslation("gregtech.universal.netpredicatedisconnect")); + } + + private NetPredicateRegistry() {} } diff --git a/src/main/java/gregtech/api/graphnet/predicate/NetPredicateType.java b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateType.java new file mode 100644 index 00000000000..12b6c414d0c --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateType.java @@ -0,0 +1,47 @@ +package gregtech.api.graphnet.predicate; + +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.ResourceLocation; + +import org.jetbrains.annotations.NotNull; + +import java.util.function.Supplier; + +public class NetPredicateType> implements IStringSerializable { + + private final String name; + private final @NotNull Supplier<@NotNull T> supplier; + private final @NotNull T defaultable; + + public NetPredicateType(@NotNull ResourceLocation name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + this.name = name.toString(); + this.supplier = supplier; + this.defaultable = defaultable; + } + + public NetPredicateType(@NotNull String namespace, @NotNull String name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + this.name = namespace + ":" + name; + this.supplier = supplier; + this.defaultable = defaultable; + } + + @SuppressWarnings("unchecked") + public T cast(EdgePredicate predicate) { + return (T) predicate; + } + + public final @NotNull T getNew() { + return supplier.get(); + } + + public final @NotNull T getDefault() { + return defaultable; + } + + @Override + public @NotNull String getName() { + return name; + } +} diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java index 6773cb99745..4daeba5eaf7 100644 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java @@ -63,8 +63,8 @@ public void removeNode(@NotNull NetNode node) { public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays) { nodeClassCheck(source); nodeClassCheck(target); - double weight = source.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue() + - target.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue(); + double weight = source.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue() + + target.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue(); NetEdge edge = backer.addEdge(source, target, weight); if (bothWays) { if (this.getGraph().isDirected()) { diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java index 8f3a944eff8..97b171d8082 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -76,8 +76,8 @@ public void removeNode(@NotNull NetNode node) { public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays) { nodeClassCheck(source); nodeClassCheck(target); - double weight = source.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue() + - target.getData().getLogicEntryDefaultable(WeightFactorLogic.INSTANCE).getValue(); + double weight = source.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue() + + target.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue(); NetEdge edge = backer.addEdge(source, target, weight); if (bothWays) { if (this.getGraph().isDirected()) { diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 996a50bbadf..c23c5c1f5a6 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -998,7 +998,7 @@ public static BitSet setToMask(@NotNull EnumSet enumSet) { * * @param clazz the class object to initialize. */ - public static void forceInitialization(Class clazz) { + public static void forceInitialization(@NotNull Class clazz) { try { Class.forName(clazz.getName(), true, clazz.getClassLoader()); } catch (ClassNotFoundException e) { diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index 95db77674e2..666a548f8b7 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -4,8 +4,17 @@ import gregtech.api.GregTechAPI; import gregtech.api.block.VariantItemBlock; import gregtech.api.block.machines.MachineItemBlock; +import gregtech.api.graphnet.logic.ChannelCountLogic; +import gregtech.api.graphnet.logic.NetLogicRegistrationEvent; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistrationEvent; import gregtech.api.graphnet.pipenet.physical.block.ItemPipeBlock; import gregtech.api.graphnet.pipenet.physical.block.ItemPipeMaterialBlock; +import gregtech.api.graphnet.pipenet.predicate.BlockedPredicate; +import gregtech.api.graphnet.pipenet.predicate.FilterPredicate; +import gregtech.api.graphnet.predicate.NetPredicateRegistrationEvent; import gregtech.api.items.metaitem.MetaItem; import gregtech.api.items.toolitem.IGTTool; import gregtech.api.metatileentity.registry.MTERegistry; @@ -37,9 +46,20 @@ import gregtech.common.items.MetaItems; import gregtech.common.items.ToolItems; import gregtech.common.pipelike.block.cable.CableBlock; +import gregtech.common.pipelike.block.cable.CableStructure; import gregtech.common.pipelike.block.laser.LaserPipeBlock; +import gregtech.common.pipelike.block.laser.LaserStructure; import gregtech.common.pipelike.block.optical.OpticalPipeBlock; +import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.block.pipe.MaterialPipeBlock; +import gregtech.common.pipelike.block.pipe.MaterialPipeStructure; +import gregtech.common.pipelike.net.energy.EnergyFlowLogic; +import gregtech.common.pipelike.net.energy.SuperconductorLogic; +import gregtech.common.pipelike.net.energy.VoltageLimitLogic; +import gregtech.common.pipelike.net.energy.VoltageLossLogic; +import gregtech.common.pipelike.net.fluid.FluidContainmentLogic; +import gregtech.common.pipelike.net.fluid.FluidFlowLogic; +import gregtech.common.pipelike.net.item.ItemFlowLogic; import gregtech.datafix.GTDataFixers; import gregtech.integration.groovy.GroovyScriptModule; import gregtech.loaders.MaterialInfoLoader; @@ -364,6 +384,35 @@ public static void modifyFuelBurnTime(FurnaceFuelBurnTimeEvent event) { } } + @SubscribeEvent + public static void registerPipeStructures(PipeStructureRegistrationEvent event) { + CableStructure.register(event); + MaterialPipeStructure.register(event); + LaserStructure.register(event); + OpticalStructure.register(event); + } + + @SubscribeEvent + public static void registerNetLogics(NetLogicRegistrationEvent event) { + event.accept(ChannelCountLogic.TYPE); + event.accept(EnergyFlowLogic.TYPE); + event.accept(FluidFlowLogic.TYPE); + event.accept(ItemFlowLogic.TYPE); + event.accept(FluidContainmentLogic.TYPE); + event.accept(SuperconductorLogic.TYPE); + event.accept(TemperatureLogic.TYPE); + event.accept(ThroughputLogic.TYPE); + event.accept(WeightFactorLogic.TYPE); + event.accept(VoltageLimitLogic.TYPE); + event.accept(VoltageLossLogic.TYPE); + } + + @SubscribeEvent + public static void registerNetPredicates(NetPredicateRegistrationEvent event) { + event.accept(BlockedPredicate.TYPE); + event.accept(FilterPredicate.TYPE); + } + private static ItemBlock createItemBlock(T block, Function producer) { ItemBlock itemBlock = producer.apply(block); ResourceLocation registryName = block.getRegistryName(); diff --git a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java index b509e16e626..10964ee384e 100644 --- a/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java +++ b/src/main/java/gregtech/common/items/behaviors/TricorderBehavior.java @@ -302,7 +302,7 @@ else if (metaTileEntity instanceof IDataInfoProvider) if (data != null) { long cumulativeVoltage = 0; long cumulativeAmperage = 0; - for (var memory : data.getLogicEntryDefaultable(EnergyFlowLogic.INSTANCE).getMemory().values()) { + for (var memory : data.getLogicEntryDefaultable(EnergyFlowLogic.TYPE).getMemory().values()) { double voltage = 0; long amperage = 0; for (EnergyFlowData flow : memory) { diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index 81dd17b170f..ba90653a726 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -100,8 +100,8 @@ public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @No if (tile != null && tile.getFrameMaterial() == null && tile.getOffsetTimer() % 10 == 0) { WorldPipeNetNode node = WorldEnergyNet.getWorldNet(worldIn).getNode(pos); if (node != null) { - if (node.getData().getLogicEntryNullable(SuperconductorLogic.INSTANCE) != null) return; - EnergyFlowLogic logic = node.getData().getLogicEntryNullable(EnergyFlowLogic.INSTANCE); + if (node.getData().getLogicEntryNullable(SuperconductorLogic.TYPE) != null) return; + EnergyFlowLogic logic = node.getData().getLogicEntryNullable(EnergyFlowLogic.TYPE); if (logic != null) { long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); long cumulativeDamage = 0; diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java index ae57598f22d..8de78b98c7b 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableStructure.java @@ -2,7 +2,7 @@ import gregtech.api.graphnet.pipenet.physical.IInsulatable; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; -import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; +import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistrationEvent; import gregtech.api.unification.ore.OrePrefix; import gregtech.client.renderer.pipe.PipeModelRedirector; import gregtech.client.renderer.pipe.PipeModelRegistry; @@ -42,20 +42,6 @@ public record CableStructure(String name, int material, int costFactor, OrePrefi public static final CableStructure CABLE_HEX = new CableStructure("cable_hex", 16, 1, OrePrefix.cableGtHex, WIRE_HEX, INSULATION_BURN_TEMP, 1f, PipeModelRegistry.getCableModel(5)); - public CableStructure(String name, int material, int costFactor, OrePrefix ore, - @Nullable CableStructure partialBurnStructure, @Nullable Integer partialBurnThreshold, - float renderThickness, PipeModelRedirector model) { - this.name = name; - this.material = material; - this.costFactor = costFactor; - this.ore = ore; - this.partialBurnStructure = partialBurnStructure; - this.partialBurnThreshold = partialBurnThreshold; - this.renderThickness = renderThickness; - this.model = model; - PipeStructureRegistry.register(this); - } - @Override public @NotNull String getName() { return name; @@ -85,4 +71,17 @@ public boolean isInsulated() { public PipeModelRedirector getModel() { return model; } + + public static void register(@NotNull PipeStructureRegistrationEvent event) { + event.register(WIRE_SINGLE); + event.register(WIRE_DOUBLE); + event.register(WIRE_QUADRUPLE); + event.register(WIRE_OCTAL); + event.register(WIRE_HEX); + event.register(CABLE_SINGLE); + event.register(CABLE_DOUBLE); + event.register(CABLE_QUADRUPLE); + event.register(CABLE_OCTAL); + event.register(CABLE_HEX); + } } diff --git a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java index 076f38869cd..f721fac4256 100644 --- a/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/laser/LaserStructure.java @@ -1,7 +1,7 @@ package gregtech.common.pipelike.block.laser; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; +import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistrationEvent; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.PipeModelRedirector; import gregtech.client.renderer.pipe.PipeModelRegistry; @@ -21,14 +21,6 @@ public record LaserStructure(String name, float renderThickness, boolean mirror, public static final LaserStructure MIRROR = new LaserStructure("laser_pipe_mirror", 0.5f, true, PipeModelRegistry.getLaserModel()); - public LaserStructure(String name, float renderThickness, boolean mirror, PipeModelRedirector model) { - this.name = name; - this.renderThickness = renderThickness; - this.mirror = mirror; - this.model = model; - PipeStructureRegistry.register(this); - } - @Override public boolean canConnectTo(EnumFacing side, byte connectionMask) { if (mirror) { @@ -71,4 +63,9 @@ public boolean isPaintable() { public PipeModelRedirector getModel() { return model; } + + public static void register(@NotNull PipeStructureRegistrationEvent event) { + event.register(NORMAL); + event.register(MIRROR); + } } diff --git a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java index 1d62afaf3df..2b98da46698 100644 --- a/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/optical/OpticalStructure.java @@ -1,7 +1,7 @@ package gregtech.common.pipelike.block.optical; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; -import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; +import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistrationEvent; import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.PipeModelRedirector; import gregtech.client.renderer.pipe.PipeModelRegistry; @@ -18,13 +18,6 @@ public record OpticalStructure(String name, float renderThickness, PipeModelRedi public static final OpticalStructure INSTANCE = new OpticalStructure("optical_pipe_normal", 0.375f, PipeModelRegistry.getOpticalModel()); - public OpticalStructure(String name, float renderThickness, PipeModelRedirector model) { - this.name = name; - this.renderThickness = renderThickness; - this.model = model; - PipeStructureRegistry.register(this); - } - @Override public boolean canConnectTo(EnumFacing side, byte connectionMask) { byte connectionCount = 0; @@ -57,4 +50,8 @@ public boolean isPaintable() { public PipeModelRedirector getModel() { return model; } + + public static void register(@NotNull PipeStructureRegistrationEvent event) { + event.register(INSTANCE); + } } diff --git a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java index 3faccc5f53d..1fc02ac83a5 100644 --- a/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java +++ b/src/main/java/gregtech/common/pipelike/block/pipe/MaterialPipeStructure.java @@ -2,7 +2,7 @@ import gregtech.api.graphnet.pipenet.physical.IPipeChanneledStructure; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; -import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistry; +import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistrationEvent; import gregtech.api.unification.ore.OrePrefix; import gregtech.client.renderer.pipe.PipeModelRedirector; import gregtech.client.renderer.pipe.PipeModelRegistry; @@ -50,18 +50,6 @@ public record MaterialPipeStructure(String name, int material, int channelCount, "pipe_nonuple_restrictive", 18, 9, true, OrePrefix.pipeNonupleRestrictive, 0.95f, PipeModelRegistry.getPipeRestrictiveModel(6)); - public MaterialPipeStructure(String name, int material, int channelCount, boolean restrictive, OrePrefix ore, - float renderThickness, PipeModelRedirector model) { - this.name = name; - this.material = material; - this.channelCount = channelCount; - this.restrictive = restrictive; - this.ore = ore; - this.renderThickness = renderThickness; - this.model = model; - PipeStructureRegistry.register(this); - } - @Override public @NotNull String getName() { return name; @@ -91,4 +79,21 @@ public boolean isPaintable() { public PipeModelRedirector getModel() { return model; } + + public static void register(@NotNull PipeStructureRegistrationEvent event) { + event.register(TINY); + event.register(SMALL); + event.register(NORMAL); + event.register(LARGE); + event.register(HUGE); + event.register(QUADRUPLE); + event.register(NONUPLE); + event.register(TINY_RESTRICTIVE); + event.register(SMALL_RESTRICTIVE); + event.register(NORMAL_RESTRICTIVE); + event.register(LARGE_RESTRICTIVE); + event.register(HUGE_RESTRICTIVE); + event.register(QUADRUPLE_RESTRICTIVE); + event.register(NONUPLE_RESTRICTIVE); + } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 9b20e0e3960..6586408b844 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -182,37 +182,37 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { boolean insulated = cable.partialBurnStructure() != null; // insulated cables cool down half as fast float coolingFactor = (float) (Math.sqrt(cable.material()) / (insulated ? 8 : 4)); - TemperatureLogic existing = data.getLogicEntryNullable(TemperatureLogic.INSTANCE); + TemperatureLogic existing = data.getLogicEntryNullable(TemperatureLogic.TYPE); float energy = existing == null ? 0 : existing.getThermalEnergy(); - data.setLogicEntry(VoltageLossLogic.INSTANCE.getWith(loss)) - .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) - .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) - .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) - .setLogicEntry(TemperatureLogic.INSTANCE + data.setLogicEntry(VoltageLossLogic.TYPE.getWith(loss)) + .setLogicEntry(WeightFactorLogic.TYPE.getWith(loss + 0.001 / amperage)) + .setLogicEntry(ThroughputLogic.TYPE.getWith(amperage)) + .setLogicEntry(VoltageLimitLogic.TYPE.getWith(voltageLimit)) + .setLogicEntry(TemperatureLogic.TYPE .getWith(TemperatureLossFunction.getOrCreateCable(coolingFactor), materialMeltTemperature, 1, 100 * cable.material(), cable.partialBurnThreshold()) .setInitialThermalEnergy(energy)); if (superconductorCriticalTemperature > 0) { - data.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorCriticalTemperature)); + data.setLogicEntry(SuperconductorLogic.TYPE.getWith(superconductorCriticalTemperature)); } } else if (structure instanceof MaterialPipeStructure pipe) { long amperage = getAmperage(structure); if (amperage == 0) return; // skip pipes that are too small long loss = getLoss(structure); float coolingFactor = (float) Math.sqrt((double) pipe.material() / (4 + pipe.channelCount())); - TemperatureLogic existing = data.getLogicEntryNullable(TemperatureLogic.INSTANCE); + TemperatureLogic existing = data.getLogicEntryNullable(TemperatureLogic.TYPE); float energy = existing == null ? 0 : existing.getThermalEnergy(); - data.setLogicEntry(VoltageLossLogic.INSTANCE.getWith(loss)) - .setLogicEntry(WeightFactorLogic.INSTANCE.getWith(loss + 0.001 / amperage)) - .setLogicEntry(ThroughputLogic.INSTANCE.getWith(amperage)) - .setLogicEntry(VoltageLimitLogic.INSTANCE.getWith(voltageLimit)) - .setLogicEntry(TemperatureLogic.INSTANCE + data.setLogicEntry(VoltageLossLogic.TYPE.getWith(loss)) + .setLogicEntry(WeightFactorLogic.TYPE.getWith(loss + 0.001 / amperage)) + .setLogicEntry(ThroughputLogic.TYPE.getWith(amperage)) + .setLogicEntry(VoltageLimitLogic.TYPE.getWith(voltageLimit)) + .setLogicEntry(TemperatureLogic.TYPE .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), materialMeltTemperature, 1, 50 * pipe.material(), null) .setInitialThermalEnergy(energy)); if (superconductorCriticalTemperature > 0) { - data.setLogicEntry(SuperconductorLogic.INSTANCE.getWith(superconductorCriticalTemperature)); + data.setLogicEntry(SuperconductorLogic.TYPE.getWith(superconductorCriticalTemperature)); } } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index c71d820b373..c5a5669a4ad 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -181,18 +181,18 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { if (structure instanceof MaterialPipeStructure pipe) { long throughput = getThroughput(structure); float coolingFactor = (float) Math.sqrt((double) pipe.material() / (4 + pipe.channelCount())); - TemperatureLogic existing = data.getLogicEntryNullable(TemperatureLogic.INSTANCE); + TemperatureLogic existing = data.getLogicEntryNullable(TemperatureLogic.TYPE); float energy = existing == null ? 0 : existing.getThermalEnergy(); - data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(getFlowPriority(structure))) - .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)) - .setLogicEntry(FluidContainmentLogic.INSTANCE.getWith(containableStates, containableAttributes, + data.setLogicEntry(WeightFactorLogic.TYPE.getWith(getFlowPriority(structure))) + .setLogicEntry(ThroughputLogic.TYPE.getWith(throughput)) + .setLogicEntry(FluidContainmentLogic.TYPE.getWith(containableStates, containableAttributes, maxFluidTemperature)) - .setLogicEntry(TemperatureLogic.INSTANCE + .setLogicEntry(TemperatureLogic.TYPE .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), materialMeltTemperature, minFluidTemperature, 50 * pipe.material(), null) .setInitialThermalEnergy(energy)); if (pipe.channelCount() > 1) { - data.setLogicEntry(ChannelCountLogic.INSTANCE.getWith(pipe.channelCount())); + data.setLogicEntry(ChannelCountLogic.TYPE.getWith(pipe.channelCount())); } } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index f9d0dac25b7..e5256156c94 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -84,10 +84,10 @@ public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStruc public void mutateData(NetLogicData data, IPipeStructure structure) { if (structure instanceof MaterialPipeStructure pipe) { long throughput = baseItemsPer5Ticks * pipe.material(); - data.setLogicEntry(WeightFactorLogic.INSTANCE.getWith(getFlowPriority(structure))) - .setLogicEntry(ThroughputLogic.INSTANCE.getWith(throughput)); + data.setLogicEntry(WeightFactorLogic.TYPE.getWith(getFlowPriority(structure))) + .setLogicEntry(ThroughputLogic.TYPE.getWith(throughput)); if (pipe.channelCount() > 1) { - data.setLogicEntry(ChannelCountLogic.INSTANCE.getWith(pipe.channelCount())); + data.setLogicEntry(ChannelCountLogic.TYPE.getWith(pipe.channelCount())); } } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 2558f7da51a..0ef6ff35df4 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -131,13 +131,13 @@ private EnergyGroupData getEnergyData() { @Override public long getInputAmperage() { if (tile == null) return 0; - return tile.getNetLogicData(net.getNetworkID()).getLogicEntryDefaultable(ThroughputLogic.INSTANCE).getValue(); + return tile.getNetLogicData(net.getNetworkID()).getLogicEntryDefaultable(ThroughputLogic.TYPE).getValue(); } @Override public long getInputVoltage() { if (tile == null) return 0; - return tile.getNetLogicData(net.getNetworkID()).getLogicEntryDefaultable(VoltageLimitLogic.INSTANCE).getValue(); + return tile.getNetLogicData(net.getNetworkID()).getLogicEntryDefaultable(VoltageLimitLogic.TYPE).getValue(); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java index 97ee3c93eb2..100a6c3b865 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyFlowLogic.java @@ -1,6 +1,8 @@ package gregtech.common.pipelike.net.energy; +import gregtech.api.GTValues; import gregtech.api.graphnet.logic.AbstractTransientLogicData; +import gregtech.api.graphnet.logic.NetLogicType; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -14,14 +16,16 @@ public class EnergyFlowLogic extends AbstractTransientLogicData { - public static final EnergyFlowLogic INSTANCE = new EnergyFlowLogic(); + public static final NetLogicType TYPE = new NetLogicType<>(GTValues.MODID, "EnergyFlow", + EnergyFlowLogic::new, new EnergyFlowLogic()); public static final int MEMORY_TICKS = 10; private final Long2ObjectOpenHashMap> memory = new Long2ObjectOpenHashMap<>(); - protected EnergyFlowLogic() { - super("EnergyFlow"); + @Override + public @NotNull NetLogicType getType() { + return TYPE; } public @NotNull Long2ObjectOpenHashMap> getMemory() { @@ -48,9 +52,4 @@ private void updateMemory(long tick) { } } } - - @Override - public @NotNull EnergyFlowLogic getNew() { - return new EnergyFlowLogic(); - } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java index 2571c072a94..f7ea63a7d4e 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java @@ -65,16 +65,16 @@ public void resetPathVoltage() { @Override public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, long flowReachingNode) { - VoltageLimitLogic limitLogic = node.getData().getLogicEntryNullable(VoltageLimitLogic.INSTANCE); + VoltageLimitLogic limitLogic = node.getData().getLogicEntryNullable(VoltageLimitLogic.TYPE); if (limitLogic != null) { long voltage = limitLogic.getValue(); if (voltage < pathVoltage) overVoltageInformation.put(node, new OverVoltageInformation(voltage)); } - TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); - if (!node.getData().getLogicEntryDefaultable(SuperconductorLogic.INSTANCE) + TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); + if (!node.getData().getLogicEntryDefaultable(SuperconductorLogic.TYPE) .canSuperconduct(temperatureLogic == null ? TemperatureLogic.DEFAULT_TEMPERATURE : temperatureLogic.getTemperature(getQueryTick()))) { - pathVoltage -= node.getData().getLogicEntryDefaultable(VoltageLossLogic.INSTANCE).getValue(); + pathVoltage -= node.getData().getLogicEntryDefaultable(VoltageLossLogic.TYPE).getValue(); } NodeLossCache.Key key = NodeLossCache.key(node, this); @@ -103,7 +103,7 @@ public void handleOverflow(@NotNull WorldPipeNetNode node, long overflow) { } } if (overflow > 0) { - TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); if (logic != null) { // this occurs after finalization but before path reset. logic.applyThermalEnergy(calculateHeatA(overflow, pathVoltage), getQueryTick()); @@ -140,9 +140,9 @@ public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNo } private void recordFlow(@NotNull NetNode node, long amperes) { - EnergyFlowLogic logic = node.getData().getLogicEntryNullable(EnergyFlowLogic.INSTANCE); + EnergyFlowLogic logic = node.getData().getLogicEntryNullable(EnergyFlowLogic.TYPE); if (logic == null) { - logic = EnergyFlowLogic.INSTANCE.getNew(); + logic = EnergyFlowLogic.TYPE.getNew(); node.getData().setLogicEntry(logic); } logic.recordFlow(getQueryTick(), new EnergyFlowData(amperes, pathVoltage)); @@ -165,7 +165,7 @@ public OverVoltageInformation(long voltageCap) { } public void doHeating(WorldPipeNetNode node, long finalVoltage, long tick, long amperage) { - TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); if (logic != null) { logic.applyThermalEnergy(calculateHeatV(amperage, finalVoltage, voltageCap), tick); } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java index 368a8926a5b..dc5885c6eb8 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java @@ -1,23 +1,21 @@ package gregtech.common.pipelike.net.energy; +import gregtech.api.GTValues; import gregtech.api.graphnet.logic.AbstractIntLogicData; import org.jetbrains.annotations.NotNull; public final class SuperconductorLogic extends AbstractIntLogicData { - public static final SuperconductorLogic INSTANCE = new SuperconductorLogic().setValue(0); + public static final IntLogicType TYPE = new IntLogicType<>(GTValues.MODID, "Superconductor", + SuperconductorLogic::new, new SuperconductorLogic()); - public SuperconductorLogic() { - super("Superconductor"); + @Override + public @NotNull IntLogicType getType() { + return TYPE; } public boolean canSuperconduct(int temp) { return this.getValue() > temp; } - - @Override - public @NotNull SuperconductorLogic getNew() { - return new SuperconductorLogic(); - } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java index e73944e7afa..3f4cb275543 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLimitLogic.java @@ -1,5 +1,6 @@ package gregtech.common.pipelike.net.energy; +import gregtech.api.GTValues; import gregtech.api.graphnet.logic.AbstractLongLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; @@ -7,15 +8,12 @@ public final class VoltageLimitLogic extends AbstractLongLogicData { - public static final VoltageLimitLogic INSTANCE = new VoltageLimitLogic().setValue(0); - - private VoltageLimitLogic() { - super("VoltageLimit"); - } + public static final LongLogicType TYPE = new LongLogicType<>(GTValues.MODID, "VoltageLimit", + VoltageLimitLogic::new, new VoltageLimitLogic()); @Override - public @NotNull VoltageLimitLogic getNew() { - return new VoltageLimitLogic().setValue(INSTANCE.getValue()); + public @NotNull LongLogicType getType() { + return TYPE; } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java index d025b66be39..b6ae9286152 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java @@ -1,5 +1,6 @@ package gregtech.common.pipelike.net.energy; +import gregtech.api.GTValues; import gregtech.api.graphnet.logic.AbstractLongLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; @@ -7,21 +8,18 @@ public final class VoltageLossLogic extends AbstractLongLogicData { - public static final VoltageLossLogic INSTANCE = new VoltageLossLogic().setValue(0); - - private VoltageLossLogic() { - super("VoltageLoss"); - } + public static final LongLogicType TYPE = new LongLogicType<>(GTValues.MODID, "VoltageLoss", + VoltageLossLogic::new, new VoltageLossLogic()); @Override - public @NotNull VoltageLossLogic getNew() { - return new VoltageLossLogic(); + public @NotNull LongLogicType getType() { + return TYPE; } @Override public VoltageLossLogic union(NetLogicEntry other) { if (other instanceof VoltageLossLogic l) { - return this.getWith(this.getValue() + l.getValue()); + return TYPE.getWith(this.getValue() + l.getValue()); } else return this; } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index 485c5bbf169..b9c9e594bc8 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -47,7 +47,7 @@ public FluidCapabilityO WorldPipeNetNode node) { this.net = net; this.node = node; - properties = new IFluidTankProperties[node.getData().getLogicEntryDefaultable(ChannelCountLogic.INSTANCE) + properties = new IFluidTankProperties[node.getData().getLogicEntryDefaultable(ChannelCountLogic.TYPE) .getValue()]; Arrays.fill(properties, this); for (EnumFacing facing : EnumFacing.VALUES) { diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java index 5641537e177..87fcae99e84 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java @@ -1,8 +1,10 @@ package gregtech.common.pipelike.net.fluid; +import gregtech.api.GTValues; import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.graphnet.logic.NetLogicEntry; +import gregtech.api.graphnet.logic.NetLogicType; import gregtech.api.util.GTUtility; import net.minecraft.nbt.NBTTagCompound; @@ -23,27 +25,16 @@ public final class FluidContainmentLogic extends NetLogicEntry { - public static final FluidContainmentLogic INSTANCE = new FluidContainmentLogic().contain(FluidState.LIQUID); + public static final FluidContainmentLogicType TYPE = new FluidContainmentLogicType(); private int maximumTemperature; private final Set containableAttributes = new ObjectOpenHashSet<>(); private @NotNull EnumSet containableStates = EnumSet.noneOf(FluidState.class); - public FluidContainmentLogic() { - super("FluidContainment"); - } - - public @NotNull FluidContainmentLogic getWith(Collection states, - @NotNull Collection attributes, - int maximumTemperature) { - FluidContainmentLogic logic = getNew(); - logic.containableStates.addAll(states); - for (FluidAttribute attribute : attributes) { - logic.contain(attribute); - } - logic.maximumTemperature = maximumTemperature; - return logic; + @Override + public @NotNull FluidContainmentLogicType getType() { + return TYPE; } @Contract("_ -> this") @@ -93,7 +84,7 @@ public int getMaximumTemperature() { this.containableStates.equals(logic.containableStates)) { return this; } else { - FluidContainmentLogic returnable = getNew(); + FluidContainmentLogic returnable = TYPE.getNew(); returnable.containableStates = EnumSet.copyOf(this.containableStates); returnable.containableStates.retainAll(logic.containableStates); returnable.containableAttributes.addAll(this.containableAttributes); @@ -125,11 +116,6 @@ public void deserializeNBT(NBTTagCompound nbt) { containableStates = GTUtility.maskToSet(FluidState.class, BitSet.valueOf(nbt.getByteArray("States"))); } - @Override - public @NotNull FluidContainmentLogic getNew() { - return new FluidContainmentLogic(); - } - @Override public void encode(PacketBuffer buf, boolean fullChange) { buf.writeVarInt(containableAttributes.size()); @@ -147,4 +133,24 @@ public void decode(PacketBuffer buf, boolean fullChange) { } containableStates = GTUtility.maskToSet(FluidState.class, BitSet.valueOf(buf.readByteArray(255))); } + + public static final class FluidContainmentLogicType extends NetLogicType { + + public FluidContainmentLogicType() { + super(GTValues.MODID, "FluidContainment", FluidContainmentLogic::new, + new FluidContainmentLogic().contain(FluidState.LIQUID)); + } + + public @NotNull FluidContainmentLogic getWith(Collection states, + @NotNull Collection attributes, + int maximumTemperature) { + FluidContainmentLogic logic = getNew(); + logic.containableStates.addAll(states); + for (FluidAttribute attribute : attributes) { + logic.contain(attribute); + } + logic.maximumTemperature = maximumTemperature; + return logic; + } + } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java index 6c7b10455c3..229cdacca95 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java @@ -1,6 +1,8 @@ package gregtech.common.pipelike.net.fluid; +import gregtech.api.GTValues; import gregtech.api.graphnet.logic.AbstractTransientLogicData; +import gregtech.api.graphnet.logic.NetLogicType; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -15,15 +17,17 @@ public class FluidFlowLogic extends AbstractTransientLogicData { - public static final FluidFlowLogic INSTANCE = new FluidFlowLogic(); + public static final NetLogicType TYPE = new NetLogicType<>(GTValues.MODID, "FluidFlow", + FluidFlowLogic::new, new FluidFlowLogic()); public static final int MEMORY_TICKS = 10; private final Long2ObjectOpenHashMap> memory = new Long2ObjectOpenHashMap<>(); private FluidStack last; - protected FluidFlowLogic() { - super("FluidFlow"); + @Override + public @NotNull NetLogicType getType() { + return TYPE; } public @NotNull Long2ObjectOpenHashMap> getMemory() { @@ -55,9 +59,4 @@ private void updateMemory(long tick) { } } } - - @Override - public @NotNull FluidFlowLogic getNew() { - return new FluidFlowLogic(); - } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index 3b591b2e9a7..a372f8103d2 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -82,9 +82,9 @@ public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, lon return result.getLossFunction(); } else { FluidContainmentLogic containmentLogic = node.getData() - .getLogicEntryDefaultable(FluidContainmentLogic.INSTANCE); + .getLogicEntryDefaultable(FluidContainmentLogic.TYPE); - TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); if (temperatureLogic != null) { result = temperatureLogic.getLossResult(getQueryTick()); boolean overMax = fluidTemp > containmentLogic.getMaximumTemperature() && @@ -168,10 +168,10 @@ public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNo super.consumeFlowLimit(edge, targetNode, consumption); if (consumption > 0 && !simulating()) { recordFlow(targetNode, consumption); - TemperatureLogic temperatureLogic = targetNode.getData().getLogicEntryNullable(TemperatureLogic.INSTANCE); + TemperatureLogic temperatureLogic = targetNode.getData().getLogicEntryNullable(TemperatureLogic.TYPE); if (temperatureLogic != null) { FluidContainmentLogic containmentLogic = targetNode.getData() - .getLogicEntryDefaultable(FluidContainmentLogic.INSTANCE); + .getLogicEntryDefaultable(FluidContainmentLogic.TYPE); boolean overMax = fluidTemp > containmentLogic.getMaximumTemperature() && !(state == FluidState.PLASMA && containmentLogic.contains(FluidState.PLASMA)); temperatureLogic.moveTowardsTemperature(fluidTemp, @@ -181,9 +181,9 @@ public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNo } private void recordFlow(@NotNull NetNode node, long flow) { - FluidFlowLogic logic = node.getData().getLogicEntryNullable(FluidFlowLogic.INSTANCE); + FluidFlowLogic logic = node.getData().getLogicEntryNullable(FluidFlowLogic.TYPE); if (logic == null) { - logic = FluidFlowLogic.INSTANCE.getNew(); + logic = FluidFlowLogic.TYPE.getNew(); node.getData().setLogicEntry(logic); } logic.recordFlow(getQueryTick(), getTestObject().recombine(GTUtility.safeCastLongToInt(flow))); diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 75423e3d62a..b6895c1c6e3 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -57,27 +57,27 @@ public boolean supportsPredication() { @Override protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { super.coverPredication(edge, a, b); - if (edge.getPredicateHandler().hasPredicate(BlockedPredicate.INSTANCE)) return; + if (edge.getPredicateHandler().hasPredicate(BlockedPredicate.TYPE)) return; FilterPredicate predicate = null; if (a instanceof CoverWithFluidFilter filter) { if (filter.getManualMode() == ManualImportExportMode.DISABLED) { edge.getPredicateHandler().clearPredicates(); - edge.getPredicateHandler().setPredicate(BlockedPredicate.INSTANCE); + edge.getPredicateHandler().setPredicate(BlockedPredicate.TYPE.getNew()); return; } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && filter.getFilterMode() != FluidFilterMode.FILTER_FILL) { - predicate = FilterPredicate.INSTANCE.getNew(); + predicate = FilterPredicate.TYPE.getNew(); predicate.setSourceFilter(filter.getFluidFilter()); } } if (b instanceof CoverWithFluidFilter filter) { if (filter.getManualMode() == ManualImportExportMode.DISABLED) { edge.getPredicateHandler().clearPredicates(); - edge.getPredicateHandler().setPredicate(BlockedPredicate.INSTANCE); + edge.getPredicateHandler().setPredicate(BlockedPredicate.TYPE.getNew()); return; } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && filter.getFilterMode() != FluidFilterMode.FILTER_DRAIN) { - if (predicate == null) predicate = FilterPredicate.INSTANCE.getNew(); + if (predicate == null) predicate = FilterPredicate.TYPE.getNew(); predicate.setTargetFilter(filter.getFluidFilter()); } } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java index 068abe32267..b7471316f94 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java @@ -1,6 +1,8 @@ package gregtech.common.pipelike.net.item; +import gregtech.api.GTValues; import gregtech.api.graphnet.logic.AbstractTransientLogicData; +import gregtech.api.graphnet.logic.NetLogicType; import net.minecraft.item.ItemStack; import net.minecraftforge.fml.common.FMLCommonHandler; @@ -15,15 +17,17 @@ public class ItemFlowLogic extends AbstractTransientLogicData { - public static final ItemFlowLogic INSTANCE = new ItemFlowLogic(); + public static final NetLogicType TYPE = new NetLogicType<>(GTValues.MODID, "ItemFlow", + ItemFlowLogic::new, new ItemFlowLogic()); public static final int MEMORY_TICKS = 10; private final Long2ObjectOpenHashMap> memory = new Long2ObjectOpenHashMap<>(); private ItemStack last; - protected ItemFlowLogic() { - super("ItemFlow"); + @Override + public @NotNull NetLogicType getType() { + return TYPE; } public @NotNull Long2ObjectOpenHashMap> getMemory() { @@ -55,9 +59,4 @@ private void updateMemory(long tick) { } } } - - @Override - public @NotNull ItemFlowLogic getNew() { - return new ItemFlowLogic(); - } } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java index 41e654894f1..a18d5d37835 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java @@ -73,9 +73,9 @@ public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNo } private void recordFlow(@NotNull NetNode node, long flow) { - ItemFlowLogic logic = node.getData().getLogicEntryNullable(ItemFlowLogic.INSTANCE); + ItemFlowLogic logic = node.getData().getLogicEntryNullable(ItemFlowLogic.TYPE); if (logic == null) { - logic = ItemFlowLogic.INSTANCE.getNew(); + logic = ItemFlowLogic.TYPE.getNew(); node.getData().setLogicEntry(logic); } logic.recordFlow(getQueryTick(), getTestObject().recombine(GTUtility.safeCastLongToInt(flow))); diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 39e92b08ad2..6e6ccd1226b 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -57,27 +57,27 @@ public boolean supportsPredication() { @Override protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { super.coverPredication(edge, a, b); - if (edge.getPredicateHandler().hasPredicate(BlockedPredicate.INSTANCE)) return; + if (edge.getPredicateHandler().hasPredicate(BlockedPredicate.TYPE)) return; FilterPredicate predicate = null; if (a instanceof CoverWithItemFilter filter) { if (filter.getManualMode() == ManualImportExportMode.DISABLED) { edge.getPredicateHandler().clearPredicates(); - edge.getPredicateHandler().setPredicate(BlockedPredicate.INSTANCE); + edge.getPredicateHandler().setPredicate(BlockedPredicate.TYPE.getNew()); return; } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && filter.getFilterMode() != ItemFilterMode.FILTER_INSERT) { - predicate = FilterPredicate.INSTANCE.getNew(); + predicate = FilterPredicate.TYPE.getNew(); predicate.setSourceFilter(filter.getItemFilter()); } } if (b instanceof CoverWithItemFilter filter) { if (filter.getManualMode() == ManualImportExportMode.DISABLED) { edge.getPredicateHandler().clearPredicates(); - edge.getPredicateHandler().setPredicate(BlockedPredicate.INSTANCE); + edge.getPredicateHandler().setPredicate(BlockedPredicate.TYPE.getNew()); return; } else if (filter.getManualMode() == ManualImportExportMode.FILTERED && filter.getFilterMode() != ItemFilterMode.FILTER_EXTRACT) { - if (predicate == null) predicate = FilterPredicate.INSTANCE.getNew(); + if (predicate == null) predicate = FilterPredicate.TYPE.getNew(); predicate.setTargetFilter(filter.getItemFilter()); } } diff --git a/src/main/java/gregtech/core/CoreModule.java b/src/main/java/gregtech/core/CoreModule.java index 5e80c4b3b31..a4fb58573e6 100644 --- a/src/main/java/gregtech/core/CoreModule.java +++ b/src/main/java/gregtech/core/CoreModule.java @@ -134,6 +134,7 @@ public Logger getLogger() { @Override public void preInit(FMLPreInitializationEvent event) { GregTechAPIInternal.preInit(); + GregTechAPI.advancementManager = AdvancementManager.getInstance(); AdvancementTriggers.register(); diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java index 990ebbf46ad..f868ad6b133 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java @@ -43,15 +43,15 @@ public void addProbeInfo(ProbeMode probeMode, IProbeInfo iProbeInfo, EntityPlaye PipeTileEntity tile = pipe.getTileEntity(world, iProbeHitData.getPos()); if (tile != null) { for (NetLogicData data : tile.getNetLogicDatas().values()) { - EnergyFlowLogic energy = data.getLogicEntryNullable(EnergyFlowLogic.INSTANCE); + EnergyFlowLogic energy = data.getLogicEntryNullable(EnergyFlowLogic.TYPE); if (energy != null) { addEnergyFlowInformation(probeMode, iProbeInfo, entityPlayer, iProbeHitData, energy); } - FluidFlowLogic fluid = data.getLogicEntryNullable(FluidFlowLogic.INSTANCE); + FluidFlowLogic fluid = data.getLogicEntryNullable(FluidFlowLogic.TYPE); if (fluid != null) { addFluidFlowInformation(probeMode, iProbeInfo, entityPlayer, iProbeHitData, fluid); } - ItemFlowLogic item = data.getLogicEntryNullable(ItemFlowLogic.INSTANCE); + ItemFlowLogic item = data.getLogicEntryNullable(ItemFlowLogic.TYPE); if (item != null) { addItemFlowInformation(probeMode, iProbeInfo, entityPlayer, iProbeHitData, item); } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 2ba1def719c..d3582f169f7 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -5379,6 +5379,8 @@ gregtech.universal.tooltip.base_production_fluid=§eBase Production: §f%,d L/t gregtech.universal.tooltip.produces_fluid=§eProduces: §f%,d L/t gregtech.universal.tooltip.terrain_resist=This Machine will not explode when exposed to the Elements gregtech.universal.tooltip.requires_redstone=§4Requires Redstone power +gregtech.universal.netlogicdisconnect=Failed to decode an encoded NetLogicEntry. This suggests that the server and client have different GT versions or modifications. +gregtech.universal.netpredicatedisconnect=Failed to decode an encoded EdgePredicate. This suggests that the server and client have different GT versions or modifications. gregtech.block.tooltip.no_mob_spawning=§bMobs cannot spawn on this block From 3dfb46fa4c7ae3bc952a24688402d73f2b7ce1db Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Sat, 26 Oct 2024 13:58:01 -0600 Subject: [PATCH 146/157] New energy net impl (broken commit) --- .../api/graphnet/AbstractGroupData.java | 20 -- .../gregtech/api/graphnet/GraphNetBacker.java | 61 +--- .../java/gregtech/api/graphnet/IGraphNet.java | 33 +- .../java/gregtech/api/graphnet/NetGroup.java | 191 ----------- .../java/gregtech/api/graphnet/NetNode.java | 37 +-- .../DynamicWeightsShortestPathsAlgorithm.java | 10 +- .../api/graphnet/alg/INetAlgorithm.java | 6 +- .../api/graphnet/alg/NetAlgorithmWrapper.java | 12 +- .../api/graphnet/alg/NetPathMapper.java | 39 --- .../graphnet/alg/ShortestPathsAlgorithm.java | 10 +- .../api/graphnet/alg/SinglePathAlgorithm.java | 6 +- .../gregtech/api/graphnet/edge/NetEdge.java | 14 +- .../api/graphnet/graph/INetGraph.java | 8 - .../api/graphnet/graph/NetDirectedGraph.java | 34 -- .../graphnet/graph/NetUndirectedGraph.java | 34 -- .../api/graphnet/group/GroupData.java | 97 ++++++ .../api/graphnet/group/MergeDirection.java | 21 ++ .../gregtech/api/graphnet/group/NetGroup.java | 228 +++++++++++++ .../graphnet/group/PathCacheGroupData.java | 180 ++++++++++ .../api/graphnet/path/AbstractNetPath.java | 90 ----- .../graphnet/path/GenericGraphNetPath.java | 44 --- .../gregtech/api/graphnet/path/INetPath.java | 35 -- .../gregtech/api/graphnet/path/NetPath.java | 43 +++ .../api/graphnet/path/PathBuilder.java | 21 ++ .../api/graphnet/path/SingletonNetPath.java | 70 ++++ .../api/graphnet/path/StandardNetPath.java | 183 +++++++++++ .../pipenet/BasicWorldPipeNetPath.java | 44 --- .../pipenet/FlowWorldPipeNetPath.java | 44 --- .../api/graphnet/servernet/ServerNet.java | 10 +- .../traverse/AbstractTraverseData.java | 4 +- .../traverse/IEqualizableTraverseData.java | 6 +- .../traverse/IRoundRobinTraverseData.java | 6 +- .../api/graphnet/traverse/ITraverseData.java | 4 +- .../traverse/ITraverseGuideProvider.java | 4 +- .../api/graphnet/traverse/TraverseGuide.java | 4 +- .../graphnet/traverse/TraverseHelpers.java | 32 +- .../graphnet/traverse/iter/EdgeDirection.java | 20 ++ .../traverse/iter/NetBreadthIterator.java | 74 +++++ .../traverse/iter/NetClosestIterator.java | 54 +++ .../graphnet/traverse/iter/NetIterator.java | 15 + .../traverse/iter/NetIteratorSupplier.java | 12 + .../api/graphnet/worldnet/WorldNet.java | 15 +- .../properties/MaterialEnergyProperties.java | 6 +- .../common/pipelike/net/SlowActiveWalker.java | 19 +- .../net/energy/AmperageLimitLogic.java | 25 ++ .../net/energy/EnergyCapabilityObject.java | 136 +++----- .../pipelike/net/energy/EnergyGroupData.java | 43 ++- .../pipelike/net/energy/EnergyPath.java | 44 +++ .../net/energy/EnergyTraverseData.java | 229 ------------- .../net/energy/StandardEnergyPath.java | 307 ++++++++++++++++++ .../pipelike/net/energy/VoltageLossLogic.java | 8 +- .../pipelike/net/energy/WorldEnergyNet.java | 23 +- .../net/fluid/FluidCapabilityObject.java | 1 - .../net/fluid/FluidEQTraverseData.java | 1 - .../net/fluid/FluidRRTraverseData.java | 1 - .../pipelike/net/fluid/FluidTraverseData.java | 1 - .../fluid/IFluidTraverseGuideProvider.java | 1 - .../pipelike/net/fluid/WorldFluidNet.java | 1 - .../net/item/IItemTraverseGuideProvider.java | 1 - .../net/item/ItemCapabilityObject.java | 1 - .../pipelike/net/item/ItemEQTraverseData.java | 1 - .../pipelike/net/item/ItemRRTraverseData.java | 1 - .../pipelike/net/item/ItemTraverseData.java | 1 - .../pipelike/net/item/WorldItemNet.java | 1 - .../net/laser/LaserCapabilityObject.java | 98 ++++-- .../pipelike/net/laser/WorldLaserNet.java | 23 +- .../net/optical/DataCapabilityObject.java | 78 ++--- .../pipelike/net/optical/WorldOpticalNet.java | 23 +- 68 files changed, 1708 insertions(+), 1241 deletions(-) delete mode 100644 src/main/java/gregtech/api/graphnet/AbstractGroupData.java delete mode 100644 src/main/java/gregtech/api/graphnet/NetGroup.java delete mode 100644 src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java create mode 100644 src/main/java/gregtech/api/graphnet/group/GroupData.java create mode 100644 src/main/java/gregtech/api/graphnet/group/MergeDirection.java create mode 100644 src/main/java/gregtech/api/graphnet/group/NetGroup.java create mode 100644 src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java delete mode 100644 src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java delete mode 100644 src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java delete mode 100644 src/main/java/gregtech/api/graphnet/path/INetPath.java create mode 100644 src/main/java/gregtech/api/graphnet/path/NetPath.java create mode 100644 src/main/java/gregtech/api/graphnet/path/PathBuilder.java create mode 100644 src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java create mode 100644 src/main/java/gregtech/api/graphnet/path/StandardNetPath.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/AmperageLimitLogic.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/EnergyPath.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java create mode 100644 src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java diff --git a/src/main/java/gregtech/api/graphnet/AbstractGroupData.java b/src/main/java/gregtech/api/graphnet/AbstractGroupData.java deleted file mode 100644 index 677d06d211c..00000000000 --- a/src/main/java/gregtech/api/graphnet/AbstractGroupData.java +++ /dev/null @@ -1,20 +0,0 @@ -package gregtech.api.graphnet; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public abstract class AbstractGroupData { - - protected NetGroup group; - - public void withGroup(NetGroup group) { - this.group = group; - } - - public abstract boolean mergeAllowed(@NotNull AbstractGroupData other); - - @Nullable - public AbstractGroupData merge(@NotNull AbstractGroupData other) { - return null; - } -} diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index a568287e564..9e5707abed7 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -1,16 +1,11 @@ package gregtech.api.graphnet; -import gregtech.api.graphnet.alg.AlgorithmBuilder; -import gregtech.api.graphnet.alg.NetAlgorithmWrapper; -import gregtech.api.graphnet.alg.NetPathMapper; -import gregtech.api.graphnet.alg.iter.IteratorFactory; import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.graph.INetGraph; -import gregtech.api.graphnet.path.INetPath; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.group.MergeDirection; +import gregtech.api.graphnet.group.NetGroup; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -23,30 +18,20 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collections; -import java.util.Iterator; - /** * The bridge between JGraphT graphs and graphnet abstractions. * Doesn't do any automatic linking, weighting, predicating, etc. Simply handles storing the JGraphT graph to disk, - * interfacing with graph algorithms, and interacting with the JGraphT graph. + * interacting with the JGraphT graph, and managing NetGroups. */ public final class GraphNetBacker { private final IGraphNet backedNet; private final INetGraph pipeGraph; private final Object2ObjectOpenHashMap vertexMap; - private final NetAlgorithmWrapper[] netAlgorithms; - public GraphNetBacker(IGraphNet backedNet, INetGraph graph, - AlgorithmBuilder @NotNull... algorithmBuilders) { + public GraphNetBacker(IGraphNet backedNet, INetGraph graph) { this.backedNet = backedNet; this.pipeGraph = graph; - this.netAlgorithms = new NetAlgorithmWrapper[algorithmBuilders.length]; - for (int i = 0; i < algorithmBuilders.length; i++) { - this.netAlgorithms[i] = new NetAlgorithmWrapper(backedNet, algorithmBuilders[i], - backedNet.supportsPredication() || backedNet.usesDynamicWeights(i)); - } this.vertexMap = new Object2ObjectOpenHashMap<>(); } @@ -76,7 +61,6 @@ public boolean removeNode(@Nullable NetNode node) { NetGroup group = node.getGroupUnsafe(); if (group != null) group.removeNode(node); } - if (!this.getGraph().edgesOf(node.wrapper).isEmpty()) this.invalidateAlgs(); NetGroup group = node.getGroupUnsafe(); if (group != null) { group.splitNode(node); @@ -97,11 +81,12 @@ public void removeVertex(GraphVertex vertex) { @Nullable public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, double weight) { - if (!NetGroup.isEdgeAllowed(source, target)) return null; + MergeDirection direction = NetGroup.isEdgeAllowed(source, target); + if (!direction.allowsEdgeCreation()) return null; GraphEdge graphEdge = getGraph().addEdge(source.wrapper, target.wrapper); if (graphEdge != null) { getGraph().setEdgeWeight(graphEdge, weight); - NetGroup.mergeEdge(source, target); + NetGroup.mergeEdge(graphEdge.wrapped, direction); backedNet.markDirty(); } return graphEdge == null ? null : graphEdge.wrapped; @@ -139,38 +124,6 @@ public boolean removeEdge(GraphEdge edge) { return false; } - /** - * Note - if an error is thrown with a stacktrace descending from this method, - * most likely a bad remapper was passed in.
- * This method should never be exposed outside the net this backer is backing due to this fragility. - */ - public > Iterator getPaths(@Nullable NetNode node, int algorithmID, - @NotNull NetPathMapper remapper, - IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, long queryTick) { - if (node == null) return Collections.emptyIterator(); - this.getGraph().setupInternal(this, backedNet.usesDynamicWeights(algorithmID)); - - Iterator> cache = node.getPathCache(testObject, simulator, queryTick); - if (cache != null) return (Iterator) cache; - - IteratorFactory factory = this.netAlgorithms[algorithmID] - .getPathsIterator(node.wrapper, remapper, testObject, simulator, queryTick); - if (factory.cacheable()) { - return (Iterator) (node.setPathCache(factory).getPathCache(testObject, simulator, queryTick)); - } else return factory.newIterator(getGraph(), testObject, simulator, queryTick); - } - - public void invalidateAlg(int algorithmID) { - this.netAlgorithms[algorithmID].invalidate(); - } - - public void invalidateAlgs() { - for (NetAlgorithmWrapper netAlgorithm : this.netAlgorithms) { - netAlgorithm.invalidate(); - } - } - public INetGraph getGraph() { return pipeGraph; } diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/IGraphNet.java index c8d58446a9d..8d69f69caec 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/IGraphNet.java @@ -1,9 +1,8 @@ package gregtech.api.graphnet; import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.graph.INetGraph; +import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; @@ -11,9 +10,6 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jgrapht.traverse.BreadthFirstIterator; - -import java.util.Iterator; public interface IGraphNet { @@ -114,7 +110,7 @@ default INetGraph getGraph() { * @return The correct data variant. */ @Nullable - default AbstractGroupData getBlankGroupData() { + default GroupData getBlankGroupData() { return null; } @@ -138,31 +134,6 @@ default boolean containsNode(NetNode node) { return getGraph().containsVertex(node.wrapper); } - /** - * Returns a breadth-first iterator through this graph, starting from the passed in node. - * - * @param node the node to start from. - * @return a breadth-first iterator through this graph. - */ - @NotNull - default Iterator breadthIterator(NetNode node) { - return new Iterator<>() { - - private final BreadthFirstIterator iterator = new BreadthFirstIterator<>(getGraph(), - node.wrapper); - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public NetNode next() { - return iterator.next().wrapped; - } - }; - } - /** * Used in {@link MultiNodeHelper} to determine if a node can be traversed, based on the nets that have been * recently traversed in the {@link MultiNodeHelper}. diff --git a/src/main/java/gregtech/api/graphnet/NetGroup.java b/src/main/java/gregtech/api/graphnet/NetGroup.java deleted file mode 100644 index 7b6f5d292d3..00000000000 --- a/src/main/java/gregtech/api/graphnet/NetGroup.java +++ /dev/null @@ -1,191 +0,0 @@ -package gregtech.api.graphnet; - -import gregtech.api.graphnet.graph.GraphVertex; - -import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Iterator; -import java.util.Set; -import java.util.stream.Collectors; - -public class NetGroup { - - public final IGraphNet net; - - private final Set nodes; - - private AbstractGroupData data; - - public NetGroup(IGraphNet net) { - this(net, new ObjectOpenHashSet<>()); - } - - public NetGroup(@NotNull IGraphNet net, - Set nodes) { - this.net = net; - this.data = net.getBlankGroupData(); - if (data != null) data.withGroup(this); - this.nodes = nodes; - nodes.forEach(this::onAddedToGroup); - } - - public void addNode(NetNode node) { - this.nodes.add(node); - this.onAddedToGroup(node); - } - - protected void addNodes(Collection nodes) { - this.nodes.addAll(nodes); - nodes.forEach(this::onAddedToGroup); - } - - protected void removeNode(NetNode node) { - this.nodes.remove(node); - } - - protected void removeNodes(Collection nodes) { - this.nodes.removeAll(nodes); - } - - protected void clearNodes() { - this.nodes.clear(); - } - - protected void onAddedToGroup(@NotNull NetNode node) { - node.setGroup(this); - } - - public static boolean isEdgeAllowed(@NotNull NetNode source, @NotNull NetNode target) { - NetGroup sourceGroup = source.getGroupUnsafe(); - NetGroup targetGroup = target.getGroupUnsafe(); - - if (sourceGroup == null || targetGroup == null) return true; - AbstractGroupData sourceData = sourceGroup.getData(); - AbstractGroupData targetData = targetGroup.getData(); - if (sourceData == null || targetData == null) return true; - - return sourceData.mergeAllowed(targetData) && targetData.mergeAllowed(sourceData); - } - - /** - * Merges the groups of an edge if necessary. Does not actually perform the edge creation. - * - * @param source the source node of the edge - * @param target the target node of the edge - */ - public static void mergeEdge(@NotNull NetNode source, @NotNull NetNode target) { - NetGroup sourceGroup = source.getGroupUnsafe(); - NetGroup targetGroup = target.getGroupUnsafe(); - if (sourceGroup == targetGroup) { - if (sourceGroup == null) { - sourceGroup = source.getGroupSafe(); - } else { - sourceGroup.clearPathCaches(); - return; - } - } - if (sourceGroup != null) { - sourceGroup.mergeNode(target); - } else { - targetGroup.mergeNode(source); - } - } - - protected void mergeNode(@NotNull NetNode node) { - NetGroup group = node.getGroupUnsafe(); - if (group != null) { - this.addNodes(group.getNodes()); - group.clearNodes(); - AbstractGroupData data = group.getData(); - if (data != null) { - if (this.data == null) this.data = data; - else this.data.merge(data); - } - } else addNode(node); - this.clearPathCaches(); - } - - /** - * Split this group by removing a node. Automatically removes the node from the backing graph. - * - * @param source node to remove - */ - public void splitNode(NetNode source) { - if (!this.net.containsNode(source)) return; - this.clearPathCaches(); - ObjectLinkedOpenHashSet targets = this.net.getGraph().outgoingEdgesOf(source.wrapper).stream() - .map(a -> { - GraphVertex target = a.getTarget(); - // handling so undirected graphs don't throw an error - if (!net.getGraph().isDirected() && target == source.wrapper) - return a.getSource().wrapped; - return target.wrapped; - }).collect(Collectors.toCollection(ObjectLinkedOpenHashSet::new)); - this.net.getBacker().removeVertex(source.wrapper); - this.removeNode(source); - while (!targets.isEmpty()) { - NetNode target = targets.removeLast(); - - Set targetGroup = new ObjectOpenHashSet<>(); - Iterator i = this.net.breadthIterator(target); - NetNode temp; - while (i.hasNext()) { - temp = i.next(); - if (temp == source) continue; - targetGroup.add(temp); - // if we find a target node in our search, remove it from the list - targets.remove(temp); - } - this.removeNodes(targetGroup); - if (!targetGroup.isEmpty()) { - new NetGroup(this.net, targetGroup); - } - } - } - - /** - * Split this group by removing an edge. Automatically removes the edge from the graph. - * - * @param source source of the edge - * @param target target of the edge - * @return Whether the edge existed in the graph - */ - public boolean splitEdge(@NotNull NetNode source, @NotNull NetNode target) { - if (this.net.getBacker().removeEdge(source.wrapper, target.wrapper) != null) { - this.clearPathCaches(); - Set targetGroup = new ObjectOpenHashSet<>(); - Iterator i = this.net.breadthIterator(target); - NetNode temp; - while (i.hasNext()) { - temp = i.next(); - // if there's another complete path to the source node from the target node, there's no need to split - if (source == temp) return true; - targetGroup.add(temp); - } - this.removeNodes(targetGroup); - if (targetGroup.size() != 0) { - new NetGroup(this.net, targetGroup); - } - return true; - } - return false; - } - - /** - * For memory considerations, returns the uncloned set. Do not modify this directly. - */ - public Set getNodes() { - return nodes; - } - - public void clearPathCaches() { - this.getNodes().forEach(NetNode::clearPathCache); - } - - public AbstractGroupData getData() { - return this.data; - } -} diff --git a/src/main/java/gregtech/api/graphnet/NetNode.java b/src/main/java/gregtech/api/graphnet/NetNode.java index d659506081c..1d562728f69 100644 --- a/src/main/java/gregtech/api/graphnet/NetNode.java +++ b/src/main/java/gregtech/api/graphnet/NetNode.java @@ -1,11 +1,8 @@ package gregtech.api.graphnet; -import gregtech.api.graphnet.alg.iter.IteratorFactory; -import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.path.INetPath; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -15,7 +12,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Iterator; import java.util.Objects; public abstract class NetNode implements INBTSerializable { @@ -32,9 +28,6 @@ public abstract class NetNode implements INBTSerializable { private final @NotNull NetLogicData data; private @Nullable NetGroup group = null; - @Nullable - private IteratorFactory> pathCache = null; - public NetNode(@NotNull IGraphNet net) { this.net = net; this.data = net.getDefaultNodeData(); @@ -58,8 +51,7 @@ public void setActive(boolean active) { if (isActive != active) { isActive = active; NetGroup group = getGroupUnsafe(); - if (group != null) group.clearPathCaches(); - else this.clearPathCache(); + if (group != null) group.notifyActiveChange(this, active); } } @@ -71,28 +63,6 @@ public boolean traverse(long queryTick, boolean simulate) { return true; } - @Nullable - public Iterator> getPathCache(IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, long queryTick) { - if (pathCache == null) return null; - return pathCache.newIterator(net.getGraph(), testObject, simulator, queryTick); - } - - /** - * Sets the path cache to the provided iterator factory. Returns itself for convenience. - * - * @param pathCache The new cache. - * @return The new cache. - */ - public NetNode setPathCache(IteratorFactory> pathCache) { - this.pathCache = pathCache; - return this; - } - - public void clearPathCache() { - this.pathCache = null; - } - @NotNull public NetGroup getGroupSafe() { if (this.group == null) { @@ -107,9 +77,8 @@ public NetGroup getGroupUnsafe() { return this.group; } - public NetGroup setGroup(NetGroup group) { + public void setGroup(@NotNull NetGroup group) { this.group = group; - return group; } /** diff --git a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java index 381268fb87f..a4e970c8add 100644 --- a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java @@ -5,7 +5,7 @@ import gregtech.api.graphnet.alg.iter.IteratorFactory; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.Nullable; @@ -31,8 +31,8 @@ public DynamicWeightsShortestPathsAlgorithm(IGraphNet net, boolean recomputeEver } @Override - public > IteratorFactory getPathsIteratorFactory(GraphVertex source, - NetPathMapper remapper) { + public > IteratorFactory getPathsIteratorFactory(GraphVertex source, + NetPathMapper remapper) { Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream().filter(NetNode::isActive) .map(n -> n.wrapper).filter(node -> !(source == node) && graph.containsVertex(node)) .collect(Collectors.toSet()); @@ -42,7 +42,7 @@ public DynamicWeightsShortestPathsAlgorithm(IGraphNet net, boolean recomputeEver }; } - protected class LimitedIterator> implements Iterator { + protected class LimitedIterator> implements Iterator { private static final int MAX_ITERATIONS = 100; @@ -84,7 +84,7 @@ private void calculateNext() { ManyToManyShortestPaths paths = getManyToManyPaths(Collections.singleton(source), searchSpace); Optional next = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) - .map(remapper::map).filter(this::isUnique).min(Comparator.comparingDouble(INetPath::getWeight)); + .map(remapper::map).filter(this::isUnique).min(Comparator.comparingDouble(NetPath::getWeight)); this.next = next.orElse(null); next.ifPresent(this.visited::add); } diff --git a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java index dcb84e5a66f..f3022917ea9 100644 --- a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java @@ -2,10 +2,10 @@ import gregtech.api.graphnet.alg.iter.IteratorFactory; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; public interface INetAlgorithm { - > IteratorFactory getPathsIteratorFactory(GraphVertex source, - NetPathMapper remapper); + > IteratorFactory getPathsIteratorFactory(GraphVertex source, + NetPathMapper remapper); } diff --git a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java index 54f1e19ec0e..1639b1fb4f4 100644 --- a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java +++ b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java @@ -4,7 +4,7 @@ import gregtech.api.graphnet.alg.iter.IteratorFactory; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import org.jetbrains.annotations.NotNull; @@ -33,11 +33,11 @@ public void invalidate() { this.alg = null; } - public > IteratorFactory getPathsIterator(GraphVertex source, - NetPathMapper remapper, - IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, - long queryTick) { + public > IteratorFactory getPathsIterator(GraphVertex source, + NetPathMapper remapper, + IPredicateTestObject testObject, + @Nullable SimulatorKey simulator, + long queryTick) { if (!recomputeEveryCall) net.getGraph().prepareForAlgorithmRun(testObject, simulator, queryTick); if (alg == null) alg = builder.build(net, recomputeEveryCall); return alg.getPathsIteratorFactory(source, remapper); diff --git a/src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java b/src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java deleted file mode 100644 index 816a40232ad..00000000000 --- a/src/main/java/gregtech/api/graphnet/alg/NetPathMapper.java +++ /dev/null @@ -1,39 +0,0 @@ -package gregtech.api.graphnet.alg; - -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.path.INetPath; -import gregtech.api.util.function.TriFunction; - -import org.jetbrains.annotations.NotNull; -import org.jgrapht.GraphPath; - -import java.util.List; -import java.util.function.Function; - -public class NetPathMapper> { - - private final Function singlePathMapper; - private final TriFunction, List, @NotNull Double, Path> fullConstructMapper; - private final Function, Path> graphPathMapper; - - public NetPathMapper(Function singlePathMapper, - TriFunction, List, @NotNull Double, Path> fullConstructMapper, - Function, Path> graphPathMapper) { - this.singlePathMapper = singlePathMapper; - this.fullConstructMapper = fullConstructMapper; - this.graphPathMapper = graphPathMapper; - } - - public Path map(GraphVertex graphVertex) { - return singlePathMapper.apply(graphVertex); - } - - public Path map(List vertices, List graphEdges, double weight) { - return fullConstructMapper.apply(vertices, graphEdges, weight); - } - - public Path map(GraphPath graphPath) { - return graphPathMapper.apply(graphPath); - } -} diff --git a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java index 0e70d04b2da..61f4fe8faa7 100644 --- a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java @@ -6,7 +6,7 @@ import gregtech.api.graphnet.alg.iter.SimpleIteratorFactories; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; @@ -26,8 +26,8 @@ public ShortestPathsAlgorithm(IGraphNet net, boolean recomputeEveryCall) { } @Override - public > IteratorFactory getPathsIteratorFactory(GraphVertex source, - NetPathMapper remapper) { + public > IteratorFactory getPathsIteratorFactory(GraphVertex source, + NetPathMapper remapper) { if (!graph.containsVertex(source)) { throw new IllegalArgumentException("Graph must contain the source vertex"); } @@ -47,14 +47,14 @@ public ShortestPathsAlgorithm(IGraphNet net, boolean recomputeEveryCall) { ManyToManyShortestPaths manyToManyPaths = getManyToManyPaths(singleton, searchSpace); return searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)) - .map(remapper::map).sorted(Comparator.comparingDouble(INetPath::getWeight)).iterator(); + .map(remapper::map).sorted(Comparator.comparingDouble(NetPath::getWeight)).iterator(); }; } else { ManyToManyShortestPaths manyToManyPaths = getManyToManyPaths(singleton, searchSpace); return SimpleIteratorFactories.fromIterable(searchSpace.stream() .map(node -> manyToManyPaths.getPath(source, node)) - .map(remapper::map).sorted(Comparator.comparingDouble(INetPath::getWeight)) + .map(remapper::map).sorted(Comparator.comparingDouble(NetPath::getWeight)) .collect(Collectors.toList())); } } diff --git a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java index 3c73b8c78d4..c0e3963479b 100644 --- a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java +++ b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java @@ -5,7 +5,7 @@ import gregtech.api.graphnet.alg.iter.SimpleIteratorFactories; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import com.github.bsideup.jabel.Desugar; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -24,8 +24,8 @@ public SinglePathAlgorithm(IGraphNet pipenet, boolean recomputeEveryCall) { } @Override - public > IteratorFactory getPathsIteratorFactory(GraphVertex source, - NetPathMapper remapper) { + public > IteratorFactory getPathsIteratorFactory(GraphVertex source, + NetPathMapper remapper) { if (recomputeEveryCall) { return (graph, testObject, simulator, queryTick) -> { graph.prepareForAlgorithmRun(testObject, simulator, queryTick); diff --git a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java index 7ca69a83f79..36714d98be0 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java @@ -27,16 +27,26 @@ public class NetEdge implements INBTSerializable { private @Nullable NetLogicData data; - protected @Nullable NetNode getSource() { + public @Nullable NetNode getSource() { if (wrapper == null) return null; return wrapper.getSource().wrapped; } - protected @Nullable NetNode getTarget() { + public @Nullable NetNode getTarget() { if (wrapper == null) return null; return wrapper.getTarget().wrapped; } + public @Nullable NetNode getOppositeNode(@NotNull NetNode node) { + if (getSource() == node) return getTarget(); + else if (getTarget() == node) return getSource(); + else return null; + } + + public double getWeight() { + return wrapper == null ? Double.POSITIVE_INFINITY : wrapper.getWeight(); + } + /** * Should only be used on fake edges that are not registered to the graph. */ diff --git a/src/main/java/gregtech/api/graphnet/graph/INetGraph.java b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java index 05edbcecc16..96499a11b87 100644 --- a/src/main/java/gregtech/api/graphnet/graph/INetGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java @@ -9,13 +9,5 @@ public interface INetGraph extends Graph { - void prepareForAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, long queryTick); - boolean isDirected(); - - /** - * This should only be called by {@link GraphNetBacker} - */ - @ApiStatus.Internal - void setupInternal(GraphNetBacker backer, boolean dynamicWeights); } diff --git a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java index e86b5709fc8..f96cd54e561 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java @@ -12,49 +12,15 @@ public class NetDirectedGraph extends SimpleDirectedWeightedGraph implements INetGraph { - private boolean dynamicWeights; - private IGraphNet net; - - private IPredicateTestObject testObject; - private SimulatorKey simulator; - private long queryTick; - public NetDirectedGraph(Supplier vertexSupplier, Supplier edgeSupplier) { super(vertexSupplier, edgeSupplier); } - @Override - public void prepareForAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, long queryTick) { - this.testObject = testObject; - this.simulator = simulator; - this.queryTick = queryTick; - } - @Override public boolean isDirected() { return true; } - @Override - public void setupInternal(GraphNetBacker backer, boolean dynamicWeights) { - this.net = backer.getBackedNet(); - this.dynamicWeights = dynamicWeights; - } - - @Override - public double getEdgeWeight(GraphEdge graphEdge) { - if (!graphEdge.getSource().wrapped.traverse(queryTick, true) || - !graphEdge.getTarget().wrapped.traverse(queryTick, true)) - return Double.POSITIVE_INFINITY; - - if (graphEdge.wrapped.test(testObject)) { - if (dynamicWeights) { - return graphEdge.wrapped.getDynamicWeight(testObject, net, simulator, queryTick, - graphEdge.getWeight()); - } else return graphEdge.getWeight(); - } else return Double.POSITIVE_INFINITY; - } - public static Function standardBuilder() { return iGraphNet -> new NetDirectedGraph(() -> new GraphVertex(iGraphNet.getNewNode()), () -> new GraphEdge(iGraphNet.getNewEdge())); diff --git a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java index 8946773f418..8aa894f0816 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java @@ -12,49 +12,15 @@ public class NetUndirectedGraph extends SimpleWeightedGraph implements INetGraph { - private boolean dynamicWeights; - private IGraphNet net; - - private IPredicateTestObject testObject; - private SimulatorKey simulator; - private long queryTick; - public NetUndirectedGraph(Supplier vertexSupplier, Supplier edgeSupplier) { super(vertexSupplier, edgeSupplier); } - @Override - public void prepareForAlgorithmRun(IPredicateTestObject testObject, SimulatorKey simulator, long queryTick) { - this.testObject = testObject; - this.simulator = simulator; - this.queryTick = queryTick; - } - @Override public boolean isDirected() { return false; } - @Override - public void setupInternal(GraphNetBacker backer, boolean dynamicWeights) { - this.net = backer.getBackedNet(); - this.dynamicWeights = dynamicWeights; - } - - @Override - public double getEdgeWeight(GraphEdge graphEdge) { - if (!graphEdge.getSource().wrapped.traverse(queryTick, true) || - !graphEdge.getTarget().wrapped.traverse(queryTick, true)) - return Double.POSITIVE_INFINITY; - - if (graphEdge.wrapped.test(testObject)) { - if (dynamicWeights) { - return graphEdge.wrapped.getDynamicWeight(testObject, net, simulator, queryTick, - graphEdge.getWeight()); - } else return graphEdge.getWeight(); - } else return Double.POSITIVE_INFINITY; - } - public static Function standardBuilder() { return iGraphNet -> new NetUndirectedGraph(() -> new GraphVertex(iGraphNet.getNewNode()), () -> new GraphEdge(iGraphNet.getNewEdge())); diff --git a/src/main/java/gregtech/api/graphnet/group/GroupData.java b/src/main/java/gregtech/api/graphnet/group/GroupData.java new file mode 100644 index 00000000000..aa49b3847a5 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/group/GroupData.java @@ -0,0 +1,97 @@ +package gregtech.api.graphnet.group; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; + +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.MustBeInvokedByOverriders; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Set; + +public abstract class GroupData { + + private static final Pair EMPTY = ImmutablePair.of(null, null); + + private NetGroup group; + + @MustBeInvokedByOverriders + public void withGroup(@NotNull NetGroup group) { + this.group = group; + } + + @Nullable + public NetGroup getGroup() { + return group; + } + + /** + * Used to determine if merging two groups is allowed. Will be called in both directions. If the merge is allowed, + * {@link #mergeAcross(GroupData, NetEdge)} will be called later after the graph is modified. + * + * @param other the group data of the other group + * @return whether they can be merged. Completely blocks edge creation if false. + */ + protected boolean mergeAllowed(@Nullable GroupData other) { + return other == null || other.getClass() == this.getClass(); + } + + /** + * Used to determine if merging two groups is allowed. Will test both directions. If the merge is allowed, + * {@link #mergeAcross(GroupData, NetEdge)} will be called later after the graph is modified. + * + * @param source the first group data + * @param target the second group data + * @return which datas authorized the merge. Completely blocks edge creation if none. + */ + @NotNull + public static MergeDirection mergeAllowed(@Nullable GroupData source, @Nullable GroupData target) { + if (source != null && source.mergeAllowed(target)) return MergeDirection.SOURCE; + if (target != null && target.mergeAllowed(source)) return MergeDirection.TARGET; + return MergeDirection.NONE; + } + + /** + * Called when a new edge bridges the interior of a net group rather than connecting two separate net groups. + * + * @param edge the bridging edge + */ + public void notifyOfBridgingEdge(@NotNull NetEdge edge) {} + + /** + * Called when an edge belonging to a group is removed, before the graph is modified. If this splits the group, + * {@link #splitAcross(Set, Set)} will be called later after the graph is modified. + * + * @param edge the edge removed. + */ + public void notifyOfRemovedEdge(@NotNull NetEdge edge) {} + + /** + * Merge data across an edge. Accompanies the process of merging groups. + * + * @param other the group data to merge with. + * @param edge the edge merged across + * @return the result of the merge. + */ + @Nullable + protected GroupData mergeAcross(@Nullable GroupData other, @NotNull NetEdge edge) { + if (other != null) return null; + else return this; + } + + /** + * Split data across an edge. Accompanies the process of splitting groups. + * + * @param sourceNodes the first set of nodes. + * @param targetNodes the second set of nodes. + * @return a pair, where the first value is the group data associated with the first set of nodes, and the second + * value is the group data associated with the second set of nodes. + */ + @NotNull + public Pair splitAcross(@NotNull Set sourceNodes, + @NotNull Set targetNodes) { + return EMPTY; + } +} diff --git a/src/main/java/gregtech/api/graphnet/group/MergeDirection.java b/src/main/java/gregtech/api/graphnet/group/MergeDirection.java new file mode 100644 index 00000000000..931febed56a --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/group/MergeDirection.java @@ -0,0 +1,21 @@ +package gregtech.api.graphnet.group; + +public enum MergeDirection { + + NONE, + SOURCE, + TARGET, + NULL; + + public boolean allowsEdgeCreation() { + return this != NONE; + } + + public boolean source() { + return this == SOURCE; + } + + public boolean target() { + return this == TARGET; + } +} diff --git a/src/main/java/gregtech/api/graphnet/group/NetGroup.java b/src/main/java/gregtech/api/graphnet/group/NetGroup.java new file mode 100644 index 00000000000..8dc43258157 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/group/NetGroup.java @@ -0,0 +1,228 @@ +package gregtech.api.graphnet.group; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.traverse.iter.EdgeDirection; +import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; + +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; +import org.jgrapht.Graphs; + +import java.util.Collection; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public final class NetGroup { + + public final IGraphNet net; + + private final @NotNull Set nodes; + + private final @NotNull Set activeNodes; + + private @Nullable GroupData data; + + public NetGroup(IGraphNet net) { + this(net, new ObjectOpenHashSet<>(), new ObjectOpenHashSet<>()); + } + + public NetGroup(@NotNull IGraphNet net, @NotNull Set nodes) { + this(net, nodes, net.getBlankGroupData()); + } + + public NetGroup(@NotNull IGraphNet net, @NotNull Set nodes, @Nullable GroupData data) { + this(net, nodes, nodes.stream().filter(NetNode::isActive) + .collect(ObjectOpenHashSet::new, ObjectOpenHashSet::add, ObjectOpenHashSet::addAll), data); + } + + public NetGroup(@NotNull IGraphNet net, @NotNull Set nodes, @NotNull Set activeNodes) { + this(net, nodes, activeNodes, net.getBlankGroupData()); + } + + public NetGroup(@NotNull IGraphNet net, @NotNull Set nodes, @NotNull Set activeNodes, + @Nullable GroupData data) { + this.net = net; + this.data = data; + if (data != null) data.withGroup(this); + this.nodes = nodes; + this.activeNodes = activeNodes; + nodes.forEach(this::onAddedToGroup); + } + + public void addNode(NetNode node) { + this.nodes.add(node); + this.onAddedToGroup(node); + if (node.isActive()) activeNodes.add(node); + } + + private void addNodes(Collection nodes) { + this.nodes.addAll(nodes); + nodes.stream().peek(this::onAddedToGroup).filter(NetNode::isActive).forEach(this.activeNodes::add); + } + + @ApiStatus.Internal + public void removeNode(NetNode node) { + this.nodes.remove(node); + } + + private void removeNodes(Collection nodes) { + this.nodes.removeAll(nodes); + } + + private void clearNodes() { + this.nodes.clear(); + } + + private void onAddedToGroup(@NotNull NetNode node) { + node.setGroup(this); + } + + public void notifyActiveChange(NetNode node, boolean active) { + if (active) activeNodes.add(node); + else activeNodes.remove(node); + } + + public static MergeDirection isEdgeAllowed(@NotNull NetNode source, @NotNull NetNode target) { + NetGroup sourceGroup = source.getGroupUnsafe(); + NetGroup targetGroup = target.getGroupUnsafe(); + + if (sourceGroup == null || targetGroup == null) return MergeDirection.NULL; + + return GroupData.mergeAllowed(sourceGroup.getData(), targetGroup.getData()); + } + + /** + * Merges the groups on either side of an edge if necessary. + * + * @param edge the edge to merge across + */ + public static void mergeEdge(@NotNull NetEdge edge, @NotNull MergeDirection direction) { + NetNode source = edge.getSource(); + NetNode target = edge.getTarget(); + assert source != null; + assert target != null; + NetGroup sourceGroup = source.getGroupUnsafe(); + NetGroup targetGroup = target.getGroupUnsafe(); + if (sourceGroup == targetGroup) { + if (sourceGroup == null) { + sourceGroup = source.getGroupSafe(); + } else { + GroupData data = sourceGroup.getData(); + if (data != null) data.notifyOfBridgingEdge(edge); + return; + } + } + if (sourceGroup != null) { + sourceGroup.mergeNode(target, edge, direction.source()); + } else { + targetGroup.mergeNode(source, edge, direction.target()); + } + } + + private void mergeNode(@NotNull NetNode node, @NotNull NetEdge edge, boolean dataMergeTo) { + NetGroup group = node.getGroupUnsafe(); + if (group != null) { + this.addNodes(group.getNodes()); + GroupData data = group.getData(); + if (data != null) { + if (this.data == null) this.data = data; + else this.data = dataMergeTo ? this.data.mergeAcross(data, edge) : data.mergeAcross(this.data, edge); + } + } else addNode(node); + } + + /** + * Split this group by removing a node. Automatically removes the node from the backing graph. + * + * @param source node to remove + */ + public void splitNode(NetNode source) { + if (!this.net.containsNode(source)) return; + Stream stream = this.net.getGraph().edgesOf(source.wrapper).stream(); + GroupData data = getData(); + if (data != null) stream = stream.peek(e -> data.notifyOfRemovedEdge(e.wrapped)); + ObjectLinkedOpenHashSet targets = stream + .map(a -> Graphs.getOppositeVertex(net.getGraph(), a, source.wrapper).getWrapped()) + .collect(Collectors.toCollection(ObjectLinkedOpenHashSet::new)); + this.net.getBacker().removeVertex(source.wrapper); + this.removeNode(source); + while (!targets.isEmpty()) { + NetNode target = targets.removeLast(); + Set targetGroup = new ObjectOpenHashSet<>(); + NetBreadthIterator i = new NetBreadthIterator(target, EdgeDirection.ALL); + NetNode temp; + while (i.hasNext()) { + temp = i.next(); + if (temp == source) continue; + targetGroup.add(temp); + // if we find a target node in our search, remove it from the list + targets.remove(temp); + } + this.removeNodes(targetGroup); + if (!targetGroup.isEmpty()) { + new NetGroup(this.net, targetGroup); + } + } + } + + /** + * Split this group by removing an edge. Automatically removes the edge from the graph. + * + * @param source source of the edge + * @param target target of the edge + * @return Whether the edge existed in the graph + */ + public boolean splitEdge(@NotNull NetNode source, @NotNull NetNode target) { + GroupData data = getData(); + NetEdge edge = this.net.getEdge(source, target); + if (edge == null) return false; + if (data != null) data.notifyOfRemovedEdge(edge); + if (this.net.getBacker().removeEdge(source.wrapper, target.wrapper) != null) { + Set targetGroup = new ObjectOpenHashSet<>(); + NetBreadthIterator i = new NetBreadthIterator(target, EdgeDirection.ALL); + NetNode temp; + while (i.hasNext()) { + temp = i.next(); + // if there's another complete path to the source node from the target node, there's no need to split + if (source == temp) return true; + targetGroup.add(temp); + } + this.removeNodes(targetGroup); + if (targetGroup.size() != 0) { + if (data == null) new NetGroup(this.net, targetGroup); + else { + Pair split = data.splitAcross(this.nodes, targetGroup); + this.data = split.getLeft(); + new NetGroup(this.net, targetGroup, split.getRight()); + } + } + return true; + } + return false; + } + + @NotNull + @UnmodifiableView + public Set getNodes() { + return nodes; + } + + @NotNull + @UnmodifiableView + public Set getActiveNodes() { + return activeNodes; + } + + public @Nullable GroupData getData() { + return this.data; + } +} diff --git a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java new file mode 100644 index 00000000000..d59e3f6e80a --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java @@ -0,0 +1,180 @@ +package gregtech.api.graphnet.group; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.path.NetPath; +import gregtech.api.graphnet.path.PathBuilder; +import gregtech.api.graphnet.path.SingletonNetPath; +import gregtech.api.graphnet.path.StandardNetPath; +import gregtech.api.graphnet.traverse.iter.EdgeDirection; +import gregtech.api.graphnet.traverse.iter.NetIterator; +import gregtech.api.graphnet.traverse.iter.NetIteratorSupplier; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Set; + +public class PathCacheGroupData extends GroupData { + + protected final NetIteratorSupplier iteratorSupplier; + + protected final @NotNull Object2ObjectOpenHashMap cache; + + public PathCacheGroupData(NetIteratorSupplier iteratorSupplier) { + this(iteratorSupplier, new Object2ObjectOpenHashMap<>()); + } + + public PathCacheGroupData(NetIteratorSupplier iteratorSupplier, + @NotNull Object2ObjectOpenHashMap cache) { + this.cache = cache; + this.iteratorSupplier = iteratorSupplier; + } + + @NotNull + public SecondaryCache getOrCreate(@NotNull NetNode source) { + return cache.computeIfAbsent(source, SecondaryCache::new); + } + + public void invalidateAll() { + cache.clear(); + cache.trim(16); + } + + public void notifyTopologicalChange() { + cache.forEach((key, value) -> value.notifyTopologicalChange()); + } + + public class SecondaryCache extends Object2ObjectOpenHashMap { + + protected final @NotNull NetNode source; + protected @Nullable NetIterator searchFrontier; + + protected NetPath singleton; + + protected int frontierPosition; + + public SecondaryCache(@NotNull NetNode source) { + this.source = source; + } + + @Nullable + public NetPath getOrCompute(@NotNull NetNode target) { + if (target == source) { + if (singleton == null) singleton = buildSingleton(source); + return singleton; + } + + if (searchFrontier == null) searchFrontier = iteratorSupplier.create(source, EdgeDirection.OUTGOING); + + NetPath existing = this.get(target); + if (existing != null) return existing; + NetIterator targetFrontier = iteratorSupplier.create(target, EdgeDirection.INCOMING); + int frontierPosition = 0; + // first, attempt to bring the target frontier up to date with the search frontier. + while (frontierPosition < this.frontierPosition && targetFrontier.hasNext()) { + NetNode node = targetFrontier.next(); + frontierPosition++; + if (searchFrontier.getSpanningTreeEdge(node) != null) { + NetPath built = buildPath(node, targetFrontier, searchFrontier); + this.put(target, built); + return built; + } + } + // second, move both frontiers forward until intersect or exhaustion of iterators. + while (searchFrontier.hasNext() && targetFrontier.hasNext()) { + searchFrontier.next(); + NetNode node = targetFrontier.next(); + this.frontierPosition++; + if (searchFrontier.getSpanningTreeEdge(node) != null) { + NetPath built = buildPath(node, targetFrontier, searchFrontier); + this.put(target, built); + return built; + } + } + return null; + } + + public void notifyTopologicalChange() { + this.searchFrontier = null; + this.frontierPosition = 0; + } + } + + protected PathBuilder createBuilder(@NotNull NetNode origin) { + return new StandardNetPath.Builder(origin); + } + + protected NetPath buildSingleton(@NotNull NetNode singleton) { + return new SingletonNetPath(singleton); + } + + protected NetPath buildPath(@NotNull NetNode intersect, @NotNull NetIterator targetFrontier, + @NotNull NetIterator searchFrontier) { + PathBuilder builder = createBuilder(intersect); + // first, assemble the path leading to the target frontier origin + NetNode link = intersect; + while (true) { + NetEdge span = targetFrontier.getSpanningTreeEdge(link); + if (span == null) break; + link = span.getOppositeNode(link); + if (link == null) return null; + builder.addToEnd(link, span); + } + // second, assemble the path leading to the search frontier origin + link = intersect; + while (true) { + NetEdge span = searchFrontier.getSpanningTreeEdge(link); + if (span == null) break; + link = span.getOppositeNode(link); + if (link == null) return null; + builder.addToStart(link, span); + } + return builder.build(); + } + + @Override + public void notifyOfBridgingEdge(@NotNull NetEdge edge) { + notifyTopologicalChange(); + invalidateAll(); + } + + @Override + public void notifyOfRemovedEdge(@NotNull NetEdge edge) { + notifyTopologicalChange(); + this.cache.values().removeIf(c -> { + c.values().removeIf(p -> p.getOrderedEdges().contains(edge)); + return c.isEmpty(); + }); + } + + @Override + protected @Nullable GroupData mergeAcross(@Nullable GroupData other, @NotNull NetEdge edge) { + if (other instanceof PathCacheGroupData data) { + this.cache.putAll(data.cache); + } + notifyTopologicalChange(); + return this; + } + + @Override + public @NotNull Pair splitAcross(@NotNull Set sourceNodes, + @NotNull Set targetNodes) { + notifyTopologicalChange(); + return ImmutablePair.of(buildFilteredCache(sourceNodes), buildFilteredCache(targetNodes)); + } + + protected @NotNull PathCacheGroupData buildFilteredCache(@NotNull Set filterNodes) { + Object2ObjectOpenHashMap child = new Object2ObjectOpenHashMap<>(this.cache); + child.entrySet().removeIf(entry -> { + if (!filterNodes.contains(entry.getKey())) return true; + SecondaryCache cache = entry.getValue(); + cache.keySet().retainAll(filterNodes); + return cache.isEmpty(); + }); + return new PathCacheGroupData(iteratorSupplier, child); + } +} diff --git a/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java b/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java deleted file mode 100644 index 5e515ed7eea..00000000000 --- a/src/main/java/gregtech/api/graphnet/path/AbstractNetPath.java +++ /dev/null @@ -1,90 +0,0 @@ -package gregtech.api.graphnet.path; - -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.logic.NetLogicData; - -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Objects; - -public abstract class AbstractNetPath implements INetPath { - - protected final List nodes; - - protected final List edges; - - protected final double weight; - - protected NetLogicData unifiedNodeData; - protected NetLogicData unifiedEdgeData; - - public AbstractNetPath(List nodes, List edges, double weight) { - this.nodes = nodes; - this.edges = edges; - this.weight = weight; - } - - @Override - public List getOrderedNodes() { - return nodes; - } - - @Override - public List getOrderedEdges() { - return edges; - } - - @Override - public double getWeight() { - return weight; - } - - @Override - public NetLogicData getUnifiedNodeData() { - if (unifiedNodeData == null) { - if (nodes.size() == 1) { - unifiedNodeData = nodes.get(0).getData(); - } else if (nodes.size() == 2) { - unifiedNodeData = NetLogicData.union(nodes.get(0).getData(), nodes.get(1).getData()); - } else { - unifiedNodeData = NetLogicData.union(nodes.get(0).getData(), - nodes.stream().skip(1).map(NetNode::getData).toArray(NetLogicData[]::new)); - } - } - return unifiedNodeData; - } - - @Override - @Nullable - public NetLogicData getUnifiedEdgeData() { - if (unifiedEdgeData == null) { - if (edges.size() == 0) { - return null; - } else if (edges.size() == 1) { - unifiedEdgeData = edges.get(0).getData(); - } else if (edges.size() == 2) { - unifiedEdgeData = NetLogicData.union(edges.get(0).getData(), edges.get(1).getData()); - } else { - unifiedEdgeData = NetLogicData.union(edges.get(0).getData(), - edges.stream().skip(1).map(NetEdge::getData).toArray(NetLogicData[]::new)); - } - } - return unifiedEdgeData; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AbstractNetPath that = (AbstractNetPath) o; - return Double.compare(that.weight, weight) == 0 && Objects.equals(nodes, that.nodes) && - Objects.equals(edges, that.edges); - } - - @Override - public int hashCode() { - return Objects.hash(nodes, edges, weight); - } -} diff --git a/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java b/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java deleted file mode 100644 index 7d0088f58dc..00000000000 --- a/src/main/java/gregtech/api/graphnet/path/GenericGraphNetPath.java +++ /dev/null @@ -1,44 +0,0 @@ -package gregtech.api.graphnet.path; - -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.alg.NetPathMapper; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import org.jetbrains.annotations.Nullable; -import org.jgrapht.GraphPath; - -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.stream.Collectors; - -public class GenericGraphNetPath extends AbstractNetPath { - - public static final NetPathMapper MAPPER = new NetPathMapper<>(GenericGraphNetPath::new, - GenericGraphNetPath::new, GenericGraphNetPath::new); - - public GenericGraphNetPath(GraphVertex vertex) { - this(Collections.singletonList(vertex), Collections.emptyList(), - vertex.wrapped.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue()); - } - - public GenericGraphNetPath(List vertices, List edges, double weight) { - super(vertices.stream().map(v -> v.wrapped).collect(Collectors.toList()), - edges.stream().map(e -> e.wrapped).collect(Collectors.toList()), weight); - } - - public GenericGraphNetPath(GraphPath path) { - this(path.getVertexList(), path.getEdgeList(), path.getWeight()); - } - - public interface Provider { - - Iterator getPaths(NetNode node, IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, long queryTick); - } -} diff --git a/src/main/java/gregtech/api/graphnet/path/INetPath.java b/src/main/java/gregtech/api/graphnet/path/INetPath.java deleted file mode 100644 index 8b369110058..00000000000 --- a/src/main/java/gregtech/api/graphnet/path/INetPath.java +++ /dev/null @@ -1,35 +0,0 @@ -package gregtech.api.graphnet.path; - -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.logic.NetLogicData; - -import org.jetbrains.annotations.Nullable; -import org.jgrapht.alg.util.ToleranceDoubleComparator; - -import java.util.List; - -public interface INetPath { - - ToleranceDoubleComparator WEIGHT_COMPARATOR = new ToleranceDoubleComparator(); - - List getOrderedNodes(); - - default N getSourceNode() { - return getOrderedNodes().get(0); - } - - default N getTargetNode() { - List nodes = getOrderedNodes(); - return nodes.get(nodes.size() - 1); - } - - List getOrderedEdges(); - - double getWeight(); - - NetLogicData getUnifiedNodeData(); - - @Nullable - NetLogicData getUnifiedEdgeData(); -} diff --git a/src/main/java/gregtech/api/graphnet/path/NetPath.java b/src/main/java/gregtech/api/graphnet/path/NetPath.java new file mode 100644 index 00000000000..a3d3f597c82 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/path/NetPath.java @@ -0,0 +1,43 @@ +package gregtech.api.graphnet.path; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.logic.NetLogicData; + +import com.google.common.collect.ImmutableCollection; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; + +public interface NetPath { + + @NotNull + @Unmodifiable + ImmutableCollection getOrderedNodes(); + + @NotNull + default N getSourceNode() { + ImmutableCollection nodes = getOrderedNodes(); + return (N) nodes.asList().get(0); + } + + @NotNull + default N getTargetNode() { + ImmutableCollection nodes = getOrderedNodes(); + return (N) nodes.asList().get(nodes.size() - 1); + } + + @NotNull + @Unmodifiable + ImmutableCollection getOrderedEdges(); + + double getWeight(); + + @NotNull + NetPath reversed(); + + NetLogicData getUnifiedNodeData(); + + @Nullable + NetLogicData getUnifiedEdgeData(); +} diff --git a/src/main/java/gregtech/api/graphnet/path/PathBuilder.java b/src/main/java/gregtech/api/graphnet/path/PathBuilder.java new file mode 100644 index 00000000000..bd786dc37f5 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/path/PathBuilder.java @@ -0,0 +1,21 @@ +package gregtech.api.graphnet.path; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +public interface PathBuilder { + + @Contract("_, _ -> this") + PathBuilder addToEnd(@NotNull NetNode node, @NotNull NetEdge edge); + + @Contract("_, _ -> this") + PathBuilder addToStart(@NotNull NetNode node, @NotNull NetEdge edge); + + @Contract("-> this") + PathBuilder reverse(); + + NetPath build(); +} diff --git a/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java b/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java new file mode 100644 index 00000000000..f4655bae688 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java @@ -0,0 +1,70 @@ +package gregtech.api.graphnet.path; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.WeightFactorLogic; + +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; + +public class SingletonNetPath implements NetPath { + + protected final NetNode node; + protected final ImmutableSet singleton; + + protected final double weight; + + public SingletonNetPath(NetNode node) { + this(node, node.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue()); + } + + public SingletonNetPath(NetNode node, double weight) { + this.node = node; + this.singleton = ImmutableSet.of(node); + this.weight = weight; + } + + @Override + public @NotNull @Unmodifiable ImmutableCollection getOrderedNodes() { + return (ImmutableCollection) singleton; + } + + @Override + public @NotNull N getSourceNode() { + return (N) node; + } + + @Override + public @NotNull N getTargetNode() { + return (N) node; + } + + @Override + public @NotNull @Unmodifiable ImmutableCollection getOrderedEdges() { + return ImmutableSet.of(); + } + + @Override + public double getWeight() { + return weight; + } + + @Override + public @NotNull NetPath reversed() { + return this; + } + + @Override + public NetLogicData getUnifiedNodeData() { + return node.getData(); + } + + @Override + public @Nullable NetLogicData getUnifiedEdgeData() { + return null; + } +} diff --git a/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java b/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java new file mode 100644 index 00000000000..08e7b6a73ec --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java @@ -0,0 +1,183 @@ +package gregtech.api.graphnet.path; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.logic.NetLogicData; + +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class StandardNetPath implements NetPath { + + protected final ImmutableCollection nodes; + + protected final ImmutableCollection edges; + + protected final double weight; + + protected final int hash; + + protected StandardNetPath reversed; + + protected NetLogicData unifiedNodeData; + protected NetLogicData unifiedEdgeData; + + public StandardNetPath(@NotNull ImmutableCollection nodes, @NotNull ImmutableCollection edges, + double weight) { + this.nodes = nodes; + this.edges = edges; + this.weight = weight; + ImmutableList listForm = nodes.asList(); + this.hash = Objects.hash(nodes, edges, weight, listForm.get(0), listForm.get(listForm.size() - 1)); + } + + public StandardNetPath(@NotNull StandardNetPath reverse) { + ImmutableCollection.Builder builderNodes = reverse.nodes instanceof ImmutableSet ? + ImmutableSet.builder() : ImmutableList.builder(); + List nodesList = reverse.nodes.asList(); + for (int i = nodesList.size(); i > 0; i--) { + builderNodes.add(nodesList.get(i - 1)); + } + ImmutableCollection.Builder builderEdges = reverse.edges instanceof ImmutableSet ? + ImmutableSet.builder() : ImmutableList.builder(); + List edgesList = reverse.edges.asList(); + for (int i = edgesList.size(); i > 0; i--) { + builderEdges.add(edgesList.get(i - 1)); + } + this.nodes = builderNodes.build(); + this.edges = builderEdges.build(); + this.weight = reverse.weight; + ImmutableList listForm = nodes.asList(); + this.hash = Objects.hash(nodes, edges, weight, listForm.get(0), listForm.get(listForm.size() - 1)); + this.reversed = reverse; + } + + @Override + public @NotNull @Unmodifiable ImmutableCollection getOrderedNodes() { + return (ImmutableCollection) nodes; + } + + @Override + public @NotNull @Unmodifiable ImmutableCollection getOrderedEdges() { + return (ImmutableCollection) edges; + } + + @Override + public double getWeight() { + return weight; + } + + @Override + public NetLogicData getUnifiedNodeData() { + if (unifiedNodeData == null) { + ImmutableList nodesList = nodes.asList(); + if (nodes.size() == 1) { + unifiedNodeData = nodesList.get(0).getData(); + } else if (nodes.size() == 2) { + unifiedNodeData = NetLogicData.union(nodesList.get(0).getData(), nodesList.get(1).getData()); + } else { + unifiedNodeData = NetLogicData.union(nodesList.get(0).getData(), + nodes.stream().skip(1).map(NetNode::getData).toArray(NetLogicData[]::new)); + } + } + return unifiedNodeData; + } + + @Override + @Nullable + public NetLogicData getUnifiedEdgeData() { + if (unifiedEdgeData == null) { + ImmutableList edgesList = edges.asList(); + if (edges.size() == 0) { + return null; + } else if (edges.size() == 1) { + unifiedEdgeData = edgesList.get(0).getData(); + } else if (edges.size() == 2) { + unifiedEdgeData = NetLogicData.union(edgesList.get(0).getData(), edgesList.get(1).getData()); + } else { + unifiedEdgeData = NetLogicData.union(edgesList.get(0).getData(), + edges.stream().skip(1).map(NetEdge::getData).toArray(NetLogicData[]::new)); + } + } + return unifiedEdgeData; + } + + @Override + public @NotNull StandardNetPath reversed() { + if (reversed == null) { + reversed = new StandardNetPath(this); + } + return reversed; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + StandardNetPath that = (StandardNetPath) o; + return Double.compare(that.weight, weight) == 0 && that.getSourceNode() == getSourceNode() && + that.getTargetNode() == getTargetNode() && Objects.equals(nodes, that.nodes) && + Objects.equals(edges, that.edges); + } + + @Override + public int hashCode() { + return hash; + } + + public static final class Builder implements PathBuilder { + + public final List nodes = new ObjectArrayList<>(); + public final List edges = new ObjectArrayList<>(); + + public Builder(@NotNull NetNode startingNode) { + nodes.add(startingNode); + } + + @Override + @Contract("_, _ -> this") + public Builder addToEnd(@NotNull NetNode node, @NotNull NetEdge edge) { + NetNode end = nodes.get(nodes.size() - 1); + if (edge.getOppositeNode(node) != end) + throw new IllegalArgumentException("Edge does not link last node and new node!"); + nodes.add(node); + edges.add(edge); + return this; + } + + @Override + @Contract("_, _ -> this") + public Builder addToStart(@NotNull NetNode node, @NotNull NetEdge edge) { + NetNode end = nodes.get(0); + if (edge.getOppositeNode(node) != end) + throw new IllegalArgumentException("Edge does not link last node and new node!"); + nodes.add(0, node); + edges.add(0, edge); + return this; + } + + @Override + @Contract("-> this") + public Builder reverse() { + Collections.reverse(nodes); + Collections.reverse(edges); + return this; + } + + @Override + public StandardNetPath build() { + return new StandardNetPath(ImmutableSet.copyOf(nodes), ImmutableSet.copyOf(edges), + edges.stream().mapToDouble(NetEdge::getWeight).sum()); + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java deleted file mode 100644 index b310f8748d5..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/BasicWorldPipeNetPath.java +++ /dev/null @@ -1,44 +0,0 @@ -package gregtech.api.graphnet.pipenet; - -import gregtech.api.graphnet.alg.NetPathMapper; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.path.AbstractNetPath; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import org.jetbrains.annotations.Nullable; -import org.jgrapht.GraphPath; - -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.stream.Collectors; - -public class BasicWorldPipeNetPath extends AbstractNetPath { - - public static final NetPathMapper MAPPER = new NetPathMapper<>(BasicWorldPipeNetPath::new, - BasicWorldPipeNetPath::new, BasicWorldPipeNetPath::new); - - public BasicWorldPipeNetPath(GraphVertex vertex) { - this(Collections.singletonList(vertex), Collections.emptyList(), - vertex.wrapped.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue()); - } - - public BasicWorldPipeNetPath(List vertices, List edges, double weight) { - super(vertices.stream().map(v -> (WorldPipeNetNode) v.wrapped).collect(Collectors.toList()), - edges.stream().map(e -> e.wrapped).collect(Collectors.toList()), weight); - } - - public BasicWorldPipeNetPath(GraphPath path) { - this(path.getVertexList(), path.getEdgeList(), path.getWeight()); - } - - public interface Provider { - - Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, long queryTick); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java b/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java deleted file mode 100644 index 67e35007938..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/FlowWorldPipeNetPath.java +++ /dev/null @@ -1,44 +0,0 @@ -package gregtech.api.graphnet.pipenet; - -import gregtech.api.graphnet.alg.NetPathMapper; -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.path.AbstractNetPath; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import org.jetbrains.annotations.Nullable; -import org.jgrapht.GraphPath; - -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.stream.Collectors; - -public class FlowWorldPipeNetPath extends AbstractNetPath { - - public static final NetPathMapper MAPPER = new NetPathMapper<>(FlowWorldPipeNetPath::new, - FlowWorldPipeNetPath::new, FlowWorldPipeNetPath::new); - - public FlowWorldPipeNetPath(GraphVertex vertex) { - this(Collections.singletonList(vertex), Collections.emptyList(), - vertex.wrapped.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue()); - } - - public FlowWorldPipeNetPath(List vertices, List edges, double weight) { - super(vertices.stream().map(v -> (WorldPipeNetNode) v.wrapped).collect(Collectors.toList()), - edges.stream().map(e -> (AbstractNetFlowEdge) e.wrapped).collect(Collectors.toList()), weight); - } - - public FlowWorldPipeNetPath(GraphPath path) { - this(path.getVertexList(), path.getEdgeList(), path.getWeight()); - } - - public interface Provider { - - Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, long queryTick); - } -} diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java index 4daeba5eaf7..dca9e334a96 100644 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java @@ -27,15 +27,13 @@ public abstract class ServerNet extends WorldSavedData implements IGraphNet { protected final GraphNetBacker backer; - public ServerNet(String name, Function graphBuilder, - AlgorithmBuilder... algorithmBuilders) { + public ServerNet(String name, Function graphBuilder) { super(name); - this.backer = new GraphNetBacker(this, graphBuilder.apply(this), algorithmBuilders); + this.backer = new GraphNetBacker(this, graphBuilder.apply(this)); } - public ServerNet(String name, boolean directed, AlgorithmBuilder... algorithmBuilders) { - this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), - algorithmBuilders); + public ServerNet(String name, boolean directed) { + this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder()); } @Override diff --git a/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java index 6c4b71f194f..c0b5231218a 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java @@ -3,12 +3,12 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import org.jetbrains.annotations.Nullable; -public abstract class AbstractTraverseData> implements ITraverseData { +public abstract class AbstractTraverseData> implements ITraverseData { private final IGraphNet net; private final IPredicateTestObject testObject; diff --git a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java index 50edd683349..5fa89ae4a37 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java @@ -1,17 +1,17 @@ package gregtech.api.graphnet.traverse; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import org.jetbrains.annotations.NotNull; -public interface IEqualizableTraverseData> extends ITraverseData { +public interface IEqualizableTraverseData> extends ITraverseData { int getDestinationsAtNode(@NotNull N node); /** * Whether a path should be skipped before running the collection process on it. - * The return of {@link ITraverseData#prepareForPathWalk(INetPath, long)} will be ignored during traversal. + * The return of {@link ITraverseData#prepareForPathWalk(NetPath, long)} will be ignored during traversal. */ boolean shouldSkipPath(@NotNull P path); diff --git a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java index 2e974fe2f48..a4b3c024d79 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java @@ -1,14 +1,14 @@ package gregtech.api.graphnet.traverse; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.jetbrains.annotations.NotNull; import java.util.ArrayDeque; -public interface IRoundRobinTraverseData, N extends NetNode, P extends INetPath> +public interface IRoundRobinTraverseData, N extends NetNode, P extends NetPath> extends ITraverseData { /** @@ -25,7 +25,7 @@ public interface IRoundRobinTraverseData, N extends /** * Whether a path should be skipped before checking it against the round robin cache. - * The return of {@link ITraverseData#prepareForPathWalk(INetPath, long)} will be ignored during traversal. + * The return of {@link ITraverseData#prepareForPathWalk(NetPath, long)} will be ignored during traversal. */ boolean shouldSkipPath(@NotNull P path); diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java index 4955d50e318..3fd86cdde6c 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java @@ -4,7 +4,7 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; @@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public interface ITraverseData> { +public interface ITraverseData> { IGraphNet getGraphNet(); diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java b/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java index af0469ae203..9f7c3feb819 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java +++ b/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java @@ -1,12 +1,12 @@ package gregtech.api.graphnet.traverse; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import org.jetbrains.annotations.Nullable; -public interface ITraverseGuideProvider, T extends IPredicateTestObject> { +public interface ITraverseGuideProvider, T extends IPredicateTestObject> { @Nullable > TraverseGuide getGuide( diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java index d76ff3a5e7e..9387c47e5fa 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.traverse; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import org.jetbrains.annotations.Nullable; @@ -9,7 +9,7 @@ import java.util.function.LongConsumer; import java.util.function.Supplier; -public class TraverseGuide, T extends ITraverseData> { +public class TraverseGuide, T extends ITraverseData> { private final T data; private final Supplier> pathsSupplier; diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java index 17329651bff..27080f7009d 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java @@ -3,7 +3,7 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.traverse.util.FlowConsumptionStack; import gregtech.api.util.GTUtility; @@ -37,7 +37,7 @@ private TraverseHelpers() {} * @param flowIn the flow to traverse with. * @return the consumed flow. */ - public static , + public static , D extends ITraverseData> long traverseFlood( @NotNull D data, @NotNull Iterator

paths, @@ -99,7 +99,7 @@ D extends ITraverseData> long traverseFlood( * @param flowIn the flow to traverse with. * @return the consumed flow. */ - public static , + public static , D extends ITraverseData> long traverseDumb( @NotNull D data, @NotNull Iterator

paths, @@ -192,7 +192,7 @@ D extends ITraverseData> long traverseDumb( * not edge restrictions. * @return the consumed flow. */ - public static , + public static , D extends IEqualizableTraverseData> long traverseEqualDistribution( @NotNull D data, @NotNull Iterator

paths, @@ -312,7 +312,7 @@ D extends IEqualizableTraverseData> long traverseEqualDistribution( * not edge restrictions. * @return the consumed flow. */ - public static , + public static , D extends IEqualizableTraverseData> long traverseEqualDistribution( @NotNull D data, @NotNull Supplier> pathsSupplier, @@ -344,11 +344,11 @@ D extends IEqualizableTraverseData> long traverseEqualDistribution( * @return the consumed flow. */ public static , N extends NetNode, E extends AbstractNetFlowEdge, - P extends INetPath, D extends IRoundRobinTraverseData> long traverseRoundRobin( - @NotNull D data, - @NotNull Iterator

paths, - long flowIn, - boolean strict) { + P extends NetPath, D extends IRoundRobinTraverseData> long traverseRoundRobin( + @NotNull D data, + @NotNull Iterator

paths, + long flowIn, + boolean strict) { long availableFlow = flowIn; Object2ObjectLinkedOpenHashMap cache = data.getTraversalCache(); Predicate invalidityCheck = null; @@ -431,12 +431,12 @@ P extends INetPath, D extends IRoundRobinTraverseData> long trave } private static , N extends NetNode, E extends AbstractNetFlowEdge, - P extends INetPath, D extends ITraverseData & IRoundRobinTraverseData> long rrTraverse( - @NotNull D data, - @NotNull P path, - @NotNull T rr, - long flowIn, - boolean strict) { + P extends NetPath, D extends ITraverseData & IRoundRobinTraverseData> long rrTraverse( + @NotNull D data, + @NotNull P path, + @NotNull T rr, + long flowIn, + boolean strict) { boolean simulate = data.getSimulatorKey() != null; List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); long pathFlow = flowIn; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java new file mode 100644 index 00000000000..1081435b4a6 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java @@ -0,0 +1,20 @@ +package gregtech.api.graphnet.traverse.iter; + +import org.jgrapht.Graph; + +import java.util.Set; + +public enum EdgeDirection { + + OUTGOING, + INCOMING, + ALL; + + public Set selectEdges(Graph graph, V vertex) { + return switch (this) { + case ALL -> graph.edgesOf(vertex); + case INCOMING -> graph.incomingEdgesOf(vertex); + case OUTGOING -> graph.outgoingEdgesOf(vertex); + }; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java new file mode 100644 index 00000000000..6c7dc82e129 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java @@ -0,0 +1,74 @@ +package gregtech.api.graphnet.traverse.iter; + +import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.traverse.BreadthFirstIterator; + +import java.util.Set; + +public class NetBreadthIterator implements NetIterator { + + protected BreadthFirstIterator backer; + + /** + * Creates a breadth-first iterator that traverses a connected component, starting at the given node. + * + * @param origin the node to start at + */ + public NetBreadthIterator(@NotNull NetNode origin, @NotNull EdgeDirection direction) { + this.backer = new BreadthFirstIterator<>(origin.getNet().getGraph(), origin.wrapper) { + + @Override + protected Set selectOutgoingEdges(GraphVertex vertex) { + return direction.selectEdges(graph, vertex); + } + }; + } + + /** + * Creates a breadth-first iterator that traverses the entire graph, starting at an arbitrary point. + * + * @param graphNet the graph to traverse. + */ + public NetBreadthIterator(@NotNull IGraphNet graphNet) { + this.backer = new BreadthFirstIterator<>(graphNet.getGraph(), (GraphVertex) null) { + + @Override + protected Set selectOutgoingEdges(GraphVertex vertex) { + return graph.edgesOf(vertex); + } + }; + } + + public BreadthFirstIterator getBacker() { + return backer; + } + + @Override + public boolean hasNext() { + return backer.hasNext(); + } + + @Override + public NetNode next() { + return backer.next().getWrapped(); + } + + public @Nullable NetNode getParent(@NotNull NetNode node) { + return backer.getParent(node.wrapper).getWrapped(); + } + + public @Nullable NetEdge getSpanningTreeEdge(@NotNull NetNode node) { + return backer.getSpanningTreeEdge(node.wrapper).getWrapped(); + } + + public int getDepth(@NotNull NetNode node) { + return backer.getDepth(node.wrapper); + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java new file mode 100644 index 00000000000..528d1ca2085 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java @@ -0,0 +1,54 @@ +package gregtech.api.graphnet.traverse.iter; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.traverse.ClosestFirstIterator; + +import java.util.Set; + +public class NetClosestIterator implements NetIterator { + + protected ClosestFirstIterator backer; + + /** + * Creates a closest-first iterator that traverses a connected component, starting at the given node. + * + * @param origin the node to start at + */ + public NetClosestIterator(@NotNull NetNode origin, EdgeDirection direction) { + this.backer = new ClosestFirstIterator<>(origin.getNet().getGraph(), origin.wrapper) { + + @Override + protected Set selectOutgoingEdges(GraphVertex vertex) { + return direction.selectEdges(graph, vertex); + } + }; + } + + public ClosestFirstIterator getBacker() { + return backer; + } + + @Override + public boolean hasNext() { + return backer.hasNext(); + } + + @Override + public NetNode next() { + return backer.next().getWrapped(); + } + + public double getShortestPathLength(@NotNull NetNode node) { + return backer.getShortestPathLength(node.wrapper); + } + + public @Nullable NetEdge getSpanningTreeEdge(@NotNull NetNode node) { + return backer.getSpanningTreeEdge(node.wrapper).getWrapped(); + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java new file mode 100644 index 00000000000..fe3df2bd2e6 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java @@ -0,0 +1,15 @@ +package gregtech.api.graphnet.traverse.iter; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Iterator; + +public interface NetIterator extends Iterator { + + @Nullable + NetEdge getSpanningTreeEdge(@NotNull NetNode node); +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java new file mode 100644 index 00000000000..b6f42681386 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java @@ -0,0 +1,12 @@ +package gregtech.api.graphnet.traverse.iter; + +import gregtech.api.graphnet.NetNode; + +import org.jetbrains.annotations.NotNull; + +@FunctionalInterface +public interface NetIteratorSupplier { + + @NotNull + NetIterator create(@NotNull NetNode origin, @NotNull EdgeDirection direction); +} diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java index 97b171d8082..fb1950fbe1b 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -5,13 +5,10 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.alg.AlgorithmBuilder; import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.graph.NetDirectedGraph; import gregtech.api.graphnet.graph.NetUndirectedGraph; import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.path.GenericGraphNetPath; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; @@ -20,10 +17,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Iterator; import java.util.function.Function; -public abstract class WorldNet extends WorldSavedData implements IGraphNet, GenericGraphNetPath.Provider { +public abstract class WorldNet extends WorldSavedData implements IGraphNet { protected final GraphNetBacker backer; private World world; @@ -32,7 +28,7 @@ public abstract class WorldNet extends WorldSavedData implements IGraphNet, Gene public WorldNet(String name, @NotNull Function graphBuilder, AlgorithmBuilder... algorithmBuilders) { super(name); - this.backer = new GraphNetBacker(this, graphBuilder.apply(this), algorithmBuilders); + this.backer = new GraphNetBacker(this, graphBuilder.apply(this)); } public WorldNet(String name, boolean directed, AlgorithmBuilder... algorithmBuilders) { @@ -48,13 +44,6 @@ public World getWorld() { return world; } - @Override - public Iterator getPaths(NetNode node, IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, long queryTick) { - nodeClassCheck(node); - return backer.getPaths(node, 0, GenericGraphNetPath.MAPPER, testObject, simulator, queryTick); - } - @Override public void addNode(@NotNull NetNode node) { nodeClassCheck(node); diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 6586408b844..cf691520ffd 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -5,7 +5,6 @@ import gregtech.api.fluids.store.FluidStorageKeys; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; @@ -23,6 +22,7 @@ import gregtech.api.util.function.TriConsumer; import gregtech.common.pipelike.block.cable.CableStructure; import gregtech.common.pipelike.block.pipe.MaterialPipeStructure; +import gregtech.common.pipelike.net.energy.AmperageLimitLogic; import gregtech.common.pipelike.net.energy.SuperconductorLogic; import gregtech.common.pipelike.net.energy.VoltageLimitLogic; import gregtech.common.pipelike.net.energy.VoltageLossLogic; @@ -186,7 +186,7 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { float energy = existing == null ? 0 : existing.getThermalEnergy(); data.setLogicEntry(VoltageLossLogic.TYPE.getWith(loss)) .setLogicEntry(WeightFactorLogic.TYPE.getWith(loss + 0.001 / amperage)) - .setLogicEntry(ThroughputLogic.TYPE.getWith(amperage)) + .setLogicEntry(AmperageLimitLogic.TYPE.getWith(amperage)) .setLogicEntry(VoltageLimitLogic.TYPE.getWith(voltageLimit)) .setLogicEntry(TemperatureLogic.TYPE .getWith(TemperatureLossFunction.getOrCreateCable(coolingFactor), materialMeltTemperature, @@ -205,7 +205,7 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { float energy = existing == null ? 0 : existing.getThermalEnergy(); data.setLogicEntry(VoltageLossLogic.TYPE.getWith(loss)) .setLogicEntry(WeightFactorLogic.TYPE.getWith(loss + 0.001 / amperage)) - .setLogicEntry(ThroughputLogic.TYPE.getWith(amperage)) + .setLogicEntry(AmperageLimitLogic.TYPE.getWith(amperage)) .setLogicEntry(VoltageLimitLogic.TYPE.getWith(voltageLimit)) .setLogicEntry(TemperatureLogic.TYPE .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), materialMeltTemperature, 1, diff --git a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java index 6fb83a841c6..03feba30351 100644 --- a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java +++ b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java @@ -1,6 +1,6 @@ package gregtech.common.pipelike.net; -import gregtech.api.graphnet.path.INetPath; +import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.util.TaskScheduler; @@ -9,6 +9,7 @@ import net.minecraft.world.World; import net.minecraftforge.fml.common.FMLCommonHandler; +import com.google.common.collect.ImmutableCollection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,7 +20,7 @@ public class SlowActiveWalker implements Task { private static final int RECENT_WALKER_CUTOFF = 10; - private static final Map, Long> RECENT_DISPATCHES = new WeakHashMap<>(); + private static final Map RECENT_DISPATCHES = new WeakHashMap<>(); /** * Dispatches a slow walker along a path with default parameters. @@ -29,7 +30,7 @@ public class SlowActiveWalker implements Task { * @param path the path to walk. * @param delay the ticks between steps of the walker */ - public static void dispatch(World world, INetPath path, int delay) { + public static void dispatch(World world, NetPath path, int delay) { dispatch(world, path, delay, 1, 1); } @@ -43,7 +44,7 @@ public static void dispatch(World world, INetPath * @param stepSize the number of nodes within the path that the walker progresses every step * @param activeLength the number of tiles that will be left active behind a progressing walker */ - public static void dispatch(World world, INetPath path, int delay, + public static void dispatch(World world, NetPath path, int delay, int stepSize, int activeLength) { long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); RECENT_DISPATCHES.compute(path, (k, v) -> { @@ -55,7 +56,7 @@ public static void dispatch(World world, INetPath }); } - private final INetPath path; + private final NetPath path; private final int lastStep; private int index = 0; @@ -64,7 +65,7 @@ public static void dispatch(World world, INetPath private final int activeLength; private int counter; - protected SlowActiveWalker(INetPath path, int delay, int stepSize, + protected SlowActiveWalker(NetPath path, int delay, int stepSize, int activeLength) { this.path = path; this.delay = delay; @@ -93,7 +94,11 @@ public boolean run() { protected @Nullable WorldPipeNetNode getSafe(int index) { if (index >= path.getOrderedNodes().size()) return null; else if (index < 0) return null; - else return path.getOrderedNodes().get(index); + else return getNodes().asList().get(index); + } + + protected ImmutableCollection getNodes() { + return path.getOrderedNodes(); } protected void step(@Nullable WorldPipeNetNode previous, @Nullable WorldPipeNetNode next) { diff --git a/src/main/java/gregtech/common/pipelike/net/energy/AmperageLimitLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/AmperageLimitLogic.java new file mode 100644 index 00000000000..d5a3538938a --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/AmperageLimitLogic.java @@ -0,0 +1,25 @@ +package gregtech.common.pipelike.net.energy; + +import gregtech.api.GTValues; +import gregtech.api.graphnet.logic.AbstractLongLogicData; +import gregtech.api.graphnet.logic.NetLogicEntry; + +import org.jetbrains.annotations.NotNull; + +public final class AmperageLimitLogic extends AbstractLongLogicData { + + public static final LongLogicType TYPE = new LongLogicType<>(GTValues.MODID, "AmperageLimit", + AmperageLimitLogic::new, new AmperageLimitLogic()); + + @Override + public @NotNull LongLogicType getType() { + return TYPE; + } + + @Override + public AmperageLimitLogic union(NetLogicEntry other) { + if (other instanceof AmperageLimitLogic l) { + return this.getValue() < l.getValue() ? this : l; + } else return this; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 0ef6ff35df4..5ac6bef2d6a 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -2,55 +2,35 @@ import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IEnergyContainer; -import gregtech.api.graphnet.AbstractGroupData; -import gregtech.api.graphnet.NetGroup; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.logic.ThroughputLogic; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; -import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.group.GroupData; +import gregtech.api.graphnet.group.NetGroup; +import gregtech.api.graphnet.group.PathCacheGroupData; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.api.graphnet.traverse.TraverseHelpers; import gregtech.api.util.GTLog; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fml.common.FMLCommonHandler; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.EnumMap; -import java.util.Iterator; +import java.util.List; public class EnergyCapabilityObject implements IPipeCapabilityObject, IEnergyContainer { - private final WorldPipeNet net; private @Nullable PipeTileEntity tile; - private final EnumMap internalBuffers = new EnumMap<>(EnumFacing.class); - private final WorldPipeNetNode node; + private final @NotNull WorldPipeNetNode node; private boolean transferring = false; - public EnergyCapabilityObject(@NotNull N net, - WorldPipeNetNode node) { - this.net = net; + public EnergyCapabilityObject(@NotNull WorldPipeNetNode node) { this.node = node; - for (EnumFacing facing : EnumFacing.VALUES) { - AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); - edge.setData(NetLogicData.union(node.getData(), (NetLogicData) null)); - internalBuffers.put(facing, edge); - } - } - - private FlowWorldPipeNetPath.Provider getProvider() { - return (FlowWorldPipeNetPath.Provider) net; } private boolean inputDisallowed(EnumFacing side) { @@ -62,82 +42,69 @@ private boolean inputDisallowed(EnumFacing side) { @Override public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage, boolean simulate) { if (tile == null || this.transferring || inputDisallowed(side)) return 0; + NetGroup group = node.getGroupSafe(); + if (!(group.getData() instanceof EnergyGroupData data)) return 0; + this.transferring = true; - SimulatorKey simulator = null; - if (simulate) simulator = SimulatorKey.getNewSimulatorInstance(); - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - - AbstractNetFlowEdge internalBuffer = this.internalBuffers.get(side); - long bufferOverflowAmperage = 0; - if (internalBuffer != null) { - long limit = internalBuffer.getFlowLimit(IPredicateTestObject.INSTANCE, net, tick, simulator); - if (limit <= 0) { - this.transferring = false; - return 0; - } else if (amperage > limit) { - bufferOverflowAmperage = amperage - limit; - } - } - long availableAmperage = amperage; - - EnergyTraverseData data = new EnergyTraverseData(net, IPredicateTestObject.INSTANCE, simulator, tick, voltage, - tile.getPos(), side, bufferOverflowAmperage); - availableAmperage -= TraverseHelpers.traverseFlood(data, getPaths(data), - availableAmperage - bufferOverflowAmperage); - if (availableAmperage > 0) { - availableAmperage -= TraverseHelpers.traverseDumb(data, getPaths(data), data::handleOverflow, - availableAmperage); - } - long accepted = amperage - availableAmperage; - - if (internalBuffer != null) { - data.resetPathVoltage(); - bufferOverflowAmperage = data.calculateActualBufferOverflow(bufferOverflowAmperage); - data.consumeFlowLimit(internalBuffer, node, accepted - bufferOverflowAmperage); - if (bufferOverflowAmperage > 0) { - data.handleOverflow(node, bufferOverflowAmperage); - accepted += bufferOverflowAmperage; + PathCacheGroupData.SecondaryCache cache = data.getOrCreate(node); + List paths = new ObjectArrayList<>(group.getActiveNodes().size()); + for (NetNode dest : group.getActiveNodes()) { + EnergyPath path = (EnergyPath) cache.getOrCompute(dest); + if (path == null) continue; + // construct the path list in order of ascending weight + int i = 0; + while (i < paths.size()) { + if (paths.get(i).getWeight() >= path.getWeight()) break; + else i++; } + paths.add(i, path); } - if (!simulate) { - EnergyGroupData group = getEnergyData(); - if (group != null) { - group.addEnergyInPerSec(accepted * voltage, data.getQueryTick()); + long available = amperage; + for (EnergyPath path : paths) { + NetNode target = path.getTargetNode(); + for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { + if (node == target && capability.getKey() == side) continue; // anti insert-to-our-source logic + + IEnergyContainer container = capability.getValue().getCapability( + GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, capability.getKey().getOpposite()); + if (container != null) { + IEnergyTransferController controller = IEnergyTransferController.CONTROL + .get(tile.getCoverHolder().getCoverAtSide(capability.getKey())); + long allowed = controller.insertToHandler(voltage, available, container, capability.getKey(), true); + EnergyPath.PathFlowReport flow = path.traverse(voltage, allowed); + if (flow.euOut() > 0) { + available -= allowed; + if (!simulate) { + flow.report(); + controller.insertToHandler(flow.voltageOut(), flow.amperageOut(), container, capability.getKey(), false); + } + } + } } } - this.transferring = false; - return accepted; - } - private Iterator getPaths(EnergyTraverseData data) { - assert tile != null; - return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), - data.getQueryTick()); + this.transferring = false; + return amperage - available; } @Nullable - private EnergyGroupData getEnergyData() { - if (tile == null) return null; - NetNode node = net.getNode(tile.getPos()); - if (node == null) return null; + private EnergyGroupData getGroupData() { NetGroup group = node.getGroupUnsafe(); if (group == null) return null; - AbstractGroupData data = group.getData(); + GroupData data = group.getData(); if (!(data instanceof EnergyGroupData e)) return null; return e; } @Override public long getInputAmperage() { - if (tile == null) return 0; - return tile.getNetLogicData(net.getNetworkID()).getLogicEntryDefaultable(ThroughputLogic.TYPE).getValue(); + return node.getData().getLogicEntryDefaultable(AmperageLimitLogic.TYPE).getValue(); } @Override public long getInputVoltage() { - if (tile == null) return 0; - return tile.getNetLogicData(net.getNetworkID()).getLogicEntryDefaultable(VoltageLimitLogic.TYPE).getValue(); + return node.getData().getLogicEntryDefaultable(VoltageLimitLogic.TYPE).getValue(); } @Override @@ -153,15 +120,14 @@ public Capability[] getCapabilities() { @Override public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { if (capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER) { - return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER - .cast(this); + return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER.cast(this); } return null; } @Override public long getInputPerSec() { - EnergyGroupData data = getEnergyData(); + EnergyGroupData data = getGroupData(); if (data == null) return 0; else return data .getEnergyInPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); @@ -169,7 +135,7 @@ public long getInputPerSec() { @Override public long getOutputPerSec() { - EnergyGroupData data = getEnergyData(); + EnergyGroupData data = getGroupData(); if (data == null) return 0; else return data .getEnergyOutPerSec(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java index b5f10b325c8..f696b0a03f5 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java @@ -1,11 +1,17 @@ package gregtech.common.pipelike.net.energy; -import gregtech.api.graphnet.AbstractGroupData; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.group.PathCacheGroupData; +import gregtech.api.graphnet.path.NetPath; +import gregtech.api.graphnet.path.PathBuilder; +import gregtech.api.graphnet.traverse.iter.NetIteratorSupplier; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -public class EnergyGroupData extends AbstractGroupData { +import java.util.Set; + +public class EnergyGroupData extends PathCacheGroupData { private long lastEnergyInPerSec; private long lastEnergyOutPerSec; @@ -13,6 +19,15 @@ public class EnergyGroupData extends AbstractGroupData { private long energyOutPerSec; private long updateTime; + public EnergyGroupData(NetIteratorSupplier iteratorSupplier) { + super(iteratorSupplier); + } + + public EnergyGroupData(NetIteratorSupplier iteratorSupplier, + @NotNull Object2ObjectOpenHashMap cache) { + super(iteratorSupplier, cache); + } + public long getEnergyInPerSec(long queryTick) { updateCache(queryTick); return lastEnergyInPerSec; @@ -48,14 +63,24 @@ public void clearCache() { } @Override - public boolean mergeAllowed(@NotNull AbstractGroupData other) { - return true; + protected PathBuilder createBuilder(@NotNull NetNode origin) { + return new StandardEnergyPath.Builder(origin); + } + + @Override + protected NetPath buildSingleton(@NotNull NetNode singleton) { + return new StandardEnergyPath.SingletonEnergyPath(singleton); } @Override - public @Nullable AbstractGroupData merge(@NotNull AbstractGroupData other) { - if (other instanceof EnergyGroupData) - return new EnergyGroupData(); - else return null; + protected @NotNull PathCacheGroupData buildFilteredCache(@NotNull Set filterNodes) { + Object2ObjectOpenHashMap child = new Object2ObjectOpenHashMap<>(this.cache); + child.entrySet().removeIf(entry -> { + if (!filterNodes.contains(entry.getKey())) return true; + SecondaryCache cache = entry.getValue(); + cache.keySet().retainAll(filterNodes); + return cache.isEmpty(); + }); + return new EnergyGroupData(iteratorSupplier, child); } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyPath.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyPath.java new file mode 100644 index 00000000000..f7b0fa26af1 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyPath.java @@ -0,0 +1,44 @@ +package gregtech.common.pipelike.net.energy; + +import gregtech.api.graphnet.path.NetPath; + +import org.jetbrains.annotations.NotNull; + +public interface EnergyPath extends NetPath { + + /** + * Does the calculations to traverse the path. + * + * @param voltage the input voltage. + * @param amperage the input amperage. + * @return the flow report for the traversal. + */ + @NotNull + PathFlowReport traverse(long voltage, long amperage); + + interface PathFlowReport { + + /** + * @return the total voltage that was allowed through the path + */ + long voltageOut(); + + /** + * @return the total amperage that was allowed through the path + */ + long amperageOut(); + + /** + * @return the total EU that was allowed through the path + */ + default long euOut() { + return voltageOut() * amperageOut(); + } + + /** + * Called when this flow report should stop being simulated; + * e.g. flow should be reported and heating should occur. + */ + void report(); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java deleted file mode 100644 index f7ea63a7d4e..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyTraverseData.java +++ /dev/null @@ -1,229 +0,0 @@ -package gregtech.common.pipelike.net.energy; - -import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.capability.IEnergyContainer; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; -import gregtech.api.graphnet.pipenet.NodeLossCache; -import gregtech.api.graphnet.pipenet.NodeLossResult; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; -import gregtech.api.graphnet.pipenet.traverse.FlowManagerMap; -import gregtech.api.graphnet.pipenet.traverse.ITileFlowManager; -import gregtech.api.graphnet.pipenet.traverse.LocalTransferInformation; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.api.graphnet.traverse.AbstractTraverseData; -import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; -import gregtech.api.util.GTUtility; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; - -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.jetbrains.annotations.NotNull; - -public class EnergyTraverseData extends AbstractTraverseData { - - private final Object2ObjectOpenHashMap overVoltageInformation; - - protected final FlowManagerMap managers = new FlowManagerMap(EnergyFlowManager::new); - - private final long startVoltage; - private long pathVoltage; - private long bufferOverflow; - - private final BlockPos sourcePos; - private final EnumFacing inputFacing; - - public EnergyTraverseData(IGraphNet net, IPredicateTestObject testObject, SimulatorKey simulator, long queryTick, - long startVoltage, BlockPos sourcePos, EnumFacing inputFacing, long bufferOverflow) { - super(net, testObject, simulator, queryTick); - this.overVoltageInformation = new Object2ObjectOpenHashMap<>(); - this.startVoltage = startVoltage; - this.sourcePos = sourcePos; - this.inputFacing = inputFacing; - this.bufferOverflow = bufferOverflow; - } - - @Override - public boolean prepareForPathWalk(@NotNull FlowWorldPipeNetPath path, long flow) { - resetPathVoltage(); - if (flow <= 0 || !managers.access(path.getTargetNode()).canAcceptFlow()) return true; - managers.access(path.getTargetNode()).reportAttemptingFlow(flow); - this.overVoltageInformation.clear(); - this.overVoltageInformation.trim(10); - return false; - } - - public void resetPathVoltage() { - this.pathVoltage = startVoltage; - } - - @Override - public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, long flowReachingNode) { - VoltageLimitLogic limitLogic = node.getData().getLogicEntryNullable(VoltageLimitLogic.TYPE); - if (limitLogic != null) { - long voltage = limitLogic.getValue(); - if (voltage < pathVoltage) overVoltageInformation.put(node, new OverVoltageInformation(voltage)); - } - TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); - if (!node.getData().getLogicEntryDefaultable(SuperconductorLogic.TYPE) - .canSuperconduct(temperatureLogic == null ? TemperatureLogic.DEFAULT_TEMPERATURE : - temperatureLogic.getTemperature(getQueryTick()))) { - pathVoltage -= node.getData().getLogicEntryDefaultable(VoltageLossLogic.TYPE).getValue(); - } - - NodeLossCache.Key key = NodeLossCache.key(node, this); - NodeLossResult result = NodeLossCache.getLossResult(key, simulating()); - if (result != null) { - return result.getLossFunction(); - } else { - result = temperatureLogic == null ? null : temperatureLogic.getLossResult(getQueryTick()); - if (result == null) { - return ReversibleLossOperator.IDENTITY; - } - if (result.hasPostAction()) NodeLossCache.registerLossResult(key, result, simulating()); - return result.getLossFunction(); - } - } - - public void handleOverflow(@NotNull WorldPipeNetNode node, long overflow) { - if (bufferOverflow > 0) { - long difference = bufferOverflow - overflow; - if (difference < 0) { - overflow -= bufferOverflow; - bufferOverflow = 0; - } else { - bufferOverflow -= overflow; - return; - } - } - if (overflow > 0) { - TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); - if (logic != null) { - // this occurs after finalization but before path reset. - logic.applyThermalEnergy(calculateHeatA(overflow, pathVoltage), getQueryTick()); - } - } - } - - public long calculateActualBufferOverflow(long startingOverflow) { - return startingOverflow - bufferOverflow; - } - - @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { - this.pathVoltage = (long) GTUtility.geometricMean(pathVoltage, - overVoltageInformation.values().stream().filter(o -> o.voltageCap < this.pathVoltage) - .mapToDouble(o -> (double) o.voltageCap).toArray()); - long accepted = managers.access(destination).acceptFlow(flowReachingDestination); - if (!simulating() && destination.getGroupUnsafe() != null && - destination.getGroupSafe().getData() instanceof EnergyGroupData data) { - data.addEnergyOutPerSec(accepted * pathVoltage, getQueryTick()); - } - return accepted; - } - - @Override - public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, - long consumption) { - super.consumeFlowLimit(edge, targetNode, consumption); - if (consumption > 0 && !simulating()) { - recordFlow(targetNode, consumption); - OverVoltageInformation info = overVoltageInformation.get((WorldPipeNetNode) targetNode); - if (info != null) info.doHeating((WorldPipeNetNode) targetNode, pathVoltage, getQueryTick(), consumption); - } - } - - private void recordFlow(@NotNull NetNode node, long amperes) { - EnergyFlowLogic logic = node.getData().getLogicEntryNullable(EnergyFlowLogic.TYPE); - if (logic == null) { - logic = EnergyFlowLogic.TYPE.getNew(); - node.getData().setLogicEntry(logic); - } - logic.recordFlow(getQueryTick(), new EnergyFlowData(amperes, pathVoltage)); - } - - private static int calculateHeatV(long amperage, long voltage, long maxVoltage) { - return (int) (amperage * (Math.log1p((double) voltage / maxVoltage) * 85 + 36)); - } - - private static int calculateHeatA(long amperage, long voltage) { - return (int) (amperage * (Math.log1p(Math.log(voltage)) * 85 + 36)); - } - - protected static class OverVoltageInformation { - - public final long voltageCap; - - public OverVoltageInformation(long voltageCap) { - this.voltageCap = voltageCap; - } - - public void doHeating(WorldPipeNetNode node, long finalVoltage, long tick, long amperage) { - TemperatureLogic logic = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); - if (logic != null) { - logic.applyThermalEnergy(calculateHeatV(amperage, finalVoltage, voltageCap), tick); - } - } - } - - protected class EnergyFlowManager extends - Object2LongOpenHashMap> - implements ITileFlowManager { - - public EnergyFlowManager(@NotNull WorldPipeNetNode node) { - for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { - if (GTUtility.arePosEqual(node.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IEnergyContainer container = capability.getValue() - .getCapability(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, - capability.getKey().getOpposite()); - if (container != null) { - IEnergyTransferController controller = IEnergyTransferController.CONTROL.get(node.getTileEntity() - .getCoverHolder().getCoverAtSide(capability.getKey())); - this.put(new LocalTransferInformation<>(capability.getKey(), controller, container), - controller.insertToHandler(pathVoltage, Long.MAX_VALUE, container, capability.getKey(), - true)); - } - } - } - - @Override - public long getMaximumFlow() { - long sum = 0; - for (long l : this.values()) { - sum += l; - } - return sum; - } - - @Override - public void reportAttemptingFlow(long flow) { - for (var entry : this.entrySet()) { - entry.setValue(Math.max(entry.getValue() - flow, 0)); - } - } - - @Override - public long acceptFlow(long flow) { - long availableFlow = flow; - var iter = this.entrySet().iterator(); - while (iter.hasNext()) { - var entry = iter.next(); - var info = entry.getKey(); - long accepted = info.controller().insertToHandler(pathVoltage, availableFlow, info.container(), - info.facing(), simulating()); - if (entry.getValue() == 0) iter.remove(); - availableFlow -= accepted; - } - return flow - availableFlow; - } - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java new file mode 100644 index 00000000000..800404d5378 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java @@ -0,0 +1,307 @@ +package gregtech.common.pipelike.net.energy; + +import com.github.bsideup.jabel.Desugar; + +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.group.NetGroup; +import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.path.PathBuilder; +import gregtech.api.graphnet.path.SingletonNetPath; +import gregtech.api.graphnet.path.StandardNetPath; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; + +import net.minecraftforge.fml.common.FMLCommonHandler; + +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableSet; +import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap; +import it.unimi.dsi.fastutil.longs.LongComparator; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +public class StandardEnergyPath extends StandardNetPath implements EnergyPath { + + // reverse of natural order so that larger longs come first in iteration order. + public static final LongComparator voltageLimitComparator = new LongComparator() { + + @Override + public int compare(long k1, long k2) { + return Long.compare(k2, k1); + } + + @Override + public int compare(Long o1, Long o2) { + return Long.compare(o2, o1); + } + }; + + protected final @NotNull Long2ObjectAVLTreeMap> voltageLimitInfo; + + protected final long loss; + + public StandardEnergyPath(@NotNull ImmutableCollection nodes, @NotNull ImmutableCollection edges, + double weight, @NotNull Long2ObjectAVLTreeMap> voltageLimitInfo, long loss) { + super(nodes, edges, weight); + this.voltageLimitInfo = voltageLimitInfo; + this.loss = loss; + } + + public StandardEnergyPath(@NotNull StandardEnergyPath reverse) { + super(reverse); + this.voltageLimitInfo = reverse.voltageLimitInfo; + this.loss = reverse.loss; + } + + @NotNull + @Override + public PathFlowReport traverse(final long voltage, final long amperage) { + long resultVoltage = voltage - loss; + if (resultVoltage <= 0) return EMPTY; + for (NetEdge edge : getOrderedEdges()) { + if (!edge.test(IPredicateTestObject.INSTANCE)) return EMPTY; + } + + var set = voltageLimitInfo.tailMap(resultVoltage).long2ObjectEntrySet(); + for (var entry : set) { + long key = entry.getLongKey(); + if (key >= resultVoltage) continue; + // move 90% of the way towards the limiting voltage for every node with this limit + int count = entry.getValue().size(); + resultVoltage = (long) (key + (resultVoltage - key) * Math.pow(0.1, count)); + } + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + long resultAmperage = amperage; + List postActions = new ObjectArrayList<>(); + for (NetNode node : getOrderedNodes()) { + NetLogicData data = node.getData(); + EnergyFlowLogic energyFlow = data.getLogicEntryNullable(EnergyFlowLogic.TYPE); + if (energyFlow == null) { + energyFlow = new EnergyFlowLogic(); + data.setLogicEntry(energyFlow); + } + long correctedAmperage = Math.min(data.getLogicEntryDefaultable(AmperageLimitLogic.TYPE).getValue() - + energyFlow.getFlow(tick).stream().mapToLong(EnergyFlowData::amperage).sum(), resultAmperage); + + EnergyFlowLogic finalEnergyFlow = energyFlow; + long finalResultVoltage = resultVoltage; + long finalResultAmperage = resultAmperage; + postActions.add(() -> { + TemperatureLogic tempLogic = data.getLogicEntryNullable(TemperatureLogic.TYPE); + if (tempLogic != null) { + long endVoltage = Math.min(voltage, + data.getLogicEntryDefaultable(VoltageLimitLogic.TYPE).getValue()); + float heat = (float) computeHeat(voltage, endVoltage, finalResultAmperage, correctedAmperage); + if (heat > 0) tempLogic.applyThermalEnergy(heat, tick); + } + finalEnergyFlow.recordFlow(tick, new EnergyFlowData(correctedAmperage, finalResultVoltage)); + }); + resultAmperage = correctedAmperage; + } + long finalResultVoltage = resultVoltage; + long finalResultAmperage = resultAmperage; + postActions.add(() -> { + NetGroup group = getSourceNode().getGroupUnsafe(); + if (group != null && group.getData() instanceof EnergyGroupData data) { + data.addEnergyInPerSec(voltage * amperage, tick); + data.addEnergyOutPerSec(finalResultVoltage * finalResultAmperage, tick); + } + }); + return new StandardReport(resultAmperage, resultVoltage, postActions); + } + + public static double computeHeat(long startVoltage, long endVoltage, long startAmperage, long endAmperage) { + return Math.pow((double) startVoltage * startAmperage - (double) endVoltage * endAmperage, 0.6); + } + + @Override + public @NotNull StandardEnergyPath reversed() { + if (reversed == null) { + reversed = new StandardEnergyPath(this); + } + return (StandardEnergyPath) reversed; + } + + public static final class Builder implements PathBuilder { + + public final List nodes = new ObjectArrayList<>(); + public final List edges = new ObjectArrayList<>(); + public final Long2ObjectAVLTreeMap> voltageLimitInfo = new Long2ObjectAVLTreeMap<>( + voltageLimitComparator); + public double loss = 0; + + public Builder(@NotNull NetNode startingNode) { + nodes.add(startingNode); + handleAdditionalInfo(startingNode); + } + + private void handleAdditionalInfo(@NotNull NetNode node) { + long value = node.getData().getLogicEntryDefaultable(VoltageLimitLogic.TYPE).getValue(); + Set set = voltageLimitInfo.get(value); + if (set == null) { + set = new ObjectOpenHashSet<>(); + voltageLimitInfo.put(value, set); + } + set.add(node); + loss += node.getData().getLogicEntryDefaultable(VoltageLossLogic.TYPE).getValue(); + } + + @Override + @Contract("_, _ -> this") + public Builder addToEnd(@NotNull NetNode node, @NotNull NetEdge edge) { + NetNode end = nodes.get(nodes.size() - 1); + if (edge.getOppositeNode(node) != end) + throw new IllegalArgumentException("Edge does not link last node and new node!"); + nodes.add(node); + handleAdditionalInfo(node); + edges.add(edge); + return this; + } + + @Override + @Contract("_, _ -> this") + public Builder addToStart(@NotNull NetNode node, @NotNull NetEdge edge) { + NetNode end = nodes.get(0); + if (edge.getOppositeNode(node) != end) + throw new IllegalArgumentException("Edge does not link last node and new node!"); + nodes.add(0, node); + handleAdditionalInfo(node); + edges.add(0, edge); + return this; + } + + @Override + @Contract("-> this") + public Builder reverse() { + Collections.reverse(nodes); + Collections.reverse(edges); + return this; + } + + @Override + public StandardEnergyPath build() { + return new StandardEnergyPath(ImmutableSet.copyOf(nodes), ImmutableSet.copyOf(edges), + edges.stream().mapToDouble(NetEdge::getWeight).sum(), voltageLimitInfo, (long) Math.ceil(loss)); + } + } + + public static class SingletonEnergyPath extends SingletonNetPath implements EnergyPath { + + protected final long voltageLimit; + + protected final long loss; + + protected final long amperageLimit; + + public SingletonEnergyPath(NetNode node) { + this(node, node.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue()); + } + + public SingletonEnergyPath(NetNode node, double weight) { + super(node, weight); + NetLogicData data = node.getData(); + this.voltageLimit = data.getLogicEntryDefaultable(VoltageLimitLogic.TYPE).getValue(); + this.loss = (long) Math.ceil(data.getLogicEntryDefaultable(VoltageLossLogic.TYPE).getValue()); + this.amperageLimit = data.getLogicEntryDefaultable(AmperageLimitLogic.TYPE).getValue(); + } + + @Override + public @NotNull EnergyPath.PathFlowReport traverse(long voltage, long amperage) { + long resultVoltage = voltage - loss; + if (resultVoltage <= 0) return EMPTY; + else if (resultVoltage > voltageLimit) { + resultVoltage = (long) (voltageLimit + (resultVoltage - voltageLimit) * 0.1); + } + + NetLogicData data = node.getData(); + EnergyFlowLogic energyFlow = data.getLogicEntryNullable(EnergyFlowLogic.TYPE); + if (energyFlow == null) { + energyFlow = new EnergyFlowLogic(); + data.setLogicEntry(energyFlow); + } + long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + long resultAmperage = Math.min(amperageLimit - + energyFlow.getFlow(tick).stream().mapToLong(EnergyFlowData::amperage).sum(), amperage); + + EnergyFlowLogic finalEnergyFlow = energyFlow; + long finalResultVoltage = resultVoltage; + return new StandardReport(resultAmperage, resultVoltage, () -> { + TemperatureLogic tempLogic = data.getLogicEntryNullable(TemperatureLogic.TYPE); + if (tempLogic != null) { + long endVoltage = Math.min(voltage, + data.getLogicEntryDefaultable(VoltageLimitLogic.TYPE).getValue()); + float heat = (float) computeHeat(voltage, endVoltage, resultAmperage, resultAmperage); + if (heat > 0) tempLogic.applyThermalEnergy(heat, tick); + } + finalEnergyFlow.recordFlow(tick, new EnergyFlowData(resultAmperage, finalResultVoltage)); + + NetGroup group = getSourceNode().getGroupUnsafe(); + if (group != null && group.getData() instanceof EnergyGroupData gData) { + gData.addEnergyInPerSec(voltage * amperage, tick); + gData.addEnergyOutPerSec(finalResultVoltage * resultAmperage, tick); + } + }); + } + } + + protected static final EnergyPath.PathFlowReport EMPTY = new PathFlowReport() { + + @Override + public long voltageOut() { + return 0; + } + + @Override + public long amperageOut() { + return 0; + } + + @Override + public void report() {} + }; + + public static final class StandardReport implements PathFlowReport { + + private final long amperage; + private final long voltage; + private final Runnable[] report; + + public StandardReport(long amperage, long voltage, @NotNull Runnable @NotNull ... report) { + this.amperage = amperage; + this.voltage = voltage; + this.report = report; + } + + public StandardReport(long amperage, long voltage, @NotNull List<@NotNull Runnable> report) { + this.amperage = amperage; + this.voltage = voltage; + this.report = report.toArray(new Runnable[0]); + } + + @Override + public long voltageOut() { + return voltage; + } + + @Override + public long amperageOut() { + return amperage; + } + + @Override + public void report() { + for (Runnable runnable : report) { + runnable.run(); + } + } + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java index b6ae9286152..878b0127963 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/VoltageLossLogic.java @@ -1,18 +1,18 @@ package gregtech.common.pipelike.net.energy; import gregtech.api.GTValues; -import gregtech.api.graphnet.logic.AbstractLongLogicData; +import gregtech.api.graphnet.logic.AbstractDoubleLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; import org.jetbrains.annotations.NotNull; -public final class VoltageLossLogic extends AbstractLongLogicData { +public final class VoltageLossLogic extends AbstractDoubleLogicData { - public static final LongLogicType TYPE = new LongLogicType<>(GTValues.MODID, "VoltageLoss", + public static final DoubleLogicType TYPE = new DoubleLogicType<>(GTValues.MODID, "VoltageLoss", VoltageLossLogic::new, new VoltageLossLogic()); @Override - public @NotNull LongLogicType getType() { + public @NotNull DoubleLogicType getType() { return TYPE; } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java index 3a69ec2e40c..19a7c609a48 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java @@ -1,25 +1,20 @@ package gregtech.common.pipelike.net.energy; import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.graphnet.AbstractGroupData; import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; +import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.traverse.iter.NetClosestIterator; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.Iterator; - -public final class WorldEnergyNet extends WorldPipeNet implements FlowWorldPipeNetPath.Provider { +public final class WorldEnergyNet extends WorldPipeNet { public static final Capability[] CAPABILITIES = new Capability[] { GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER }; @@ -53,13 +48,7 @@ public Capability[] getTargetCapabilities() { @Override public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return new IPipeCapabilityObject[] { new EnergyCapabilityObject(this, node) }; - } - - @Override - public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, long queryTick) { - return backer.getPaths(node, 0, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); + return new IPipeCapabilityObject[] { new EnergyCapabilityObject(node) }; } @Override @@ -68,8 +57,8 @@ public Iterator getPaths(WorldPipeNetNode node, IPredicate } @Override - public AbstractGroupData getBlankGroupData() { - return new EnergyGroupData(); + public GroupData getBlankGroupData() { + return new EnergyGroupData(NetClosestIterator::new); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index b9c9e594bc8..78f27a81f94 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -4,7 +4,6 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java index 5f11c9d878d..afd0d35c003 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java @@ -2,7 +2,6 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.traverse.IEqualizableTraverseData; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java index 92d424c395c..6272d227eaa 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java @@ -2,7 +2,6 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.FluidTestObject; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index a372f8103d2..68965485028 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -8,7 +8,6 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.NodeLossCache; import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java index e40e81a2e70..aeee3f075a9 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java @@ -1,6 +1,5 @@ package gregtech.common.pipelike.net.fluid; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.traverse.ITraverseData; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index b6895c1c6e3..86cddb22bff 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -7,7 +7,6 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; diff --git a/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java b/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java index 3bd33cce2ad..bb4591d8c0c 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java +++ b/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java @@ -1,6 +1,5 @@ package gregtech.common.pipelike.net.item; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.graphnet.traverse.ITraverseData; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index 522729b7f8f..c75ff9a808f 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -3,7 +3,6 @@ import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java index 6f8246a7a66..8a08f60f06d 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java @@ -2,7 +2,6 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.graphnet.traverse.IEqualizableTraverseData; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java index 0eb5893a4f1..6622e20fbcb 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java @@ -2,7 +2,6 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.ItemTestObject; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java index a18d5d37835..75f51065121 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java @@ -4,7 +4,6 @@ import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.graphnet.traverse.AbstractTraverseData; diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 6e6ccd1226b..18c3cfa3a37 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -7,7 +7,6 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.FlowWorldPipeNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; diff --git a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java index b7b114732a4..a27ec2e47ae 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java @@ -2,36 +2,38 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserRelay; -import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; -import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.group.PathCacheGroupData; +import gregtech.api.graphnet.path.NetPath; +import gregtech.api.graphnet.path.SingletonNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.common.pipelike.net.SlowActiveWalker; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Iterator; +import java.util.EnumMap; +import java.util.Set; public class LaserCapabilityObject implements IPipeCapabilityObject, ILaserRelay { - private final WorldPipeNet net; + protected final WorldPipeNetNode node; private @Nullable PipeTileEntity tile; - private boolean transmitting; + private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); - public LaserCapabilityObject(@NotNull N net) { - this.net = net; - } + private boolean transmitting; - private BasicWorldPipeNetPath.Provider getProvider() { - return (BasicWorldPipeNetPath.Provider) net; + public LaserCapabilityObject(@NotNull WorldPipeNetNode node) { + this.node = node; + for (EnumFacing facing : EnumFacing.VALUES) { + wrappers.put(facing, new Wrapper(facing)); + } } @Override @@ -39,34 +41,46 @@ public void setTile(@Nullable PipeTileEntity tile) { this.tile = tile; } - private Iterator getPaths() { - assert tile != null; - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - return getProvider().getPaths(net.getNode(tile.getPos()), IPredicateTestObject.INSTANCE, null, tick); - } - @Override public long receiveLaser(long laserVoltage, long laserAmperage) { + return receiveLaser(laserVoltage, laserAmperage, null); + } + + protected long receiveLaser(long laserVoltage, long laserAmperage, EnumFacing facing) { if (tile == null || this.transmitting) return 0; this.transmitting = true; + NetPath path; + if (node.getGroupUnsafe() == null || node.getGroupSafe().getNodes().size() == 1) + path = new SingletonNetPath(node); + else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { + Set actives = node.getGroupSafe().getActiveNodes(); + if (actives.size() > 2) return 0; // single-destination contract violated + var iter = actives.iterator(); + NetNode target = iter.next(); + if (target == node) { + if (!iter.hasNext()) return 0; // no destinations + target = iter.next(); + } + path = cache.getOrCreate(node).getOrCompute(target); + if (path == null) return 0; // no path + } else return 0; // no cache to lookup with + long available = laserAmperage; - for (Iterator it = getPaths(); it.hasNext();) { - BasicWorldPipeNetPath path = it.next(); - WorldPipeNetNode destination = path.getTargetNode(); - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - ILaserRelay laser = capability.getValue() - .getCapability(GregtechTileCapabilities.CAPABILITY_LASER, capability.getKey().getOpposite()); - if (laser != null) { - long transmitted = ILaserTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(laserVoltage, laserAmperage, laser); - if (transmitted > 0) { - SlowActiveWalker.dispatch(tile.getWorld(), path, 1, 2, 2); - available -= transmitted; - if (available <= 0) { - this.transmitting = false; - return laserAmperage; - } + WorldPipeNetNode destination = path.getTargetNode(); + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (destination == node && capability.getKey() == facing) continue; // anti insert-to-our-source logic + ILaserRelay laser = capability.getValue() + .getCapability(GregtechTileCapabilities.CAPABILITY_LASER, capability.getKey().getOpposite()); + if (laser != null) { + long transmitted = ILaserTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())).insertToHandler(laserVoltage, laserAmperage, laser); + if (transmitted > 0) { + SlowActiveWalker.dispatch(tile.getWorld(), path, 1, 2, 2); + available -= transmitted; + if (available <= 0) { + this.transmitting = false; + return laserAmperage; } } } @@ -84,8 +98,22 @@ public Capability[] getCapabilities() { @Override public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { if (capability == GregtechTileCapabilities.CAPABILITY_LASER) { - return GregtechTileCapabilities.CAPABILITY_LASER.cast(this); + return GregtechTileCapabilities.CAPABILITY_LASER.cast(facing == null ? this : wrappers.get(facing)); } return null; } + + protected class Wrapper implements ILaserRelay { + + private final EnumFacing facing; + + public Wrapper(EnumFacing facing) { + this.facing = facing; + } + + @Override + public long receiveLaser(long laserVoltage, long laserAmperage) { + return LaserCapabilityObject.this.receiveLaser(laserVoltage, laserAmperage, facing); + } + } } diff --git a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java index 13d4f2bb206..429d2a6d631 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java @@ -2,12 +2,12 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.graphnet.alg.SinglePathAlgorithm; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; +import gregtech.api.graphnet.group.GroupData; +import gregtech.api.graphnet.group.PathCacheGroupData; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; @@ -15,9 +15,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Iterator; - -public class WorldLaserNet extends WorldPipeNet implements BasicWorldPipeNetPath.Provider { +public class WorldLaserNet extends WorldPipeNet { public static final Capability[] CAPABILITIES = new Capability[] { GregtechTileCapabilities.CAPABILITY_LASER }; @@ -38,12 +36,6 @@ public WorldLaserNet(String name) { super(name, false, SinglePathAlgorithm::new); } - @Override - public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, long queryTick) { - return backer.getPaths(node, 0, BasicWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); - } - @Override public Capability[] getTargetCapabilities() { return CAPABILITIES; @@ -51,7 +43,12 @@ public Capability[] getTargetCapabilities() { @Override public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return new IPipeCapabilityObject[] { new LaserCapabilityObject(this) }; + return new IPipeCapabilityObject[] { new LaserCapabilityObject(node) }; + } + + @Override + public @Nullable GroupData getBlankGroupData() { + return new PathCacheGroupData(NetBreadthIterator::new); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index a19fc657675..e959d7d14d3 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -4,44 +4,39 @@ import gregtech.api.capability.data.IDataAccess; import gregtech.api.capability.data.query.DataAccessFormat; import gregtech.api.capability.data.query.DataQueryObject; -import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; -import gregtech.api.graphnet.pipenet.WorldPipeNet; +import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.group.PathCacheGroupData; +import gregtech.api.graphnet.path.NetPath; +import gregtech.api.graphnet.path.SingletonNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.api.util.GTUtility; import gregtech.common.pipelike.net.SlowActiveWalker; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.EnumMap; -import java.util.Iterator; +import java.util.Set; public class DataCapabilityObject implements IPipeCapabilityObject, IDataAccess { - private final WorldPipeNet net; + private final WorldPipeNetNode node; private @Nullable PipeTileEntity tile; private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); - public DataCapabilityObject(@NotNull N net) { - this.net = net; + public DataCapabilityObject(@NotNull WorldPipeNetNode node) { + this.node = node; for (EnumFacing facing : EnumFacing.VALUES) { wrappers.put(facing, new Wrapper(facing)); } } - private BasicWorldPipeNetPath.Provider getProvider() { - return (BasicWorldPipeNetPath.Provider) net; - } - @Override public void setTile(@Nullable PipeTileEntity tile) { this.tile = tile; @@ -55,27 +50,38 @@ public boolean accessData(@NotNull DataQueryObject queryObject) { private boolean accessData(@NotNull DataQueryObject queryObject, @Nullable EnumFacing facing) { if (tile == null) return false; - for (Iterator it = getPaths(); it.hasNext();) { - BasicWorldPipeNetPath path = it.next(); - WorldPipeNetNode destination = path.getTargetNode(); - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), tile.getPos()) && - capability.getKey() == facing) - continue; // anti insert-to-our-source logic - IDataAccess access = capability.getValue() - .getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, - capability.getKey().getOpposite()); - if (access != null) { - queryObject.setShouldTriggerWalker(false); - boolean cancelled = IOpticalTransferController.CONTROL - .get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())) - .queryHandler(queryObject, access); - if (queryObject.shouldTriggerWalker()) { - SlowActiveWalker.dispatch(tile.getWorld(), path, 1); - } - if (cancelled) return true; + NetPath path; + if (node.getGroupUnsafe() == null || node.getGroupSafe().getNodes().size() == 1) + path = new SingletonNetPath(node); + else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { + Set actives = node.getGroupSafe().getActiveNodes(); + if (actives.size() > 2) return false; // single-destination contract violated + var iter = actives.iterator(); + NetNode target = iter.next(); + if (target == node) { + if (!iter.hasNext()) return false; // no destinations + target = iter.next(); + } + path = cache.getOrCreate(node).getOrCompute(target); + if (path == null) return false; // no path + } else return false; // no cache to lookup with + + WorldPipeNetNode destination = path.getTargetNode(); + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (destination == node && capability.getKey() == facing) continue; // anti insert-to-our-source logic + IDataAccess access = capability.getValue() + .getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, + capability.getKey().getOpposite()); + if (access != null) { + queryObject.setShouldTriggerWalker(false); + boolean cancelled = IOpticalTransferController.CONTROL + .get(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey())) + .queryHandler(queryObject, access); + if (queryObject.shouldTriggerWalker()) { + SlowActiveWalker.dispatch(tile.getWorld(), path, 1); } + if (cancelled) return true; } } return false; @@ -86,12 +92,6 @@ private boolean accessData(@NotNull DataQueryObject queryObject, @Nullable EnumF return DataAccessFormat.UNIVERSAL; } - private Iterator getPaths() { - assert tile != null; - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - return getProvider().getPaths(net.getNode(tile.getPos()), IPredicateTestObject.INSTANCE, null, tick); - } - @Override public Capability[] getCapabilities() { return WorldOpticalNet.CAPABILITIES; diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java index c36dbbb8bea..c64ed4b7a29 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -2,12 +2,12 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.graphnet.alg.SinglePathAlgorithm; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.BasicWorldPipeNetPath; +import gregtech.api.graphnet.group.GroupData; +import gregtech.api.graphnet.group.PathCacheGroupData; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; @@ -15,9 +15,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Iterator; - -public class WorldOpticalNet extends WorldPipeNet implements BasicWorldPipeNetPath.Provider { +public class WorldOpticalNet extends WorldPipeNet { public static final Capability[] CAPABILITIES = new Capability[] { GregtechTileCapabilities.CAPABILITY_DATA_ACCESS }; @@ -39,12 +37,6 @@ public WorldOpticalNet(String name) { super(name, false, SinglePathAlgorithm::new); } - @Override - public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, long queryTick) { - return backer.getPaths(node, 0, BasicWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); - } - @Override public Capability[] getTargetCapabilities() { return CAPABILITIES; @@ -52,7 +44,12 @@ public Capability[] getTargetCapabilities() { @Override public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return new IPipeCapabilityObject[] { new DataCapabilityObject(this) }; + return new IPipeCapabilityObject[] { new DataCapabilityObject(node) }; + } + + @Override + public @Nullable GroupData getBlankGroupData() { + return new PathCacheGroupData(NetBreadthIterator::new); } @Override From 6e294e4393a1750953070ece7bd651fb0e5ce40c Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Fri, 29 Nov 2024 16:26:02 -0700 Subject: [PATCH 147/157] stuff --- .../api/graphnet/alg/AlgorithmBuilder.java | 12 --- .../DynamicWeightsShortestPathsAlgorithm.java | 101 ------------------ .../api/graphnet/alg/INetAlgorithm.java | 11 -- .../api/graphnet/alg/NetAlgorithmWrapper.java | 45 -------- .../graphnet/alg/ShortestPathsAlgorithm.java | 61 ----------- .../api/graphnet/alg/SinglePathAlgorithm.java | 89 --------------- .../graphnet/alg/iter/IteratorFactory.java | 29 ----- .../alg/iter/SimpleIteratorFactories.java | 43 -------- .../gregtech/api/graphnet/edge/NetEdge.java | 2 +- .../api/graphnet/graph/GraphEdge.java | 11 +- .../api/graphnet/graph/GraphVertex.java | 12 ++- .../api/graphnet/pipenet/NodeLossCache.java | 2 +- .../api/graphnet/pipenet/NodeLossResult.java | 4 +- .../api/graphnet/pipenet/WorldPipeNet.java | 10 +- .../graphnet/pipenet/WorldPipeNetNode.java | 2 +- .../pipenet/logic/TemperatureLogic.java | 4 +- .../traverse/AbstractTileRoundRobinData.java | 2 +- .../api/graphnet/servernet/ServerNet.java | 1 - .../traverse/AbstractMinCostTraverse.java | 51 +++++++++ .../api/graphnet/traverse/FloodTraverse.java | 17 +++ .../AbstractTraverseData.java | 2 +- .../DistributorHelper.java | 2 +- .../IEqualizableTraverseData.java | 2 +- .../IRoundRobinData.java | 2 +- .../IRoundRobinTraverseData.java | 2 +- .../ITraverseData.java | 4 +- .../ITraverseGuideProvider.java | 2 +- .../TraverseDataProvider.java | 2 +- .../TraverseGuide.java | 2 +- .../TraverseHelpers.java | 4 +- .../util/CompleteLossOperator.java | 2 +- .../util/CompositeLossOperator.java | 2 +- .../util/FlatLossOperator.java | 2 +- .../util/FlowConsumptionStack.java | 2 +- .../util/MultLossOperator.java | 2 +- .../util/ReversibleLossOperator.java | 2 +- .../api/graphnet/worldnet/WorldNet.java | 9 +- .../api/graphnet/worldnet/WorldPosNet.java | 10 +- .../gregtech/common/covers/CoverConveyor.java | 2 +- .../gregtech/common/covers/CoverPump.java | 2 +- .../pipelike/net/energy/WorldEnergyNet.java | 3 +- .../net/fluid/ContainmentFailure.java | 2 +- .../net/fluid/FluidCapabilityObject.java | 8 +- .../net/fluid/FluidEQTraverseData.java | 2 +- .../net/fluid/FluidRRTraverseData.java | 2 +- .../pipelike/net/fluid/FluidTraverseData.java | 6 +- .../fluid/IFluidTraverseGuideProvider.java | 8 +- .../pipelike/net/fluid/WorldFluidNet.java | 3 +- .../net/item/IItemTraverseGuideProvider.java | 8 +- .../net/item/ItemCapabilityObject.java | 8 +- .../pipelike/net/item/ItemEQTraverseData.java | 2 +- .../pipelike/net/item/ItemRRTraverseData.java | 2 +- .../pipelike/net/item/ItemTraverseData.java | 4 +- .../pipelike/net/item/WorldItemNet.java | 3 +- .../pipelike/net/laser/WorldLaserNet.java | 3 +- .../pipelike/net/optical/WorldOpticalNet.java | 3 +- 56 files changed, 157 insertions(+), 478 deletions(-) delete mode 100644 src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java delete mode 100644 src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java delete mode 100644 src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java delete mode 100644 src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java delete mode 100644 src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java delete mode 100644 src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java delete mode 100644 src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java delete mode 100644 src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/FloodTraverse.java rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/AbstractTraverseData.java (96%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/DistributorHelper.java (92%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/IEqualizableTraverseData.java (96%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/IRoundRobinData.java (96%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/IRoundRobinTraverseData.java (98%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/ITraverseData.java (96%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/ITraverseGuideProvider.java (93%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/TraverseDataProvider.java (92%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/TraverseGuide.java (96%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/TraverseHelpers.java (99%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/util/CompleteLossOperator.java (88%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/util/CompositeLossOperator.java (92%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/util/FlatLossOperator.java (89%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/util/FlowConsumptionStack.java (97%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/util/MultLossOperator.java (94%) rename src/main/java/gregtech/api/graphnet/{traverse => traverseold}/util/ReversibleLossOperator.java (89%) diff --git a/src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java b/src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java deleted file mode 100644 index 6fb0c6eee88..00000000000 --- a/src/main/java/gregtech/api/graphnet/alg/AlgorithmBuilder.java +++ /dev/null @@ -1,12 +0,0 @@ -package gregtech.api.graphnet.alg; - -import gregtech.api.graphnet.IGraphNet; - -import org.jetbrains.annotations.NotNull; - -@FunctionalInterface -public interface AlgorithmBuilder { - - @NotNull - INetAlgorithm build(@NotNull IGraphNet net, boolean recomputeEveryCall); -} diff --git a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java deleted file mode 100644 index a4e970c8add..00000000000 --- a/src/main/java/gregtech/api/graphnet/alg/DynamicWeightsShortestPathsAlgorithm.java +++ /dev/null @@ -1,101 +0,0 @@ -package gregtech.api.graphnet.alg; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.alg.iter.IteratorFactory; -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.path.NetPath; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jetbrains.annotations.Nullable; -import org.jgrapht.alg.shortestpath.DefaultManyToManyShortestPaths; - -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -public class DynamicWeightsShortestPathsAlgorithm extends DefaultManyToManyShortestPaths - implements INetAlgorithm { - - private final boolean recomputeEveryCall; - - public DynamicWeightsShortestPathsAlgorithm(IGraphNet net, boolean recomputeEveryCall) { - super(net.getGraph()); - this.recomputeEveryCall = recomputeEveryCall; - } - - @Override - public > IteratorFactory getPathsIteratorFactory(GraphVertex source, - NetPathMapper remapper) { - Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream().filter(NetNode::isActive) - .map(n -> n.wrapper).filter(node -> !(source == node) && graph.containsVertex(node)) - .collect(Collectors.toSet()); - return (graph, testObject, simulator, queryTick) -> { - if (recomputeEveryCall) graph.prepareForAlgorithmRun(testObject, simulator, queryTick); - return new LimitedIterator<>(source, searchSpace, remapper); - }; - } - - protected class LimitedIterator> implements Iterator { - - private static final int MAX_ITERATIONS = 100; - - private final GraphVertex source; - private final Set searchSpace; - private final NetPathMapper remapper; - - private int iterationCount = 0; - private final ObjectArrayList visited = new ObjectArrayList<>(); - private @Nullable Path next; - - public LimitedIterator(GraphVertex source, Set searchSpace, NetPathMapper remapper) { - this.source = source; - this.searchSpace = searchSpace; - this.remapper = remapper; - } - - @Override - public boolean hasNext() { - if (next == null && iterationCount < MAX_ITERATIONS) calculateNext(); - return next != null; - } - - @Override - public Path next() { - if (!hasNext()) throw new NoSuchElementException(); - Path temp = next; - next = null; - return temp; - } - - private void calculateNext() { - iterationCount++; - if (iterationCount == 1) { - next = remapper.map(source); - return; - } - searchSpace.removeIf(vertex -> !graph.containsVertex(vertex)); - ManyToManyShortestPaths paths = getManyToManyPaths(Collections.singleton(source), - searchSpace); - Optional next = searchSpace.stream().map(node -> paths.getPath(source, node)).filter(Objects::nonNull) - .map(remapper::map).filter(this::isUnique).min(Comparator.comparingDouble(NetPath::getWeight)); - this.next = next.orElse(null); - next.ifPresent(this.visited::add); - } - - private boolean isUnique(Path path) { - for (Path other : visited) { - if (path.getOrderedNodes().equals(other.getOrderedNodes()) && - path.getOrderedEdges().equals(other.getOrderedEdges())) - return false; - } - return true; - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java deleted file mode 100644 index f3022917ea9..00000000000 --- a/src/main/java/gregtech/api/graphnet/alg/INetAlgorithm.java +++ /dev/null @@ -1,11 +0,0 @@ -package gregtech.api.graphnet.alg; - -import gregtech.api.graphnet.alg.iter.IteratorFactory; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.path.NetPath; - -public interface INetAlgorithm { - - > IteratorFactory getPathsIteratorFactory(GraphVertex source, - NetPathMapper remapper); -} diff --git a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java b/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java deleted file mode 100644 index 1639b1fb4f4..00000000000 --- a/src/main/java/gregtech/api/graphnet/alg/NetAlgorithmWrapper.java +++ /dev/null @@ -1,45 +0,0 @@ -package gregtech.api.graphnet.alg; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.alg.iter.IteratorFactory; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.path.NetPath; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class NetAlgorithmWrapper { - - private final IGraphNet net; - private final boolean recomputeEveryCall; - @Nullable - private INetAlgorithm alg; - - private final AlgorithmBuilder builder; - - public NetAlgorithmWrapper(IGraphNet net, @NotNull AlgorithmBuilder builder, boolean recomputeEveryCall) { - this.net = net; - this.builder = builder; - this.recomputeEveryCall = recomputeEveryCall; - } - - public IGraphNet getNet() { - return net; - } - - public void invalidate() { - this.alg = null; - } - - public > IteratorFactory getPathsIterator(GraphVertex source, - NetPathMapper remapper, - IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, - long queryTick) { - if (!recomputeEveryCall) net.getGraph().prepareForAlgorithmRun(testObject, simulator, queryTick); - if (alg == null) alg = builder.build(net, recomputeEveryCall); - return alg.getPathsIteratorFactory(source, remapper); - } -} diff --git a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java deleted file mode 100644 index 61f4fe8faa7..00000000000 --- a/src/main/java/gregtech/api/graphnet/alg/ShortestPathsAlgorithm.java +++ /dev/null @@ -1,61 +0,0 @@ -package gregtech.api.graphnet.alg; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.alg.iter.IteratorFactory; -import gregtech.api.graphnet.alg.iter.SimpleIteratorFactories; -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.path.NetPath; - -import org.jgrapht.alg.shortestpath.CHManyToManyShortestPaths; - -import java.util.Collections; -import java.util.Comparator; -import java.util.Set; -import java.util.stream.Collectors; - -public final class ShortestPathsAlgorithm extends CHManyToManyShortestPaths - implements INetAlgorithm { - - private final boolean recomputeEveryCall; - - public ShortestPathsAlgorithm(IGraphNet net, boolean recomputeEveryCall) { - super(net.getGraph()); - this.recomputeEveryCall = recomputeEveryCall; - } - - @Override - public > IteratorFactory getPathsIteratorFactory(GraphVertex source, - NetPathMapper remapper) { - if (!graph.containsVertex(source)) { - throw new IllegalArgumentException("Graph must contain the source vertex"); - } - // if the source has no group, it has no paths other than the path to itself. - if (source.wrapped.getGroupUnsafe() == null) { - Path path = remapper.map(source); - return SimpleIteratorFactories.fromSingleton(path); - } - - Set searchSpace = source.wrapped.getGroupSafe().getNodes().stream().filter(NetNode::isActive) - .map(n -> n.wrapper).filter(node -> !source.equals(node) && graph.containsVertex(node)) - .collect(Collectors.toSet()); - Set singleton = Collections.singleton(source); - if (recomputeEveryCall) { - return (graph1, testObject, simulator, queryTick) -> { - graph1.prepareForAlgorithmRun(testObject, simulator, queryTick); - ManyToManyShortestPaths manyToManyPaths = getManyToManyPaths(singleton, - searchSpace); - return searchSpace.stream().map(node -> manyToManyPaths.getPath(source, node)) - .map(remapper::map).sorted(Comparator.comparingDouble(NetPath::getWeight)).iterator(); - }; - } else { - ManyToManyShortestPaths manyToManyPaths = getManyToManyPaths(singleton, - searchSpace); - return SimpleIteratorFactories.fromIterable(searchSpace.stream() - .map(node -> manyToManyPaths.getPath(source, node)) - .map(remapper::map).sorted(Comparator.comparingDouble(NetPath::getWeight)) - .collect(Collectors.toList())); - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java b/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java deleted file mode 100644 index c0e3963479b..00000000000 --- a/src/main/java/gregtech/api/graphnet/alg/SinglePathAlgorithm.java +++ /dev/null @@ -1,89 +0,0 @@ -package gregtech.api.graphnet.alg; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.alg.iter.IteratorFactory; -import gregtech.api.graphnet.alg.iter.SimpleIteratorFactories; -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.path.NetPath; - -import com.github.bsideup.jabel.Desugar; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import java.util.Iterator; -import java.util.List; - -public final class SinglePathAlgorithm implements INetAlgorithm { - - private final IGraphNet net; - private final boolean recomputeEveryCall; - - public SinglePathAlgorithm(IGraphNet pipenet, boolean recomputeEveryCall) { - this.net = pipenet; - this.recomputeEveryCall = recomputeEveryCall; - } - - @Override - public > IteratorFactory getPathsIteratorFactory(GraphVertex source, - NetPathMapper remapper) { - if (recomputeEveryCall) { - return (graph, testObject, simulator, queryTick) -> { - graph.prepareForAlgorithmRun(testObject, simulator, queryTick); - List graphEdges = new ObjectArrayList<>(); - List nodes = new ObjectArrayList<>(); - Results results = compute(source, nodes, graphEdges); - if (!results.valid()) return SimpleIteratorFactories.getSingletonIterator(null); - if (graphEdges.isEmpty()) return SimpleIteratorFactories.getSingletonIterator(remapper.map(source)); - return SimpleIteratorFactories.getSingletonIterator(remapper.map(nodes, graphEdges, results.weight())); - }; - } else { - List graphEdges = new ObjectArrayList<>(); - List nodes = new ObjectArrayList<>(); - Results results = compute(source, nodes, graphEdges); - if (!results.valid()) return SimpleIteratorFactories.emptyFactory(); - if (graphEdges.isEmpty()) return SimpleIteratorFactories.fromSingleton(remapper.map(source)); - return SimpleIteratorFactories.fromSingleton(remapper.map(nodes, graphEdges, results.weight())); - } - } - - private Results compute(GraphVertex source, - List nodes, List graphEdges) { - nodes.add(source); - GraphVertex lastNode = null; - GraphVertex node = source; - GraphEdge graphEdge; - double sumWeight = 0; - boolean valid = true; - while (valid) { - Iterator i = this.net.getGraph().outgoingEdgesOf(node).iterator(); - if (!i.hasNext()) break; // we've reached the end, exit the loop while still valid - graphEdge = i.next(); - // if we are directed, we know that the target is the target. - // if we aren't directed, we need to see if the graphEdge's target is secretly the source - boolean reversedEdge = !this.net.getGraph().isDirected() && graphEdge.getTarget() == node; - if ((!reversedEdge && graphEdge.getTarget() == lastNode) || - (reversedEdge && graphEdge.getSource() == lastNode)) { - // current edge points to a previous node, either get the other edge or exit safely. - if (i.hasNext()) { - graphEdge = i.next(); - reversedEdge = !this.net.getGraph().isDirected() && graphEdge.getTarget() == node; - // we know that the new edge cannot point to the previous node - } else break; // we've reached the end, exit the loop while still valid - } else if (i.hasNext()) i.next(); // remove the second edge, if it exists. - if (i.hasNext()) valid = false; // third graphEdge detected - that's an invalid group - lastNode = node; - node = reversedEdge ? graphEdge.getSource() : graphEdge.getTarget(); - graphEdges.add(graphEdge); - nodes.add(node); - sumWeight += getWeight(graphEdge); - } - return new Results(sumWeight, valid); - } - - private double getWeight(GraphEdge graphEdge) { - return this.net.getGraph().getEdgeWeight(graphEdge); - } - - @Desugar - private record Results(double weight, boolean valid) {} -} diff --git a/src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java b/src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java deleted file mode 100644 index 0a9a4455280..00000000000 --- a/src/main/java/gregtech/api/graphnet/alg/iter/IteratorFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -package gregtech.api.graphnet.alg.iter; - -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.graph.INetGraph; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.Nullable; - -import java.util.Iterator; - -public interface IteratorFactory { - - /** - * The provided iterator must always be used and discarded before the end of the tick. - */ - @Contract("_, _, _, _ -> new") - Iterator newIterator(INetGraph graph, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, - long queryTick); - - static void defaultPrepareRun(INetGraph graph, IPredicateTestObject testObject, @Nullable SimulatorKey simulator, - long queryTick) { - graph.prepareForAlgorithmRun(testObject, simulator, queryTick); - } - - default boolean cacheable() { - return true; - } -} diff --git a/src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java b/src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java deleted file mode 100644 index f72432b23d1..00000000000 --- a/src/main/java/gregtech/api/graphnet/alg/iter/SimpleIteratorFactories.java +++ /dev/null @@ -1,43 +0,0 @@ -package gregtech.api.graphnet.alg.iter; - -import java.util.Iterator; - -public final class SimpleIteratorFactories { - - public static IteratorFactory emptyFactory() { - return (graph, testObject, simulator, queryTick) -> new SingletonIterator<>(null); - } - - public static IteratorFactory fromIterable(Iterable prototype) { - return (graph, testObject, simulator, queryTick) -> prototype.iterator(); - } - - public static IteratorFactory fromSingleton(T singleton) { - return (graph, testObject, simulator, queryTick) -> new SingletonIterator<>(singleton); - } - - public static SingletonIterator getSingletonIterator(T singleton) { - return new SingletonIterator<>(singleton); - } - - private static class SingletonIterator implements Iterator { - - private T singleton; - - public SingletonIterator(T singleton) { - this.singleton = singleton; - } - - @Override - public boolean hasNext() { - return singleton != null; - } - - @Override - public T next() { - T temp = singleton; - singleton = null; - return temp; - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java index 36714d98be0..27a43006b3c 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java @@ -43,7 +43,7 @@ public class NetEdge implements INBTSerializable { else return null; } - public double getWeight() { + public final double getWeight() { return wrapper == null ? Double.POSITIVE_INFINITY : wrapper.getWeight(); } diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java index e04b6cc73a3..4547e0091ba 100644 --- a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java +++ b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java @@ -2,21 +2,28 @@ import gregtech.api.graphnet.edge.NetEdge; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jgrapht.graph.DefaultWeightedEdge; import java.util.Objects; public final class GraphEdge extends DefaultWeightedEdge { - public final @NotNull NetEdge wrapped; + public final NetEdge wrapped; public GraphEdge(@NotNull NetEdge wrapped) { this.wrapped = wrapped; wrapped.wrapper = this; } - public @NotNull NetEdge getWrapped() { + @ApiStatus.Internal + public GraphEdge() { + this.wrapped = null; + } + + public NetEdge getWrapped() { return wrapped; } diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java b/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java index e77a5e4a7ba..ba95d226572 100644 --- a/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java +++ b/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java @@ -2,20 +2,28 @@ import gregtech.api.graphnet.NetNode; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnknownNullability; import java.util.Objects; public final class GraphVertex { - public final @NotNull NetNode wrapped; + public final NetNode wrapped; public GraphVertex(@NotNull NetNode wrapped) { this.wrapped = wrapped; wrapped.wrapper = this; } - public @NotNull NetNode getWrapped() { + @ApiStatus.Internal + public GraphVertex() { + wrapped = null; + } + + public NetNode getWrapped() { return wrapped; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java index 51b03c5cce4..3488c512f30 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.pipenet; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.api.graphnet.traverse.ITraverseData; +import gregtech.api.graphnet.traverseold.ITraverseData; import gregtech.api.util.TaskScheduler; import gregtech.api.util.function.Task; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java index e3cfd778aaa..59919b1045f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.pipenet; -import gregtech.api.graphnet.traverse.util.CompositeLossOperator; -import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; +import gregtech.api.graphnet.traverseold.util.CompositeLossOperator; +import gregtech.api.graphnet.traverseold.util.ReversibleLossOperator; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index d11d5338d2e..31edd5188d9 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -4,7 +4,6 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.MultiNodeHelper; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.alg.AlgorithmBuilder; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; @@ -43,13 +42,12 @@ public abstract class WorldPipeNet extends WorldPosNet { private static final Int2ObjectOpenHashMap> dimensionNets = new Int2ObjectOpenHashMap<>(); - public WorldPipeNet(String name, Function graphBuilder, - AlgorithmBuilder... algorithmBuilders) { - super(name, graphBuilder, algorithmBuilders); + public WorldPipeNet(String name, Function graphBuilder) { + super(name, graphBuilder); } - public WorldPipeNet(String name, boolean directed, AlgorithmBuilder... algorithmBuilders) { - super(name, directed, algorithmBuilders); + public WorldPipeNet(String name, boolean directed) { + super(name, directed); } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java index 98f2d8962b0..7520daee20c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java @@ -85,6 +85,6 @@ public boolean traverse(long queryTick, boolean simulate) { @Override public BlockPos getEquivalencyData() { - return (BlockPos) super.getEquivalencyData(); + return super.getEquivalencyData(); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index e9a23fe0197..6ce23b4254f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -10,8 +10,8 @@ import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.IFreezable; -import gregtech.api.graphnet.traverse.util.CompleteLossOperator; -import gregtech.api.graphnet.traverse.util.MultLossOperator; +import gregtech.api.graphnet.traverseold.util.CompleteLossOperator; +import gregtech.api.graphnet.traverseold.util.MultLossOperator; import gregtech.client.particle.GTOverheatParticle; import net.minecraft.block.state.IBlockState; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java index c814979e520..859816136aa 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java @@ -3,7 +3,7 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; -import gregtech.api.graphnet.traverse.IRoundRobinData; +import gregtech.api.graphnet.traverseold.IRoundRobinData; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java index dca9e334a96..f871001f28f 100644 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java +++ b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java @@ -3,7 +3,6 @@ import gregtech.api.graphnet.GraphNetBacker; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.alg.AlgorithmBuilder; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.graph.NetDirectedGraph; diff --git a/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java new file mode 100644 index 00000000000..9bc1f2d98f2 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java @@ -0,0 +1,51 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; + +import it.unimi.dsi.fastutil.objects.Object2DoubleMap; +import it.unimi.dsi.fastutil.objects.Object2DoubleMaps; +import org.apache.commons.lang3.tuple.Pair; +import org.jgrapht.Graph; +import org.jgrapht.alg.flow.mincost.CapacityScalingMinimumCostFlow; +import org.jgrapht.alg.flow.mincost.MinimumCostFlowProblem; + +import java.util.Collections; +import java.util.function.Function; + +public abstract class AbstractMinCostTraverse implements MinimumCostFlowProblem { + + protected static final CapacityScalingMinimumCostFlow MINCOST = new CapacityScalingMinimumCostFlow<>(); + + protected static final GraphVertex CORRECTOR = new GraphVertex(); + + public Object2DoubleMap evaluate() { + try { + // setup: + MINCOST.getMinimumCostFlow(this) + } catch (Exception ignored) { + return Object2DoubleMaps.emptyMap(); + } + } + + @Override + public Graph getGraph() { + return null; + } + + @Override + public Function getNodeSupply() { + return null; + } + + @Override + public Function getArcCapacityLowerBounds() { + return e -> 0; + } + + @Override + public Function getArcCapacityUpperBounds() { + return null; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/FloodTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/FloodTraverse.java new file mode 100644 index 00000000000..737e58bcd47 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/FloodTraverse.java @@ -0,0 +1,17 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; + +import org.jgrapht.Graph; +import org.jgrapht.traverse.ClosestFirstIterator; + +public class FloodTraverse { + + protected static class Iterator extends ClosestFirstIterator { + + public Iterator(Graph g, GraphVertex startVertex) { + super(g, startVertex); + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java similarity index 96% rename from src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java rename to src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java index c0b5231218a..929d986d443 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/AbstractTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse; +package gregtech.api.graphnet.traverseold; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; diff --git a/src/main/java/gregtech/api/graphnet/traverse/DistributorHelper.java b/src/main/java/gregtech/api/graphnet/traverseold/DistributorHelper.java similarity index 92% rename from src/main/java/gregtech/api/graphnet/traverse/DistributorHelper.java rename to src/main/java/gregtech/api/graphnet/traverseold/DistributorHelper.java index 5cd56fec94b..cdbdcc23127 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/DistributorHelper.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/DistributorHelper.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse; +package gregtech.api.graphnet.traverseold; public class DistributorHelper { diff --git a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/IEqualizableTraverseData.java similarity index 96% rename from src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java rename to src/main/java/gregtech/api/graphnet/traverseold/IEqualizableTraverseData.java index 5fa89ae4a37..a6f996ce88d 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/IEqualizableTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/IEqualizableTraverseData.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse; +package gregtech.api.graphnet.traverseold; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.path.NetPath; diff --git a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinData.java b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java similarity index 96% rename from src/main/java/gregtech/api/graphnet/traverse/IRoundRobinData.java rename to src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java index 5ccf9156e94..413944a8b8c 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse; +package gregtech.api.graphnet.traverseold; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.SimulatorKey; diff --git a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinTraverseData.java similarity index 98% rename from src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java rename to src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinTraverseData.java index a4b3c024d79..16fbaf442bf 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/IRoundRobinTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinTraverseData.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse; +package gregtech.api.graphnet.traverseold; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.path.NetPath; diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java similarity index 96% rename from src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java rename to src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java index 3fd86cdde6c..f8edf77efcc 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/ITraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse; +package gregtech.api.graphnet.traverseold; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; @@ -6,7 +6,7 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; +import gregtech.api.graphnet.traverseold.util.ReversibleLossOperator; import org.jetbrains.annotations.MustBeInvokedByOverriders; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseGuideProvider.java similarity index 93% rename from src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java rename to src/main/java/gregtech/api/graphnet/traverseold/ITraverseGuideProvider.java index 9f7c3feb819..82d59605c1d 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/ITraverseGuideProvider.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseGuideProvider.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse; +package gregtech.api.graphnet.traverseold; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.path.NetPath; diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseDataProvider.java b/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java similarity index 92% rename from src/main/java/gregtech/api/graphnet/traverse/TraverseDataProvider.java rename to src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java index 98ec3348ac6..01cf9ec9e50 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseDataProvider.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse; +package gregtech.api.graphnet.traverseold; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java b/src/main/java/gregtech/api/graphnet/traverseold/TraverseGuide.java similarity index 96% rename from src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java rename to src/main/java/gregtech/api/graphnet/traverseold/TraverseGuide.java index 9387c47e5fa..79ad651f4e8 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseGuide.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/TraverseGuide.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse; +package gregtech.api.graphnet.traverseold; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.path.NetPath; diff --git a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java similarity index 99% rename from src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java rename to src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java index 27080f7009d..9deba1c0f3a 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java @@ -1,10 +1,10 @@ -package gregtech.api.graphnet.traverse; +package gregtech.api.graphnet.traverseold; import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.path.NetPath; -import gregtech.api.graphnet.traverse.util.FlowConsumptionStack; +import gregtech.api.graphnet.traverseold.util.FlowConsumptionStack; import gregtech.api.util.GTUtility; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/CompleteLossOperator.java b/src/main/java/gregtech/api/graphnet/traverseold/util/CompleteLossOperator.java similarity index 88% rename from src/main/java/gregtech/api/graphnet/traverse/util/CompleteLossOperator.java rename to src/main/java/gregtech/api/graphnet/traverseold/util/CompleteLossOperator.java index 64eeef293fb..5cb4b1b3236 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/CompleteLossOperator.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/util/CompleteLossOperator.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.util; +package gregtech.api.graphnet.traverseold.util; public class CompleteLossOperator implements ReversibleLossOperator { diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/CompositeLossOperator.java b/src/main/java/gregtech/api/graphnet/traverseold/util/CompositeLossOperator.java similarity index 92% rename from src/main/java/gregtech/api/graphnet/traverse/util/CompositeLossOperator.java rename to src/main/java/gregtech/api/graphnet/traverseold/util/CompositeLossOperator.java index 979116b379c..8234e3a916d 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/CompositeLossOperator.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/util/CompositeLossOperator.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.util; +package gregtech.api.graphnet.traverseold.util; public class CompositeLossOperator implements ReversibleLossOperator { diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/FlatLossOperator.java b/src/main/java/gregtech/api/graphnet/traverseold/util/FlatLossOperator.java similarity index 89% rename from src/main/java/gregtech/api/graphnet/traverse/util/FlatLossOperator.java rename to src/main/java/gregtech/api/graphnet/traverseold/util/FlatLossOperator.java index b53ca293d37..668f7295a50 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/FlatLossOperator.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/util/FlatLossOperator.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.util; +package gregtech.api.graphnet.traverseold.util; public class FlatLossOperator implements ReversibleLossOperator { diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java b/src/main/java/gregtech/api/graphnet/traverseold/util/FlowConsumptionStack.java similarity index 97% rename from src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java rename to src/main/java/gregtech/api/graphnet/traverseold/util/FlowConsumptionStack.java index 673c66c5f5a..10ce63ed51e 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/FlowConsumptionStack.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/util/FlowConsumptionStack.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.util; +package gregtech.api.graphnet.traverseold.util; import it.unimi.dsi.fastutil.objects.ObjectArrayList; diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java b/src/main/java/gregtech/api/graphnet/traverseold/util/MultLossOperator.java similarity index 94% rename from src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java rename to src/main/java/gregtech/api/graphnet/traverseold/util/MultLossOperator.java index 8addf391e0b..b3c778a62f3 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/MultLossOperator.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/util/MultLossOperator.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.util; +package gregtech.api.graphnet.traverseold.util; public class MultLossOperator implements ReversibleLossOperator { diff --git a/src/main/java/gregtech/api/graphnet/traverse/util/ReversibleLossOperator.java b/src/main/java/gregtech/api/graphnet/traverseold/util/ReversibleLossOperator.java similarity index 89% rename from src/main/java/gregtech/api/graphnet/traverse/util/ReversibleLossOperator.java rename to src/main/java/gregtech/api/graphnet/traverseold/util/ReversibleLossOperator.java index 7f3cc05aa56..9fe0ff8b656 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/util/ReversibleLossOperator.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/util/ReversibleLossOperator.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.util; +package gregtech.api.graphnet.traverseold.util; public interface ReversibleLossOperator { diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java index fb1950fbe1b..574b00c26fc 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java @@ -3,7 +3,6 @@ import gregtech.api.graphnet.GraphNetBacker; import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.alg.AlgorithmBuilder; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.graph.NetDirectedGraph; @@ -25,15 +24,13 @@ public abstract class WorldNet extends WorldSavedData implements IGraphNet { private World world; private int fallbackDimensionID; - public WorldNet(String name, @NotNull Function graphBuilder, - AlgorithmBuilder... algorithmBuilders) { + public WorldNet(String name, @NotNull Function graphBuilder) { super(name); this.backer = new GraphNetBacker(this, graphBuilder.apply(this)); } - public WorldNet(String name, boolean directed, AlgorithmBuilder... algorithmBuilders) { - this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder(), - algorithmBuilders); + public WorldNet(String name, boolean directed) { + this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder()); } public void setWorld(World world) { diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java index cfcd4433355..ccc6645b7c4 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java +++ b/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java @@ -2,7 +2,6 @@ import gregtech.api.graphnet.IGraphNet; import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.alg.AlgorithmBuilder; import gregtech.api.graphnet.graph.INetGraph; import net.minecraft.util.math.BlockPos; @@ -14,13 +13,12 @@ public abstract class WorldPosNet extends WorldNet { - public WorldPosNet(String name, @NotNull Function graphBuilder, - AlgorithmBuilder... algorithmBuilders) { - super(name, graphBuilder, algorithmBuilders); + public WorldPosNet(String name, @NotNull Function graphBuilder) { + super(name, graphBuilder); } - public WorldPosNet(String name, boolean directed, AlgorithmBuilder... algorithmBuilders) { - super(name, directed, algorithmBuilders); + public WorldPosNet(String name, boolean directed) { + super(name, directed); } @NotNull diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 1b2ea5b14c2..b96292ee463 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -15,7 +15,7 @@ import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverse.TraverseHelpers; +import gregtech.api.graphnet.traverseold.TraverseHelpers; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; import gregtech.api.util.ItemStackHashStrategy; diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index e0ec083f81f..4770e2ca3fb 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -15,7 +15,7 @@ import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverse.TraverseHelpers; +import gregtech.api.graphnet.traverseold.TraverseHelpers; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; import gregtech.api.util.function.BiIntConsumer; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java index 19a7c609a48..cd52ee29f51 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java @@ -1,7 +1,6 @@ package gregtech.common.pipelike.net.energy; import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.pipenet.WorldPipeNet; @@ -33,7 +32,7 @@ public final class WorldEnergyNet extends WorldPipeNet { } public WorldEnergyNet(String name) { - super(name, false, DynamicWeightsShortestPathsAlgorithm::new); + super(name, false); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java b/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java index f6ff9c755a9..02913eb2aad 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java @@ -6,7 +6,7 @@ import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; -import gregtech.api.graphnet.traverse.util.MultLossOperator; +import gregtech.api.graphnet.traverseold.util.MultLossOperator; import gregtech.api.util.EntityDamageUtil; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index 78f27a81f94..e09bd4a1b84 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -9,10 +9,10 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverse.ITraverseData; -import gregtech.api.graphnet.traverse.TraverseDataProvider; -import gregtech.api.graphnet.traverse.TraverseGuide; -import gregtech.api.graphnet.traverse.TraverseHelpers; +import gregtech.api.graphnet.traverseold.ITraverseData; +import gregtech.api.graphnet.traverseold.TraverseDataProvider; +import gregtech.api.graphnet.traverseold.TraverseGuide; +import gregtech.api.graphnet.traverseold.TraverseHelpers; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java index afd0d35c003..367a97f1dd8 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java @@ -4,7 +4,7 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverse.IEqualizableTraverseData; +import gregtech.api.graphnet.traverseold.IEqualizableTraverseData; import gregtech.api.util.GTUtility; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java index 6272d227eaa..4c725074adc 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java @@ -5,7 +5,7 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverse.IRoundRobinTraverseData; +import gregtech.api.graphnet.traverseold.IRoundRobinTraverseData; import gregtech.api.util.GTUtility; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java index 68965485028..fbac96e256c 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java @@ -14,9 +14,9 @@ import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverse.AbstractTraverseData; -import gregtech.api.graphnet.traverse.util.MultLossOperator; -import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; +import gregtech.api.graphnet.traverseold.AbstractTraverseData; +import gregtech.api.graphnet.traverseold.util.MultLossOperator; +import gregtech.api.graphnet.traverseold.util.ReversibleLossOperator; import gregtech.api.util.EntityDamageUtil; import gregtech.api.util.GTUtility; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java index aeee3f075a9..1306396ef3b 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java @@ -2,10 +2,10 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverse.ITraverseData; -import gregtech.api.graphnet.traverse.ITraverseGuideProvider; -import gregtech.api.graphnet.traverse.TraverseDataProvider; -import gregtech.api.graphnet.traverse.TraverseGuide; +import gregtech.api.graphnet.traverseold.ITraverseData; +import gregtech.api.graphnet.traverseold.ITraverseGuideProvider; +import gregtech.api.graphnet.traverseold.TraverseDataProvider; +import gregtech.api.graphnet.traverseold.TraverseGuide; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 86cddb22bff..ad096f74031 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -3,7 +3,6 @@ import gregtech.api.cover.Cover; import gregtech.api.cover.filter.CoverWithFluidFilter; import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; @@ -45,7 +44,7 @@ public class WorldFluidNet extends WorldPipeNet implements FlowWorldPipeNetPath. } public WorldFluidNet(String name) { - super(name, true, DynamicWeightsShortestPathsAlgorithm::new); + super(name, true); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java b/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java index bb4591d8c0c..1ead544c3e6 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java +++ b/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java @@ -2,10 +2,10 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverse.ITraverseData; -import gregtech.api.graphnet.traverse.ITraverseGuideProvider; -import gregtech.api.graphnet.traverse.TraverseDataProvider; -import gregtech.api.graphnet.traverse.TraverseGuide; +import gregtech.api.graphnet.traverseold.ITraverseData; +import gregtech.api.graphnet.traverseold.ITraverseGuideProvider; +import gregtech.api.graphnet.traverseold.TraverseDataProvider; +import gregtech.api.graphnet.traverseold.TraverseGuide; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index c75ff9a808f..10e31717ed1 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -8,10 +8,10 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverse.ITraverseData; -import gregtech.api.graphnet.traverse.TraverseDataProvider; -import gregtech.api.graphnet.traverse.TraverseGuide; -import gregtech.api.graphnet.traverse.TraverseHelpers; +import gregtech.api.graphnet.traverseold.ITraverseData; +import gregtech.api.graphnet.traverseold.TraverseDataProvider; +import gregtech.api.graphnet.traverseold.TraverseGuide; +import gregtech.api.graphnet.traverseold.TraverseHelpers; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java index 8a08f60f06d..63f0493755b 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java @@ -4,7 +4,7 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverse.IEqualizableTraverseData; +import gregtech.api.graphnet.traverseold.IEqualizableTraverseData; import gregtech.api.util.GTUtility; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java index 6622e20fbcb..35433d556a0 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java @@ -5,7 +5,7 @@ import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverse.IRoundRobinTraverseData; +import gregtech.api.graphnet.traverseold.IRoundRobinTraverseData; import gregtech.api.util.GTUtility; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java index 75f51065121..01f60d9df51 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java @@ -6,8 +6,8 @@ import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.WorldPipeNetNode; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverse.AbstractTraverseData; -import gregtech.api.graphnet.traverse.util.ReversibleLossOperator; +import gregtech.api.graphnet.traverseold.AbstractTraverseData; +import gregtech.api.graphnet.traverseold.util.ReversibleLossOperator; import gregtech.api.util.GTUtility; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 18c3cfa3a37..e689ed01ba5 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -3,7 +3,6 @@ import gregtech.api.cover.Cover; import gregtech.api.cover.filter.CoverWithItemFilter; import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.alg.DynamicWeightsShortestPathsAlgorithm; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; @@ -45,7 +44,7 @@ public class WorldItemNet extends WorldPipeNet implements FlowWorldPipeNetPath.P } public WorldItemNet(String name) { - super(name, true, DynamicWeightsShortestPathsAlgorithm::new); + super(name, true); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java index 429d2a6d631..97259a4c126 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java @@ -1,7 +1,6 @@ package gregtech.common.pipelike.net.laser; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.graphnet.alg.SinglePathAlgorithm; import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.group.PathCacheGroupData; import gregtech.api.graphnet.pipenet.WorldPipeNet; @@ -33,7 +32,7 @@ public class WorldLaserNet extends WorldPipeNet { } public WorldLaserNet(String name) { - super(name, false, SinglePathAlgorithm::new); + super(name, false); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java index c64ed4b7a29..4b98c515198 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -1,7 +1,6 @@ package gregtech.common.pipelike.net.optical; import gregtech.api.capability.GregtechTileCapabilities; -import gregtech.api.graphnet.alg.SinglePathAlgorithm; import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.group.PathCacheGroupData; import gregtech.api.graphnet.pipenet.WorldPipeNet; @@ -34,7 +33,7 @@ public class WorldOpticalNet extends WorldPipeNet { } public WorldOpticalNet(String name) { - super(name, false, SinglePathAlgorithm::new); + super(name, false); } @Override From 1db5648d58a89ecf00374142dd34ed1bb05df21d Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:56:32 -0700 Subject: [PATCH 148/157] Stuff, pt2 --- .../api/fluids/ContainmentFailureHandler.java | 13 + .../java/gregtech/api/fluids/FluidState.java | 121 ++++++++- .../api/fluids/attribute/FluidAttribute.java | 37 ++- .../api/fluids/attribute/FluidAttributes.java | 52 +++- .../graphnet/GraphClassRegistrationEvent.java | 22 ++ .../api/graphnet/GraphClassRegistry.java | 98 +++++++ .../gregtech/api/graphnet/GraphClassType.java | 39 +++ .../gregtech/api/graphnet/GraphNetBacker.java | 37 ++- .../api/graphnet/MultiNodeHelper.java | 7 +- .../graphnet/edge/AbstractNetFlowEdge.java | 22 +- .../graphnet/edge/FlowBufferTickProvider.java | 10 + .../gregtech/api/graphnet/edge/NetEdge.java | 17 +- .../api/graphnet/edge/NetFlowEdge.java | 7 +- .../api/graphnet/edge/NetFlowSharedEdge.java | 2 +- .../api/graphnet/graph/GraphEdge.java | 7 + .../api/graphnet/graph/GraphVertex.java | 5 +- .../api/graphnet/graph/NetDirectedGraph.java | 9 +- .../graphnet/graph/NetUndirectedGraph.java | 9 +- .../api/graphnet/group/GroupData.java | 2 +- .../gregtech/api/graphnet/group/NetGroup.java | 67 +++-- .../graphnet/group/PathCacheGroupData.java | 2 +- .../api/graphnet/logic/NetLogicEntry.java | 2 +- .../api/graphnet/logic/WeightFactorLogic.java | 2 +- .../api/graphnet/net/BlankNetNode.java | 25 ++ .../BlockPosNode.java} | 25 +- .../api/graphnet/{ => net}/IGraphNet.java | 51 +--- .../api/graphnet/{ => net}/NetNode.java | 29 +- .../WorldNet.java => net/WorldSavedNet.java} | 39 +-- .../gregtech/api/graphnet/path/NetPath.java | 14 +- .../api/graphnet/path/PathBuilder.java | 2 +- .../api/graphnet/path/SingletonNetPath.java | 16 +- .../api/graphnet/path/StandardNetPath.java | 10 +- .../graphnet/pipenet/IPipeNetNodeHandler.java | 10 +- .../pipenet/NodeExposingCapabilities.java | 13 + .../api/graphnet/pipenet/NodeLossCache.java | 6 +- .../api/graphnet/pipenet/NodeLossResult.java | 10 +- .../api/graphnet/pipenet/NodeWithCovers.java | 10 + .../pipenet/NodeWithFacingToOthers.java | 13 + .../pipenet/WorldPipeCapConnectionNode.java | 98 +++++++ .../api/graphnet/pipenet/WorldPipeNet.java | 114 +++++--- ...rldPipeNetNode.java => WorldPipeNode.java} | 52 +++- .../pipenet/logic/TemperatureLogic.java | 2 +- .../physical/IPipeCapabilityObject.java | 20 +- .../pipenet/physical/block/PipeBlock.java | 36 +-- .../physical/tile/IWorldPipeNetTile.java | 26 +- .../physical/tile/NodeManagingPCW.java | 57 ++++ .../physical/tile/PipeCapabilityWrapper.java | 75 +++-- .../pipenet/physical/tile/PipeTileEntity.java | 93 +------ .../pipenet/transfer/TransferControl.java | 28 -- .../transfer/TransferControlProvider.java | 8 - .../traverse/AbstractTileRoundRobinData.java | 10 +- .../pipenet/traverse/FlowManagerMap.java | 10 +- .../traverse/SimpleTileRoundRobinData.java | 8 +- .../predicate/test/ItemTestObject.java | 5 + .../api/graphnet/servernet/ServerNet.java | 115 -------- .../api/graphnet/servernet/ServerNetNode.java | 37 --- .../traverse/AbstractMinCostTraverse.java | 105 +++++-- .../api/graphnet/traverse/EQTraverse.java | 128 +++++++++ .../api/graphnet/traverse/FDTraverse.java | 63 +++++ .../api/graphnet/traverse/FloodTraverse.java | 17 -- .../api/graphnet/traverse/RRTraverse.java | 71 +++++ .../traverse/iter/NetBreadthIterator.java | 4 +- .../traverse/iter/NetClosestIterator.java | 14 +- .../graphnet/traverse/iter/NetIterator.java | 2 +- .../traverse/iter/NetIteratorSupplier.java | 2 +- .../traverseold/AbstractTraverseData.java | 4 +- .../traverseold/IEqualizableTraverseData.java | 2 +- .../graphnet/traverseold/IRoundRobinData.java | 2 +- .../traverseold/IRoundRobinTraverseData.java | 2 +- .../graphnet/traverseold/ITraverseData.java | 4 +- .../traverseold/ITraverseGuideProvider.java | 2 +- .../traverseold/TraverseDataProvider.java | 2 +- .../graphnet/traverseold/TraverseGuide.java | 2 +- .../graphnet/traverseold/TraverseHelpers.java | 6 +- .../api/graphnet/worldnet/WorldPosNet.java | 47 ---- .../properties/PipeNetProperties.java | 20 +- .../gregtech/api/util/EntityDamageUtil.java | 12 +- .../java/gregtech/api/util/GTUtility.java | 38 +++ .../api/util/function/ToBooleanFunction.java | 7 + .../gregtech/common/covers/CoverConveyor.java | 15 +- .../common/covers/CoverFluidFilter.java | 2 +- .../common/covers/CoverFluidRegulator.java | 20 +- .../common/covers/CoverItemFilter.java | 2 +- .../gregtech/common/covers/CoverPump.java | 12 +- .../common/covers/CoverRoboticArm.java | 20 +- .../pipelike/block/cable/CableBlock.java | 4 +- .../pipelike/handlers/LaserNetHandler.java | 12 +- .../pipelike/handlers/OpticalNetHandler.java | 12 +- .../properties/MaterialEnergyProperties.java | 12 +- .../properties/MaterialFluidProperties.java | 10 +- .../properties/MaterialItemProperties.java | 10 +- .../common/pipelike/net/SlowActiveWalker.java | 16 +- .../net/energy/EnergyCapabilityObject.java | 24 +- .../pipelike/net/energy/EnergyGroupData.java | 2 +- .../net/energy/StandardEnergyPath.java | 5 +- .../pipelike/net/energy/WorldEnergyNet.java | 28 +- .../net/fluid/ContainmentFailure.java | 152 ----------- .../net/fluid/FluidCapabilityObject.java | 257 ++++++++++-------- .../net/fluid/FluidContainmentLogic.java | 16 ++ .../net/fluid/FluidEQTraverseData.java | 86 ------ .../net/fluid/FluidRRTraverseData.java | 62 ----- .../pipelike/net/fluid/FluidTraverseData.java | 190 ------------- .../net/fluid/IFluidTransferController.java | 74 ----- .../fluid/IFluidTraverseGuideProvider.java | 22 -- .../pipelike/net/fluid/WorldFluidNet.java | 47 +--- .../net/item/IItemTransferController.java | 79 ------ .../net/item/IItemTraverseGuideProvider.java | 22 -- .../net/item/ItemCapabilityObject.java | 220 ++++++++------- .../pipelike/net/item/ItemEQTraverseData.java | 86 ------ .../pipelike/net/item/ItemRRTraverseData.java | 63 ----- .../pipelike/net/item/ItemTraverseData.java | 82 ------ .../pipelike/net/item/WorldItemNet.java | 46 ++-- .../net/laser/LaserCapabilityObject.java | 25 +- .../pipelike/net/laser/WorldLaserNet.java | 20 +- .../net/optical/DataCapabilityObject.java | 25 +- .../pipelike/net/optical/WorldOpticalNet.java | 20 +- 116 files changed, 1957 insertions(+), 2055 deletions(-) create mode 100644 src/main/java/gregtech/api/fluids/ContainmentFailureHandler.java create mode 100644 src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java create mode 100644 src/main/java/gregtech/api/graphnet/GraphClassRegistry.java create mode 100644 src/main/java/gregtech/api/graphnet/GraphClassType.java create mode 100644 src/main/java/gregtech/api/graphnet/edge/FlowBufferTickProvider.java create mode 100644 src/main/java/gregtech/api/graphnet/net/BlankNetNode.java rename src/main/java/gregtech/api/graphnet/{worldnet/WorldPosNetNode.java => net/BlockPosNode.java} (55%) rename src/main/java/gregtech/api/graphnet/{ => net}/IGraphNet.java (73%) rename src/main/java/gregtech/api/graphnet/{ => net}/NetNode.java (80%) rename src/main/java/gregtech/api/graphnet/{worldnet/WorldNet.java => net/WorldSavedNet.java} (69%) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/NodeExposingCapabilities.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/NodeWithCovers.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/NodeWithFacingToOthers.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java rename src/main/java/gregtech/api/graphnet/pipenet/{WorldPipeNetNode.java => WorldPipeNode.java} (57%) create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControl.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControlProvider.java delete mode 100644 src/main/java/gregtech/api/graphnet/servernet/ServerNet.java delete mode 100644 src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverse/FloodTraverse.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java delete mode 100644 src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java create mode 100644 src/main/java/gregtech/api/util/function/ToBooleanFunction.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java diff --git a/src/main/java/gregtech/api/fluids/ContainmentFailureHandler.java b/src/main/java/gregtech/api/fluids/ContainmentFailureHandler.java new file mode 100644 index 00000000000..afbfd7f3c4c --- /dev/null +++ b/src/main/java/gregtech/api/fluids/ContainmentFailureHandler.java @@ -0,0 +1,13 @@ +package gregtech.api.fluids; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; + +public interface ContainmentFailureHandler { + + void handleFailure(World world, BlockPos failingBlock, FluidStack failingStack); + + void handleFailure(EntityPlayer failingPlayer, FluidStack failingStack); +} diff --git a/src/main/java/gregtech/api/fluids/FluidState.java b/src/main/java/gregtech/api/fluids/FluidState.java index 90d856c7eb6..b05f0a4e46d 100644 --- a/src/main/java/gregtech/api/fluids/FluidState.java +++ b/src/main/java/gregtech/api/fluids/FluidState.java @@ -1,12 +1,29 @@ package gregtech.api.fluids; +import gregtech.api.GTValues; import gregtech.api.fluids.attribute.AttributedFluid; +import gregtech.api.util.EntityDamageUtil; + +import gregtech.api.util.GTUtility; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; import org.jetbrains.annotations.NotNull; -public enum FluidState { +import java.util.List; + +public enum FluidState implements ContainmentFailureHandler { LIQUID("gregtech.fluid.state_liquid"), GAS("gregtech.fluid.state_gas"), @@ -26,4 +43,106 @@ public static FluidState inferState(FluidStack stack) { if (stack.getFluid() instanceof AttributedFluid fluid) return fluid.getState(); else return stack.getFluid().isGaseous(stack) ? GAS : LIQUID; } + + @Override + public void handleFailure(World world, BlockPos failingBlock, FluidStack failingStack) { + world.playSound(null, failingBlock, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); + switch (this) { + default -> { + for (EnumFacing facing : EnumFacing.HORIZONTALS) { + int particles = GTValues.RNG.nextInt(5); + if (particles != 0) { + GTUtility.spawnParticles(world, facing, EnumParticleTypes.DRIP_WATER, failingBlock, particles); + } + } + float scalar = (float) Math.log(failingStack.amount); + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(failingBlock).grow(scalar * 0.5)); + for (EntityLivingBase entity : entities) { + EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + scalar, 20); + } + world.setBlockToAir(failingBlock); + } + case GAS -> { + GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingBlock, 9 + GTValues.RNG.nextInt(3)); + float scalar = (float) Math.log(failingStack.amount); + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(failingBlock).grow(scalar)); + for (EntityLivingBase entity : entities) { + EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + scalar * 0.75f, 15); + } + world.setBlockToAir(failingBlock); + } + case PLASMA -> { + GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingBlock, 3 + GTValues.RNG.nextInt(3)); + float scalar = (float) Math.log(failingStack.amount); + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(failingBlock).grow(scalar * 1.5)); + for (EntityLivingBase entity : entities) { + EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + scalar, 30); + } + world.setBlockToAir(failingBlock); + world.createExplosion(null, failingBlock.getX() + 0.5, failingBlock.getY() + 0.5, failingBlock.getZ() + 0.5, + 1.0f + GTValues.RNG.nextFloat(), true); + } + } + } + + @Override + public void handleFailure(EntityPlayer failingPlayer, FluidStack failingStack) { + World world = failingPlayer.world; + world.playSound(null, failingPlayer.getPosition(), SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); + switch (this) { + default -> { + for (EnumFacing facing : EnumFacing.HORIZONTALS) { + int particles = GTValues.RNG.nextInt(5); + if (particles != 0) { + GTUtility.spawnParticles(world, facing, EnumParticleTypes.DRIP_WATER, failingPlayer, particles); + } + } + float scalar = (float) Math.log(failingStack.amount); + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(failingPlayer.getPosition()).grow(scalar * 0.5)); + for (EntityLivingBase entity : entities) { + if (entity == failingPlayer) continue; + EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + scalar, 20); + } + EntityDamageUtil.applyTemperatureDamage(failingPlayer, failingStack.getFluid().getTemperature(failingStack), + scalar * 3, 60); + } + case GAS -> { + GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingPlayer, 9 + GTValues.RNG.nextInt(3)); + float scalar = (float) Math.log(failingStack.amount); + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(failingPlayer.getPosition()).grow(scalar)); + for (EntityLivingBase entity : entities) { + if (entity == failingPlayer) continue; + EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + scalar * 0.75f, 15); + } + EntityDamageUtil.applyTemperatureDamage(failingPlayer, failingStack.getFluid().getTemperature(failingStack), + scalar * 2.25f, 45); + } + case PLASMA -> { + GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingPlayer, 3 + GTValues.RNG.nextInt(3)); + float scalar = (float) Math.log(failingStack.amount); + List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(failingPlayer.getPosition()).grow(scalar * 1.5)); + for (EntityLivingBase entity : entities) { + if (entity == failingPlayer) continue; + EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + scalar, 30); + } + EntityDamageUtil.applyTemperatureDamage(failingPlayer, failingStack.getFluid().getTemperature(failingStack), + scalar * 3, 90); + Vec3d vec = failingPlayer.getPositionEyes(1); + world.createExplosion(null, vec.x, vec.y, vec.z, + 1.0f + GTValues.RNG.nextFloat(), true); + } + } + } } diff --git a/src/main/java/gregtech/api/fluids/attribute/FluidAttribute.java b/src/main/java/gregtech/api/fluids/attribute/FluidAttribute.java index ad99e07821b..abfb3e77a29 100644 --- a/src/main/java/gregtech/api/fluids/attribute/FluidAttribute.java +++ b/src/main/java/gregtech/api/fluids/attribute/FluidAttribute.java @@ -1,26 +1,49 @@ package gregtech.api.fluids.attribute; +import gregtech.api.fluids.ContainmentFailureHandler; + +import gregtech.api.util.function.TriConsumer; + +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidStack; + import org.jetbrains.annotations.NotNull; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.function.BiConsumer; import java.util.function.Consumer; -public final class FluidAttribute { +public final class FluidAttribute implements ContainmentFailureHandler { private final ResourceLocation resourceLocation; private final Consumer> fluidTooltip; private final Consumer> containerTooltip; + private final TriConsumer blockContainmentFailure; + private final BiConsumer playerContainmentFailure; private final int hashCode; public FluidAttribute(@NotNull ResourceLocation resourceLocation, @NotNull Consumer> fluidTooltip, - @NotNull Consumer> containerTooltip) { + @NotNull Consumer> containerTooltip, + @NotNull TriConsumer blockContainmentFailure, + @NotNull BiConsumer playerContainmentFailure) { this.resourceLocation = resourceLocation; this.fluidTooltip = fluidTooltip; this.containerTooltip = containerTooltip; this.hashCode = resourceLocation.hashCode(); + this.blockContainmentFailure = blockContainmentFailure; + this.playerContainmentFailure = playerContainmentFailure; + } + + public static Collection inferAttributes(FluidStack stack) { + if (stack.getFluid() instanceof AttributedFluid fluid) return fluid.getAttributes(); + else return Collections.emptyList(); } public @NotNull ResourceLocation getResourceLocation() { @@ -35,6 +58,16 @@ public void appendContainerTooltips(@NotNull List<@NotNull String> tooltip) { containerTooltip.accept(tooltip); } + @Override + public void handleFailure(World world, BlockPos failingBlock, FluidStack failingStack) { + blockContainmentFailure.accept(world, failingBlock, failingStack); + } + + @Override + public void handleFailure(EntityPlayer failingPlayer, FluidStack failingStack) { + playerContainmentFailure.accept(failingPlayer, failingStack); + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/api/fluids/attribute/FluidAttributes.java b/src/main/java/gregtech/api/fluids/attribute/FluidAttributes.java index b683d21c4fc..b0564a64564 100644 --- a/src/main/java/gregtech/api/fluids/attribute/FluidAttributes.java +++ b/src/main/java/gregtech/api/fluids/attribute/FluidAttributes.java @@ -1,6 +1,23 @@ package gregtech.api.fluids.attribute; +import gregtech.api.GTValues; +import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; +import gregtech.api.util.EntityDamageUtil; + +import gregtech.api.util.GTUtility; + import net.minecraft.client.resources.I18n; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.SoundEvents; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; + +import java.util.List; import static gregtech.api.util.GTUtility.gregtechId; @@ -11,7 +28,40 @@ public final class FluidAttributes { */ public static final FluidAttribute ACID = new FluidAttribute(gregtechId("acid"), list -> list.add(I18n.format("gregtech.fluid.type_acid.tooltip")), - list -> list.add(I18n.format("gregtech.fluid_pipe.acid_proof"))); + list -> list.add(I18n.format("gregtech.fluid_pipe.acid_proof")), + (w, b, f) -> { + w.playSound(null, b, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); + boolean gaseous = f.getFluid().isGaseous(f); + for (EnumFacing facing : EnumFacing.HORIZONTALS) { + GTUtility.spawnParticles(w, facing, EnumParticleTypes.CRIT_MAGIC, b, 3 + GTValues.RNG.nextInt(2)); + } + GTUtility.spawnParticles(w, gaseous ? EnumFacing.UP : EnumFacing.DOWN, EnumParticleTypes.CRIT_MAGIC, + b, 6 + GTValues.RNG.nextInt(4)); + float scalar = (float) Math.log(f.amount); + List entities = w.getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(b).grow(scalar * (gaseous ? 0.4 : 0.2))); + for (EntityLivingBase entity : entities) { + EntityDamageUtil.applyChemicalDamage(entity, scalar * (gaseous ? 0.6f : 0.8f)); + } + w.setBlockToAir(b); + }, + (p, f) -> { + p.world.playSound(null, p.getPosition(), SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); + boolean gaseous = f.getFluid().isGaseous(f); + for (EnumFacing facing : EnumFacing.HORIZONTALS) { + GTUtility.spawnParticles(p.world, facing, EnumParticleTypes.CRIT_MAGIC, p, 3 + GTValues.RNG.nextInt(2)); + } + GTUtility.spawnParticles(p.world, gaseous ? EnumFacing.UP : EnumFacing.DOWN, EnumParticleTypes.CRIT_MAGIC, + p, 6 + GTValues.RNG.nextInt(4)); + float scalar = (float) Math.log(f.amount); + List entities = p.world.getEntitiesWithinAABB(EntityLivingBase.class, + new AxisAlignedBB(p.getPosition()).grow(scalar * (gaseous ? 0.4 : 0.2))); + for (EntityLivingBase entity : entities) { + if (entity == p) continue; + EntityDamageUtil.applyChemicalDamage(entity, scalar * (gaseous ? 0.6f : 0.8f)); + } + EntityDamageUtil.applyChemicalDamage(p, scalar * (gaseous ? 3f : 4f)); + }); private FluidAttributes() {} } diff --git a/src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java b/src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java new file mode 100644 index 00000000000..9547dc6664c --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java @@ -0,0 +1,22 @@ +package gregtech.api.graphnet; + +import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; + +import net.minecraftforge.fml.common.eventhandler.Event; + +import java.util.Comparator; + +public final class GraphClassRegistrationEvent extends Event { + + private final ObjectRBTreeSet> gather = new ObjectRBTreeSet<>( + Comparator.comparing(GraphClassType::getName)); + + public void accept(GraphClassType type) { + if (!gather.add(type)) + throw new IllegalStateException("Detected a name collision during Graph Class registration!"); + } + + ObjectRBTreeSet> getGather() { + return gather; + } +} diff --git a/src/main/java/gregtech/api/graphnet/GraphClassRegistry.java b/src/main/java/gregtech/api/graphnet/GraphClassRegistry.java new file mode 100644 index 00000000000..17fe1a49e02 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/GraphClassRegistry.java @@ -0,0 +1,98 @@ +package gregtech.api.graphnet; + +import gregtech.api.graphnet.logic.NetLogicEntry; +import gregtech.api.graphnet.logic.NetLogicRegistrationEvent; +import gregtech.api.graphnet.logic.NetLogicType; + +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.IntIdentityHashBiMap; +import net.minecraft.util.text.TextComponentTranslation; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.relauncher.Side; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Comparator; +import java.util.Set; + +public final class GraphClassRegistry { + + private static final Int2ObjectArrayMap> REGISTRY; + + private static final IntIdentityHashBiMap NAMES_TO_NETWORK_IDS; + + static { + GraphClassRegistrationEvent event = new GraphClassRegistrationEvent(); + MinecraftForge.EVENT_BUS.post(event); + Set> gather = event.getGather(); + NAMES_TO_NETWORK_IDS = new IntIdentityHashBiMap<>(gather.size()); + REGISTRY = new Int2ObjectArrayMap<>(gather.size()); + int id = 1; + for (GraphClassType type : gather) { + NAMES_TO_NETWORK_IDS.put(type.getName(), id); + REGISTRY.put(id, type); + id++; + } + } + + public static String getName(int networkID) { + return NAMES_TO_NETWORK_IDS.get(networkID); + } + + public static int getNetworkID(@NotNull String name) { + return NAMES_TO_NETWORK_IDS.getId(name); + } + + public static int getNetworkID(@NotNull NetLogicType type) { + return getNetworkID(type.getName()); + } + + public static int getNetworkID(@NotNull NetLogicEntry entry) { + return getNetworkID(entry.getType()); + } + + public static @Nullable GraphClassType getTypeNullable(int networkID) { + return REGISTRY.get(networkID); + } + + public static @Nullable GraphClassType getTypeNullable(@NotNull String name) { + return getTypeNullable(getNetworkID(name)); + } + + public static @NotNull GraphClassType getType(int networkID) { + GraphClassType type = REGISTRY.get(networkID); + if (type == null) throwNonexistenceError(); + assert type != null; + return type; + } + + public static @NotNull GraphClassType getType(@NotNull String name) { + return getType(getNetworkID(name)); + } + + public static void throwNonexistenceError() { + if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) disconnect(); + throw new RuntimeException("Could not find the type of an encoded Graph Class. " + + "This suggests that the server and client have different GT versions or modifications."); + } + + public static void throwDecodingError() { + if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) disconnect(); + throw new RuntimeException("Failed to decode an encoded Graph Class. " + + "This suggests that the server and client have different GT versions or modifications."); + } + + private static void disconnect() { + if (Minecraft.getMinecraft().getConnection() != null) + Minecraft.getMinecraft().getConnection() + .onDisconnect(new TextComponentTranslation("gregtech.universal.netlogicdisconnect")); + } + + private GraphClassRegistry() {} + +} diff --git a/src/main/java/gregtech/api/graphnet/GraphClassType.java b/src/main/java/gregtech/api/graphnet/GraphClassType.java new file mode 100644 index 00000000000..4ed141900b4 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/GraphClassType.java @@ -0,0 +1,39 @@ +package gregtech.api.graphnet; + +import gregtech.api.graphnet.logic.NetLogicEntry; + +import gregtech.api.graphnet.net.IGraphNet; + +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.ResourceLocation; + +import org.jetbrains.annotations.NotNull; + +import java.util.function.Function; +import java.util.function.Supplier; + +public class GraphClassType implements IStringSerializable { + + private final @NotNull String name; + private final @NotNull Function supplier; + + public GraphClassType(@NotNull ResourceLocation name, @NotNull Function supplier) { + this.name = name.toString(); + this.supplier = supplier; + + } + + public GraphClassType(@NotNull String namespace, @NotNull String name, @NotNull Function supplier) { + this.name = namespace + ":" + name; + this.supplier = supplier; + } + + public final T getNew(@NotNull IGraphNet net) { + return supplier.apply(net); + } + + @Override + public final @NotNull String getName() { + return name; + } +} diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index 9e5707abed7..b740de9808f 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -7,6 +7,12 @@ import gregtech.api.graphnet.group.MergeDirection; import gregtech.api.graphnet.group.NetGroup; +import gregtech.api.graphnet.net.IGraphNet; + +import gregtech.api.graphnet.net.NetNode; + +import gregtech.api.graphnet.traverse.iter.EdgeDirection; + import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -18,6 +24,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; +import java.util.Iterator; +import java.util.Objects; + /** * The bridge between JGraphT graphs and graphnet abstractions. * Doesn't do any automatic linking, weighting, predicating, etc. Simply handles storing the JGraphT graph to disk, @@ -41,8 +51,9 @@ public IGraphNet getBackedNet() { public void addNode(NetNode node) { GraphVertex vertex = new GraphVertex(node); + GraphVertex existing = this.vertexMap.put(node.getEquivalencyData(), vertex); + if (existing != null) getGraph().removeVertex(existing); getGraph().addVertex(vertex); - this.vertexMap.put(node.getEquivalencyData(), vertex); backedNet.markDirty(); } @@ -73,6 +84,7 @@ public boolean removeNode(@Nullable NetNode node) { @ApiStatus.Internal public void removeVertex(GraphVertex vertex) { if (this.getGraph().removeVertex(vertex)) { + if (vertex.wrapped == null) return; this.vertexMap.remove(vertex.wrapped.getEquivalencyData()); vertex.wrapped.onRemove(); backedNet.markDirty(); @@ -86,6 +98,7 @@ public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, double GraphEdge graphEdge = getGraph().addEdge(source.wrapper, target.wrapper); if (graphEdge != null) { getGraph().setEdgeWeight(graphEdge, weight); + assert graphEdge.wrapped != null; NetGroup.mergeEdge(graphEdge.wrapped, direction); backedNet.markDirty(); } @@ -98,6 +111,12 @@ public NetEdge getEdge(@NotNull NetNode source, @NotNull NetNode target) { return graphEdge == null ? null : graphEdge.wrapped; } + @NotNull + public Iterable getTouchingEdges(@NotNull NetNode node, @NotNull EdgeDirection direction) { + return direction.selectEdges(getGraph(), node.wrapper).stream() + .map(GraphEdge::getWrapped).filter(Objects::nonNull)::iterator; + } + public boolean removeEdge(@NotNull NetNode source, NetNode target) { NetGroup group = source.getGroupUnsafe(); if (group == null) { @@ -162,7 +181,9 @@ public void readFromNBT(@NotNull NBTTagCompound nbt) { Int2ObjectOpenHashMap vertexMap = new Int2ObjectOpenHashMap<>(vertexCount); for (int i = 0; i < vertexCount; i++) { NBTTagCompound tag = vertices.getCompoundTagAt(i); - NetNode node = this.backedNet.getNewNode(); + GraphClassType type = GraphClassRegistry.getTypeNullable(tag.getString("ClassType")); + Object o = type == null ? null : type.getNew(backedNet); + NetNode node = o instanceof NetNode n ? n : backedNet.getDefaultNodeType().getNew(backedNet); node.deserializeNBT(tag); if (tag.hasKey("GroupID")) { int id = tag.getInteger("GroupID"); @@ -183,9 +204,13 @@ public void readFromNBT(@NotNull NBTTagCompound nbt) { int edgeCount = edges.tagCount(); for (int i = 0; i < edgeCount; i++) { NBTTagCompound tag = edges.getCompoundTagAt(i); - GraphEdge graphEdge = this.getGraph().addEdge(vertexMap.get(tag.getInteger("SourceID")), - vertexMap.get(tag.getInteger("TargetID"))); + GraphClassType type = GraphClassRegistry.getTypeNullable(tag.getString("ClassType")); + Object o = type == null ? null : type.getNew(backedNet); + GraphEdge graphEdge = new GraphEdge(o instanceof NetEdge e ? e : backedNet.getDefaultEdgeType().getNew(backedNet)); + this.getGraph().addEdge(vertexMap.get(tag.getInteger("SourceID")), + vertexMap.get(tag.getInteger("TargetID")), graphEdge); this.getGraph().setEdgeWeight(graphEdge, tag.getDouble("Weight")); + assert graphEdge.wrapped != null; graphEdge.wrapped.deserializeNBT(tag); } } @@ -201,9 +226,11 @@ public void readFromNBT(@NotNull NBTTagCompound nbt) { int g = 0; NBTTagList vertices = new NBTTagList(); for (GraphVertex graphVertex : this.getGraph().vertexSet()) { + if (graphVertex.wrapped == null) continue; vertexMap.put(graphVertex, i); NetGroup group = graphVertex.wrapped.getGroupUnsafe(); NBTTagCompound tag = graphVertex.wrapped.serializeNBT(); + tag.setString("ClassType", graphVertex.wrapped.getType().getName()); if (group != null) { int groupID; if (!groupMap.containsKey(group)) { @@ -220,10 +247,12 @@ public void readFromNBT(@NotNull NBTTagCompound nbt) { NBTTagList edges = new NBTTagList(); for (GraphEdge graphEdge : this.getGraph().edgeSet()) { + if (graphEdge.wrapped == null) continue; NBTTagCompound tag = graphEdge.wrapped.serializeNBT(); tag.setInteger("SourceID", vertexMap.getInt(graphEdge.getSource())); tag.setInteger("TargetID", vertexMap.getInt(graphEdge.getTarget())); tag.setDouble("Weight", graphEdge.getWeight()); + tag.setString("ClassType", graphEdge.wrapped.getType().getName()); edges.appendTag(tag); } compound.setTag("Edges", edges); diff --git a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java index 7db90c646ad..c752b39b278 100644 --- a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java +++ b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java @@ -4,6 +4,11 @@ import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; + +import gregtech.api.graphnet.pipenet.WorldPipeNode; + import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -20,7 +25,7 @@ * B) making sure that logic entries requiring it are the same object across all synced nodes.
*
* MultiNodeHelpers have no standard implementation and must be handled by a net and its nodes; see - * {@link gregtech.api.graphnet.pipenet.WorldPipeNet} and {@link gregtech.api.graphnet.pipenet.WorldPipeNetNode} + * {@link gregtech.api.graphnet.pipenet.WorldPipeNet} and {@link WorldPipeNode} * for an example of this in action. */ public class MultiNodeHelper implements INetLogicEntryListener { diff --git a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java index 1ea0158b368..1fe33d04bb5 100644 --- a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.edge; -import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; @@ -21,16 +21,6 @@ public AbstractNetFlowEdge() { this.simulatedChannels = new WeakHashMap<>(9); } - @Override - public double getDynamicWeight(IPredicateTestObject channel, IGraphNet net, @Nullable SimulatorKey simulator, - long queryTick, - double defaultWeight) { - long flow = getFlowLimit(channel, net, queryTick, simulator); - if (flow <= 0) { - return defaultWeight * getThroughput() * Short.MAX_VALUE; - } else return defaultWeight * getThroughput() / flow; - } - public boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick, @Nullable SimulatorKey simulator) { if (!this.test(channel)) return false; @@ -59,20 +49,16 @@ public long getThroughput() { public long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick, @Nullable SimulatorKey simulator) { - if (!this.test(channel)) return 0; - else return getChannels(simulator).getFlowLimit(channel, graph, queryTick); + return getChannels(simulator).getFlowLimit(channel, graph, queryTick); } protected long getConsumedLimit(IPredicateTestObject channel, long queryTick, @Nullable SimulatorKey simulator) { - if (!this.test(channel)) return 0; - else return getChannels(simulator).getConsumedLimit(channel, queryTick); + return getChannels(simulator).getConsumedLimit(channel, queryTick); } public void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick, @Nullable SimulatorKey simulator) { - if (this.test(channel)) { - getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); - } + getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); } public Set getActiveChannels(@Nullable SimulatorKey simulator, long queryTick) { diff --git a/src/main/java/gregtech/api/graphnet/edge/FlowBufferTickProvider.java b/src/main/java/gregtech/api/graphnet/edge/FlowBufferTickProvider.java new file mode 100644 index 00000000000..4fe9fee1c6e --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/edge/FlowBufferTickProvider.java @@ -0,0 +1,10 @@ +package gregtech.api.graphnet.edge; + +public interface FlowBufferTickProvider { + + int getFlowBufferTicks(); + + default int getRegenerationTime() { + return 1; + } +} diff --git a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java index 27a43006b3c..92063f0342f 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java @@ -1,7 +1,9 @@ package gregtech.api.graphnet.edge; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; +import gregtech.api.GTValues; +import gregtech.api.graphnet.GraphClassType; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.predicate.EdgePredicateHandler; @@ -17,6 +19,8 @@ public class NetEdge implements INBTSerializable { + public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "NetEdge", n -> new NetEdge()); + /** * For interacting with the internal graph representation ONLY, do not use or set this field otherwise. */ @@ -78,11 +82,6 @@ public boolean test(IPredicateTestObject object) { else return predicateHandler.test(object); } - public double getDynamicWeight(IPredicateTestObject channel, IGraphNet graph, @Nullable SimulatorKey simulator, - long queryTick, double defaultWeight) { - return defaultWeight; - } - @Override public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); @@ -99,4 +98,8 @@ public void deserializeNBT(NBTTagCompound nbt) { this.predicateHandler.deserializeNBT((NBTTagList) nbt.getTag("Predicate")); } } + + public GraphClassType getType() { + return TYPE; + } } diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java index ffe518dfea5..bc74ea386f0 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java @@ -1,6 +1,8 @@ package gregtech.api.graphnet.edge; -import gregtech.api.graphnet.IGraphNet; +import gregtech.api.GTValues; +import gregtech.api.graphnet.GraphClassType; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; @@ -12,6 +14,9 @@ public class NetFlowEdge extends AbstractNetFlowEdge { + public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "NetFlowEdge", + n -> n instanceof FlowBufferTickProvider p ? new NetFlowEdge(p.getFlowBufferTicks(), p.getRegenerationTime()) : new NetFlowEdge(10)); + private final int flowBufferTicks; private final int regenerationTime; diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java index 0da255830c5..6ce462f1fd0 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.edge; -import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.util.math.MathHelper; diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java index 4547e0091ba..a83af67b4eb 100644 --- a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java +++ b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java @@ -11,6 +11,7 @@ public final class GraphEdge extends DefaultWeightedEdge { + @ApiStatus.Internal public final NetEdge wrapped; public GraphEdge(@NotNull NetEdge wrapped) { @@ -37,6 +38,12 @@ public GraphVertex getTarget() { return (GraphVertex) super.getTarget(); } + public @Nullable GraphVertex getOppositeVertex(@NotNull GraphVertex node) { + if (getSource() == node) return getTarget(); + else if (getTarget() == node) return getSource(); + else return null; + } + /** * Use this very sparingly. It's significantly better to go through {@link org.jgrapht.Graph#getEdgeWeight(Object)} * instead, unless you are doing nbt serialization for example. diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java b/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java index ba95d226572..36df5cea44b 100644 --- a/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java +++ b/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java @@ -1,16 +1,15 @@ package gregtech.api.graphnet.graph; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.UnknownNullability; import java.util.Objects; public final class GraphVertex { + @ApiStatus.Internal public final NetNode wrapped; public GraphVertex(@NotNull NetNode wrapped) { diff --git a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java index f96cd54e561..af14e6abcd6 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java @@ -1,9 +1,6 @@ package gregtech.api.graphnet.graph; -import gregtech.api.graphnet.GraphNetBacker; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.net.IGraphNet; import org.jgrapht.graph.SimpleDirectedWeightedGraph; @@ -22,7 +19,7 @@ public boolean isDirected() { } public static Function standardBuilder() { - return iGraphNet -> new NetDirectedGraph(() -> new GraphVertex(iGraphNet.getNewNode()), - () -> new GraphEdge(iGraphNet.getNewEdge())); + return iGraphNet -> new NetDirectedGraph(() -> new GraphVertex(iGraphNet.getDefaultNodeType().getNew(iGraphNet)), + () -> new GraphEdge(iGraphNet.getDefaultEdgeType().getNew(iGraphNet))); } } diff --git a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java index 8aa894f0816..4fdbf04d5a1 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java @@ -1,9 +1,6 @@ package gregtech.api.graphnet.graph; -import gregtech.api.graphnet.GraphNetBacker; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.net.IGraphNet; import org.jgrapht.graph.SimpleWeightedGraph; @@ -22,7 +19,7 @@ public boolean isDirected() { } public static Function standardBuilder() { - return iGraphNet -> new NetUndirectedGraph(() -> new GraphVertex(iGraphNet.getNewNode()), - () -> new GraphEdge(iGraphNet.getNewEdge())); + return iGraphNet -> new NetUndirectedGraph(() -> new GraphVertex(iGraphNet.getDefaultNodeType().getNew(iGraphNet)), + () -> new GraphEdge(iGraphNet.getDefaultEdgeType().getNew(iGraphNet))); } } diff --git a/src/main/java/gregtech/api/graphnet/group/GroupData.java b/src/main/java/gregtech/api/graphnet/group/GroupData.java index aa49b3847a5..18a2428f4d8 100644 --- a/src/main/java/gregtech/api/graphnet/group/GroupData.java +++ b/src/main/java/gregtech/api/graphnet/group/GroupData.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.group; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import org.apache.commons.lang3.tuple.ImmutablePair; diff --git a/src/main/java/gregtech/api/graphnet/group/NetGroup.java b/src/main/java/gregtech/api/graphnet/group/NetGroup.java index 8dc43258157..d7ca4bd9b79 100644 --- a/src/main/java/gregtech/api/graphnet/group/NetGroup.java +++ b/src/main/java/gregtech/api/graphnet/group/NetGroup.java @@ -1,12 +1,14 @@ package gregtech.api.graphnet.group; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.traverse.iter.EdgeDirection; import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.apache.commons.lang3.tuple.Pair; @@ -17,6 +19,7 @@ import org.jgrapht.Graphs; import java.util.Collection; +import java.util.Collections; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -27,12 +30,12 @@ public final class NetGroup { private final @NotNull Set nodes; - private final @NotNull Set activeNodes; + private final @NotNull Int2ObjectMap> sortingNodes; private @Nullable GroupData data; public NetGroup(IGraphNet net) { - this(net, new ObjectOpenHashSet<>(), new ObjectOpenHashSet<>()); + this(net, new ObjectOpenHashSet<>(), new Int2ObjectOpenHashMap<>()); } public NetGroup(@NotNull IGraphNet net, @NotNull Set nodes) { @@ -40,33 +43,46 @@ public NetGroup(@NotNull IGraphNet net, @NotNull Set nodes) { } public NetGroup(@NotNull IGraphNet net, @NotNull Set nodes, @Nullable GroupData data) { - this(net, nodes, nodes.stream().filter(NetNode::isActive) - .collect(ObjectOpenHashSet::new, ObjectOpenHashSet::add, ObjectOpenHashSet::addAll), data); + this(net, nodes, new Int2ObjectOpenHashMap<>(), data); + for (NetNode node : nodes) { + initialSort(node); + } } - public NetGroup(@NotNull IGraphNet net, @NotNull Set nodes, @NotNull Set activeNodes) { - this(net, nodes, activeNodes, net.getBlankGroupData()); + public NetGroup(@NotNull IGraphNet net, @NotNull Set nodes, + @NotNull Int2ObjectMap> sortingNodes) { + this(net, nodes, sortingNodes, net.getBlankGroupData()); } - public NetGroup(@NotNull IGraphNet net, @NotNull Set nodes, @NotNull Set activeNodes, - @Nullable GroupData data) { + public NetGroup(@NotNull IGraphNet net, @NotNull Set nodes, + @NotNull Int2ObjectMap> sortingNodes, @Nullable GroupData data) { this.net = net; this.data = data; if (data != null) data.withGroup(this); this.nodes = nodes; - this.activeNodes = activeNodes; + this.sortingNodes = sortingNodes; nodes.forEach(this::onAddedToGroup); } + private void initialSort(NetNode node) { + int key = node.getSortingKey(); + Set s = this.sortingNodes.get(key); + if (s == null) this.sortingNodes.put(key, s = new ObjectOpenHashSet<>()); + s.add(node); + } + public void addNode(NetNode node) { this.nodes.add(node); - this.onAddedToGroup(node); - if (node.isActive()) activeNodes.add(node); + onAddedToGroup(node); + initialSort(node); } private void addNodes(Collection nodes) { this.nodes.addAll(nodes); - nodes.stream().peek(this::onAddedToGroup).filter(NetNode::isActive).forEach(this.activeNodes::add); + for (NetNode node : nodes) { + onAddedToGroup(node); + initialSort(node); + } } @ApiStatus.Internal @@ -86,9 +102,15 @@ private void onAddedToGroup(@NotNull NetNode node) { node.setGroup(this); } - public void notifyActiveChange(NetNode node, boolean active) { - if (active) activeNodes.add(node); - else activeNodes.remove(node); + public void notifySortingChange(NetNode node, int oldKey, int newKey) { + Set old = this.sortingNodes.get(oldKey); + if (old != null) { + old.remove(node); + if (old.size() == 0) this.sortingNodes.remove(oldKey); + } + Set n = this.sortingNodes.get(newKey); + if (n == null) this.sortingNodes.put(newKey, n = new ObjectOpenHashSet<>()); + n.add(node); } public static MergeDirection isEdgeAllowed(@NotNull NetNode source, @NotNull NetNode target) { @@ -218,8 +240,15 @@ public Set getNodes() { @NotNull @UnmodifiableView - public Set getActiveNodes() { - return activeNodes; + public Set getNodesUnderKey(int key) { + Set set = sortingNodes.get(key); + return set == null ? Collections.emptySet() : set; + } + + @NotNull + @UnmodifiableView + public Int2ObjectMap> getSortingNodes() { + return sortingNodes; } public @Nullable GroupData getData() { diff --git a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java index d59e3f6e80a..5099c2ecc64 100644 --- a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java +++ b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.group; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.path.PathBuilder; diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java index 83957c55068..b9551ea0e07 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicEntry.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.logic; import gregtech.api.graphnet.MultiNodeHelper; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.network.IPacket; diff --git a/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java index b2cdafb3d75..f9380952bf2 100644 --- a/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java +++ b/src/main/java/gregtech/api/graphnet/logic/WeightFactorLogic.java @@ -7,7 +7,7 @@ public final class WeightFactorLogic extends AbstractDoubleLogicData { public static final DoubleLogicType TYPE = new DoubleLogicType<>(GTValues.MODID, "WeightFactor", - WeightFactorLogic::new, new WeightFactorLogic().setValue(0.1)); + WeightFactorLogic::new, new WeightFactorLogic().setValue(0)); @Override public @NotNull DoubleLogicType getType() { diff --git a/src/main/java/gregtech/api/graphnet/net/BlankNetNode.java b/src/main/java/gregtech/api/graphnet/net/BlankNetNode.java new file mode 100644 index 00000000000..44c8ba62bd5 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/net/BlankNetNode.java @@ -0,0 +1,25 @@ +package gregtech.api.graphnet.net; + +import gregtech.api.GTValues; +import gregtech.api.graphnet.GraphClassType; + +import org.jetbrains.annotations.NotNull; + +public final class BlankNetNode extends NetNode { + + public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "BlankNode", BlankNetNode::new); + + public BlankNetNode(@NotNull IGraphNet net) { + super(net); + } + + @Override + public @NotNull Object getEquivalencyData() { + return this; + } + + @Override + public @NotNull GraphClassType getType() { + return TYPE; + } +} diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNetNode.java b/src/main/java/gregtech/api/graphnet/net/BlockPosNode.java similarity index 55% rename from src/main/java/gregtech/api/graphnet/worldnet/WorldPosNetNode.java rename to src/main/java/gregtech/api/graphnet/net/BlockPosNode.java index d6dfc872cda..358ca4f1242 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNetNode.java +++ b/src/main/java/gregtech/api/graphnet/net/BlockPosNode.java @@ -1,26 +1,24 @@ -package gregtech.api.graphnet.worldnet; +package gregtech.api.graphnet.net; -import gregtech.api.graphnet.NetNode; +import gregtech.api.GTValues; +import gregtech.api.graphnet.GraphClassType; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; import org.jetbrains.annotations.NotNull; -public class WorldPosNetNode extends NetNode { +public class BlockPosNode extends NetNode { + + public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "BlockPosNode", BlockPosNode::new); private BlockPos pos; - public WorldPosNetNode(WorldPosNet net) { + public BlockPosNode(IGraphNet net) { super(net); } - @Override - public @NotNull WorldPosNet getNet() { - return (WorldPosNet) super.getNet(); - } - - public WorldPosNetNode setPos(BlockPos pos) { + public BlockPosNode setPos(BlockPos pos) { this.pos = pos; return this; } @@ -39,7 +37,12 @@ public void deserializeNBT(NBTTagCompound nbt) { } @Override - public BlockPos getEquivalencyData() { + public @NotNull BlockPos getEquivalencyData() { return pos; } + + @Override + public @NotNull GraphClassType getType() { + return TYPE; + } } diff --git a/src/main/java/gregtech/api/graphnet/IGraphNet.java b/src/main/java/gregtech/api/graphnet/net/IGraphNet.java similarity index 73% rename from src/main/java/gregtech/api/graphnet/IGraphNet.java rename to src/main/java/gregtech/api/graphnet/net/IGraphNet.java index 8d69f69caec..b17d676b639 100644 --- a/src/main/java/gregtech/api/graphnet/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/net/IGraphNet.java @@ -1,5 +1,8 @@ -package gregtech.api.graphnet; +package gregtech.api.graphnet.net; +import gregtech.api.graphnet.GraphClassType; +import gregtech.api.graphnet.GraphNetBacker; +import gregtech.api.graphnet.MultiNodeHelper; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.group.GroupData; @@ -10,27 +13,10 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.UnmodifiableView; public interface IGraphNet { - /** - * Controls whether dynamic weight lookup will be used. - * Dynamic weight lookup can be more expensive, so this should not be enabled unless necessary. - */ - default boolean usesDynamicWeights(int algorithmID) { - return false; - } - - /** - * Controls whether predication of edges is allowed for this net. When false, path caching is improved by - * skipping the recomputation required in order to compensate for predication. - * - * @return whether predication should be allowed for this net. - */ - default boolean supportsPredication() { - return false; - } - /** * Adds a node to the graphnet. * @@ -90,8 +76,7 @@ default boolean supportsPredication() { * * @return the backing net graph */ - @ApiStatus.Internal - default INetGraph getGraph() { + default @UnmodifiableView INetGraph getGraph() { return getBacker().getGraph(); } @@ -120,6 +105,7 @@ default GroupData getBlankGroupData() { * @return A default node data object. */ @NotNull + @Contract("->new") default NetLogicData getDefaultNodeData() { return new NetLogicData().setLogicEntry(WeightFactorLogic.TYPE.getWith(1)); } @@ -145,35 +131,18 @@ default boolean clashesWith(IGraphNet net) { return false; } - /** - * @return the class all registered nodes are expected to be children of. - */ - Class getNodeClass(); - - /** - * While this is crude, it does allow for avoiding generics literally everywhere. - * The systems that make up a graphnet intertwine such that generics would be needed in basically every class. - * Basically, instead of a bunch of generics everywhere, we just instate an honor system that crashes the game if - * you violate it. - */ - default void nodeClassCheck(NetNode node) { - if (!(getNodeClass().isInstance(node))) - throw new IllegalArgumentException("Cannot provide a " + this.getClass().getSimpleName() + - " with a " + node.getClass().getSimpleName() + " node!"); - } - /** * @return a new node with no data, to be either nbt deserialized or initialized in some other way. */ @NotNull - NetNode getNewNode(); + GraphClassType getDefaultNodeType(); /** * @return a new edge with no data, to be either nbt deserialized or initialized in some other way. */ @NotNull - default NetEdge getNewEdge() { - return new NetEdge(); + default GraphClassType getDefaultEdgeType() { + return NetEdge.TYPE; } /** diff --git a/src/main/java/gregtech/api/graphnet/NetNode.java b/src/main/java/gregtech/api/graphnet/net/NetNode.java similarity index 80% rename from src/main/java/gregtech/api/graphnet/NetNode.java rename to src/main/java/gregtech/api/graphnet/net/NetNode.java index 1d562728f69..85bc95fa361 100644 --- a/src/main/java/gregtech/api/graphnet/NetNode.java +++ b/src/main/java/gregtech/api/graphnet/net/NetNode.java @@ -1,5 +1,6 @@ -package gregtech.api.graphnet; +package gregtech.api.graphnet.net; +import gregtech.api.graphnet.GraphClassType; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.logic.NetLogicData; @@ -22,7 +23,7 @@ public abstract class NetNode implements INBTSerializable { @ApiStatus.Internal public GraphVertex wrapper; - private boolean isActive = false; + protected int sortingKey = 0; private final @NotNull IGraphNet net; private final @NotNull NetLogicData data; @@ -38,20 +39,20 @@ public NetNode(@NotNull IGraphNet net) { } /** - * Determines whether the node should be treated as a valid destination of pathing algorithms + * Sorts nodes into distinct groups in NetGroups for later use. */ - public boolean isActive() { - return isActive; + public int getSortingKey() { + return sortingKey; } /** - * Sets whether the node should be treated as a valid destination of pathing algorithms + * Sets the distinct group in a NetGroup this node will be sorted into. */ - public void setActive(boolean active) { - if (isActive != active) { - isActive = active; + public void setSortingKey(int key) { + if (key != sortingKey) { NetGroup group = getGroupUnsafe(); - if (group != null) group.notifyActiveChange(this, active); + if (group != null) group.notifySortingChange(this, sortingKey, key); + sortingKey = key; } } @@ -91,13 +92,13 @@ public void onRemove() {} public NBTTagCompound serializeNBT() { NBTTagCompound tag = new NBTTagCompound(); tag.setTag("Data", this.data.serializeNBT()); - tag.setBoolean("IsActive", this.isActive()); + tag.setInteger("SortingKey", sortingKey); return tag; } @Override public void deserializeNBT(NBTTagCompound nbt) { - this.isActive = nbt.getBoolean("IsActive"); + this.sortingKey = nbt.getInteger("SortingKey"); this.data.clearData(); this.data.deserializeNBT((NBTTagList) nbt.getTag("Data")); } @@ -108,7 +109,9 @@ public void deserializeNBT(NBTTagCompound nbt) { * * @return equivalency data. Needs to work with {@link Objects#equals(Object, Object)} */ - public abstract Object getEquivalencyData(); + public abstract @NotNull Object getEquivalencyData(); + + public abstract @NotNull GraphClassType getType(); @Override public boolean equals(Object o) { diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java b/src/main/java/gregtech/api/graphnet/net/WorldSavedNet.java similarity index 69% rename from src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java rename to src/main/java/gregtech/api/graphnet/net/WorldSavedNet.java index 574b00c26fc..74700cc0097 100644 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldNet.java +++ b/src/main/java/gregtech/api/graphnet/net/WorldSavedNet.java @@ -1,16 +1,16 @@ -package gregtech.api.graphnet.worldnet; +package gregtech.api.graphnet.net; import gregtech.api.graphnet.GraphNetBacker; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.graph.NetDirectedGraph; import gregtech.api.graphnet.graph.NetUndirectedGraph; import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; + import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.world.World; import net.minecraft.world.storage.WorldSavedData; import org.jetbrains.annotations.NotNull; @@ -18,32 +18,21 @@ import java.util.function.Function; -public abstract class WorldNet extends WorldSavedData implements IGraphNet { +public abstract class WorldSavedNet extends WorldSavedData implements IGraphNet { protected final GraphNetBacker backer; - private World world; - private int fallbackDimensionID; - public WorldNet(String name, @NotNull Function graphBuilder) { + public WorldSavedNet(String name, @NotNull Function graphBuilder) { super(name); this.backer = new GraphNetBacker(this, graphBuilder.apply(this)); } - public WorldNet(String name, boolean directed) { + public WorldSavedNet(String name, boolean directed) { this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder()); } - public void setWorld(World world) { - this.world = world; - } - - public World getWorld() { - return world; - } - @Override public void addNode(@NotNull NetNode node) { - nodeClassCheck(node); this.backer.addNode(node); } @@ -54,14 +43,11 @@ public void addNode(@NotNull NetNode node) { @Override public void removeNode(@NotNull NetNode node) { - nodeClassCheck(node); this.backer.removeNode(node); } @Override public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays) { - nodeClassCheck(source); - nodeClassCheck(target); double weight = source.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue() + target.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue(); NetEdge edge = backer.addEdge(source, target, weight); @@ -75,35 +61,24 @@ public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, boolean @Override public @Nullable NetEdge getEdge(@NotNull NetNode source, @NotNull NetNode target) { - nodeClassCheck(source); - nodeClassCheck(target); return backer.getEdge(source, target); } @Override public void removeEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays) { - nodeClassCheck(source); - nodeClassCheck(target); this.backer.removeEdge(source, target); if (bothWays && this.getGraph().isDirected()) { this.backer.removeEdge(target, source); } } - protected int getDimension() { - if (world == null) return fallbackDimensionID; - else return world.provider.getDimension(); - } - @Override public void readFromNBT(@NotNull NBTTagCompound nbt) { - fallbackDimensionID = nbt.getInteger("Dimension"); backer.readFromNBT(nbt); } @Override public @NotNull NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { - compound.setInteger("Dimension", getDimension()); return backer.writeToNBT(compound); } diff --git a/src/main/java/gregtech/api/graphnet/path/NetPath.java b/src/main/java/gregtech/api/graphnet/path/NetPath.java index a3d3f597c82..2629cb13906 100644 --- a/src/main/java/gregtech/api/graphnet/path/NetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/NetPath.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.logic.NetLogicData; @@ -13,23 +13,23 @@ public interface NetPath { @NotNull @Unmodifiable - ImmutableCollection getOrderedNodes(); + ImmutableCollection getOrderedNodes(); @NotNull - default N getSourceNode() { + default NetNode getSourceNode() { ImmutableCollection nodes = getOrderedNodes(); - return (N) nodes.asList().get(0); + return nodes.asList().get(0); } @NotNull - default N getTargetNode() { + default NetNode getTargetNode() { ImmutableCollection nodes = getOrderedNodes(); - return (N) nodes.asList().get(nodes.size() - 1); + return nodes.asList().get(nodes.size() - 1); } @NotNull @Unmodifiable - ImmutableCollection getOrderedEdges(); + ImmutableCollection getOrderedEdges(); double getWeight(); diff --git a/src/main/java/gregtech/api/graphnet/path/PathBuilder.java b/src/main/java/gregtech/api/graphnet/path/PathBuilder.java index bd786dc37f5..5aa8956da80 100644 --- a/src/main/java/gregtech/api/graphnet/path/PathBuilder.java +++ b/src/main/java/gregtech/api/graphnet/path/PathBuilder.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import org.jetbrains.annotations.Contract; diff --git a/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java b/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java index f4655bae688..35d26798190 100644 --- a/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; @@ -29,22 +29,22 @@ public SingletonNetPath(NetNode node, double weight) { } @Override - public @NotNull @Unmodifiable ImmutableCollection getOrderedNodes() { - return (ImmutableCollection) singleton; + public @NotNull @Unmodifiable ImmutableCollection getOrderedNodes() { + return singleton; } @Override - public @NotNull N getSourceNode() { - return (N) node; + public @NotNull NetNode getSourceNode() { + return node; } @Override - public @NotNull N getTargetNode() { - return (N) node; + public @NotNull NetNode getTargetNode() { + return node; } @Override - public @NotNull @Unmodifiable ImmutableCollection getOrderedEdges() { + public @NotNull @Unmodifiable ImmutableCollection getOrderedEdges() { return ImmutableSet.of(); } diff --git a/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java b/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java index 08e7b6a73ec..f69b29cf86e 100644 --- a/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.logic.NetLogicData; @@ -63,13 +63,13 @@ public StandardNetPath(@NotNull StandardNetPath reverse) { } @Override - public @NotNull @Unmodifiable ImmutableCollection getOrderedNodes() { - return (ImmutableCollection) nodes; + public @NotNull @Unmodifiable ImmutableCollection getOrderedNodes() { + return nodes; } @Override - public @NotNull @Unmodifiable ImmutableCollection getOrderedEdges() { - return (ImmutableCollection) edges; + public @NotNull @Unmodifiable ImmutableCollection getOrderedEdges() { + return edges; } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java index 4e2eac6d798..b5e8a436fc7 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/IPipeNetNodeHandler.java @@ -16,10 +16,10 @@ public interface IPipeNetNodeHandler { @NotNull - Collection getOrCreateFromNets(World world, BlockPos pos, IPipeStructure structure); + Collection getOrCreateFromNets(World world, BlockPos pos, IPipeStructure structure); @NotNull - Collection getFromNets(World world, BlockPos pos, IPipeStructure structure); + Collection getFromNets(World world, BlockPos pos, IPipeStructure structure); void removeFromNets(World world, BlockPos pos, IPipeStructure structure); @@ -30,13 +30,13 @@ void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List getOrCreateFromNets(World world, BlockPos pos, - IPipeStructure structure) { + public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, + IPipeStructure structure) { return Collections.emptyList(); } @Override - public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { return Collections.emptyList(); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeExposingCapabilities.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeExposingCapabilities.java new file mode 100644 index 00000000000..80aee2ec274 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeExposingCapabilities.java @@ -0,0 +1,13 @@ +package gregtech.api.graphnet.pipenet; + +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.capabilities.ICapabilityProvider; + +public interface NodeExposingCapabilities { + + ICapabilityProvider getProvider(); + + default EnumFacing exposedFacing() { + return null; + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java index 3488c512f30..f803c429128 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java @@ -64,14 +64,14 @@ public boolean run() { return true; } - public static Key key(WorldPipeNetNode node, IPredicateTestObject testObject) { + public static Key key(WorldPipeNode node, IPredicateTestObject testObject) { return new Key(node, testObject); } - public static Key key(WorldPipeNetNode node, ITraverseData data) { + public static Key key(WorldPipeNode node, ITraverseData data) { return new Key(node, data.getTestObject()); } @Desugar - public record Key(WorldPipeNetNode node, IPredicateTestObject testObject) {} + public record Key(WorldPipeNode node, IPredicateTestObject testObject) {} } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java index 59919b1045f..95e29333915 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java @@ -13,12 +13,12 @@ public final class NodeLossResult { public static final NodeLossResult IDENTITY = new NodeLossResult(null, ReversibleLossOperator.IDENTITY); - private final @Nullable Consumer postAction; + private final @Nullable Consumer postAction; private final @NotNull ReversibleLossOperator lossFunction; boolean simulated = true; - public NodeLossResult(@Nullable Consumer postAction, + public NodeLossResult(@Nullable Consumer postAction, @NotNull ReversibleLossOperator lossFunction) { this.postAction = postAction; this.lossFunction = lossFunction; @@ -28,7 +28,7 @@ public NodeLossResult(@Nullable Consumer postAction, public static NodeLossResult combine(@Nullable NodeLossResult a, @Nullable NodeLossResult b) { if (a == null) return b; if (b == null) return a; - Consumer postAction = a.postAction; + Consumer postAction = a.postAction; if (b.postAction != null) { if (postAction == null) postAction = b.postAction; else postAction = postAction.andThen(b.postAction); @@ -40,7 +40,7 @@ public boolean hasPostAction() { return postAction != null; } - public @Nullable Consumer getPostAction() { + public @Nullable Consumer getPostAction() { return postAction; } @@ -48,7 +48,7 @@ public NodeLossResult copy() { return new NodeLossResult(postAction, lossFunction); } - public void triggerPostAction(WorldPipeNetNode node) { + public void triggerPostAction(WorldPipeNode node) { if (postAction == null) return; this.postAction.accept(node); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeWithCovers.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeWithCovers.java new file mode 100644 index 00000000000..cb2abf7a6c6 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeWithCovers.java @@ -0,0 +1,10 @@ +package gregtech.api.graphnet.pipenet; + +import gregtech.api.cover.CoverableView; + +import org.jetbrains.annotations.Nullable; + +public interface NodeWithCovers { + + @Nullable CoverableView getCoverableView(); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeWithFacingToOthers.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeWithFacingToOthers.java new file mode 100644 index 00000000000..649fc55f083 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeWithFacingToOthers.java @@ -0,0 +1,13 @@ +package gregtech.api.graphnet.pipenet; + +import gregtech.api.graphnet.net.NetNode; + +import net.minecraft.util.EnumFacing; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface NodeWithFacingToOthers { + + @Nullable EnumFacing getFacingToOther(@NotNull NetNode other); +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java new file mode 100644 index 00000000000..cfc7577c547 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java @@ -0,0 +1,98 @@ +package gregtech.api.graphnet.pipenet; + +import gregtech.api.GTValues; +import gregtech.api.graphnet.GraphClassType; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; + +import gregtech.api.util.FacingPos; + +import gregtech.api.util.GTLog; +import gregtech.api.util.GTUtility; + +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +import net.minecraftforge.common.capabilities.ICapabilityProvider; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class WorldPipeCapConnectionNode extends NetNode implements NodeWithFacingToOthers, NodeExposingCapabilities { + + public static final int SORTING_KEY = 432; + + public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "WorldPipeCapConnectionNode", + WorldPipeCapConnectionNode::resolve); + + private FacingPos posAndFacing; + + public WorldPipeCapConnectionNode(WorldPipeNet net) { + super(net); + sortingKey = SORTING_KEY; + } + + private static WorldPipeCapConnectionNode resolve(IGraphNet net) { + if (net instanceof WorldPipeNet w) return new WorldPipeCapConnectionNode(w); + GTLog.logger.fatal("Attempted to initialize a WorldPipeCapConnectionNode to a non-WorldPipeNet. If relevant NPEs occur later, this is most likely the cause."); + return null; + } + + public WorldPipeNode getParent() { + return getNet().getNode(getEquivalencyData().getPos()); + } + + public WorldPipeCapConnectionNode setPosAndFacing(FacingPos posAndFacing) { + this.posAndFacing = posAndFacing; + return this; + } + + @Override + public NBTTagCompound serializeNBT() { + NBTTagCompound tag = super.serializeNBT(); + tag.setLong("Pos", posAndFacing.getPos().toLong()); + tag.setByte("Facing", (byte) posAndFacing.getFacing().getIndex()); + return tag; + } + + @Override + public void deserializeNBT(NBTTagCompound nbt) { + super.deserializeNBT(nbt); + this.setPosAndFacing(new FacingPos(BlockPos.fromLong(nbt.getLong("Pos")), + EnumFacing.byIndex(nbt.getByte("Facing")))); + } + + @Override + public @NotNull WorldPipeNet getNet() { + return (WorldPipeNet) super.getNet(); + } + + @Override + public @NotNull FacingPos getEquivalencyData() { + return posAndFacing; + } + + @Override + public @NotNull GraphClassType getType() { + return TYPE; + } + + @Override + public @Nullable EnumFacing getFacingToOther(@NotNull NetNode other) { + if (other instanceof WorldPipeNode n && GTUtility.arePosEqual(n.getEquivalencyData(), posAndFacing.getPos())) + return posAndFacing.getFacing().getOpposite(); + else return null; + } + + @Override + public ICapabilityProvider getProvider() { + WorldPipeNode parent = getParent(); + return parent.getTileEntity().getTargetWithCapabilities(parent, posAndFacing.getFacing()); + } + + @Override + public EnumFacing exposedFacing() { + return posAndFacing.getFacing().getOpposite(); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 31edd5188d9..f8c9683c40d 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -1,21 +1,29 @@ package gregtech.api.graphnet.pipenet; import gregtech.api.cover.Cover; -import gregtech.api.graphnet.IGraphNet; +import gregtech.api.cover.CoverableView; +import gregtech.api.graphnet.GraphClassType; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.MultiNodeHelper; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; +import gregtech.api.graphnet.net.WorldSavedNet; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.pipenet.predicate.BlockedPredicate; import gregtech.api.graphnet.predicate.EdgePredicate; import gregtech.api.graphnet.predicate.NetPredicateType; -import gregtech.api.graphnet.worldnet.WorldPosNet; +import gregtech.api.graphnet.traverse.iter.EdgeDirection; +import gregtech.api.util.GTUtility; import gregtech.api.util.IDirtyNotifiable; import gregtech.api.util.reference.WeakHashSet; import gregtech.common.covers.CoverShutter; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; + +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -30,18 +38,22 @@ import org.jetbrains.annotations.Nullable; import java.util.Collections; +import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Function; import java.util.stream.Stream; -public abstract class WorldPipeNet extends WorldPosNet { +public abstract class WorldPipeNet extends WorldSavedNet { public static final int MULTI_NET_TIMEOUT = 10; private static final Int2ObjectOpenHashMap> dimensionNets = new Int2ObjectOpenHashMap<>(); + private World world; + private int fallbackDimensionID; + public WorldPipeNet(String name, Function graphBuilder) { super(name, graphBuilder); } @@ -50,10 +62,9 @@ public WorldPipeNet(String name, boolean directed) { super(name, directed); } - @Override public void setWorld(World world) { if (getWorld() == world) return; - super.setWorld(world); + this.world = world; dimensionNets.compute(getDimension(), (k, v) -> { if (v == null) v = new WeakHashSet<>(); v.add(this); @@ -61,28 +72,52 @@ public void setWorld(World world) { }); } - public final void updatePredication(@NotNull WorldPipeNetNode node, @NotNull PipeTileEntity tile) { - if (supportsPredication()) updatePredicationInternal(node, tile); + public World getWorld() { + return world; + } + + protected int getDimension() { + if (world == null) return fallbackDimensionID; + else return world.provider.getDimension(); + } + + @Override + public void readFromNBT(@NotNull NBTTagCompound nbt) { + fallbackDimensionID = nbt.getInteger("Dimension"); + super.readFromNBT(nbt); + } + + @Override + public @NotNull NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { + compound.setInteger("Dimension", getDimension()); + return super.writeToNBT(compound); } /** * Called when a PipeTileEntity is marked dirty through {@link IDirtyNotifiable#markAsDirty()}, which is generally * when the state of its covers is changed. - * + * * @param tile the tile marked dirty. * @param node the associated node. */ - protected void updatePredicationInternal(@NotNull WorldPipeNetNode node, @NotNull PipeTileEntity tile) { + public void updatePredication(@NotNull WorldPipeNode node, @NotNull PipeTileEntity tile) { boolean dirty = false; - for (EnumFacing facing : EnumFacing.VALUES) { - PipeTileEntity neighbor = tile.getPipeNeighbor(facing, false); + for (NetEdge edge : getBacker().getTouchingEdges(node, EdgeDirection.ALL)) { + NetNode neighbor = edge.getOppositeNode(node); if (neighbor == null) continue; - WorldPipeNetNode neighborNode = this.getNode(neighbor.getPos()); - if (neighborNode == null) continue; - NetEdge edge = getEdge(node, neighborNode); - if (edge == null) continue; - dirty |= predicateEdge(edge, node, tile.getCoverHolder().getCoverAtSide(facing), neighborNode, - neighbor.getCoverHolder().getCoverAtSide(facing.getOpposite())); + Cover cNode = null; + Cover cNeighbor = null; + if (neighbor instanceof NodeWithFacingToOthers n) { + EnumFacing facing = n.getFacingToOther(node); + if (facing != null) { + cNode = node.getTileEntity().getCoverHolder().getCoverAtSide(facing.getOpposite()); + CoverableView view; + if (neighbor instanceof NodeWithCovers c && (view = c.getCoverableView()) != null) { + cNeighbor = view.getCoverAtSide(facing); + } + } + } + dirty |= predicateEdge(edge, node, cNode, neighbor, cNeighbor); } if (dirty) markDirty(); } @@ -97,9 +132,9 @@ protected void updatePredicationInternal(@NotNull WorldPipeNetNode node, @NotNul * @param coverTarget the cover on the target facing the source. * @return whether the predication state has changed and this net needs to be marked dirty. */ - protected boolean predicateEdge(@NotNull NetEdge edge, @NotNull WorldPipeNetNode source, + protected boolean predicateEdge(@NotNull NetEdge edge, @NotNull NetNode source, @Nullable Cover coverSource, - @NotNull WorldPipeNetNode target, @Nullable Cover coverTarget) { + @NotNull NetNode target, @Nullable Cover coverTarget) { Map, EdgePredicate> prevValue = new Object2ObjectOpenHashMap<>( edge.getPredicateHandler().getPredicateSet()); edge.getPredicateHandler().clearPredicates(); @@ -137,18 +172,23 @@ protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nulla } } - public abstract Capability[] getTargetCapabilities(); + public Capability[] getTargetCapabilities() { + return null; + } + + public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNode node) { + return null; + } - public abstract IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node); + public abstract PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEntity owner, @NotNull WorldPipeNode node); @Override - public @NotNull WorldPipeNetNode getOrCreateNode(@NotNull BlockPos pos) { - return (WorldPipeNetNode) super.getOrCreateNode(pos); + public @NotNull GraphClassType getDefaultNodeType() { + return WorldPipeNode.TYPE; } - @Override - public @Nullable WorldPipeNetNode getNode(@NotNull BlockPos equivalencyData) { - return (WorldPipeNetNode) getNode((Object) equivalencyData); + public @Nullable WorldPipeNode getNode(@NotNull BlockPos equivalencyData) { + return (WorldPipeNode) getNode((Object) equivalencyData); } protected Stream<@NotNull WorldPipeNet> sameDimensionNetsStream() { @@ -156,7 +196,7 @@ protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nulla .filter(Objects::nonNull); } - public void synchronizeNode(WorldPipeNetNode node) { + public void synchronizeNode(WorldPipeNode node) { // basically, if another net has a node in the exact same position, then we know it's the same block. // thus, we set up a multi net node handler for the node in order to manage the overlap // this is disk-load safe, since this method is called during nbt deserialization. @@ -195,32 +235,22 @@ public static String getDataID(final String baseID, final World world) { */ public abstract int getNetworkID(); - @Override - public final Class getNodeClass() { - return WorldPipeNetNode.class; - } - - @Override - public final @NotNull WorldPipeNetNode getNewNode() { - return new WorldPipeNetNode(this); - } - @Contract(value = " -> new", pure = true) - public static @NotNull Object2ObjectOpenCustomHashMap getSensitiveHashMap() { + public static @NotNull Object2ObjectOpenCustomHashMap getSensitiveHashMap() { return new Object2ObjectOpenCustomHashMap<>(SensitiveStrategy.INSTANCE); } - protected static class SensitiveStrategy implements Hash.Strategy { + protected static class SensitiveStrategy implements Hash.Strategy { public static final SensitiveStrategy INSTANCE = new SensitiveStrategy(); @Override - public int hashCode(WorldPipeNetNode o) { + public int hashCode(NetNode o) { return Objects.hash(o, o.getNet()); } @Override - public boolean equals(WorldPipeNetNode a, WorldPipeNetNode b) { + public boolean equals(NetNode a, NetNode b) { return a.equals(b) && a.getNet().equals(b.getNet()); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNode.java similarity index 57% rename from src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java rename to src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNode.java index 7520daee20c..0045db5d502 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNetNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNode.java @@ -1,20 +1,36 @@ package gregtech.api.graphnet.pipenet; +import gregtech.api.GTValues; +import gregtech.api.cover.CoverableView; +import gregtech.api.graphnet.GraphClassType; import gregtech.api.graphnet.MultiNodeHelper; +import gregtech.api.graphnet.net.BlankNetNode; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.worldnet.WorldPosNetNode; +import gregtech.api.graphnet.net.BlockPosNode; + +import gregtech.api.util.GTLog; + +import gregtech.api.util.GTUtility; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.ICapabilityProvider; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; -public final class WorldPipeNetNode extends WorldPosNetNode { +public class WorldPipeNode extends BlockPosNode implements NodeWithFacingToOthers, NodeWithCovers, NodeExposingCapabilities { + + public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "WorldPipeNode", + WorldPipeNode::resolve); private static final PipeTileEntity FALLBACK = new PipeTileEntity(); @@ -23,10 +39,16 @@ public final class WorldPipeNetNode extends WorldPosNetNode { private WeakReference tileReference; - public WorldPipeNetNode(WorldPipeNet net) { + public WorldPipeNode(WorldPipeNet net) { super(net); } + private static WorldPipeNode resolve(IGraphNet net) { + if (net instanceof WorldPipeNet w) return new WorldPipeNode(w); + GTLog.logger.fatal("Attempted to initialize a WorldPipeNode to a non-WorldPipeNet. If relevant NPEs occur later, this is most likely the cause."); + return null; + } + public @NotNull IWorldPipeNetTile getTileEntity() { IWorldPipeNetTile tile = getTileEntity(true); if (tile == null) { @@ -70,7 +92,7 @@ public void onRemove() { } @Override - public WorldPipeNetNode setPos(BlockPos pos) { + public WorldPipeNode setPos(BlockPos pos) { super.setPos(pos); this.getNet().synchronizeNode(this); return this; @@ -84,7 +106,27 @@ public boolean traverse(long queryTick, boolean simulate) { } @Override - public BlockPos getEquivalencyData() { + public @NotNull BlockPos getEquivalencyData() { return super.getEquivalencyData(); } + + @Override + public @NotNull GraphClassType getType() { + return TYPE; + } + + @Override + public @Nullable EnumFacing getFacingToOther(@NotNull NetNode other) { + return other instanceof WorldPipeNode n ? GTUtility.getFacingToNeighbor(this.getEquivalencyData(), n.getEquivalencyData()) : null; + } + + @Override + public @Nullable CoverableView getCoverableView() { + return getTileEntity().getCoverHolder(); + } + + @Override + public ICapabilityProvider getProvider() { + return getTileEntity(); + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index 6ce23b4254f..ad5f4b31eee 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -2,7 +2,7 @@ import gregtech.api.GTValues; import gregtech.api.graphnet.MultiNodeHelper; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.logic.INetLogicEntryListener; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java index 5cfa305a3da..aea849a80ff 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java @@ -1,17 +1,27 @@ package gregtech.api.graphnet.pipenet.physical; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; -import org.jetbrains.annotations.Nullable; +import net.minecraftforge.common.capabilities.ICapabilityProvider; -public interface IPipeCapabilityObject { +import net.minecraftforge.fml.common.FMLCommonHandler; - void setTile(PipeTileEntity tile); +import org.jetbrains.annotations.NotNull; - Capability[] getCapabilities(); +public interface IPipeCapabilityObject extends ICapabilityProvider { - T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing); + void init(@NotNull PipeTileEntity tile, @NotNull PipeCapabilityWrapper wrapper); + + @Override + default boolean hasCapability(@NotNull Capability capability, EnumFacing facing) { + return getCapability(capability, facing) != null; + } + + default long getQueryTick() { + return FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index b66bd683e1b..26d7b68eea7 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -5,7 +5,7 @@ import gregtech.api.cover.CoverRayTracer; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; import gregtech.api.graphnet.pipenet.WorldPipeNet; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.IPipeChanneledStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; @@ -292,14 +292,14 @@ public static void connectTile(@NotNull PipeTileEntity tile, @Nullable PipeTileE boolean blocked1 = tile.isBlocked(facing); boolean blocked2 = tileAcross.isBlocked(facing.getOpposite()); - Map tile2Nodes = new Object2ObjectOpenHashMap<>(); - for (WorldPipeNetNode node : getNodesForTile(tileAcross)) { + Map tile2Nodes = new Object2ObjectOpenHashMap<>(); + for (WorldPipeNode node : getNodesForTile(tileAcross)) { tile2Nodes.put(node.getNet(), node); } - for (WorldPipeNetNode node : getNodesForTile(tile)) { + for (WorldPipeNode node : getNodesForTile(tile)) { WorldPipeNet net = node.getNet(); - WorldPipeNetNode other = tile2Nodes.get(net); + WorldPipeNode other = tile2Nodes.get(net); if (other == null) continue; if (!blocked1 && !blocked2) { net.addEdge(node, other, true); @@ -317,14 +317,14 @@ public static void disconnectTile(@NotNull PipeTileEntity tile, @Nullable PipeTi tileAcross.setDisconnected(facing.getOpposite()); if (tile.getWorld().isRemote) return; - Map tile2Nodes = new Object2ObjectOpenHashMap<>(); - for (WorldPipeNetNode node : getNodesForTile(tileAcross)) { + Map tile2Nodes = new Object2ObjectOpenHashMap<>(); + for (WorldPipeNode node : getNodesForTile(tileAcross)) { tile2Nodes.put(node.getNet(), node); } - for (WorldPipeNetNode node : getNodesForTile(tile)) { + for (WorldPipeNode node : getNodesForTile(tile)) { WorldPipeNet net = node.getNet(); - WorldPipeNetNode other = tile2Nodes.get(net); + WorldPipeNode other = tile2Nodes.get(net); if (other == null) continue; net.removeEdge(node, other, true); } @@ -334,14 +334,14 @@ public static void blockTile(@NotNull PipeTileEntity tile, @Nullable PipeTileEnt tile.setBlocked(facing); if (tileAcross == null || tile.getWorld().isRemote) return; - Map tile2Nodes = new Object2ObjectOpenHashMap<>(); - for (WorldPipeNetNode node : getNodesForTile(tileAcross)) { + Map tile2Nodes = new Object2ObjectOpenHashMap<>(); + for (WorldPipeNode node : getNodesForTile(tileAcross)) { tile2Nodes.put(node.getNet(), node); } - for (WorldPipeNetNode node : getNodesForTile(tile)) { + for (WorldPipeNode node : getNodesForTile(tile)) { WorldPipeNet net = node.getNet(); - WorldPipeNetNode other = tile2Nodes.get(net); + WorldPipeNode other = tile2Nodes.get(net); if (other == null) continue; net.removeEdge(other, node, false); } @@ -352,14 +352,14 @@ public static void unblockTile(@NotNull PipeTileEntity tile, @Nullable PipeTileE tile.setUnblocked(facing); if (tileAcross == null || tile.getWorld().isRemote) return; - Map tile2Nodes = new Object2ObjectOpenHashMap<>(); - for (WorldPipeNetNode node : getNodesForTile(tileAcross)) { + Map tile2Nodes = new Object2ObjectOpenHashMap<>(); + for (WorldPipeNode node : getNodesForTile(tileAcross)) { tile2Nodes.put(node.getNet(), node); } - for (WorldPipeNetNode node : getNodesForTile(tile)) { + for (WorldPipeNode node : getNodesForTile(tile)) { WorldPipeNet net = node.getNet(); - WorldPipeNetNode other = tile2Nodes.get(net); + WorldPipeNode other = tile2Nodes.get(net); if (other == null) continue; net.addEdge(other, node, false); } @@ -369,7 +369,7 @@ protected boolean allowsBlocking() { return true; } - public static Collection getNodesForTile(PipeTileEntity tile) { + public static Collection getNodesForTile(PipeTileEntity tile) { assert !tile.getWorld().isRemote; return tile.getBlockType().getHandler(tile) .getOrCreateFromNets(tile.getWorld(), tile.getPos(), tile.getStructure()); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java index 9a68bab2964..e500e26690d 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java @@ -1,43 +1,31 @@ package gregtech.api.graphnet.pipenet.physical.tile; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import net.minecraft.entity.EntityLivingBase; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumParticleTypes; +import net.minecraftforge.common.capabilities.ICapabilityProvider; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.EnumMap; import java.util.function.Consumer; -public interface IWorldPipeNetTile { - - // universal (mostly for active nodes) +public interface IWorldPipeNetTile extends ICapabilityProvider { @NotNull - EnumMap getTargetsWithCapabilities(WorldPipeNetNode destination); + EnumMap getTargetsWithCapabilities(WorldPipeNode destination); @Nullable - TileEntity getTargetWithCapabilities(WorldPipeNetNode destination, EnumFacing facing); + TileEntity getTargetWithCapabilities(WorldPipeNode destination, EnumFacing facing); - PipeCapabilityWrapper getWrapperForNode(WorldPipeNetNode node); + PipeCapabilityWrapper getWrapperForNode(WorldPipeNode node); @NotNull CoverableView getCoverHolder(); - - // fluid piping - - void spawnParticles(EnumFacing direction, EnumParticleTypes particleType, int particleCount); - - void dealAreaDamage(int size, Consumer damageFunction); - - void playLossSound(); - - void visuallyExplode(); - - void setNeighborsToFire(); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java new file mode 100644 index 00000000000..890aa28504f --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java @@ -0,0 +1,57 @@ +package gregtech.api.graphnet.pipenet.physical.tile; + +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.pipenet.WorldPipeCapConnectionNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; + +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.util.FacingPos; + +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; + +import net.minecraft.util.EnumFacing; + +import net.minecraftforge.common.capabilities.Capability; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.EnumMap; + +public class NodeManagingPCW extends PipeCapabilityWrapper { + + private final EnumMap managed = new EnumMap<>(EnumFacing.class); + + public NodeManagingPCW(@NotNull PipeTileEntity owner, @NotNull WorldPipeNode node, + Object2ObjectMap, IPipeCapabilityObject> capabilities, int inactiveKey, + int activeKey) { + super(owner, node, capabilities, inactiveKey, activeKey); + } + + @Override + protected void setActiveInternal(@NotNull EnumFacing facing) { + super.setActiveInternal(facing); + FacingPos pos = new FacingPos(node.getEquivalencyData(), facing); + NetNode existing = node.getNet().getNode(pos); + WorldPipeCapConnectionNode connectionNode; + if (existing instanceof WorldPipeCapConnectionNode c) { + connectionNode = c; + } else { + connectionNode = new WorldPipeCapConnectionNode(node.getNet()); + connectionNode.getNet().addNode(connectionNode); + } + managed.put(facing, connectionNode); + node.getNet().addEdge(node, connectionNode, true); + } + + @Override + protected void setIdleInternal(@NotNull EnumFacing facing) { + super.setIdleInternal(facing); + WorldPipeCapConnectionNode n = managed.remove(facing); + if (n != null) node.getNet().removeNode(n); + } + + public @Nullable WorldPipeCapConnectionNode getNodeForFacing(EnumFacing facing) { + return managed.get(facing); + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java index 4468816ab6d..907b577619e 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java @@ -1,51 +1,84 @@ package gregtech.api.graphnet.pipenet.physical.tile; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; + +import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; + +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ICapabilityProvider; + import org.jetbrains.annotations.NotNull; -import java.util.Objects; +public class PipeCapabilityWrapper implements ICapabilityProvider { + + protected byte activeMask; + protected final PipeTileEntity owner; + protected final WorldPipeNode node; -public class PipeCapabilityWrapper { + protected final Object2ObjectMap, IPipeCapabilityObject> capabilities; - private byte activeMask; - private final PipeTileEntity owner; - private final WorldPipeNetNode node; - public final Capability[] capabilities; + protected final int inactiveKey; + protected final int activeKey; - public PipeCapabilityWrapper(PipeTileEntity owner, @NotNull WorldPipeNetNode node) { + public PipeCapabilityWrapper(@NotNull PipeTileEntity owner, @NotNull WorldPipeNode node, + Object2ObjectMap, IPipeCapabilityObject> capabilities, + int inactiveKey, int activeKey) { this.owner = owner; this.node = node; - this.capabilities = node.getNet().getTargetCapabilities(); - } - - public boolean supports(Capability capability) { - for (Capability cap : capabilities) { - if (Objects.equals(cap, capability)) return true; + this.inactiveKey = inactiveKey; + this.activeKey = activeKey; + this.capabilities = capabilities; + for (IPipeCapabilityObject o : capabilities.values()) { + o.init(owner, this); } - return false; } public void setActive(@NotNull EnumFacing facing) { if (!isActive(facing)) { - this.activeMask |= 1 << facing.ordinal(); - this.node.setActive(this.activeMask > 0); - this.owner.notifyBlockUpdate(); + setActiveInternal(facing); } } + protected void setActiveInternal(@NotNull EnumFacing facing) { + this.activeMask |= 1 << facing.ordinal(); + this.node.setSortingKey(this.activeMask > 0 ? activeKey : inactiveKey); + this.owner.notifyBlockUpdate(); + } + public void setIdle(@NotNull EnumFacing facing) { if (isActive(facing)) { - this.activeMask &= ~(1 << facing.ordinal()); - this.node.setActive(this.activeMask > 0); - this.owner.notifyBlockUpdate(); + setIdleInternal(facing); } } + protected void setIdleInternal(@NotNull EnumFacing facing) { + this.activeMask &= ~(1 << facing.ordinal()); + this.node.setSortingKey(this.activeMask > 0 ? activeKey : inactiveKey); + this.owner.notifyBlockUpdate(); + } + public boolean isActive(@NotNull EnumFacing facing) { return (this.activeMask & 1 << facing.ordinal()) > 0; } + + @Override + public boolean hasCapability(@NotNull Capability capability, EnumFacing facing) { + if (facing != null && !isActive(facing)) return false; + IPipeCapabilityObject obj = capabilities.get(capability); + if (obj == null) return false; + return obj.hasCapability(capability, facing); + } + + @Override + public T getCapability(@NotNull Capability capability, EnumFacing facing) { + if (facing != null && !isActive(facing)) return null; + IPipeCapabilityObject obj = capabilities.get(capability); + if (obj == null) return null; + return obj.getCapability(capability, facing); + } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index fd45187ec12..64cceaedc83 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -1,6 +1,5 @@ package gregtech.api.graphnet.pipenet.physical.tile; -import gregtech.api.GTValues; import gregtech.api.GregTechAPI; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.cover.Cover; @@ -8,8 +7,9 @@ import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.NetLogicRegistry; import gregtech.api.graphnet.logic.NetLogicType; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.WorldPipeNet; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.IInsulatable; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; @@ -26,24 +26,18 @@ import gregtech.common.blocks.MetaBlocks; import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.Blocks; -import net.minecraft.init.SoundEvents; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ITickable; import net.minecraft.util.NonNullList; -import net.minecraft.util.SoundCategory; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; -import net.minecraft.world.WorldServer; import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.DimensionManager; import net.minecraftforge.common.capabilities.Capability; @@ -93,7 +87,7 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick protected final PipeCoverHolder covers = new PipeCoverHolder(this); private final Object2ObjectOpenHashMap, IPipeCapabilityObject> capabilities = new Object2ObjectOpenHashMap<>(); - private final Object2ObjectOpenCustomHashMap netCapabilities = WorldPipeNet + private final Object2ObjectOpenCustomHashMap netCapabilities = WorldPipeNet .getSensitiveHashMap(); @Nullable @@ -347,7 +341,7 @@ public void onNeighborChanged(@NotNull EnumFacing facing) { * @param node the node for this tile entity. Used to identify the capabilities to match. * @return a map of facings to tile entities. */ - public @NotNull EnumMap getTargetsWithCapabilities(WorldPipeNetNode node) { + public @NotNull EnumMap getTargetsWithCapabilities(WorldPipeNode node) { PipeCapabilityWrapper wrapper = netCapabilities.get(node); EnumMap caps = new EnumMap<>(EnumFacing.class); if (wrapper == null) return caps; @@ -363,14 +357,14 @@ public void onNeighborChanged(@NotNull EnumFacing facing) { } @Override - public @Nullable TileEntity getTargetWithCapabilities(WorldPipeNetNode node, EnumFacing facing) { + public @Nullable TileEntity getTargetWithCapabilities(WorldPipeNode node, EnumFacing facing) { PipeCapabilityWrapper wrapper = netCapabilities.get(node); if (wrapper == null || !wrapper.isActive(facing)) return null; else return getNeighbor(facing); } @Override - public PipeCapabilityWrapper getWrapperForNode(WorldPipeNetNode node) { + public PipeCapabilityWrapper getWrapperForNode(WorldPipeNode node) { return netCapabilities.get(node); } @@ -401,7 +395,7 @@ public void updateActiveStatus(@Nullable EnumFacing facing, boolean canOpenConne boolean oneActive = false; for (var netCapability : netCapabilities.entrySet()) { - for (Capability cap : netCapability.getValue().capabilities) { + for (Capability cap : netCapability.getValue().capabilities.keySet()) { if (tile.hasCapability(cap, facing.getOpposite())) { oneActive = true; netCapability.getValue().setActive(facing); @@ -420,19 +414,10 @@ private void setAllIdle(EnumFacing facing) { // capability // - private void addCapabilities(IPipeCapabilityObject[] capabilities) { - for (IPipeCapabilityObject capabilityObject : capabilities) { - capabilityObject.setTile(this); - for (Capability capability : capabilityObject.getCapabilities()) { - this.capabilities.put(capability, capabilityObject); - } - } - } - public T getCapabilityCoverQuery(@NotNull Capability capability, @Nullable EnumFacing facing) { // covers have access to the capability objects no matter the connection status IPipeCapabilityObject object = capabilities.get(capability); - return object == null ? null : object.getCapabilityForSide(capability, facing); + return object == null ? null : object.getCapability(capability, facing); } @Override @@ -447,7 +432,7 @@ public T getCapability(@NotNull Capability capability, @Nullable EnumFaci } T pipeCapability; IPipeCapabilityObject object = capabilities.get(capability); - if (object == null || (pipeCapability = object.getCapabilityForSide(capability, facing)) == null) + if (object == null || (pipeCapability = object.getCapability(capability, facing)) == null) pipeCapability = super.getCapability(capability, facing); Cover cover = facing == null ? null : getCoverHolder().getCoverAtSide(facing); @@ -499,10 +484,10 @@ public void initialize() { this.capabilities.clear(); this.netCapabilities.clear(); this.listeners.clear(); - for (WorldPipeNetNode node : PipeBlock.getNodesForTile(this)) { - this.addCapabilities(node.getNet().getNewCapabilityObjects(node)); - this.netCapabilities.put(node, new PipeCapabilityWrapper(this, node)); - int networkID = node.getNet().getNetworkID(); + for (WorldPipeNode node : PipeBlock.getNodesForTile(this)) { + WorldPipeNet net = node.getNet(); + this.netCapabilities.put(node, net.buildCapabilityWrapper(this, node)); + int networkID = net.getNetworkID(); netLogicDatas.put(networkID, node.getData()); listeners.add(node.getData().addListener((e, r, f) -> writeLogicData(networkID, e, r, f))); for (NetLogicEntry entry : node.getData().getEntries()) { @@ -702,21 +687,6 @@ public boolean isOverheatParticleAlive() { return overheatParticle != null && overheatParticle.isAlive(); } - @Override - public void spawnParticles(EnumFacing direction, EnumParticleTypes particleType, int particleCount) { - if (getWorld() instanceof WorldServer server) { - server.spawnParticle(particleType, - getPos().getX() + 0.5, - getPos().getY() + 0.5, - getPos().getZ() + 0.5, - particleCount, - direction.getXOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, - direction.getYOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, - direction.getZOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, - 0.1); - } - } - // misc overrides // @Override @@ -747,7 +717,7 @@ public void markAsDirty() { markDirty(); // this most notably gets called when the covers of a pipe get updated, aka the edge predicates need syncing. for (var node : this.netCapabilities.keySet()) { - node.getNet().updatePredication(node, this); + if (node instanceof WorldPipeNode n) n.getNet().updatePredication(n, this); } } @@ -816,39 +786,4 @@ public void getCoverBoxes(Consumer consumer) { } } - @Override - public void dealAreaDamage(int size, Consumer damageFunction) { - long timer = getOffsetTimer(); - if (timer >= this.nextDamageTime) { - List entities = getWorld().getEntitiesWithinAABB(EntityLivingBase.class, - new AxisAlignedBB(getPos()).grow(size)); - entities.forEach(damageFunction); - this.nextDamageTime = timer + 20; - } - } - - public void playLossSound() { - long timer = getOffsetTimer(); - if (timer >= this.nextSoundTime) { - getWorld().playSound(null, pos, SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); - this.nextSoundTime = timer + 20; - } - } - - public void visuallyExplode() { - getWorld().createExplosion(null, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, - 1.0f + GTValues.RNG.nextFloat(), false); - } - - public void setNeighborsToFire() { - for (EnumFacing side : EnumFacing.VALUES) { - if (!GTValues.RNG.nextBoolean()) continue; - BlockPos blockPos = getPos().offset(side); - IBlockState blockState = getWorld().getBlockState(blockPos); - if (blockState.getBlock().isAir(blockState, getWorld(), blockPos) || - blockState.getBlock().isFlammable(getWorld(), blockPos, side.getOpposite())) { - getWorld().setBlockState(blockPos, Blocks.FIRE.getDefaultState()); - } - } - } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControl.java b/src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControl.java deleted file mode 100644 index 4eeb4b51f3e..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControl.java +++ /dev/null @@ -1,28 +0,0 @@ -package gregtech.api.graphnet.pipenet.transfer; - -import net.minecraft.util.IStringSerializable; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public abstract class TransferControl implements IStringSerializable { - - private final String name; - - public TransferControl(@NotNull String name) { - this.name = name; - } - - @Override - public @NotNull String getName() { - return name; - } - - public abstract @NotNull T get(@Nullable Object potentialHolder); - - public abstract @NotNull T getNoPassage(); - - public T cast(Object o) { - return (T) o; - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControlProvider.java b/src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControlProvider.java deleted file mode 100644 index 3f013370f3d..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/transfer/TransferControlProvider.java +++ /dev/null @@ -1,8 +0,0 @@ -package gregtech.api.graphnet.pipenet.transfer; - -import org.jetbrains.annotations.Nullable; - -public interface TransferControlProvider { - - @Nullable T getControllerForControl(TransferControl control); -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java index 859816136aa..3fb7b81a0af 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.pipenet.traverse; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.traverseold.IRoundRobinData; @@ -17,7 +17,7 @@ import java.util.Map; import java.util.WeakHashMap; -public abstract class AbstractTileRoundRobinData implements IRoundRobinData { +public abstract class AbstractTileRoundRobinData implements IRoundRobinData { private final MutableByte pointer = new MutableByte(); @@ -26,7 +26,7 @@ public abstract class AbstractTileRoundRobinData implements IRoundRobinData capability, WorldPipeNetNode node, + public boolean hasCapabilityAtPointer(@NotNull Capability capability, WorldPipeNode node, @Nullable SimulatorKey simulator) { return getCapabilityAtPointer(capability, node, simulator) != null; } @Nullable - public E getCapabilityAtPointer(@NotNull Capability capability, WorldPipeNetNode node, + public E getCapabilityAtPointer(@NotNull Capability capability, WorldPipeNode node, @Nullable SimulatorKey simulator) { if (pointerFinished(simulator)) return null; PipeCapabilityWrapper wrapper = node.getTileEntity().getWrapperForNode(node); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java index fe5d31b2a6a..ac40dfb3751 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java @@ -1,20 +1,20 @@ package gregtech.api.graphnet.pipenet.traverse; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import java.util.function.Function; -public class FlowManagerMap extends Object2ObjectOpenHashMap { +public class FlowManagerMap extends Object2ObjectOpenHashMap { - private final Function newSupplier; + private final Function newSupplier; - public FlowManagerMap(Function newSupplier) { + public FlowManagerMap(Function newSupplier) { this.newSupplier = newSupplier; } - public ITileFlowManager access(WorldPipeNetNode node) { + public ITileFlowManager access(WorldPipeNode node) { return computeIfAbsent(node, newSupplier); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java index 0fd76f7a1ee..0ed4bbe2f69 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.pipenet.traverse; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import net.minecraftforge.common.capabilities.Capability; @@ -17,7 +17,7 @@ public SimpleTileRoundRobinData(Capability capability) { } @Override - public boolean hasNextInternalDestination(WorldPipeNetNode node, @Nullable SimulatorKey simulator) { + public boolean hasNextInternalDestination(WorldPipeNode node, @Nullable SimulatorKey simulator) { MutableByte pointer = getPointer(simulator); byte val = pointer.byteValue(); progressToNextInternalDestination(node, simulator); @@ -27,7 +27,7 @@ public boolean hasNextInternalDestination(WorldPipeNetNode node, @Nullable Simul } @Override - public void progressToNextInternalDestination(WorldPipeNetNode node, @Nullable SimulatorKey simulator) { + public void progressToNextInternalDestination(WorldPipeNode node, @Nullable SimulatorKey simulator) { MutableByte pointer = getPointer(simulator); pointer.increment(); while (!pointerFinished(pointer) && !hasCapabilityAtPointer(cap, node, simulator)) { @@ -35,7 +35,7 @@ public void progressToNextInternalDestination(WorldPipeNetNode node, @Nullable S } } - public @Nullable T getAtPointer(WorldPipeNetNode node, @Nullable SimulatorKey simulator) { + public @Nullable T getAtPointer(WorldPipeNode node, @Nullable SimulatorKey simulator) { return getCapabilityAtPointer(cap, node, simulator); } } diff --git a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java index 74a44e4a3b8..d6641de51d4 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java +++ b/src/main/java/gregtech/api/graphnet/predicate/test/ItemTestObject.java @@ -37,6 +37,11 @@ public ItemStack recombine() { return stack; } + @Contract("_ -> new") + public ItemStack recombineSafe(int amount) { + return recombine(Math.min(getStackLimit(), Math.max(0, amount))); + } + @Contract("_ -> new") public ItemStack recombine(int amount) { assert amount <= getStackLimit() && amount > 0; diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java deleted file mode 100644 index f871001f28f..00000000000 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNet.java +++ /dev/null @@ -1,115 +0,0 @@ -package gregtech.api.graphnet.servernet; - -import gregtech.api.graphnet.GraphNetBacker; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.graph.INetGraph; -import gregtech.api.graphnet.graph.NetDirectedGraph; -import gregtech.api.graphnet.graph.NetUndirectedGraph; -import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.util.DimensionPos; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.world.storage.WorldSavedData; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Function; - -/** - * Unused demonstration net that would allow for edges bridging dimensions inside the graph representation. - */ -@SuppressWarnings("unused") -public abstract class ServerNet extends WorldSavedData implements IGraphNet { - - protected final GraphNetBacker backer; - - public ServerNet(String name, Function graphBuilder) { - super(name); - this.backer = new GraphNetBacker(this, graphBuilder.apply(this)); - } - - public ServerNet(String name, boolean directed) { - this(name, directed ? NetDirectedGraph.standardBuilder() : NetUndirectedGraph.standardBuilder()); - } - - @Override - public void addNode(@NotNull NetNode node) { - nodeClassCheck(node); - this.backer.addNode(node); - } - - public @Nullable ServerNetNode getNode(@NotNull DimensionPos equivalencyData) { - return (ServerNetNode) getNode((Object) equivalencyData); - } - - @Override - public @Nullable NetNode getNode(@NotNull Object equivalencyData) { - return backer.getNode(equivalencyData); - } - - @Override - public void removeNode(@NotNull NetNode node) { - nodeClassCheck(node); - this.backer.removeNode(node); - } - - @Override - public NetEdge addEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays) { - nodeClassCheck(source); - nodeClassCheck(target); - double weight = source.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue() + - target.getData().getLogicEntryDefaultable(WeightFactorLogic.TYPE).getValue(); - NetEdge edge = backer.addEdge(source, target, weight); - if (bothWays) { - if (this.getGraph().isDirected()) { - backer.addEdge(target, source, weight); - } - return null; - } else return edge; - } - - @Override - public @Nullable NetEdge getEdge(@NotNull NetNode source, @NotNull NetNode target) { - nodeClassCheck(source); - nodeClassCheck(target); - return backer.getEdge(source, target); - } - - @Override - public void removeEdge(@NotNull NetNode source, @NotNull NetNode target, boolean bothWays) { - nodeClassCheck(source); - nodeClassCheck(target); - this.backer.removeEdge(source, target); - if (bothWays && this.getGraph().isDirected()) { - this.backer.removeEdge(target, source); - } - } - - @Override - public void readFromNBT(@NotNull NBTTagCompound nbt) { - backer.readFromNBT(nbt); - } - - @Override - public @NotNull NBTTagCompound writeToNBT(@NotNull NBTTagCompound compound) { - return backer.writeToNBT(compound); - } - - @Override - public GraphNetBacker getBacker() { - return backer; - } - - @Override - public Class getNodeClass() { - return ServerNetNode.class; - } - - @Override - public @NotNull ServerNetNode getNewNode() { - return new ServerNetNode(this); - } -} diff --git a/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java b/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java deleted file mode 100644 index 31d10bded76..00000000000 --- a/src/main/java/gregtech/api/graphnet/servernet/ServerNetNode.java +++ /dev/null @@ -1,37 +0,0 @@ -package gregtech.api.graphnet.servernet; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; -import gregtech.api.util.DimensionPos; - -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.math.BlockPos; - -public class ServerNetNode extends NetNode { - - private DimensionPos pos; - - public ServerNetNode(IGraphNet net) { - super(net); - } - - @Override - public NBTTagCompound serializeNBT() { - NBTTagCompound tag = super.serializeNBT(); - tag.setLong("Pos", pos.getPos().toLong()); - tag.setInteger("Dim", pos.getDimension()); - return tag; - } - - @Override - public void deserializeNBT(NBTTagCompound nbt) { - super.deserializeNBT(nbt); - BlockPos pos = BlockPos.fromLong(nbt.getLong("Pos")); - this.pos = new DimensionPos(pos, nbt.getInteger("Dim")); - } - - @Override - public DimensionPos getEquivalencyData() { - return pos; - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java index 9bc1f2d98f2..a1eabc1ee45 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java @@ -1,17 +1,18 @@ package gregtech.api.graphnet.traverse; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import it.unimi.dsi.fastutil.objects.Object2DoubleMap; -import it.unimi.dsi.fastutil.objects.Object2DoubleMaps; -import org.apache.commons.lang3.tuple.Pair; -import org.jgrapht.Graph; +import gregtech.api.util.GTUtility; + +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import org.jetbrains.annotations.NotNull; import org.jgrapht.alg.flow.mincost.CapacityScalingMinimumCostFlow; import org.jgrapht.alg.flow.mincost.MinimumCostFlowProblem; +import org.jgrapht.alg.interfaces.MinimumCostFlowAlgorithm; -import java.util.Collections; import java.util.function.Function; public abstract class AbstractMinCostTraverse implements MinimumCostFlowProblem { @@ -20,32 +21,100 @@ public abstract class AbstractMinCostTraverse implements MinimumCostFlowProblem< protected static final GraphVertex CORRECTOR = new GraphVertex(); - public Object2DoubleMap evaluate() { + protected int correction = 0; + + public @NotNull EvaluationResult evaluate() { try { - // setup: - MINCOST.getMinimumCostFlow(this) + correction = 0; + getGraph().addVertex(CORRECTOR); + int count = 0; + for (GraphVertex v : getGraph().vertexSet()) { + if (v.getWrapped() != null) { + int supply = getSupply(v.getWrapped()); + if (supply != 0) { + correction -= supply; + GraphEdge e = new GraphEdge(); + if (supply < 0) { + getGraph().addEdge(CORRECTOR, v, e); + } else { + getGraph().addEdge(v, CORRECTOR, e); + } + getGraph().setEdgeWeight(e, CapacityScalingMinimumCostFlow.COST_INF - 1); + count++; + } + } + } + MinimumCostFlowAlgorithm.MinimumCostFlow flow = MINCOST.getMinimumCostFlow(this); + EvaluationResult result = new EvaluationResult(count, flow.getFlowMap().size()); + for (var entry : flow.getFlowMap().entrySet()) { + NetEdge e = entry.getKey().getWrapped(); + if (e == null) { + GraphVertex v = entry.getKey().getOppositeVertex(CORRECTOR); + if (v != null && v.getWrapped() != null) { + // flow through the corrector is always unsatisfied supply/demand + int sat = GTUtility.moveACloserTo0ByB(getSupply(v.getWrapped()), entry.getValue().intValue()); + result.reportSupply(v.getWrapped(), sat); + } + } else if (entry.getValue().intValue() != 0) { + result.reportFlow(e, entry.getValue().intValue()); + } + } + getGraph().removeVertex(CORRECTOR); + return result; } catch (Exception ignored) { - return Object2DoubleMaps.emptyMap(); + return EvaluationResult.EMPTY; } } @Override - public Graph getGraph() { - return null; + public Function getArcCapacityLowerBounds() { + return e -> 0; } @Override - public Function getNodeSupply() { - return null; + public Function getArcCapacityUpperBounds() { + return e -> e.getWrapped() == null ? CapacityScalingMinimumCostFlow.CAP_INF : getCapacity(e.getWrapped()); } @Override - public Function getArcCapacityLowerBounds() { - return e -> 0; + public Function getNodeSupply() { + return v -> v.getWrapped() != null ? getSupply(v.getWrapped()) : v == CORRECTOR ? correction : 0; } - @Override - public Function getArcCapacityUpperBounds() { - return null; + protected abstract int getSupply(NetNode node); + + protected abstract int getCapacity(NetEdge edge); + + public static class EvaluationResult { + public static final EvaluationResult EMPTY = new EvaluationResult(0, 0); + + protected final Object2IntOpenHashMap flowMap; + protected final Object2IntOpenHashMap supplyMap; + + public EvaluationResult(int sizeSupply, int sizeFlow) { + supplyMap = new Object2IntOpenHashMap<>(sizeSupply); + flowMap = new Object2IntOpenHashMap<>(sizeFlow); + } + + public Object2IntOpenHashMap getFlowMap() { + return flowMap; + } + + public Object2IntOpenHashMap getSupplyMap() { + return supplyMap; + } + + public void reportFlow(NetEdge edge, int flow) { + flowMap.put(edge, flow); + } + + public void reportSupply(NetNode node, int supply) { + supplyMap.put(node, supply); + } + + public boolean isEmpty() { + // if there were no flows, there should be no supply + return flowMap.isEmpty(); + } } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java new file mode 100644 index 00000000000..a8ff077e545 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java @@ -0,0 +1,128 @@ +package gregtech.api.graphnet.traverse; + +import com.github.bsideup.jabel.Desugar; + +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; + +import gregtech.api.util.GTUtility; + +import gregtech.api.util.function.ToBooleanFunction; + +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; + +import java.util.Comparator; +import java.util.Set; +import java.util.function.ObjIntConsumer; +import java.util.function.ToIntFunction; + +public class EQTraverse extends AbstractMinCostTraverse { + + protected final Graph graph; + protected final ToIntFunction capacityFunction; + protected final ToIntFunction supplyFunction; + protected @Nullable ToBooleanFunction lossyNodes; + + protected final Set suppliers; + protected final Set consumers; + protected TestCase testCase; + + public static void equalDistribution(@NotNull IGraphNet net, + @NotNull ObjIntConsumer flowReporterNode, + @NotNull ObjIntConsumer flowReporterEdge, + @NotNull ToIntFunction capacityFunction, + @NotNull ToIntFunction supplyFunction, + @Nullable ToBooleanFunction lossyNodes) { + if (!net.getGraph().isDirected()) { + throw new IllegalArgumentException("Cannot perform equal distribution traverse logic on undirected graph!"); + } + int minSupplier = Integer.MAX_VALUE; + Set suppliers = new ObjectOpenHashSet<>(); + int minConsumer = Integer.MIN_VALUE; + Set consumers = new ObjectOpenHashSet<>(); + for (GraphVertex v : net.getGraph().vertexSet()) { + if (v.getWrapped() != null) { + int supply = supplyFunction.applyAsInt(v.getWrapped()); + if (supply > 0) { + minSupplier = Math.min(minSupplier, supply); + suppliers.add(v.getWrapped()); + } else if (supply < 0) { + minConsumer = Math.max(minConsumer, supply); + consumers.add(v.getWrapped()); + } + } + } + if (suppliers.size() == 0 || consumers.size() == 0) return; + // do some math to determine the working multiples that need to be tested + // supplier count * test supply must equal consumer count * test consumption for all tests + // naive brute force search for now + ObjectArrayList cases = new ObjectArrayList<>(); + for (int s = 1; s <= minSupplier; s++) { + for (int c = -1; c >= minConsumer; c--) { + if (suppliers.size() * s == consumers.size() * -c) + cases.add(new TestCase(minSupplier, minConsumer)); + } + } + // sort the cases from max flow to min flow + TestCase[] arr = cases.stream().sorted(Comparator.comparingInt(c -> suppliers.size() * c.supply)) + .toArray(TestCase[]::new); + // execute binary searching on test cases + EQTraverse traverse = new EQTraverse(net.getGraph(), capacityFunction, supplyFunction, suppliers, consumers); + int solution = (int) GTUtility.binarySearch(0, arr.length - 1, l -> { + traverse.testCase = arr[(int) l]; + EvaluationResult result = traverse.evaluate(); + // a success requires flow to have happened, + // supply map to contain all suppliers and consumers and nothing else, + // and all supply values to match either the supply or consumption for the test case. + return !result.isEmpty() && + result.getSupplyMap().size() == traverse.suppliers.size() + traverse.consumers.size() && + result.getSupplyMap().object2IntEntrySet().stream().map(Object2IntMap.Entry::getIntValue) + .allMatch(i -> i == traverse.testCase.supply || i == traverse.testCase.consumption); + }, false); + // finally, evaluate with loss enabled + traverse.testCase = arr[solution]; + traverse.lossyNodes = lossyNodes; + EvaluationResult result = traverse.evaluate(); + if (result.isEmpty()) return; + result.getFlowMap().forEach(flowReporterEdge::accept); + result.getSupplyMap().forEach(flowReporterNode::accept); + } + + protected EQTraverse(Graph graph, ToIntFunction capacityFunction, + ToIntFunction supplyFunction, Set suppliers, Set consumers) { + this.graph = graph; + this.capacityFunction = capacityFunction; + this.supplyFunction = supplyFunction; + this.suppliers = suppliers; + this.consumers = consumers; + } + + @Override + protected int getSupply(NetNode node) { + if (lossyNodes != null && lossyNodes.applyAsBool(node)) return Short.MIN_VALUE; + if (suppliers.contains(node)) return testCase.supply; + if (consumers.contains(node)) return testCase.consumption; + return 0; + } + + @Override + protected int getCapacity(NetEdge edge) { + return capacityFunction.applyAsInt(edge); + } + + @Override + public Graph getGraph() { + return graph; + } + + @Desugar + protected record TestCase(int supply, int consumption) {} +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java new file mode 100644 index 00000000000..d9949e7707b --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java @@ -0,0 +1,63 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; + +import gregtech.api.util.function.ToBooleanFunction; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; + +import java.util.function.ObjIntConsumer; +import java.util.function.ToIntFunction; + +public class FDTraverse extends AbstractMinCostTraverse { + + protected final Graph graph; + protected final ToIntFunction capacityFunction; + protected final ToIntFunction supplyFunction; + protected final ToBooleanFunction lossyNodes; + + public static void flood(@NotNull IGraphNet net, + @NotNull ObjIntConsumer flowReporterNode, + @NotNull ObjIntConsumer flowReporterEdge, + @NotNull ToIntFunction capacityFunction, + @NotNull ToIntFunction supplyFunction, + @Nullable ToBooleanFunction lossyNodes) { + if (!net.getGraph().isDirected()) { + throw new IllegalArgumentException("Cannot perform flood traverse logic on undirected graph!"); + } + EvaluationResult result = new FDTraverse(net.getGraph(), capacityFunction, supplyFunction, lossyNodes).evaluate(); + if (result.isEmpty()) return; + result.getFlowMap().forEach(flowReporterEdge::accept); + result.getSupplyMap().forEach(flowReporterNode::accept); + } + + protected FDTraverse(Graph graph, ToIntFunction capacityFunction, + ToIntFunction supplyFunction, @Nullable ToBooleanFunction lossyNodes) { + this.graph = graph; + this.capacityFunction = capacityFunction; + this.supplyFunction = supplyFunction; + this.lossyNodes = lossyNodes != null ? lossyNodes : n -> false; + } + + @Override + protected int getSupply(NetNode node) { + if (lossyNodes.applyAsBool(node)) return Short.MIN_VALUE; + else return supplyFunction.applyAsInt(node); + } + + @Override + protected int getCapacity(NetEdge edge) { + return capacityFunction.applyAsInt(edge); + } + + @Override + public Graph getGraph() { + return graph; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/FloodTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/FloodTraverse.java deleted file mode 100644 index 737e58bcd47..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverse/FloodTraverse.java +++ /dev/null @@ -1,17 +0,0 @@ -package gregtech.api.graphnet.traverse; - -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; - -import org.jgrapht.Graph; -import org.jgrapht.traverse.ClosestFirstIterator; - -public class FloodTraverse { - - protected static class Iterator extends ClosestFirstIterator { - - public Iterator(Graph g, GraphVertex startVertex) { - super(g, startVertex); - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java new file mode 100644 index 00000000000..bcbee5fe014 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java @@ -0,0 +1,71 @@ +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; + +import gregtech.api.util.function.ToBooleanFunction; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; +import org.jgrapht.alg.util.Pair; + +import java.util.function.ObjIntConsumer; +import java.util.function.Supplier; +import java.util.function.ToIntFunction; + +public class RRTraverse extends AbstractMinCostTraverse { + + protected final Graph graph; + protected final ToIntFunction capacityFunction; + protected final ToIntFunction supplyFunction; + protected final ToBooleanFunction lossyNodes; + + protected Pair nextPair; + + public static void roundRobin(@NotNull IGraphNet net, Supplier<@Nullable Pair> nextNodePairSupplier, + @NotNull ObjIntConsumer flowReporterNode, + @NotNull ObjIntConsumer flowReporterEdge, + @NotNull ToIntFunction capacityFunction, + @NotNull ToIntFunction supplyFunction, + @Nullable ToBooleanFunction lossyNodes) { + if (!net.getGraph().isDirected()) { + throw new IllegalArgumentException("Cannot perform RR traverse logic on undirected graph!"); + } + RRTraverse traverse = new RRTraverse(net.getGraph(), capacityFunction, supplyFunction, lossyNodes); + while ((traverse.nextPair = nextNodePairSupplier.get()) != null) { + EvaluationResult result = traverse.evaluate(); + if (result.isEmpty()) continue; + result.getFlowMap().forEach(flowReporterEdge::accept); + result.getSupplyMap().forEach(flowReporterNode::accept); + } + } + + protected RRTraverse(Graph graph, ToIntFunction capacityFunction, + ToIntFunction supplyFunction, @Nullable ToBooleanFunction lossyNodes) { + this.graph = graph; + this.capacityFunction = capacityFunction; + this.supplyFunction = supplyFunction; + this.lossyNodes = lossyNodes != null ? lossyNodes : n -> false; + } + + @Override + protected int getSupply(NetNode node) { + if (lossyNodes.applyAsBool(node)) return Short.MIN_VALUE; + if (nextPair == null || nextPair.hasElement(node)) return 0; + return supplyFunction.applyAsInt(node); + } + + @Override + protected int getCapacity(NetEdge edge) { + return capacityFunction.applyAsInt(edge); + } + + @Override + public Graph getGraph() { + return graph; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java index 6c7dc82e129..27c235544cd 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.traverse.iter; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java index 528d1ca2085..b20d1240fcd 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java @@ -1,19 +1,22 @@ package gregtech.api.graphnet.traverse.iter; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; import org.jgrapht.traverse.ClosestFirstIterator; import java.util.Set; public class NetClosestIterator implements NetIterator { - protected ClosestFirstIterator backer; + protected final ClosestFirstIterator backer; + + protected final EdgeDirection direction; /** * Creates a closest-first iterator that traverses a connected component, starting at the given node. @@ -25,15 +28,20 @@ public NetClosestIterator(@NotNull NetNode origin, EdgeDirection direction) { @Override protected Set selectOutgoingEdges(GraphVertex vertex) { - return direction.selectEdges(graph, vertex); + return selectEdges(graph, vertex); } }; + this.direction = direction; } public ClosestFirstIterator getBacker() { return backer; } + protected Set selectEdges(Graph graph, GraphVertex vertex) { + return direction.selectEdges(graph, vertex); + } + @Override public boolean hasNext() { return backer.hasNext(); diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java index fe3df2bd2e6..fb3694ab073 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.traverse.iter; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java index b6f42681386..7f06c842a87 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.traverse.iter; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java index 929d986d443..b826b7bb297 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/IEqualizableTraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/IEqualizableTraverseData.java index a6f996ce88d..30deb02c815 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/IEqualizableTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/IEqualizableTraverseData.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java index 413944a8b8c..3351d1284ff 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.SimulatorKey; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinTraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinTraverseData.java index 16fbaf442bf..bb1efb38ae8 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinTraverseData.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java index f8edf77efcc..0f5b8160ea3 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.path.NetPath; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/ITraverseGuideProvider.java b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseGuideProvider.java index 82d59605c1d..3f97ca91144 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/ITraverseGuideProvider.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseGuideProvider.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java b/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java index 01cf9ec9e50..520fa25f779 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/TraverseGuide.java b/src/main/java/gregtech/api/graphnet/traverseold/TraverseGuide.java index 79ad651f4e8..ff8a26a1fb8 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/TraverseGuide.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/TraverseGuide.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java index 9deba1c0f3a..cd71e42f275 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.path.NetPath; @@ -51,8 +51,8 @@ D extends ITraverseData> long traverseFlood( P path = paths.next(); if (data.prepareForPathWalk(path, pathFlow)) continue; - List nodes = path.getOrderedNodes(); - List edges = path.getOrderedEdges(); + List nodes = path.getOrderedNodes().asList(); + List edges = path.getOrderedEdges().asList(); assert nodes.size() == edges.size() + 1; FlowConsumptionStack stack = new FlowConsumptionStack(data.traverseToNode(nodes.get(0), pathFlow)); diff --git a/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java b/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java deleted file mode 100644 index ccc6645b7c4..00000000000 --- a/src/main/java/gregtech/api/graphnet/worldnet/WorldPosNet.java +++ /dev/null @@ -1,47 +0,0 @@ -package gregtech.api.graphnet.worldnet; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.graph.INetGraph; - -import net.minecraft.util.math.BlockPos; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Function; - -public abstract class WorldPosNet extends WorldNet { - - public WorldPosNet(String name, @NotNull Function graphBuilder) { - super(name, graphBuilder); - } - - public WorldPosNet(String name, boolean directed) { - super(name, directed); - } - - @NotNull - public WorldPosNetNode getOrCreateNode(@NotNull BlockPos pos) { - WorldPosNetNode node = getNode(pos); - if (node != null) return node; - node = getNewNode(); - node.setPos(pos); - addNode(node); - return node; - } - - public @Nullable WorldPosNetNode getNode(@NotNull BlockPos equivalencyData) { - return (WorldPosNetNode) getNode((Object) equivalencyData); - } - - @Override - public Class getNodeClass() { - return WorldPosNetNode.class; - } - - @Override - public @NotNull WorldPosNetNode getNewNode() { - return new WorldPosNetNode(this); - } -} diff --git a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java index f453f88e42f..954227bdc11 100644 --- a/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java +++ b/src/main/java/gregtech/api/unification/material/properties/PipeNetProperties.java @@ -2,7 +2,7 @@ import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; @@ -55,12 +55,12 @@ public boolean generatesStructure(IPipeStructure structure) { } @Override - public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, - IPipeStructure structure) { - List list = new ObjectArrayList<>(); + public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, + IPipeStructure structure) { + List list = new ObjectArrayList<>(); for (IPipeNetMaterialProperty p : properties.values()) { if (p.supportsStructure(structure)) { - WorldPipeNetNode node = p.getOrCreateFromNet(world, pos, structure); + WorldPipeNode node = p.getOrCreateFromNet(world, pos, structure); if (node != null) list.add(node); } } @@ -68,11 +68,11 @@ public boolean generatesStructure(IPipeStructure structure) { } @Override - public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { - List list = new ObjectArrayList<>(); + public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { + List list = new ObjectArrayList<>(); for (IPipeNetMaterialProperty p : properties.values()) { if (p.supportsStructure(structure)) { - WorldPipeNetNode node = p.getFromNet(world, pos, structure); + WorldPipeNode node = p.getFromNet(world, pos, structure); if (node != null) list.add(node); } } @@ -105,10 +105,10 @@ public void verifyProperty(MaterialProperties properties) { public interface IPipeNetMaterialProperty extends IMaterialProperty { @Nullable - WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure); + WorldPipeNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure); @Nullable - WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure); + WorldPipeNode getFromNet(World world, BlockPos pos, IPipeStructure structure); void mutateData(NetLogicData data, IPipeStructure structure); diff --git a/src/main/java/gregtech/api/util/EntityDamageUtil.java b/src/main/java/gregtech/api/util/EntityDamageUtil.java index 9809db70598..b269e1f4587 100644 --- a/src/main/java/gregtech/api/util/EntityDamageUtil.java +++ b/src/main/java/gregtech/api/util/EntityDamageUtil.java @@ -29,13 +29,13 @@ public class EntityDamageUtil { public static void applyTemperatureDamage(@NotNull EntityLivingBase entity, int temperature, float multiplier, int maximum) { if (temperature > 320) { - int damage = (int) ((multiplier * (temperature - 300)) / 50.0F); + float damage = (multiplier * (temperature - 300)) / 50.0F; if (maximum > 0) { damage = Math.min(maximum, damage); } applyHeatDamage(entity, damage); } else if (temperature < 260) { - int damage = (int) ((multiplier * (273 - temperature)) / 25.0F); + float damage = (multiplier * (273 - temperature)) / 25.0F; if (maximum > 0) { damage = Math.min(maximum, damage); } @@ -47,7 +47,7 @@ public static void applyTemperatureDamage(@NotNull EntityLivingBase entity, int * @param entity the entity to damage * @param damage the damage to apply */ - public static void applyHeatDamage(@NotNull EntityLivingBase entity, int damage) { + public static void applyHeatDamage(@NotNull EntityLivingBase entity, float damage) { // do not attempt to damage by 0 if (damage <= 0) return; if (!entity.isEntityAlive()) return; @@ -67,7 +67,7 @@ public static void applyHeatDamage(@NotNull EntityLivingBase entity, int damage) * @param entity the entity to damage * @param damage the damage to apply */ - public static void applyFrostDamage(@NotNull EntityLivingBase entity, int damage) { + public static void applyFrostDamage(@NotNull EntityLivingBase entity, float damage) { // do not attempt to damage by 0 if (damage <= 0) return; if (!entity.isEntityAlive()) return; @@ -97,7 +97,7 @@ public static void applyFrostDamage(@NotNull EntityLivingBase entity, int damage * @param entity the entity to damage * @param damage the damage to apply */ - public static void applyChemicalDamage(@NotNull EntityLivingBase entity, int damage) { + public static void applyChemicalDamage(@NotNull EntityLivingBase entity, float damage) { // do not attempt to damage by 0 if (damage <= 0) return; if (!entity.isEntityAlive()) return; @@ -105,7 +105,7 @@ public static void applyChemicalDamage(@NotNull EntityLivingBase entity, int dam if (entity instanceof AbstractSkeleton) return; entity.attackEntityFrom(DamageSources.getChemicalDamage(), damage); - entity.addPotionEffect(new PotionEffect(MobEffects.POISON, damage * 100, 1)); + entity.addPotionEffect(new PotionEffect(MobEffects.POISON, (int) (damage * 100), 1)); if (entity instanceof EntityPlayerMP) AdvancementTriggers.CHEMICAL_DEATH.trigger((EntityPlayerMP) entity); } } diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index c23c5c1f5a6..dae73a4fc5b 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -26,6 +26,7 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.SoundEvents; @@ -36,13 +37,16 @@ import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.NonNullList; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundCategory; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraft.world.WorldServer; import net.minecraft.world.biome.Biome; import net.minecraftforge.common.BiomeDictionary; import net.minecraftforge.common.util.Constants; @@ -928,6 +932,13 @@ public static EntityPlayer getSP() { return Minecraft.getMinecraft().player; } + /** + * @param minValue the minimum possible succeeding value + * @param maxValue the maximum possible succeeding value + * @param test the predicate to query for success + * @param ascending determines the direction of search + * @return the smallest succeeding value if ascending, or the largest succeeding value if descending. + */ public static long binarySearch(long minValue, long maxValue, LongPredicate test, boolean ascending) { while (maxValue - minValue > 1) { long middle = (minValue + maxValue) / 2; @@ -1005,4 +1016,31 @@ public static void forceInitialization(@NotNull Class clazz) { throw new AssertionError(e); // Can't happen } } + + public static int moveACloserTo0ByB(int a, int b) { + return a > 0 ? a - b : a + b; + } + + public static void spawnParticles(World world, EnumFacing direction, EnumParticleTypes particleType, BlockPos pos, + int particleCount) { + spawnParticles(world, direction, particleType, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, particleCount); + } + + public static void spawnParticles(World world, EnumFacing direction, EnumParticleTypes particleType, Entity entity, + int particleCount) { + Vec3d vec = entity.getPositionEyes(1); + spawnParticles(world, direction, particleType, vec.x, vec.y, vec.y, particleCount); + } + + public static void spawnParticles(World world, EnumFacing direction, EnumParticleTypes particleType, double x, double y, double z, + int particleCount) { + if (world instanceof WorldServer server) { + server.spawnParticle(particleType, + x, y, z, particleCount, + direction.getXOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, + direction.getYOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, + direction.getZOffset() * 0.2 + GTValues.RNG.nextDouble() * 0.1, + 0.1); + } + } } diff --git a/src/main/java/gregtech/api/util/function/ToBooleanFunction.java b/src/main/java/gregtech/api/util/function/ToBooleanFunction.java new file mode 100644 index 00000000000..6c39546c0a8 --- /dev/null +++ b/src/main/java/gregtech/api/util/function/ToBooleanFunction.java @@ -0,0 +1,7 @@ +package gregtech.api.util.function; + +@FunctionalInterface +public interface ToBooleanFunction { + + boolean applyAsBool(T value); +} diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index b96292ee463..884442d54e8 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -9,7 +9,7 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; -import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.transfer.TransferControl; import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; @@ -27,11 +27,11 @@ import gregtech.common.covers.filter.ItemFilterContainer; import gregtech.common.covers.filter.MatchResult; import gregtech.common.covers.filter.MergabilityInfo; -import gregtech.common.pipelike.net.item.IItemTransferController; -import gregtech.common.pipelike.net.item.IItemTraverseGuideProvider; -import gregtech.common.pipelike.net.item.ItemEQTraverseData; -import gregtech.common.pipelike.net.item.ItemRRTraverseData; -import gregtech.common.pipelike.net.item.ItemTraverseData; +import gregtech.common.pipelike.net.itemold.IItemTransferController; +import gregtech.common.pipelike.net.itemold.IItemTraverseGuideProvider; +import gregtech.common.pipelike.net.itemold.ItemEQTraverseData; +import gregtech.common.pipelike.net.itemold.ItemRRTraverseData; +import gregtech.common.pipelike.net.itemold.ItemTraverseData; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; @@ -88,8 +88,7 @@ import java.util.Map; import java.util.function.IntUnaryOperator; -public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithItemFilter, - TransferControlProvider, IItemTransferController { +public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithItemFilter { public final int tier; public final int maxItemTransferRate; diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index 48064d8af5a..f019bc6d183 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -19,7 +19,7 @@ import gregtech.common.covers.filter.BaseFilter; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.FluidFilterContainer; -import gregtech.common.pipelike.net.fluid.IFluidTransferController; +import gregtech.common.pipelike.net.fluidold.IFluidTransferController; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 9e86937858a..ece1cf7264f 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -3,19 +3,19 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTUtility; import gregtech.common.covers.filter.FluidFilterContainer; import gregtech.common.covers.filter.SimpleFluidFilter; -import gregtech.common.pipelike.net.fluid.FluidEQTraverseData; -import gregtech.common.pipelike.net.fluid.FluidRRTraverseData; -import gregtech.common.pipelike.net.fluid.FluidTraverseData; -import gregtech.common.pipelike.net.fluid.IFluidTransferController; +import gregtech.common.pipelike.net.fluidold.FluidEQTraverseData; +import gregtech.common.pipelike.net.fluidold.FluidRRTraverseData; +import gregtech.common.pipelike.net.fluidold.FluidTraverseData; +import gregtech.common.pipelike.net.fluidold.IFluidTransferController; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; @@ -291,7 +291,7 @@ public KeepFluidTraverseData(IGraphNet net, FluidTestObject testObject, Simulato } @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { + public long finalizeAtDestination(@NotNull WorldPipeNode destination, long flowReachingDestination) { long availableFlow = flowReachingDestination; for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && @@ -324,7 +324,7 @@ public KeepFluidEQTraverseData(IGraphNet net, FluidTestObject testObject, Simula } @Override - protected void compute(@NotNull WorldPipeNetNode destination) { + protected void compute(@NotNull WorldPipeNode destination) { this.destCount = 0; this.maxMinFlow = 0; for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { @@ -352,7 +352,7 @@ protected void compute(@NotNull WorldPipeNetNode destination) { } @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode node, long flowReachingNode, + public long finalizeAtDestination(@NotNull WorldPipeNode node, long flowReachingNode, int expectedDestinations) { long availableFlow = flowReachingNode; long flowPerDestination = flowReachingNode / expectedDestinations; @@ -389,7 +389,7 @@ public KeepFluidRRTraverseData(IGraphNet net, FluidTestObject testObject, Simula @Override public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData data, - @NotNull WorldPipeNetNode destination, long flowReachingDestination) { + @NotNull WorldPipeNode destination, long flowReachingDestination) { long availableFlow = flowReachingDestination; EnumFacing pointerFacing = data.getPointerFacing(getSimulatorKey()); // anti insert-to-our-source logic diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index 98b72129209..df671597ef7 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -19,7 +19,7 @@ import gregtech.common.covers.filter.BaseFilter; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.ItemFilterContainer; -import gregtech.common.pipelike.net.item.IItemTransferController; +import gregtech.common.pipelike.net.itemold.IItemTransferController; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index 4770e2ca3fb..96fe5a92aec 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -9,7 +9,7 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithFluidFilter; -import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.transfer.TransferControl; import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; @@ -25,11 +25,11 @@ import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; import gregtech.common.covers.filter.FluidFilterContainer; import gregtech.common.covers.filter.MatchResult; -import gregtech.common.pipelike.net.fluid.FluidEQTraverseData; -import gregtech.common.pipelike.net.fluid.FluidRRTraverseData; -import gregtech.common.pipelike.net.fluid.FluidTraverseData; -import gregtech.common.pipelike.net.fluid.IFluidTransferController; -import gregtech.common.pipelike.net.fluid.IFluidTraverseGuideProvider; +import gregtech.common.pipelike.net.fluidold.FluidEQTraverseData; +import gregtech.common.pipelike.net.fluidold.FluidRRTraverseData; +import gregtech.common.pipelike.net.fluidold.FluidTraverseData; +import gregtech.common.pipelike.net.fluidold.IFluidTransferController; +import gregtech.common.pipelike.net.fluidold.IFluidTraverseGuideProvider; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 911ce54bf6d..87a7e45c2b4 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -3,9 +3,9 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.mui.GTGuiTextures; @@ -14,10 +14,10 @@ import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.ItemFilterContainer; -import gregtech.common.pipelike.net.item.IItemTransferController; -import gregtech.common.pipelike.net.item.ItemEQTraverseData; -import gregtech.common.pipelike.net.item.ItemRRTraverseData; -import gregtech.common.pipelike.net.item.ItemTraverseData; +import gregtech.common.pipelike.net.itemold.IItemTransferController; +import gregtech.common.pipelike.net.itemold.ItemEQTraverseData; +import gregtech.common.pipelike.net.itemold.ItemRRTraverseData; +import gregtech.common.pipelike.net.itemold.ItemTraverseData; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -306,7 +306,7 @@ public KeepItemTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorK } @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { + public long finalizeAtDestination(@NotNull WorldPipeNode destination, long flowReachingDestination) { long availableFlow = flowReachingDestination; for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && @@ -338,7 +338,7 @@ public KeepItemEQTraverseData(IGraphNet net, ItemTestObject testObject, Simulato } @Override - protected void compute(@NotNull WorldPipeNetNode destination) { + protected void compute(@NotNull WorldPipeNode destination) { this.destCount = 0; this.maxMinFlow = 0; for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { @@ -366,7 +366,7 @@ protected void compute(@NotNull WorldPipeNetNode destination) { } @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode node, long flowReachingNode, + public long finalizeAtDestination(@NotNull WorldPipeNode node, long flowReachingNode, int expectedDestinations) { long availableFlow = flowReachingNode; long flowPerDestination = flowReachingNode / expectedDestinations; @@ -403,7 +403,7 @@ public KeepItemRRTraverseData(IGraphNet net, ItemTestObject testObject, Simulato @Override public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData data, - @NotNull WorldPipeNetNode destination, + @NotNull WorldPipeNode destination, long flowReachingDestination) { long availableFlow = flowReachingDestination; EnumFacing pointerFacing = data.getPointerFacing(getSimulatorKey()); diff --git a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java index ba90653a726..dc61420a8c0 100644 --- a/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java +++ b/src/main/java/gregtech/common/pipelike/block/cable/CableBlock.java @@ -2,7 +2,7 @@ import gregtech.api.damagesources.DamageSources; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.block.PipeMaterialBlock; import gregtech.api.graphnet.pipenet.physical.tile.PipeMaterialTileEntity; @@ -98,7 +98,7 @@ public void onEntityCollision(@NotNull World worldIn, @NotNull BlockPos pos, @No if (worldIn.isRemote || getStructure().isInsulated() || !(entityIn instanceof EntityLivingBase living)) return; PipeTileEntity tile = getTileEntity(worldIn, pos); if (tile != null && tile.getFrameMaterial() == null && tile.getOffsetTimer() % 10 == 0) { - WorldPipeNetNode node = WorldEnergyNet.getWorldNet(worldIn).getNode(pos); + WorldPipeNode node = WorldEnergyNet.getWorldNet(worldIn).getNode(pos); if (node != null) { if (node.getData().getLogicEntryNullable(SuperconductorLogic.TYPE) != null) return; EnergyFlowLogic logic = node.getData().getLogicEntryNullable(EnergyFlowLogic.TYPE); diff --git a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java index 5157614c123..706e387bdc0 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/LaserNetHandler.java @@ -1,7 +1,7 @@ package gregtech.common.pipelike.handlers; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.common.pipelike.block.laser.LaserStructure; import gregtech.common.pipelike.net.laser.WorldLaserNet; @@ -23,8 +23,8 @@ public final class LaserNetHandler implements IPipeNetNodeHandler { public static final LaserNetHandler INSTANCE = new LaserNetHandler(); @Override - public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, - IPipeStructure structure) { + public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, + IPipeStructure structure) { if (structure instanceof LaserStructure) { return Collections.singletonList(WorldLaserNet.getWorldNet(world).getOrCreateNode(pos)); } @@ -32,9 +32,9 @@ public final class LaserNetHandler implements IPipeNetNodeHandler { } @Override - public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof LaserStructure) { - WorldPipeNetNode node = WorldLaserNet.getWorldNet(world).getNode(pos); + WorldPipeNode node = WorldLaserNet.getWorldNet(world).getNode(pos); if (node != null) return Collections.singletonList(node); } return Collections.emptyList(); @@ -44,7 +44,7 @@ public final class LaserNetHandler implements IPipeNetNodeHandler { public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof LaserStructure) { WorldLaserNet net = WorldLaserNet.getWorldNet(world); - WorldPipeNetNode node = net.getNode(pos); + WorldPipeNode node = net.getNode(pos); if (node != null) net.removeNode(node); } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java index 81e82472153..1924f0b6304 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java +++ b/src/main/java/gregtech/common/pipelike/handlers/OpticalNetHandler.java @@ -1,7 +1,7 @@ package gregtech.common.pipelike.handlers; import gregtech.api.graphnet.pipenet.IPipeNetNodeHandler; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.net.optical.WorldOpticalNet; @@ -23,8 +23,8 @@ public final class OpticalNetHandler implements IPipeNetNodeHandler { public static final OpticalNetHandler INSTANCE = new OpticalNetHandler(); @Override - public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, - IPipeStructure structure) { + public @NotNull Collection getOrCreateFromNets(World world, BlockPos pos, + IPipeStructure structure) { if (structure instanceof OpticalStructure) { return Collections.singletonList(WorldOpticalNet.getWorldNet(world).getOrCreateNode(pos)); } @@ -32,9 +32,9 @@ public final class OpticalNetHandler implements IPipeNetNodeHandler { } @Override - public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { + public @NotNull Collection getFromNets(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof OpticalStructure) { - WorldPipeNetNode node = WorldOpticalNet.getWorldNet(world).getNode(pos); + WorldPipeNode node = WorldOpticalNet.getWorldNet(world).getNode(pos); if (node != null) return Collections.singletonList(node); } return Collections.emptyList(); @@ -44,7 +44,7 @@ public final class OpticalNetHandler implements IPipeNetNodeHandler { public void removeFromNets(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof OpticalStructure) { WorldOpticalNet net = WorldOpticalNet.getWorldNet(world); - WorldPipeNetNode node = net.getNode(pos); + WorldPipeNode node = net.getNode(pos); if (node != null) net.removeNode(node); } } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index cf691520ffd..b4ebbabf3b3 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -3,10 +3,10 @@ import gregtech.api.GTValues; import gregtech.api.fluids.FluidBuilder; import gregtech.api.fluids.store.FluidStorageKeys; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; @@ -159,15 +159,15 @@ public static int computeMaterialMeltTemperature(@NotNull MaterialProperties pro @Override @Nullable - public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure) { + public WorldPipeNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof CableStructure) { - WorldPipeNetNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); + WorldPipeNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); mutateData(node.getData(), structure); return node; } else if (structure instanceof MaterialPipeStructure pipe) { long amperage = amperageLimit * pipe.material() / 2; if (amperage == 0) return null; // skip pipes that are too small - WorldPipeNetNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); + WorldPipeNode node = WorldEnergyNet.getWorldNet(world).getOrCreateNode(pos); mutateData(node.getData(), pipe); return node; } @@ -235,7 +235,7 @@ private long getAmperage(IPipeStructure structure) { @Override @Nullable - public WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { + public WorldPipeNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof CableStructure || structure instanceof MaterialPipeStructure) return WorldEnergyNet.getWorldNet(world).getNode(pos); else return null; diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index c5a5669a4ad..6b5207e5dd7 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -4,12 +4,12 @@ import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; @@ -167,9 +167,9 @@ public void verifyProperty(MaterialProperties properties) { @Override @Nullable - public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure) { + public WorldPipeNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof MaterialPipeStructure) { - WorldPipeNetNode node = WorldFluidNet.getWorldNet(world).getOrCreateNode(pos); + WorldPipeNode node = WorldFluidNet.getWorldNet(world).getOrCreateNode(pos); mutateData(node.getData(), structure); return node; } @@ -210,7 +210,7 @@ private double getFlowPriority(IPipeStructure structure) { } @Override - public @Nullable WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { + public @Nullable WorldPipeNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof MaterialPipeStructure) return WorldFluidNet.getWorldNet(world).getNode(pos); else return null; diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index e5256156c94..42cbb7e076c 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -1,11 +1,11 @@ package gregtech.common.pipelike.handlers.properties; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.unification.material.properties.MaterialProperties; @@ -71,9 +71,9 @@ public void verifyProperty(MaterialProperties properties) { @Override @Nullable - public WorldPipeNetNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure) { + public WorldPipeNode getOrCreateFromNet(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof MaterialPipeStructure) { - WorldPipeNetNode node = WorldItemNet.getWorldNet(world).getOrCreateNode(pos); + WorldPipeNode node = WorldItemNet.getWorldNet(world).getOrCreateNode(pos); mutateData(node.getData(), structure); return node; } @@ -99,7 +99,7 @@ private double getFlowPriority(IPipeStructure structure) { } @Override - public @Nullable WorldPipeNetNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { + public @Nullable WorldPipeNode getFromNet(World world, BlockPos pos, IPipeStructure structure) { if (structure instanceof MaterialPipeStructure) return WorldItemNet.getWorldNet(world).getNode(pos); else return null; diff --git a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java index 03feba30351..d2a62a860a1 100644 --- a/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java +++ b/src/main/java/gregtech/common/pipelike/net/SlowActiveWalker.java @@ -1,7 +1,8 @@ package gregtech.common.pipelike.net; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.tile.PipeActivableTileEntity; import gregtech.api.util.TaskScheduler; import gregtech.api.util.function.Task; @@ -91,22 +92,25 @@ public boolean run() { return true; } - protected @Nullable WorldPipeNetNode getSafe(int index) { + protected @Nullable WorldPipeNode getSafe(int index) { if (index >= path.getOrderedNodes().size()) return null; else if (index < 0) return null; - else return getNodes().asList().get(index); + else { + NetNode n = getNodes().asList().get(index); + return n instanceof WorldPipeNode p ? p : null; + } } - protected ImmutableCollection getNodes() { + protected ImmutableCollection getNodes() { return path.getOrderedNodes(); } - protected void step(@Nullable WorldPipeNetNode previous, @Nullable WorldPipeNetNode next) { + protected void step(@Nullable WorldPipeNode previous, @Nullable WorldPipeNode next) { if (previous != null) activate(previous, false); if (next != null) activate(next, true); } - protected void activate(@NotNull WorldPipeNetNode node, boolean active) { + protected void activate(@NotNull WorldPipeNode node, boolean active) { if (node.getTileEntity() instanceof PipeActivableTileEntity activable) { activable.setActive(active); } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 5ac6bef2d6a..e0700d8b830 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -2,12 +2,13 @@ import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IEnergyContainer; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.group.PathCacheGroupData; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.util.GTLog; @@ -23,13 +24,15 @@ public class EnergyCapabilityObject implements IPipeCapabilityObject, IEnergyContainer { + public static final int ACTIVE_KEY = 122; + private @Nullable PipeTileEntity tile; - private final @NotNull WorldPipeNetNode node; + private final @NotNull WorldPipeNode node; private boolean transferring = false; - public EnergyCapabilityObject(@NotNull WorldPipeNetNode node) { + public EnergyCapabilityObject(@NotNull WorldPipeNode node) { this.node = node; } @@ -48,8 +51,8 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage this.transferring = true; PathCacheGroupData.SecondaryCache cache = data.getOrCreate(node); - List paths = new ObjectArrayList<>(group.getActiveNodes().size()); - for (NetNode dest : group.getActiveNodes()) { + List paths = new ObjectArrayList<>(group.getNodesUnderKey(ACTIVE_KEY).size()); + for (NetNode dest : group.getNodesUnderKey(ACTIVE_KEY)) { EnergyPath path = (EnergyPath) cache.getOrCompute(dest); if (path == null) continue; // construct the path list in order of ascending weight @@ -108,17 +111,12 @@ public long getInputVoltage() { } @Override - public void setTile(@Nullable PipeTileEntity tile) { + public void init(@NotNull PipeTileEntity tile, @NotNull PipeCapabilityWrapper wrapper) { this.tile = tile; } @Override - public Capability[] getCapabilities() { - return WorldEnergyNet.CAPABILITIES; - } - - @Override - public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { + public T getCapability(Capability capability, @Nullable EnumFacing facing) { if (capability == GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER) { return GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER.cast(this); } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java index f696b0a03f5..aa83d9ed38c 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java @@ -1,6 +1,6 @@ package gregtech.common.pipelike.net.energy; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.group.PathCacheGroupData; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.path.PathBuilder; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java index 800404d5378..cfefae11d9a 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java @@ -1,8 +1,6 @@ package gregtech.common.pipelike.net.energy; -import com.github.bsideup.jabel.Desugar; - -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.logic.NetLogicData; @@ -26,7 +24,6 @@ import java.util.Collections; import java.util.List; -import java.util.Objects; import java.util.Set; public class StandardEnergyPath extends StandardNetPath implements EnergyPath { diff --git a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java index cd52ee29f51..0085ba53f8c 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java @@ -1,13 +1,16 @@ package gregtech.common.pipelike.net.energy; import gregtech.api.capability.GregtechCapabilities; -import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.pipenet.WorldPipeNet; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.traverse.iter.NetClosestIterator; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; @@ -36,23 +39,10 @@ public WorldEnergyNet(String name) { } @Override - public boolean usesDynamicWeights(int algorithmID) { - return true; - } - - @Override - public Capability[] getTargetCapabilities() { - return CAPABILITIES; - } - - @Override - public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return new IPipeCapabilityObject[] { new EnergyCapabilityObject(node) }; - } - - @Override - public @NotNull NetFlowEdge getNewEdge() { - return new NetFlowEdge(1); + public PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEntity owner, @NotNull WorldPipeNode node) { + Object2ObjectOpenHashMap, IPipeCapabilityObject> map = new Object2ObjectOpenHashMap<>(); + map.put(GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, new EnergyCapabilityObject(node)); + return new PipeCapabilityWrapper(owner, node, map, 0, EnergyCapabilityObject.ACTIVE_KEY); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java b/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java deleted file mode 100644 index 02913eb2aad..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/fluid/ContainmentFailure.java +++ /dev/null @@ -1,152 +0,0 @@ -package gregtech.common.pipelike.net.fluid; - -import gregtech.api.GTValues; -import gregtech.api.fluids.FluidState; -import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.fluids.attribute.FluidAttributes; -import gregtech.api.graphnet.pipenet.NodeLossResult; -import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; -import gregtech.api.graphnet.traverseold.util.MultLossOperator; -import gregtech.api.util.EntityDamageUtil; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.fluids.FluidStack; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.jetbrains.annotations.NotNull; - -import java.util.EnumMap; -import java.util.Map; - -@FunctionalInterface -public interface ContainmentFailure { - - ContainmentFailure FALLBACK = stack -> NodeLossResult.IDENTITY; - - EnumMap STATE_FAILURES = new EnumMap<>(FluidState.class); - - Map ATTRIBUTE_FAILURES = new Object2ObjectOpenHashMap<>(); - - static void registerFailure(FluidState state, ContainmentFailure failure) { - STATE_FAILURES.put(state, failure); - } - - static void registerFailure(FluidAttribute attribute, ContainmentFailure failure) { - ATTRIBUTE_FAILURES.put(attribute.getResourceLocation(), failure); - } - - static @NotNull ContainmentFailure getFailure(FluidState state) { - return STATE_FAILURES.getOrDefault(state, FALLBACK); - } - - static @NotNull ContainmentFailure getFailure(FluidAttribute attribute) { - return ATTRIBUTE_FAILURES.getOrDefault(attribute.getResourceLocation(), FALLBACK); - } - - static @NotNull ContainmentFailure getFailure(ResourceLocation attribute) { - return ATTRIBUTE_FAILURES.getOrDefault(attribute, FALLBACK); - } - - @NotNull - NodeLossResult computeLossResult(FluidStack fluid); - - static void init() { - registerFailure(FluidState.GAS, stack -> { - if (GTValues.RNG.nextInt(8) == 0) { - return new NodeLossResult(node -> { - IWorldPipeNetTile tile = node.getTileEntityNoLoading(); - if (tile != null) { - tile.playLossSound(); - tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.SMOKE_NORMAL, 7 + GTValues.RNG.nextInt(2)); - tile.dealAreaDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, - stack.getFluid().getTemperature(stack), 1, 10)); - } - }, MultLossOperator.TENTHS[9]); - } else { - return new NodeLossResult(node -> { - node.getNet().getWorld().setBlockToAir(node.getEquivalencyData()); - IWorldPipeNetTile tile = node.getTileEntityNoLoading(); - if (tile != null) { - tile.playLossSound(); - tile.visuallyExplode(); - tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, 9 + GTValues.RNG.nextInt(3)); - tile.dealAreaDamage(2, entity -> EntityDamageUtil.applyTemperatureDamage(entity, - stack.getFluid().getTemperature(stack), 1.5f, 15)); - } - }, MultLossOperator.TENTHS[2]); - } - }); - registerFailure(FluidState.LIQUID, stack -> new NodeLossResult(node -> { - IWorldPipeNetTile tile = node.getTileEntityNoLoading(); - if (tile != null) { - tile.playLossSound(); - for (EnumFacing facing : EnumFacing.HORIZONTALS) { - int particles = GTValues.RNG.nextInt(5); - if (particles != 0) { - tile.spawnParticles(facing, EnumParticleTypes.DRIP_WATER, particles); - } - } - tile.dealAreaDamage(1, entity -> EntityDamageUtil.applyTemperatureDamage(entity, - stack.getFluid().getTemperature(stack), 2f, 20)); - } - }, MultLossOperator.TENTHS[6])); - registerFailure(FluidState.PLASMA, stack -> { - if (GTValues.RNG.nextInt(4) == 0) { - return new NodeLossResult(node -> { - IWorldPipeNetTile tile = node.getTileEntityNoLoading(); - if (tile != null) { - tile.playLossSound(); - tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.SMOKE_NORMAL, 1 + GTValues.RNG.nextInt(2)); - tile.dealAreaDamage(3, entity -> EntityDamageUtil.applyTemperatureDamage(entity, - stack.getFluid().getTemperature(stack), 1, 25)); - } - }, MultLossOperator.TENTHS[8]); - } else { - return new NodeLossResult(node -> { - node.getNet().getWorld().setBlockToAir(node.getEquivalencyData()); - IWorldPipeNetTile tile = node.getTileEntityNoLoading(); - if (tile != null) { - tile.playLossSound(); - tile.visuallyExplode(); - tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, 3 + GTValues.RNG.nextInt(3)); - tile.dealAreaDamage(3, entity -> EntityDamageUtil.applyTemperatureDamage(entity, - stack.getFluid().getTemperature(stack), 1.5f, 30)); - } - }, MultLossOperator.TENTHS[2]); - } - }); - registerFailure(FluidAttributes.ACID, stack -> { - if (GTValues.RNG.nextInt(10) == 0) { - return new NodeLossResult(node -> { - IWorldPipeNetTile tile = node.getTileEntityNoLoading(); - if (tile != null) { - tile.playLossSound(); - boolean gaseous = stack.getFluid().isGaseous(stack); - tile.spawnParticles(gaseous ? EnumFacing.UP : EnumFacing.DOWN, EnumParticleTypes.CRIT_MAGIC, - 3 + GTValues.RNG.nextInt(2)); - tile.dealAreaDamage(gaseous ? 2 : 1, - entity -> EntityDamageUtil.applyChemicalDamage(entity, gaseous ? 2 : 3)); - } - }, MultLossOperator.TENTHS[9]); - } else { - return new NodeLossResult(node -> { - node.getNet().getWorld().setBlockToAir(node.getEquivalencyData()); - IWorldPipeNetTile tile = node.getTileEntityNoLoading(); - if (tile != null) { - tile.playLossSound(); - boolean gaseous = stack.getFluid().isGaseous(stack); - for (EnumFacing facing : EnumFacing.HORIZONTALS) { - tile.spawnParticles(facing, EnumParticleTypes.CRIT_MAGIC, 3 + GTValues.RNG.nextInt(2)); - } - tile.spawnParticles(gaseous ? EnumFacing.UP : EnumFacing.DOWN, EnumParticleTypes.CRIT_MAGIC, - 6 + GTValues.RNG.nextInt(4)); - tile.dealAreaDamage(gaseous ? 2 : 1, - entity -> EntityDamageUtil.applyChemicalDamage(entity, gaseous ? 3 : 4)); - } - }, MultLossOperator.EIGHTHS[6]); - } - }); - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index e09bd4a1b84..81007232a4a 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -1,18 +1,23 @@ package gregtech.common.pipelike.net.fluid; +import gregtech.api.fluids.FluidState; +import gregtech.api.fluids.attribute.AttributedFluid; +import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.logic.ChannelCountLogic; -import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.pipenet.WorldPipeNet; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverseold.ITraverseData; -import gregtech.api.graphnet.traverseold.TraverseDataProvider; -import gregtech.api.graphnet.traverseold.TraverseGuide; -import gregtech.api.graphnet.traverseold.TraverseHelpers; +import gregtech.api.graphnet.traverse.FDTraverse; + +import gregtech.api.util.GTUtility; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; @@ -27,126 +32,172 @@ import java.util.Arrays; import java.util.EnumMap; -import java.util.Iterator; -import java.util.function.LongConsumer; +import java.util.concurrent.atomic.AtomicInteger; -public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler, IFluidTankProperties, - IFluidTraverseGuideProvider { +public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler, IFluidTankProperties { - private final WorldPipeNet net; - private @Nullable PipeTileEntity tile; + private PipeTileEntity tile; + private NodeManagingPCW capabilityWrapper; private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); - private final WorldPipeNetNode node; + private final WorldPipeNode node; private final IFluidTankProperties[] properties; private boolean transferring = false; - public FluidCapabilityObject(@NotNull N net, - WorldPipeNetNode node) { - this.net = net; + public FluidCapabilityObject(WorldPipeNode node) { this.node = node; properties = new IFluidTankProperties[node.getData().getLogicEntryDefaultable(ChannelCountLogic.TYPE) .getValue()]; Arrays.fill(properties, this); for (EnumFacing facing : EnumFacing.VALUES) { - AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); - edge.setData(NetLogicData.union(node.getData(), (NetLogicData) null)); - wrappers.put(facing, new Wrapper(facing, edge)); + wrappers.put(facing, new Wrapper(facing)); } } - private FlowWorldPipeNetPath.Provider getProvider() { - return (FlowWorldPipeNetPath.Provider) net; + @Override + public void init(@NotNull PipeTileEntity tile, @NotNull PipeCapabilityWrapper wrapper) { + this.tile = tile; + if (!(wrapper instanceof NodeManagingPCW p)) + throw new IllegalArgumentException("FluidCapabilityObjects must be initialized to NodeManagingPCWs!"); + this.capabilityWrapper = p; } private boolean inputDisallowed(EnumFacing side) { if (side == null) return false; - if (tile == null) return true; else return tile.isBlocked(side); } - private Iterator getPaths(@NotNull ITraverseData data) { - assert tile != null; - return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), - data.getQueryTick()); - } - - @Override - public void setTile(@Nullable PipeTileEntity tile) { - this.tile = tile; - } - @Override - public Capability[] getCapabilities() { - return WorldFluidNet.CAPABILITIES; - } - - @Override - public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { - if (facing == null) return null; // hard override to prevent TOP from displaying a tank. + public T getCapability(Capability capability, @Nullable EnumFacing facing) { + // can't expose the sided capability if there is no node to interact with + if (facing != null && capabilityWrapper.getNodeForFacing(facing) == null) return null; if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { - // noinspection ConstantValue return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(facing == null ? this : wrappers.get(facing)); } return null; } - @Override - public int fill(FluidStack resource, boolean doFill) { - return fill(resource, doFill, null); + protected @Nullable NetNode getRelevantNode(EnumFacing facing) { + return facing == null ? node : capabilityWrapper.getNodeForFacing(facing); } - public int fill(FluidStack resource, boolean doFill, EnumFacing side) { - if (this.transferring) return 0; + protected int fill(FluidStack resource, boolean doFill, EnumFacing side) { + if (this.transferring || inputDisallowed(side)) return 0; + NetNode node = getRelevantNode(side); + if (node == null) return 0; this.transferring = true; - var guide = getGuide(FluidTraverseData::new, new FluidTestObject(resource), resource.amount, !doFill, side); - if (guide == null) return 0; - int accepted = (int) TraverseHelpers.traverseFlood(guide.getData(), guide.getPaths(), guide.getFlow()); - guide.reportConsumedFlow(accepted); + int flow = resource.amount; + SimulatorKey key = doFill ? null : SimulatorKey.getNewSimulatorInstance(); + FluidTestObject testObject = new FluidTestObject(resource); + AtomicInteger report = new AtomicInteger(); + FDTraverse.flood(node.getNet(), + (n, f) -> { + if (n == node) report.addAndGet(f); + else if (doFill) reportFlow(n, f, testObject); + }, + (e, f) -> reportFlow(e, f, testObject, key, true), + e -> e instanceof AbstractNetFlowEdge n && e.test(testObject) ? + GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, node.getNet(), getQueryTick(), key)) : 0, + n -> n == node ? flow : getSupply(n, testObject, false), + n -> n.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE).handles(testObject)); this.transferring = false; - return accepted; + return report.get(); } - @Override - public @Nullable < - D extends ITraverseData> TraverseGuide getGuide( - TraverseDataProvider provider, - FluidTestObject testObject, - long flow, - boolean simulate) { - return getGuide(provider, testObject, flow, simulate, null); + protected FluidStack drain(int maxDrain, boolean doDrain, EnumFacing side) { + // TODO expose connected fluidnet through capability & allow untyped draining + return null; + } + + protected FluidStack drain(FluidStack resource, boolean doDrain, EnumFacing side) { + if (this.transferring) return null; + NetNode node = getRelevantNode(side); + if (node == null) return null; + this.transferring = true; + + int flow = resource.amount; + SimulatorKey key = doDrain ? null : SimulatorKey.getNewSimulatorInstance(); + FluidTestObject testObject = new FluidTestObject(resource); + AtomicInteger report = new AtomicInteger(); + FDTraverse.flood(node.getNet(), + (n, f) -> { + if (n == node) report.addAndGet(f); + else if (doDrain) reportFlow(n, f, testObject); + }, + (e, f) -> reportFlow(e, f, testObject, key, false), + e -> e instanceof AbstractNetFlowEdge n ? + GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, node.getNet(), getQueryTick(), key)) : 0, + n -> n == node ? flow : getSupply(n, testObject, true), + n -> n.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE).handles(testObject)); + + this.transferring = false; + return testObject.recombine(report.get()); + } + + protected void reportFlow(NetEdge edge, int flow, FluidTestObject testObject, SimulatorKey key, boolean sourceBias) { + if (edge instanceof AbstractNetFlowEdge n) + n.consumeFlowLimit(testObject, node.getNet(), flow, getQueryTick(), key); + if (key == null) { + NetNode node = sourceBias ? edge.getSource() : edge.getTarget(); + if (node == null) return; + FluidFlowLogic logic = node.getData().getLogicEntryNullable(FluidFlowLogic.TYPE); + if (logic == null) { + logic = FluidFlowLogic.TYPE.getNew(); + node.getData().setLogicEntry(logic); + } + logic.recordFlow(getQueryTick(), testObject.recombine(flow)); + } } - public @Nullable < - D extends ITraverseData> TraverseGuide getGuide( - TraverseDataProvider provider, - FluidTestObject testObject, - long flow, - boolean simulate, - EnumFacing side) { - if (tile == null || inputDisallowed(side)) return null; - SimulatorKey simulator = simulate ? SimulatorKey.getNewSimulatorInstance() : null; - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - D data = provider.of(net, testObject, simulator, tick, tile.getPos(), side); - - LongConsumer flowReport = null; - Wrapper wrapper = this.wrappers.get(side); - if (wrapper != null) { - AbstractNetFlowEdge internalBuffer = wrapper.getBuffer(); - if (internalBuffer != null) { - long limit = internalBuffer.getFlowLimit(testObject, net, tick, simulator); - if (limit <= 0) { - this.transferring = false; - return null; + + protected void reportFlow(NetNode node, int flow, FluidTestObject testObject) { + if (flow == 0) return; + FluidContainmentLogic logic = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE); + if (!logic.handles(testObject)) { + FluidStack stack = testObject.recombine(flow); + // failing attributes take priority over state + for (FluidAttribute attribute : FluidAttribute.inferAttributes(stack)) { + if (!logic.contains(attribute)) { + attribute.handleFailure(tile.getWorld(), tile.getPos(), stack); + return; + } + } + FluidState state = FluidState.inferState(stack); + if (!logic.contains(state)) state.handleFailure(tile.getWorld(), tile.getPos(), stack); + } else if (node instanceof NodeExposingCapabilities exposer) { + IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, exposer.exposedFacing()); + if (handler != null) { + // positive flow is supply, aka we pulled flow from this node + if (flow > 0) { + handler.drain(testObject.recombine(flow), true); + } else { + handler.fill(testObject.recombine(flow), true); } - flow = Math.min(limit, flow); - flowReport = l -> data.consumeFlowLimit(internalBuffer, node, l); } } - return new TraverseGuide<>(data, () -> getPaths(data), flow, flowReport); + } + + protected int getSupply(NetNode node, FluidTestObject testObject, boolean supply) { + if (node instanceof NodeExposingCapabilities exposer) { + IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, exposer.exposedFacing()); + if (handler != null) { + if (supply) { + FluidStack s = handler.drain(testObject.recombine(Integer.MAX_VALUE), false); + return s == null ? 0 : s.amount; + } else { + return -handler.fill(testObject.recombine(Integer.MAX_VALUE), false); + } + } + } + return 0; + } + + @Override + public int fill(FluidStack resource, boolean doFill) { + return fill(resource, doFill, null); } @Override @@ -156,12 +207,12 @@ public IFluidTankProperties[] getTankProperties() { @Override public FluidStack drain(int maxDrain, boolean doDrain) { - return null; + return drain(maxDrain, doDrain, null); } @Override public FluidStack drain(FluidStack resource, boolean doDrain) { - return null; + return drain(resource, doDrain, null); } @Override @@ -181,7 +232,7 @@ public boolean canFill() { @Override public boolean canDrain() { - return false; + return true; } @Override @@ -191,36 +242,20 @@ public boolean canFillFluidType(FluidStack fluidStack) { @Override public boolean canDrainFluidType(FluidStack fluidStack) { - return false; + return true; } - protected class Wrapper implements IFluidHandler, IFluidTankProperties, IFluidTraverseGuideProvider { + protected class Wrapper implements IFluidHandler, IFluidTankProperties { private final EnumFacing facing; - private final AbstractNetFlowEdge buffer; private final IFluidTankProperties[] properties; - public Wrapper(EnumFacing facing, AbstractNetFlowEdge buffer) { + public Wrapper(EnumFacing facing) { this.facing = facing; - this.buffer = buffer; properties = new IFluidTankProperties[FluidCapabilityObject.this.properties.length]; Arrays.fill(properties, this); } - @Override - public @Nullable < - D extends ITraverseData> TraverseGuide getGuide( - TraverseDataProvider provider, - FluidTestObject testObject, - long flow, - boolean simulate) { - return FluidCapabilityObject.this.getGuide(provider, testObject, flow, simulate, facing); - } - - public AbstractNetFlowEdge getBuffer() { - return buffer; - } - @Override public IFluidTankProperties[] getTankProperties() { return properties; @@ -233,12 +268,12 @@ public int fill(FluidStack resource, boolean doFill) { @Override public FluidStack drain(FluidStack resource, boolean doDrain) { - return null; + return FluidCapabilityObject.this.drain(resource, doDrain, facing); } @Override public FluidStack drain(int maxDrain, boolean doDrain) { - return null; + return FluidCapabilityObject.this.drain(maxDrain, doDrain, facing); } @Override @@ -248,7 +283,7 @@ public FluidStack getContents() { @Override public int getCapacity() { - return (int) Math.min(Integer.MAX_VALUE, buffer.getThroughput()); + return Integer.MAX_VALUE; } @Override @@ -258,7 +293,7 @@ public boolean canFill() { @Override public boolean canDrain() { - return false; + return true; } @Override @@ -268,7 +303,7 @@ public boolean canFillFluidType(FluidStack fluidStack) { @Override public boolean canDrainFluidType(FluidStack fluidStack) { - return false; + return true; } } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java index 87fcae99e84..e94a4241d97 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java @@ -5,6 +5,7 @@ import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.NetLogicType; +import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.util.GTUtility; import net.minecraft.nbt.NBTTagCompound; @@ -14,6 +15,9 @@ import net.minecraft.util.ResourceLocation; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; + +import net.minecraftforge.fluids.FluidStack; + import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -69,6 +73,18 @@ public boolean contains(@NotNull FluidAttribute attribute) { return this.containableAttributes.contains(attribute.getResourceLocation()); } + public boolean handles(FluidTestObject testObject) { + return handles(testObject.recombine()); + } + + public boolean handles(FluidStack stack) { + if (!contains(FluidState.inferState(stack))) return false; + for (FluidAttribute attribute : FluidAttribute.inferAttributes(stack)) { + if (!contains(attribute)) return false; + } + return true; + } + public void setMaximumTemperature(int maximumTemperature) { this.maximumTemperature = maximumTemperature; } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java deleted file mode 100644 index 367a97f1dd8..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidEQTraverseData.java +++ /dev/null @@ -1,86 +0,0 @@ -package gregtech.common.pipelike.net.fluid; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverseold.IEqualizableTraverseData; -import gregtech.api.util.GTUtility; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; - -import org.jetbrains.annotations.NotNull; - -public class FluidEQTraverseData extends FluidTraverseData - implements IEqualizableTraverseData { - - protected int destCount; - protected int maxMinFlow; - - public FluidEQTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing) { - super(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - protected void compute(@NotNull WorldPipeNetNode destination) { - this.destCount = 0; - this.maxMinFlow = 0; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IFluidHandler container = capability.getValue() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); - if (container != null) { - if (destCount == 0) maxMinFlow = Integer.MAX_VALUE; - destCount += 1; - maxMinFlow = Math.min(maxMinFlow, - IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - Integer.MAX_VALUE, - container, false)); - } - } - } - - @Override - public int getDestinationsAtNode(@NotNull WorldPipeNetNode node) { - return destCount; - } - - @Override - public boolean shouldSkipPath(@NotNull FlowWorldPipeNetPath path) { - compute(path.getTargetNode()); - return maxMinFlow == 0; - } - - @Override - public long getMaxFlowToLeastDestination(@NotNull WorldPipeNetNode destination) { - return maxMinFlow; - } - - @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode node, long flowReachingNode, int expectedDestinations) { - long availableFlow = flowReachingNode; - long flowPerDestination = flowReachingNode / expectedDestinations; - if (flowPerDestination == 0) return 0; - for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { - if (GTUtility.arePosEqual(node.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IFluidHandler container = capability.getValue() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); - if (container != null) { - availableFlow -= IFluidTransferController.CONTROL.get(node.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(Integer.MAX_VALUE, flowPerDestination), container, !simulating()); - } - } - return flowReachingNode - availableFlow; - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java deleted file mode 100644 index 4c725074adc..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidRRTraverseData.java +++ /dev/null @@ -1,62 +0,0 @@ -package gregtech.common.pipelike.net.fluid; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; -import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverseold.IRoundRobinTraverseData; -import gregtech.api.util.GTUtility; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; - -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import org.jetbrains.annotations.NotNull; - -public class FluidRRTraverseData extends FluidTraverseData implements - IRoundRobinTraverseData, WorldPipeNetNode, FlowWorldPipeNetPath> { - - private final Object2ObjectLinkedOpenHashMap> cache; - - public FluidRRTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing, - @NotNull Object2ObjectLinkedOpenHashMap> cache) { - super(net, testObject, simulator, queryTick, sourcePos, inputFacing); - this.cache = cache; - } - - @Override - public @NotNull Object2ObjectLinkedOpenHashMap> getTraversalCache() { - return cache; - } - - @Override - public boolean shouldSkipPath(@NotNull FlowWorldPipeNetPath path) { - return false; - } - - @Override - public @NotNull SimpleTileRoundRobinData createRRData(@NotNull WorldPipeNetNode destination) { - return new SimpleTileRoundRobinData<>(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY); - } - - @Override - public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData data, - @NotNull WorldPipeNetNode destination, long flowReachingDestination) { - long availableFlow = flowReachingDestination; - EnumFacing pointerFacing = data.getPointerFacing(getSimulatorKey()); - // anti insert-to-our-source logic - if (!GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) || !(pointerFacing == inputFacing)) { - IFluidHandler container = data.getAtPointer(destination, getSimulatorKey()); - if (container != null) { - availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(pointerFacing)).insertToHandler(getTestObject(), - (int) Math.min(Integer.MAX_VALUE, availableFlow), container, !simulating()); - } - } - return flowReachingDestination - availableFlow; - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java deleted file mode 100644 index fbac96e256c..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidTraverseData.java +++ /dev/null @@ -1,190 +0,0 @@ -package gregtech.common.pipelike.net.fluid; - -import gregtech.api.GTValues; -import gregtech.api.fluids.FluidState; -import gregtech.api.fluids.attribute.AttributedFluid; -import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.NodeLossCache; -import gregtech.api.graphnet.pipenet.NodeLossResult; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; -import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; -import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverseold.AbstractTraverseData; -import gregtech.api.graphnet.traverseold.util.MultLossOperator; -import gregtech.api.graphnet.traverseold.util.ReversibleLossOperator; -import gregtech.api.util.EntityDamageUtil; -import gregtech.api.util.GTUtility; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumParticleTypes; -import net.minecraft.util.math.BlockPos; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; - -public class FluidTraverseData extends AbstractTraverseData { - - public static final float TEMPERATURE_EFFECT = 0.05f; - - static { - ContainmentFailure.init(); - } - - protected final BlockPos sourcePos; - protected final EnumFacing inputFacing; - - protected final FluidStack stack; - protected final FluidState state; - protected final int fluidTemp; - protected final boolean gaseous; - protected final @Nullable Collection attributes; - - public FluidTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing) { - super(net, testObject, simulator, queryTick); - this.sourcePos = sourcePos; - this.inputFacing = inputFacing; - this.stack = testObject.recombine(); - this.state = FluidState.inferState(stack); - this.fluidTemp = stack.getFluid().getTemperature(stack); - this.gaseous = stack.getFluid().isGaseous(stack); - if (stack.getFluid() instanceof AttributedFluid at) { - attributes = at.getAttributes(); - } else attributes = null; - } - - @Override - public FluidTestObject getTestObject() { - return (FluidTestObject) super.getTestObject(); - } - - @Override - public boolean prepareForPathWalk(@NotNull FlowWorldPipeNetPath path, long flow) { - return flow <= 0; - } - - @Override - public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, long flowReachingNode) { - NodeLossCache.Key key = NodeLossCache.key(node, this); - NodeLossResult result = NodeLossCache.getLossResult(key, simulating()); - if (result != null) { - return result.getLossFunction(); - } else { - FluidContainmentLogic containmentLogic = node.getData() - .getLogicEntryDefaultable(FluidContainmentLogic.TYPE); - - TemperatureLogic temperatureLogic = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); - if (temperatureLogic != null) { - result = temperatureLogic.getLossResult(getQueryTick()); - boolean overMax = fluidTemp > containmentLogic.getMaximumTemperature() && - !(state == FluidState.PLASMA && containmentLogic.contains(FluidState.PLASMA)); - if (overMax) { - result = NodeLossResult.combine(result, new NodeLossResult(GTValues.RNG.nextInt(4) == 0 ? pipe -> { - IWorldPipeNetTile tile = pipe.getTileEntityNoLoading(); - if (tile != null) { - tile.playLossSound(); - tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); - tile.dealAreaDamage(gaseous ? 2 : 1, - entity -> EntityDamageUtil.applyTemperatureDamage(entity, - fluidTemp, 2.0F, 10)); - tile.setNeighborsToFire(); - } - } : pipe -> { - IWorldPipeNetTile tile = pipe.getTileEntityNoLoading(); - if (tile != null) { - tile.playLossSound(); - tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); - tile.dealAreaDamage(gaseous ? 2 : 1, - entity -> EntityDamageUtil.applyTemperatureDamage(entity, - fluidTemp, 2.0F, 10)); - } - }, MultLossOperator.EIGHTHS[2])); - } else if (temperatureLogic.isUnderMinimum(fluidTemp)) { - result = NodeLossResult.combine(result, new NodeLossResult(pipe -> { - IWorldPipeNetTile tile = pipe.getTileEntityNoLoading(); - if (tile != null) { - tile.playLossSound(); - tile.spawnParticles(EnumFacing.UP, EnumParticleTypes.CLOUD, 3 + GTValues.RNG.nextInt(2)); - tile.dealAreaDamage(gaseous ? 2 : 1, - entity -> EntityDamageUtil.applyTemperatureDamage(entity, - fluidTemp, 2.0F, 10)); - } - }, MultLossOperator.EIGHTHS[2])); - } - } - - if (!containmentLogic.contains(state)) { - result = NodeLossResult.combine(result, ContainmentFailure.getFailure(state).computeLossResult(stack)); - } - - if (attributes != null) { - for (FluidAttribute attribute : attributes) { - if (!containmentLogic.contains(attribute)) { - result = NodeLossResult.combine(result, - ContainmentFailure.getFailure(attribute).computeLossResult(stack)); - } - } - } - - if (result == null) return ReversibleLossOperator.IDENTITY; - NodeLossCache.registerLossResult(key, result, simulating()); - return result.getLossFunction(); - } - } - - @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { - long availableFlow = flowReachingDestination; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IFluidHandler container = capability.getValue() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, capability.getKey().getOpposite()); - if (container != null) { - availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(Integer.MAX_VALUE, availableFlow), container, !simulating()); - } - } - return flowReachingDestination - availableFlow; - } - - @Override - public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, - long consumption) { - super.consumeFlowLimit(edge, targetNode, consumption); - if (consumption > 0 && !simulating()) { - recordFlow(targetNode, consumption); - TemperatureLogic temperatureLogic = targetNode.getData().getLogicEntryNullable(TemperatureLogic.TYPE); - if (temperatureLogic != null) { - FluidContainmentLogic containmentLogic = targetNode.getData() - .getLogicEntryDefaultable(FluidContainmentLogic.TYPE); - boolean overMax = fluidTemp > containmentLogic.getMaximumTemperature() && - !(state == FluidState.PLASMA && containmentLogic.contains(FluidState.PLASMA)); - temperatureLogic.moveTowardsTemperature(fluidTemp, - getQueryTick(), consumption * TEMPERATURE_EFFECT, !overMax); - } - } - } - - private void recordFlow(@NotNull NetNode node, long flow) { - FluidFlowLogic logic = node.getData().getLogicEntryNullable(FluidFlowLogic.TYPE); - if (logic == null) { - logic = FluidFlowLogic.TYPE.getNew(); - node.getData().setLogicEntry(logic); - } - logic.recordFlow(getQueryTick(), getTestObject().recombine(GTUtility.safeCastLongToInt(flow))); - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java deleted file mode 100644 index 33c83016602..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTransferController.java +++ /dev/null @@ -1,74 +0,0 @@ -package gregtech.common.pipelike.net.fluid; - -import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; -import gregtech.api.graphnet.predicate.test.FluidTestObject; - -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandler; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface IFluidTransferController { - - TransferControl CONTROL = new TransferControl<>("Fluid") { - - @Override - public @NotNull IFluidTransferController get(@Nullable Object potentialHolder) { - if (!(potentialHolder instanceof TransferControlProvider holder)) return DEFAULT; - IFluidTransferController found = holder.getControllerForControl(CONTROL); - return found == null ? DEFAULT : found; - } - - @Override - public @NotNull IFluidTransferController getNoPassage() { - return NO_PASSAGE; - } - }; - - IFluidTransferController DEFAULT = new IFluidTransferController() {}; - - IFluidTransferController NO_PASSAGE = new IFluidTransferController() { - - @Override - public int insertToHandler(@NotNull FluidTestObject testObject, int amount, - @NotNull IFluidHandler destHandler, boolean doFill) { - return 0; - } - - @Override - public @Nullable FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, - IFluidHandler sourceHandler, boolean doDrain) { - return null; - } - }; - - /** - * @return the amount filled. - */ - default int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, - boolean doFill) { - return destHandler.fill(testObject.recombine(amount), doFill); - } - - /** - * @return the fluidstack drained. - */ - @Nullable - default FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, IFluidHandler sourceHandler, - boolean doDrain) { - if (testObject == null) return sourceHandler.drain(amount, doDrain); - else { - FluidStack recombined = testObject.recombine(); - FluidStack drained = sourceHandler.drain(recombined, false); - if (testObject.test(drained)) { - if (doDrain) { - return sourceHandler.drain(recombined, true); - } else { - return drained; - } - } else return null; - } - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java b/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java deleted file mode 100644 index 1306396ef3b..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/fluid/IFluidTraverseGuideProvider.java +++ /dev/null @@ -1,22 +0,0 @@ -package gregtech.common.pipelike.net.fluid; - -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverseold.ITraverseData; -import gregtech.api.graphnet.traverseold.ITraverseGuideProvider; -import gregtech.api.graphnet.traverseold.TraverseDataProvider; -import gregtech.api.graphnet.traverseold.TraverseGuide; - -import org.jetbrains.annotations.Nullable; - -public interface IFluidTraverseGuideProvider extends - ITraverseGuideProvider { - - @Nullable - @Override - > TraverseGuide getGuide( - TraverseDataProvider provider, - FluidTestObject testObject, - long flow, - boolean simulate); -} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index ad096f74031..5c50bb2bb89 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -2,20 +2,24 @@ import gregtech.api.cover.Cover; import gregtech.api.cover.filter.CoverWithFluidFilter; -import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.GraphClassType; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.WorldPipeNet; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.pipenet.predicate.BlockedPredicate; import gregtech.api.graphnet.pipenet.predicate.FilterPredicate; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.common.covers.FluidFilterMode; import gregtech.common.covers.ManualImportExportMode; import gregtech.common.pipelike.net.item.WorldItemNet; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; @@ -23,9 +27,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Iterator; - -public class WorldFluidNet extends WorldPipeNet implements FlowWorldPipeNetPath.Provider { +public class WorldFluidNet extends WorldPipeNet { public static final Capability[] CAPABILITIES = new Capability[] { CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY }; @@ -47,11 +49,6 @@ public WorldFluidNet(String name) { super(name, true); } - @Override - public boolean supportsPredication() { - return true; - } - @Override protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { super.coverPredication(edge, a, b); @@ -82,35 +79,21 @@ protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nulla if (predicate != null) edge.getPredicateHandler().setPredicate(predicate); } - @Override - public boolean usesDynamicWeights(int algorithmID) { - return true; - } - @Override public boolean clashesWith(IGraphNet net) { return net instanceof WorldItemNet; } @Override - public Capability[] getTargetCapabilities() { - return CAPABILITIES; - } - - @Override - public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return new IPipeCapabilityObject[] { new FluidCapabilityObject(this, node) }; - } - - @Override - public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, long queryTick) { - return backer.getPaths(node, 0, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); + public PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEntity owner, @NotNull WorldPipeNode node) { + Object2ObjectOpenHashMap, IPipeCapabilityObject> map = new Object2ObjectOpenHashMap<>(); + map.put(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, new FluidCapabilityObject(node)); + return new NodeManagingPCW(owner, node, map, 0, 0); } @Override - public @NotNull NetFlowEdge getNewEdge() { - return new NetFlowEdge(10); + public @NotNull GraphClassType getDefaultEdgeType() { + return NetFlowEdge.TYPE; } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java b/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java deleted file mode 100644 index 3c9f3e3f128..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/item/IItemTransferController.java +++ /dev/null @@ -1,79 +0,0 @@ -package gregtech.common.pipelike.net.item; - -import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; -import gregtech.api.graphnet.predicate.test.ItemTestObject; - -import net.minecraft.item.ItemStack; -import net.minecraftforge.items.IItemHandler; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface IItemTransferController { - - TransferControl CONTROL = new TransferControl<>("Item") { - - @Override - public @NotNull IItemTransferController get(@Nullable Object potentialHolder) { - if (!(potentialHolder instanceof TransferControlProvider holder)) return DEFAULT; - IItemTransferController found = holder.getControllerForControl(CONTROL); - return found == null ? DEFAULT : found; - } - - @Override - public @NotNull IItemTransferController getNoPassage() { - return NO_PASSAGE; - } - }; - - IItemTransferController DEFAULT = new IItemTransferController() {}; - - IItemTransferController NO_PASSAGE = new IItemTransferController() { - - @Override - public int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, - boolean simulate) { - return amount; - } - - @Override - public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, - @NotNull IItemHandler sourceHandler, boolean simulate) { - return 0; - } - }; - - /** - * @return the amount left uninserted; aka the remainder - */ - default int insertToHandler(@NotNull ItemTestObject testObject, int amount, - @NotNull IItemHandler destHandler, boolean simulate) { - int available = amount; - for (int i = 0; i < destHandler.getSlots(); i++) { - int allowed = Math.min(available, Math.min(destHandler.getSlotLimit(i), testObject.getStackLimit())); - available -= allowed - destHandler.insertItem(i, testObject.recombine(allowed), simulate).getCount(); - } - return available; - } - - /** - * @return the amount extracted - */ - default int extractFromHandler(@NotNull ItemTestObject testObject, int amount, - @NotNull IItemHandler sourceHandler, boolean simulate) { - int extracted = 0; - for (int i = 0; i < sourceHandler.getSlots(); i++) { - ItemStack stack = sourceHandler.extractItem(i, amount - extracted, true); - if (testObject.test(stack)) { - if (simulate) { - extracted += stack.getCount(); - } else { - extracted += sourceHandler.extractItem(i, amount - extracted, false).getCount(); - } - - } - } - return extracted; - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java b/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java deleted file mode 100644 index 1ead544c3e6..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/item/IItemTraverseGuideProvider.java +++ /dev/null @@ -1,22 +0,0 @@ -package gregtech.common.pipelike.net.item; - -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverseold.ITraverseData; -import gregtech.api.graphnet.traverseold.ITraverseGuideProvider; -import gregtech.api.graphnet.traverseold.TraverseDataProvider; -import gregtech.api.graphnet.traverseold.TraverseGuide; - -import org.jetbrains.annotations.Nullable; - -public interface IItemTraverseGuideProvider extends - ITraverseGuideProvider { - - @Nullable - @Override - > TraverseGuide getGuide( - TraverseDataProvider provider, - ItemTestObject testObject, - long flow, - boolean simulate); -} diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index 10e31717ed1..c0cacba9f4a 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -1,17 +1,22 @@ package gregtech.common.pipelike.net.item; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.pipenet.WorldPipeNet; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverseold.ITraverseData; -import gregtech.api.graphnet.traverseold.TraverseDataProvider; -import gregtech.api.graphnet.traverseold.TraverseGuide; -import gregtech.api.graphnet.traverseold.TraverseHelpers; +import gregtech.api.graphnet.traverse.FDTraverse; + +import gregtech.api.util.GTUtility; + +import gregtech.common.pipelike.net.fluid.FluidFlowLogic; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; @@ -24,116 +29,143 @@ import org.jetbrains.annotations.Nullable; import java.util.EnumMap; -import java.util.Iterator; -import java.util.function.LongConsumer; +import java.util.concurrent.atomic.AtomicInteger; -public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler, IItemTraverseGuideProvider { +public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler { - private final WorldPipeNet net; - private @Nullable PipeTileEntity tile; + private PipeTileEntity tile; + private NodeManagingPCW capabilityWrapper; private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); - private final WorldPipeNetNode node; + private final WorldPipeNode node; private boolean transferring = false; - public ItemCapabilityObject(@NotNull N net, - WorldPipeNetNode node) { - this.net = net; + public ItemCapabilityObject(WorldPipeNode node) { this.node = node; for (EnumFacing facing : EnumFacing.VALUES) { - AbstractNetFlowEdge edge = (AbstractNetFlowEdge) net.getNewEdge(); - edge.setData(NetLogicData.union(node.getData(), (NetLogicData) null)); - wrappers.put(facing, new Wrapper(facing, edge)); + wrappers.put(facing, new Wrapper(facing)); } } - private FlowWorldPipeNetPath.Provider getProvider() { - return (FlowWorldPipeNetPath.Provider) net; + @Override + public void init(@NotNull PipeTileEntity tile, @NotNull PipeCapabilityWrapper wrapper) { + this.tile = tile; + if (!(wrapper instanceof NodeManagingPCW p)) + throw new IllegalArgumentException("ItemCapabilityObjects must be initialized to NodeManagingPCWs!"); + this.capabilityWrapper = p; } private boolean inputDisallowed(EnumFacing side) { if (side == null) return false; - if (tile == null) return true; else return tile.isBlocked(side); } - private Iterator getPaths(@NotNull ITraverseData data) { - assert tile != null; - return getProvider().getPaths(net.getNode(tile.getPos()), data.getTestObject(), data.getSimulatorKey(), - data.getQueryTick()); - } - - @Override - public void setTile(@Nullable PipeTileEntity tile) { - this.tile = tile; - } - @Override - public Capability[] getCapabilities() { - return WorldItemNet.CAPABILITIES; - } - - @Override - public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { + public T getCapability(Capability capability, @Nullable EnumFacing facing) { if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(facing == null ? this : wrappers.get(facing)); } return null; } - public @NotNull ItemStack insertItem(@NotNull ItemStack stack, boolean simulate, EnumFacing side) { - if (this.transferring) return stack; + protected @Nullable NetNode getRelevantNode(EnumFacing facing) { + return facing == null ? node : capabilityWrapper.getNodeForFacing(facing); + } + + protected @NotNull ItemStack insertItem(@NotNull ItemStack stack, boolean simulate, EnumFacing side) { + if (this.transferring || inputDisallowed(side)) return stack; + NetNode node = getRelevantNode(side); + if (node == null) return stack; this.transferring = true; - var guide = getGuide(ItemTraverseData::new, new ItemTestObject(stack), stack.getCount(), simulate, side); - if (guide == null) return stack; - int consumed = (int) TraverseHelpers.traverseFlood(guide.getData(), guide.getPaths(), guide.getFlow()); - guide.reportConsumedFlow(consumed); + int flow = stack.getCount(); + long queryTick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + SimulatorKey key = simulate ? SimulatorKey.getNewSimulatorInstance() : null; + ItemTestObject testObject = new ItemTestObject(stack); + AtomicInteger report = new AtomicInteger(); + FDTraverse.flood(node.getNet(), + (n, f) -> { + if (n == node) report.addAndGet(f); + else if (!simulate) reportFlow(n, f, testObject); + }, + (e, f) -> reportFlow(e, f, testObject, key, true), + e -> e instanceof AbstractNetFlowEdge n ? + GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, node.getNet(), queryTick, key)) : 0, + n -> n == node ? flow : getSupply(n, testObject, false), null); this.transferring = false; - return guide.getData().getTestObject().recombine(stack.getCount() - consumed); + return testObject.recombine(stack.getCount() - report.get()); } - @Nullable - @Override - public > TraverseGuide getGuide( - TraverseDataProvider provider, - ItemTestObject testObject, - long flow, - boolean simulate) { - return getGuide(provider, testObject, flow, simulate, null); - } - - @Nullable - protected < - D extends ITraverseData> TraverseGuide getGuide( - TraverseDataProvider provider, - ItemTestObject testObject, - long flow, - boolean simulate, - EnumFacing side) { - if (tile == null || inputDisallowed(side)) return null; - - SimulatorKey simulator = simulate ? SimulatorKey.getNewSimulatorInstance() : null; - long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - D data = provider.of(net, testObject, simulator, tick, tile.getPos(), side); - - LongConsumer flowReport = null; - Wrapper wrapper = this.wrappers.get(side); - if (wrapper != null) { - AbstractNetFlowEdge internalBuffer = wrapper.getBuffer(); - if (internalBuffer != null) { - long limit = internalBuffer.getFlowLimit(testObject, net, tick, simulator); - if (limit <= 0) { - this.transferring = false; - return null; + protected @NotNull ItemStack extractItem(int slot, int amount, boolean simulate, EnumFacing side) { + // TODO expose connected itemnet through capability & allow extraction + return ItemStack.EMPTY; + } + + protected void reportFlow(NetEdge edge, int flow, ItemTestObject testObject, SimulatorKey key, boolean sourceBias) { + if (edge instanceof AbstractNetFlowEdge n) + n.consumeFlowLimit(testObject, node.getNet(), flow, getQueryTick(), key); + if (key == null) { + NetNode node = sourceBias ? edge.getSource() : edge.getTarget(); + if (node == null) return; + ItemFlowLogic logic = node.getData().getLogicEntryNullable(ItemFlowLogic.TYPE); + if (logic == null) { + logic = ItemFlowLogic.TYPE.getNew(); + node.getData().setLogicEntry(logic); + } + logic.recordFlow(getQueryTick(), testObject.recombine(flow)); + } + } + + protected void reportFlow(NetNode node, int flow, ItemTestObject testObject) { + if (flow == 0) return; + if (node instanceof NodeExposingCapabilities exposer) { + IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, exposer.exposedFacing()); + if (handler != null) { + // positive flow is supply, aka we pulled flow from this node + if (flow > 0) { + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack stack = handler.extractItem(i, flow, true); + if (testObject.test(stack)) { + stack = handler.extractItem(i, flow, false); + flow -= stack.getCount(); + } + if (flow == 0) return; + } + } else { + for (int i = 0; i < handler.getSlots() ; i++) { + ItemStack stack = testObject.recombineSafe(flow); + flow -= stack.getCount() - handler.insertItem(i, stack, false).getCount(); + if (flow == 0) return; + } } - flow = Math.min(limit, flow); - flowReport = l -> data.consumeFlowLimit(internalBuffer, node, l); } } - return new TraverseGuide<>(data, () -> getPaths(data), flow, flowReport); + } + + protected int getSupply(NetNode node, ItemTestObject testObject, boolean supply) { + if (node instanceof NodeExposingCapabilities exposer) { + IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, exposer.exposedFacing()); + if (handler != null) { + if (supply) { + int sum = 0; + for (int i = 0; i < handler.getSlots() ; i++) { + ItemStack stack = handler.extractItem(i, Integer.MAX_VALUE, true); + if (testObject.test(stack)) sum += stack.getCount(); + } + return sum; + } else { + int sum = 0; + for (int i = 0; i < handler.getSlots() ; i++) { + ItemStack stack = testObject.recombineSafe(Integer.MAX_VALUE); + sum += stack.getCount() - handler.insertItem(i, stack, true).getCount(); + } + return sum; + } + } + } + return 0; } @Override @@ -153,7 +185,7 @@ public int getSlots() { @Override public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { - return ItemStack.EMPTY; + return extractItem(slot, amount, simulate, null); } @Override @@ -161,28 +193,12 @@ public int getSlotLimit(int slot) { return 64; } - protected class Wrapper implements IItemHandler, IItemTraverseGuideProvider { + protected class Wrapper implements IItemHandler { private final EnumFacing facing; - private final AbstractNetFlowEdge buffer; - public Wrapper(EnumFacing facing, AbstractNetFlowEdge buffer) { + public Wrapper(EnumFacing facing) { this.facing = facing; - this.buffer = buffer; - } - - @Nullable - @Override - public > TraverseGuide getGuide( - TraverseDataProvider provider, - ItemTestObject testObject, - long flow, - boolean simulate) { - return ItemCapabilityObject.this.getGuide(provider, testObject, flow, simulate, facing); - } - - public AbstractNetFlowEdge getBuffer() { - return buffer; } @Override @@ -202,7 +218,7 @@ public int getSlots() { @Override public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { - return ItemStack.EMPTY; + return ItemCapabilityObject.this.extractItem(slot, amount, simulate, facing); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java deleted file mode 100644 index 63f0493755b..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemEQTraverseData.java +++ /dev/null @@ -1,86 +0,0 @@ -package gregtech.common.pipelike.net.item; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverseold.IEqualizableTraverseData; -import gregtech.api.util.GTUtility; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -import org.jetbrains.annotations.NotNull; - -public class ItemEQTraverseData extends ItemTraverseData - implements IEqualizableTraverseData { - - protected int destCount; - protected int maxMinFlow; - - public ItemEQTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing) { - super(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - protected void compute(@NotNull WorldPipeNetNode destination) { - this.destCount = 0; - this.maxMinFlow = 0; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IItemHandler container = capability.getValue() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); - if (container != null) { - if (destCount == 0) maxMinFlow = Integer.MAX_VALUE; - destCount += 1; - int test = Integer.MAX_VALUE; - maxMinFlow = Math.min(maxMinFlow, test - - IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), test, - container, true)); - } - } - } - - @Override - public int getDestinationsAtNode(@NotNull WorldPipeNetNode node) { - return destCount; - } - - @Override - public boolean shouldSkipPath(@NotNull FlowWorldPipeNetPath path) { - compute(path.getTargetNode()); - return maxMinFlow == 0; - } - - @Override - public long getMaxFlowToLeastDestination(@NotNull WorldPipeNetNode destination) { - return maxMinFlow; - } - - @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode node, long flowReachingNode, int expectedDestinations) { - long availableFlow = flowReachingNode; - long flowPerDestination = flowReachingNode / expectedDestinations; - if (flowPerDestination == 0) return 0; - for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { - if (GTUtility.arePosEqual(node.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IItemHandler container = capability.getValue() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); - if (container != null) { - availableFlow = IItemTransferController.CONTROL.get(node.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(Integer.MAX_VALUE, flowPerDestination), container, simulating()); - } - } - return flowReachingNode - availableFlow; - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java deleted file mode 100644 index 35433d556a0..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemRRTraverseData.java +++ /dev/null @@ -1,63 +0,0 @@ -package gregtech.common.pipelike.net.item; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; -import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverseold.IRoundRobinTraverseData; -import gregtech.api.util.GTUtility; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import org.jetbrains.annotations.NotNull; - -public class ItemRRTraverseData extends ItemTraverseData implements - IRoundRobinTraverseData, WorldPipeNetNode, FlowWorldPipeNetPath> { - - private final Object2ObjectLinkedOpenHashMap> cache; - - public ItemRRTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing, - @NotNull Object2ObjectLinkedOpenHashMap> cache) { - super(net, testObject, simulator, queryTick, sourcePos, inputFacing); - this.cache = cache; - } - - @Override - public @NotNull Object2ObjectLinkedOpenHashMap> getTraversalCache() { - return cache; - } - - @Override - public boolean shouldSkipPath(@NotNull FlowWorldPipeNetPath path) { - return false; - } - - @Override - public @NotNull SimpleTileRoundRobinData createRRData(@NotNull WorldPipeNetNode destination) { - return new SimpleTileRoundRobinData<>(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); - } - - @Override - public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData data, - @NotNull WorldPipeNetNode destination, - long flowReachingDestination) { - long availableFlow = flowReachingDestination; - EnumFacing pointerFacing = data.getPointerFacing(getSimulatorKey()); - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && pointerFacing == inputFacing) - return 0; // anti insert-to-our-source logic - - IItemHandler container = data.getAtPointer(destination, getSimulatorKey()); - if (container != null) { - availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(pointerFacing)).insertToHandler(getTestObject(), - (int) Math.min(Integer.MAX_VALUE, availableFlow), container, simulating()); - } - return flowReachingDestination - availableFlow; - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java deleted file mode 100644 index 01f60d9df51..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemTraverseData.java +++ /dev/null @@ -1,82 +0,0 @@ -package gregtech.common.pipelike.net.item; - -import gregtech.api.graphnet.IGraphNet; -import gregtech.api.graphnet.NetNode; -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; -import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverseold.AbstractTraverseData; -import gregtech.api.graphnet.traverseold.util.ReversibleLossOperator; -import gregtech.api.util.GTUtility; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; -import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.items.IItemHandler; - -import org.jetbrains.annotations.NotNull; - -public class ItemTraverseData extends AbstractTraverseData { - - protected final BlockPos sourcePos; - protected final EnumFacing inputFacing; - - public ItemTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing) { - super(net, testObject, simulator, queryTick); - this.sourcePos = sourcePos; - this.inputFacing = inputFacing; - } - - @Override - public ItemTestObject getTestObject() { - return (ItemTestObject) super.getTestObject(); - } - - @Override - public boolean prepareForPathWalk(@NotNull FlowWorldPipeNetPath path, long flow) { - return flow <= 0; - } - - @Override - public ReversibleLossOperator traverseToNode(@NotNull WorldPipeNetNode node, long flowReachingNode) { - return ReversibleLossOperator.IDENTITY; - } - - @Override - public long finalizeAtDestination(@NotNull WorldPipeNetNode destination, long flowReachingDestination) { - long availableFlow = flowReachingDestination; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IItemHandler container = capability.getValue() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, capability.getKey().getOpposite()); - if (container != null) { - availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(Integer.MAX_VALUE, availableFlow), container, simulating()); - } - } - return flowReachingDestination - availableFlow; - } - - @Override - public void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, long consumption) { - super.consumeFlowLimit(edge, targetNode, consumption); - if (consumption > 0 && !simulating()) { - recordFlow(targetNode, consumption); - } - } - - private void recordFlow(@NotNull NetNode node, long flow) { - ItemFlowLogic logic = node.getData().getLogicEntryNullable(ItemFlowLogic.TYPE); - if (logic == null) { - logic = ItemFlowLogic.TYPE.getNew(); - node.getData().setLogicEntry(logic); - } - logic.recordFlow(getQueryTick(), getTestObject().recombine(GTUtility.safeCastLongToInt(flow))); - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index e689ed01ba5..2145b43380a 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -2,20 +2,25 @@ import gregtech.api.cover.Cover; import gregtech.api.cover.filter.CoverWithItemFilter; -import gregtech.api.graphnet.IGraphNet; +import gregtech.api.graphnet.GraphClassType; +import gregtech.api.graphnet.edge.FlowBufferTickProvider; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.pipenet.WorldPipeNet; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.pipenet.predicate.BlockedPredicate; import gregtech.api.graphnet.pipenet.predicate.FilterPredicate; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.common.covers.ItemFilterMode; import gregtech.common.covers.ManualImportExportMode; import gregtech.common.pipelike.net.fluid.WorldFluidNet; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.items.CapabilityItemHandler; @@ -23,9 +28,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Iterator; - -public class WorldItemNet extends WorldPipeNet implements FlowWorldPipeNetPath.Provider { +public class WorldItemNet extends WorldPipeNet implements FlowBufferTickProvider { public static final Capability[] CAPABILITIES = new Capability[] { CapabilityItemHandler.ITEM_HANDLER_CAPABILITY }; @@ -47,11 +50,6 @@ public WorldItemNet(String name) { super(name, true); } - @Override - public boolean supportsPredication() { - return true; - } - @Override protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nullable Cover b) { super.coverPredication(edge, a, b); @@ -82,35 +80,31 @@ protected void coverPredication(@NotNull NetEdge edge, @Nullable Cover a, @Nulla if (predicate != null) edge.getPredicateHandler().setPredicate(predicate); } - @Override - public boolean usesDynamicWeights(int algorithmID) { - return true; - } - @Override public boolean clashesWith(IGraphNet net) { return net instanceof WorldFluidNet; } @Override - public Capability[] getTargetCapabilities() { - return CAPABILITIES; + public PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEntity owner, @NotNull WorldPipeNode node) { + Object2ObjectOpenHashMap, IPipeCapabilityObject> map = new Object2ObjectOpenHashMap<>(); + map.put(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, new ItemCapabilityObject(node)); + return new NodeManagingPCW(owner, node, map, 0, 0); } @Override - public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return new IPipeCapabilityObject[] { new ItemCapabilityObject(this, node) }; + public @NotNull GraphClassType getDefaultEdgeType() { + return NetFlowEdge.TYPE; } @Override - public Iterator getPaths(WorldPipeNetNode node, IPredicateTestObject testObject, - @Nullable SimulatorKey simulator, long queryTick) { - return backer.getPaths(node, 0, FlowWorldPipeNetPath.MAPPER, testObject, simulator, queryTick); + public int getFlowBufferTicks() { + return 2; } @Override - public @NotNull NetFlowEdge getNewEdge() { - return new NetFlowEdge(2, 5); + public int getRegenerationTime() { + return 5; } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java index a27ec2e47ae..f7bcf02064d 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java @@ -2,12 +2,13 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserRelay; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.group.PathCacheGroupData; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.path.SingletonNetPath; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.common.pipelike.net.SlowActiveWalker; @@ -22,14 +23,16 @@ public class LaserCapabilityObject implements IPipeCapabilityObject, ILaserRelay { - protected final WorldPipeNetNode node; + public static final int ACTIVE_KEY = 122; + + protected final WorldPipeNode node; private @Nullable PipeTileEntity tile; private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); private boolean transmitting; - public LaserCapabilityObject(@NotNull WorldPipeNetNode node) { + public LaserCapabilityObject(@NotNull WorldPipeNode node) { this.node = node; for (EnumFacing facing : EnumFacing.VALUES) { wrappers.put(facing, new Wrapper(facing)); @@ -37,7 +40,7 @@ public LaserCapabilityObject(@NotNull WorldPipeNetNode node) { } @Override - public void setTile(@Nullable PipeTileEntity tile) { + public void init(@NotNull PipeTileEntity tile, @NotNull PipeCapabilityWrapper wrapper) { this.tile = tile; } @@ -54,7 +57,7 @@ protected long receiveLaser(long laserVoltage, long laserAmperage, EnumFacing fa if (node.getGroupUnsafe() == null || node.getGroupSafe().getNodes().size() == 1) path = new SingletonNetPath(node); else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { - Set actives = node.getGroupSafe().getActiveNodes(); + Set actives = node.getGroupSafe().getNodesUnderKey(ACTIVE_KEY); if (actives.size() > 2) return 0; // single-destination contract violated var iter = actives.iterator(); NetNode target = iter.next(); @@ -62,12 +65,13 @@ else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { if (!iter.hasNext()) return 0; // no destinations target = iter.next(); } + if (!(target instanceof WorldPipeNode)) return 0; // useless target path = cache.getOrCreate(node).getOrCompute(target); if (path == null) return 0; // no path } else return 0; // no cache to lookup with long available = laserAmperage; - WorldPipeNetNode destination = path.getTargetNode(); + WorldPipeNode destination = (WorldPipeNode) path.getTargetNode(); for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { if (destination == node && capability.getKey() == facing) continue; // anti insert-to-our-source logic ILaserRelay laser = capability.getValue() @@ -91,12 +95,7 @@ else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { } @Override - public Capability[] getCapabilities() { - return WorldLaserNet.CAPABILITIES; - } - - @Override - public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { + public T getCapability(Capability capability, @Nullable EnumFacing facing) { if (capability == GregtechTileCapabilities.CAPABILITY_LASER) { return GregtechTileCapabilities.CAPABILITY_LASER.cast(facing == null ? this : wrappers.get(facing)); } diff --git a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java index 97259a4c126..d943e514087 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java @@ -1,13 +1,20 @@ package gregtech.common.pipelike.net.laser; +import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.group.PathCacheGroupData; import gregtech.api.graphnet.pipenet.WorldPipeNet; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; +import gregtech.common.pipelike.net.energy.EnergyCapabilityObject; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; @@ -36,13 +43,10 @@ public WorldLaserNet(String name) { } @Override - public Capability[] getTargetCapabilities() { - return CAPABILITIES; - } - - @Override - public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return new IPipeCapabilityObject[] { new LaserCapabilityObject(node) }; + public PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEntity owner, @NotNull WorldPipeNode node) { + Object2ObjectOpenHashMap, IPipeCapabilityObject> map = new Object2ObjectOpenHashMap<>(); + map.put(GregtechTileCapabilities.CAPABILITY_LASER, new LaserCapabilityObject(node)); + return new PipeCapabilityWrapper(owner, node, map, 0, LaserCapabilityObject.ACTIVE_KEY); } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index e959d7d14d3..4478dd69830 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -4,12 +4,13 @@ import gregtech.api.capability.data.IDataAccess; import gregtech.api.capability.data.query.DataAccessFormat; import gregtech.api.capability.data.query.DataQueryObject; -import gregtech.api.graphnet.NetNode; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.group.PathCacheGroupData; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.path.SingletonNetPath; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.common.pipelike.net.SlowActiveWalker; @@ -24,13 +25,15 @@ public class DataCapabilityObject implements IPipeCapabilityObject, IDataAccess { - private final WorldPipeNetNode node; + public static final int ACTIVE_KEY = 122; + + private final WorldPipeNode node; private @Nullable PipeTileEntity tile; private final EnumMap wrappers = new EnumMap<>(EnumFacing.class); - public DataCapabilityObject(@NotNull WorldPipeNetNode node) { + public DataCapabilityObject(@NotNull WorldPipeNode node) { this.node = node; for (EnumFacing facing : EnumFacing.VALUES) { wrappers.put(facing, new Wrapper(facing)); @@ -38,7 +41,7 @@ public DataCapabilityObject(@NotNull WorldPipeNetNode node) { } @Override - public void setTile(@Nullable PipeTileEntity tile) { + public void init(@NotNull PipeTileEntity tile, @NotNull PipeCapabilityWrapper wrapper) { this.tile = tile; } @@ -54,7 +57,7 @@ private boolean accessData(@NotNull DataQueryObject queryObject, @Nullable EnumF if (node.getGroupUnsafe() == null || node.getGroupSafe().getNodes().size() == 1) path = new SingletonNetPath(node); else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { - Set actives = node.getGroupSafe().getActiveNodes(); + Set actives = node.getGroupSafe().getNodesUnderKey(ACTIVE_KEY); if (actives.size() > 2) return false; // single-destination contract violated var iter = actives.iterator(); NetNode target = iter.next(); @@ -62,11 +65,12 @@ else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { if (!iter.hasNext()) return false; // no destinations target = iter.next(); } + if (!(target instanceof WorldPipeNode)) return false; // useless target path = cache.getOrCreate(node).getOrCompute(target); if (path == null) return false; // no path } else return false; // no cache to lookup with - WorldPipeNetNode destination = path.getTargetNode(); + WorldPipeNode destination = (WorldPipeNode) path.getTargetNode(); for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { if (destination == node && capability.getKey() == facing) continue; // anti insert-to-our-source logic IDataAccess access = capability.getValue() @@ -93,12 +97,7 @@ else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { } @Override - public Capability[] getCapabilities() { - return WorldOpticalNet.CAPABILITIES; - } - - @Override - public T getCapabilityForSide(Capability capability, @Nullable EnumFacing facing) { + public T getCapability(Capability capability, @Nullable EnumFacing facing) { if (capability == GregtechTileCapabilities.CAPABILITY_DATA_ACCESS) { return GregtechTileCapabilities.CAPABILITY_DATA_ACCESS.cast(facing == null ? this : wrappers.get(facing)); } diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java index 4b98c515198..eb37ed63be0 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -1,13 +1,20 @@ package gregtech.common.pipelike.net.optical; +import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.group.PathCacheGroupData; import gregtech.api.graphnet.pipenet.WorldPipeNet; -import gregtech.api.graphnet.pipenet.WorldPipeNetNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; +import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; +import gregtech.common.pipelike.net.energy.EnergyCapabilityObject; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; @@ -37,13 +44,10 @@ public WorldOpticalNet(String name) { } @Override - public Capability[] getTargetCapabilities() { - return CAPABILITIES; - } - - @Override - public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNetNode node) { - return new IPipeCapabilityObject[] { new DataCapabilityObject(node) }; + public PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEntity owner, @NotNull WorldPipeNode node) { + Object2ObjectOpenHashMap, IPipeCapabilityObject> map = new Object2ObjectOpenHashMap<>(); + map.put(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, new DataCapabilityObject(node)); + return new PipeCapabilityWrapper(owner, node, map, 0, DataCapabilityObject.ACTIVE_KEY); } @Override From 0537c111be1c7ddd3b97d3811ecc5c17837e053b Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Wed, 4 Dec 2024 19:58:19 -0700 Subject: [PATCH 149/157] spotless --- .../java/gregtech/api/fluids/FluidState.java | 47 ++++++++++++------- .../api/fluids/attribute/FluidAttribute.java | 2 - .../api/fluids/attribute/FluidAttributes.java | 14 +++--- .../graphnet/GraphClassRegistrationEvent.java | 4 +- .../api/graphnet/GraphClassRegistry.java | 7 +-- .../gregtech/api/graphnet/GraphClassType.java | 4 -- .../gregtech/api/graphnet/GraphNetBacker.java | 8 +--- .../api/graphnet/MultiNodeHelper.java | 2 - .../graphnet/edge/AbstractNetFlowEdge.java | 2 +- .../gregtech/api/graphnet/edge/NetEdge.java | 6 +-- .../api/graphnet/edge/NetFlowEdge.java | 3 +- .../api/graphnet/graph/INetGraph.java | 5 -- .../api/graphnet/graph/NetDirectedGraph.java | 3 +- .../graphnet/graph/NetUndirectedGraph.java | 3 +- .../api/graphnet/group/GroupData.java | 2 +- .../gregtech/api/graphnet/group/NetGroup.java | 4 +- .../graphnet/group/PathCacheGroupData.java | 2 +- .../api/graphnet/net/BlankNetNode.java | 3 +- .../api/graphnet/net/BlockPosNode.java | 3 +- .../api/graphnet/net/WorldSavedNet.java | 3 -- .../gregtech/api/graphnet/path/NetPath.java | 2 +- .../api/graphnet/path/PathBuilder.java | 2 +- .../api/graphnet/path/SingletonNetPath.java | 2 +- .../api/graphnet/path/StandardNetPath.java | 2 +- .../api/graphnet/pipenet/NodeWithCovers.java | 3 +- .../pipenet/NodeWithFacingToOthers.java | 3 +- .../pipenet/WorldPipeCapConnectionNode.java | 9 ++-- .../api/graphnet/pipenet/WorldPipeNet.java | 11 ++--- .../api/graphnet/pipenet/WorldPipeNode.java | 15 +++--- .../pipenet/logic/TemperatureLogic.java | 2 +- .../physical/IPipeCapabilityObject.java | 2 - .../physical/tile/IWorldPipeNetTile.java | 4 -- .../physical/tile/NodeManagingPCW.java | 5 +- .../physical/tile/PipeCapabilityWrapper.java | 6 +-- .../pipenet/physical/tile/PipeTileEntity.java | 1 - .../traverse/AbstractMinCostTraverse.java | 4 +- .../api/graphnet/traverse/EQTraverse.java | 11 ++--- .../api/graphnet/traverse/FDTraverse.java | 8 ++-- .../api/graphnet/traverse/RRTraverse.java | 8 ++-- .../traverse/iter/NetBreadthIterator.java | 4 +- .../traverse/iter/NetClosestIterator.java | 2 +- .../graphnet/traverse/iter/NetIterator.java | 2 +- .../traverseold/AbstractTraverseData.java | 2 +- .../graphnet/traverseold/IRoundRobinData.java | 2 +- .../graphnet/traverseold/ITraverseData.java | 4 +- .../traverseold/TraverseDataProvider.java | 2 +- .../graphnet/traverseold/TraverseHelpers.java | 2 +- .../java/gregtech/api/util/GTUtility.java | 12 +++-- .../gregtech/common/covers/CoverConveyor.java | 3 +- .../common/covers/CoverFluidRegulator.java | 2 +- .../gregtech/common/covers/CoverPump.java | 2 +- .../common/covers/CoverRoboticArm.java | 2 +- .../properties/MaterialEnergyProperties.java | 2 +- .../properties/MaterialFluidProperties.java | 2 +- .../properties/MaterialItemProperties.java | 2 +- .../net/energy/EnergyCapabilityObject.java | 5 +- .../pipelike/net/energy/EnergyGroupData.java | 2 +- .../net/energy/StandardEnergyPath.java | 4 +- .../pipelike/net/energy/WorldEnergyNet.java | 3 +- .../net/fluid/FluidCapabilityObject.java | 13 +++-- .../net/fluid/FluidContainmentLogic.java | 4 +- .../pipelike/net/fluid/WorldFluidNet.java | 5 +- .../net/item/ItemCapabilityObject.java | 16 +++---- .../pipelike/net/item/WorldItemNet.java | 5 +- .../net/laser/LaserCapabilityObject.java | 2 +- .../pipelike/net/laser/WorldLaserNet.java | 6 +-- .../net/optical/DataCapabilityObject.java | 2 +- .../pipelike/net/optical/WorldOpticalNet.java | 6 +-- 68 files changed, 152 insertions(+), 195 deletions(-) diff --git a/src/main/java/gregtech/api/fluids/FluidState.java b/src/main/java/gregtech/api/fluids/FluidState.java index b05f0a4e46d..6b5d019e94b 100644 --- a/src/main/java/gregtech/api/fluids/FluidState.java +++ b/src/main/java/gregtech/api/fluids/FluidState.java @@ -2,9 +2,7 @@ import gregtech.api.GTValues; import gregtech.api.fluids.attribute.AttributedFluid; - import gregtech.api.util.EntityDamageUtil; - import gregtech.api.util.GTUtility; import net.minecraft.entity.EntityLivingBase; @@ -59,33 +57,39 @@ public void handleFailure(World world, BlockPos failingBlock, FluidStack failing List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, new AxisAlignedBB(failingBlock).grow(scalar * 0.5)); for (EntityLivingBase entity : entities) { - EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + EntityDamageUtil.applyTemperatureDamage(entity, + failingStack.getFluid().getTemperature(failingStack), scalar, 20); } world.setBlockToAir(failingBlock); } case GAS -> { - GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingBlock, 9 + GTValues.RNG.nextInt(3)); + GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingBlock, + 9 + GTValues.RNG.nextInt(3)); float scalar = (float) Math.log(failingStack.amount); List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, new AxisAlignedBB(failingBlock).grow(scalar)); for (EntityLivingBase entity : entities) { - EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + EntityDamageUtil.applyTemperatureDamage(entity, + failingStack.getFluid().getTemperature(failingStack), scalar * 0.75f, 15); } world.setBlockToAir(failingBlock); } case PLASMA -> { - GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingBlock, 3 + GTValues.RNG.nextInt(3)); + GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingBlock, + 3 + GTValues.RNG.nextInt(3)); float scalar = (float) Math.log(failingStack.amount); List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, new AxisAlignedBB(failingBlock).grow(scalar * 1.5)); for (EntityLivingBase entity : entities) { - EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + EntityDamageUtil.applyTemperatureDamage(entity, + failingStack.getFluid().getTemperature(failingStack), scalar, 30); } world.setBlockToAir(failingBlock); - world.createExplosion(null, failingBlock.getX() + 0.5, failingBlock.getY() + 0.5, failingBlock.getZ() + 0.5, + world.createExplosion(null, failingBlock.getX() + 0.5, failingBlock.getY() + 0.5, + failingBlock.getZ() + 0.5, 1.0f + GTValues.RNG.nextFloat(), true); } } @@ -94,7 +98,8 @@ public void handleFailure(World world, BlockPos failingBlock, FluidStack failing @Override public void handleFailure(EntityPlayer failingPlayer, FluidStack failingStack) { World world = failingPlayer.world; - world.playSound(null, failingPlayer.getPosition(), SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); + world.playSound(null, failingPlayer.getPosition(), SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, + 1.0F, 1.0F); switch (this) { default -> { for (EnumFacing facing : EnumFacing.HORIZONTALS) { @@ -108,36 +113,44 @@ public void handleFailure(EntityPlayer failingPlayer, FluidStack failingStack) { new AxisAlignedBB(failingPlayer.getPosition()).grow(scalar * 0.5)); for (EntityLivingBase entity : entities) { if (entity == failingPlayer) continue; - EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + EntityDamageUtil.applyTemperatureDamage(entity, + failingStack.getFluid().getTemperature(failingStack), scalar, 20); } - EntityDamageUtil.applyTemperatureDamage(failingPlayer, failingStack.getFluid().getTemperature(failingStack), + EntityDamageUtil.applyTemperatureDamage(failingPlayer, + failingStack.getFluid().getTemperature(failingStack), scalar * 3, 60); } case GAS -> { - GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingPlayer, 9 + GTValues.RNG.nextInt(3)); + GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingPlayer, + 9 + GTValues.RNG.nextInt(3)); float scalar = (float) Math.log(failingStack.amount); List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, new AxisAlignedBB(failingPlayer.getPosition()).grow(scalar)); for (EntityLivingBase entity : entities) { if (entity == failingPlayer) continue; - EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + EntityDamageUtil.applyTemperatureDamage(entity, + failingStack.getFluid().getTemperature(failingStack), scalar * 0.75f, 15); } - EntityDamageUtil.applyTemperatureDamage(failingPlayer, failingStack.getFluid().getTemperature(failingStack), + EntityDamageUtil.applyTemperatureDamage(failingPlayer, + failingStack.getFluid().getTemperature(failingStack), scalar * 2.25f, 45); } case PLASMA -> { - GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingPlayer, 3 + GTValues.RNG.nextInt(3)); + GTUtility.spawnParticles(world, EnumFacing.UP, EnumParticleTypes.SMOKE_LARGE, failingPlayer, + 3 + GTValues.RNG.nextInt(3)); float scalar = (float) Math.log(failingStack.amount); List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, new AxisAlignedBB(failingPlayer.getPosition()).grow(scalar * 1.5)); for (EntityLivingBase entity : entities) { if (entity == failingPlayer) continue; - EntityDamageUtil.applyTemperatureDamage(entity, failingStack.getFluid().getTemperature(failingStack), + EntityDamageUtil.applyTemperatureDamage(entity, + failingStack.getFluid().getTemperature(failingStack), scalar, 30); } - EntityDamageUtil.applyTemperatureDamage(failingPlayer, failingStack.getFluid().getTemperature(failingStack), + EntityDamageUtil.applyTemperatureDamage(failingPlayer, + failingStack.getFluid().getTemperature(failingStack), scalar * 3, 90); Vec3d vec = failingPlayer.getPositionEyes(1); world.createExplosion(null, vec.x, vec.y, vec.z, diff --git a/src/main/java/gregtech/api/fluids/attribute/FluidAttribute.java b/src/main/java/gregtech/api/fluids/attribute/FluidAttribute.java index abfb3e77a29..3dc38744089 100644 --- a/src/main/java/gregtech/api/fluids/attribute/FluidAttribute.java +++ b/src/main/java/gregtech/api/fluids/attribute/FluidAttribute.java @@ -1,12 +1,10 @@ package gregtech.api.fluids.attribute; import gregtech.api.fluids.ContainmentFailureHandler; - import gregtech.api.util.function.TriConsumer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; - import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; diff --git a/src/main/java/gregtech/api/fluids/attribute/FluidAttributes.java b/src/main/java/gregtech/api/fluids/attribute/FluidAttributes.java index b0564a64564..2f16948abb2 100644 --- a/src/main/java/gregtech/api/fluids/attribute/FluidAttributes.java +++ b/src/main/java/gregtech/api/fluids/attribute/FluidAttributes.java @@ -1,9 +1,7 @@ package gregtech.api.fluids.attribute; import gregtech.api.GTValues; -import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; import gregtech.api.util.EntityDamageUtil; - import gregtech.api.util.GTUtility; import net.minecraft.client.resources.I18n; @@ -13,9 +11,6 @@ import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.SoundCategory; import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.WorldServer; import java.util.List; @@ -46,12 +41,15 @@ public final class FluidAttributes { w.setBlockToAir(b); }, (p, f) -> { - p.world.playSound(null, p.getPosition(), SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, 1.0F); + p.world.playSound(null, p.getPosition(), SoundEvents.BLOCK_LAVA_EXTINGUISH, SoundCategory.BLOCKS, 1.0F, + 1.0F); boolean gaseous = f.getFluid().isGaseous(f); for (EnumFacing facing : EnumFacing.HORIZONTALS) { - GTUtility.spawnParticles(p.world, facing, EnumParticleTypes.CRIT_MAGIC, p, 3 + GTValues.RNG.nextInt(2)); + GTUtility.spawnParticles(p.world, facing, EnumParticleTypes.CRIT_MAGIC, p, + 3 + GTValues.RNG.nextInt(2)); } - GTUtility.spawnParticles(p.world, gaseous ? EnumFacing.UP : EnumFacing.DOWN, EnumParticleTypes.CRIT_MAGIC, + GTUtility.spawnParticles(p.world, gaseous ? EnumFacing.UP : EnumFacing.DOWN, + EnumParticleTypes.CRIT_MAGIC, p, 6 + GTValues.RNG.nextInt(4)); float scalar = (float) Math.log(f.amount); List entities = p.world.getEntitiesWithinAABB(EntityLivingBase.class, diff --git a/src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java b/src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java index 9547dc6664c..95eeac71c5c 100644 --- a/src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java +++ b/src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java @@ -1,9 +1,9 @@ package gregtech.api.graphnet; -import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; - import net.minecraftforge.fml.common.eventhandler.Event; +import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; + import java.util.Comparator; public final class GraphClassRegistrationEvent extends Event { diff --git a/src/main/java/gregtech/api/graphnet/GraphClassRegistry.java b/src/main/java/gregtech/api/graphnet/GraphClassRegistry.java index 17fe1a49e02..6f843b4f041 100644 --- a/src/main/java/gregtech/api/graphnet/GraphClassRegistry.java +++ b/src/main/java/gregtech/api/graphnet/GraphClassRegistry.java @@ -1,12 +1,8 @@ package gregtech.api.graphnet; import gregtech.api.graphnet.logic.NetLogicEntry; -import gregtech.api.graphnet.logic.NetLogicRegistrationEvent; import gregtech.api.graphnet.logic.NetLogicType; -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; -import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; - import net.minecraft.client.Minecraft; import net.minecraft.util.IntIdentityHashBiMap; import net.minecraft.util.text.TextComponentTranslation; @@ -14,10 +10,10 @@ import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Comparator; import java.util.Set; public final class GraphClassRegistry { @@ -94,5 +90,4 @@ private static void disconnect() { } private GraphClassRegistry() {} - } diff --git a/src/main/java/gregtech/api/graphnet/GraphClassType.java b/src/main/java/gregtech/api/graphnet/GraphClassType.java index 4ed141900b4..08d947da056 100644 --- a/src/main/java/gregtech/api/graphnet/GraphClassType.java +++ b/src/main/java/gregtech/api/graphnet/GraphClassType.java @@ -1,7 +1,5 @@ package gregtech.api.graphnet; -import gregtech.api.graphnet.logic.NetLogicEntry; - import gregtech.api.graphnet.net.IGraphNet; import net.minecraft.util.IStringSerializable; @@ -10,7 +8,6 @@ import org.jetbrains.annotations.NotNull; import java.util.function.Function; -import java.util.function.Supplier; public class GraphClassType implements IStringSerializable { @@ -20,7 +17,6 @@ public class GraphClassType implements IStringSerializable { public GraphClassType(@NotNull ResourceLocation name, @NotNull Function supplier) { this.name = name.toString(); this.supplier = supplier; - } public GraphClassType(@NotNull String namespace, @NotNull String name, @NotNull Function supplier) { diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index b740de9808f..dc80c207b21 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -6,11 +6,8 @@ import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.group.MergeDirection; import gregtech.api.graphnet.group.NetGroup; - import gregtech.api.graphnet.net.IGraphNet; - import gregtech.api.graphnet.net.NetNode; - import gregtech.api.graphnet.traverse.iter.EdgeDirection; import net.minecraft.nbt.NBTTagCompound; @@ -24,8 +21,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; -import java.util.Iterator; import java.util.Objects; /** @@ -206,7 +201,8 @@ public void readFromNBT(@NotNull NBTTagCompound nbt) { NBTTagCompound tag = edges.getCompoundTagAt(i); GraphClassType type = GraphClassRegistry.getTypeNullable(tag.getString("ClassType")); Object o = type == null ? null : type.getNew(backedNet); - GraphEdge graphEdge = new GraphEdge(o instanceof NetEdge e ? e : backedNet.getDefaultEdgeType().getNew(backedNet)); + GraphEdge graphEdge = new GraphEdge( + o instanceof NetEdge e ? e : backedNet.getDefaultEdgeType().getNew(backedNet)); this.getGraph().addEdge(vertexMap.get(tag.getInteger("SourceID")), vertexMap.get(tag.getInteger("TargetID")), graphEdge); this.getGraph().setEdgeWeight(graphEdge, tag.getDouble("Weight")); diff --git a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java index c752b39b278..2bac02acbc7 100644 --- a/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java +++ b/src/main/java/gregtech/api/graphnet/MultiNodeHelper.java @@ -3,10 +3,8 @@ import gregtech.api.graphnet.logic.INetLogicEntryListener; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; - import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.net.NetNode; - import gregtech.api.graphnet.pipenet.WorldPipeNode; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; diff --git a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java index 1fe33d04bb5..cf89034c41d 100644 --- a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java @@ -1,8 +1,8 @@ package gregtech.api.graphnet.edge; -import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java index 92063f0342f..44a22746b09 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java @@ -2,10 +2,9 @@ import gregtech.api.GTValues; import gregtech.api.graphnet.GraphClassType; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.predicate.EdgePredicateHandler; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; @@ -19,7 +18,8 @@ public class NetEdge implements INBTSerializable { - public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "NetEdge", n -> new NetEdge()); + public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "NetEdge", + n -> new NetEdge()); /** * For interacting with the internal graph representation ONLY, do not use or set this field otherwise. diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java index bc74ea386f0..ca3238d7f47 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java @@ -15,7 +15,8 @@ public class NetFlowEdge extends AbstractNetFlowEdge { public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "NetFlowEdge", - n -> n instanceof FlowBufferTickProvider p ? new NetFlowEdge(p.getFlowBufferTicks(), p.getRegenerationTime()) : new NetFlowEdge(10)); + n -> n instanceof FlowBufferTickProvider p ? + new NetFlowEdge(p.getFlowBufferTicks(), p.getRegenerationTime()) : new NetFlowEdge(10)); private final int flowBufferTicks; private final int regenerationTime; diff --git a/src/main/java/gregtech/api/graphnet/graph/INetGraph.java b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java index 96499a11b87..da7af889543 100644 --- a/src/main/java/gregtech/api/graphnet/graph/INetGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java @@ -1,10 +1,5 @@ package gregtech.api.graphnet.graph; -import gregtech.api.graphnet.GraphNetBacker; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import org.jetbrains.annotations.ApiStatus; import org.jgrapht.Graph; public interface INetGraph extends Graph { diff --git a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java index af14e6abcd6..44f1128e704 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java @@ -19,7 +19,8 @@ public boolean isDirected() { } public static Function standardBuilder() { - return iGraphNet -> new NetDirectedGraph(() -> new GraphVertex(iGraphNet.getDefaultNodeType().getNew(iGraphNet)), + return iGraphNet -> new NetDirectedGraph( + () -> new GraphVertex(iGraphNet.getDefaultNodeType().getNew(iGraphNet)), () -> new GraphEdge(iGraphNet.getDefaultEdgeType().getNew(iGraphNet))); } } diff --git a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java index 4fdbf04d5a1..7ab4b4dd732 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java @@ -19,7 +19,8 @@ public boolean isDirected() { } public static Function standardBuilder() { - return iGraphNet -> new NetUndirectedGraph(() -> new GraphVertex(iGraphNet.getDefaultNodeType().getNew(iGraphNet)), + return iGraphNet -> new NetUndirectedGraph( + () -> new GraphVertex(iGraphNet.getDefaultNodeType().getNew(iGraphNet)), () -> new GraphEdge(iGraphNet.getDefaultEdgeType().getNew(iGraphNet))); } } diff --git a/src/main/java/gregtech/api/graphnet/group/GroupData.java b/src/main/java/gregtech/api/graphnet/group/GroupData.java index 18a2428f4d8..14966bfb461 100644 --- a/src/main/java/gregtech/api/graphnet/group/GroupData.java +++ b/src/main/java/gregtech/api/graphnet/group/GroupData.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.group; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.net.NetNode; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; diff --git a/src/main/java/gregtech/api/graphnet/group/NetGroup.java b/src/main/java/gregtech/api/graphnet/group/NetGroup.java index d7ca4bd9b79..b9789d210f3 100644 --- a/src/main/java/gregtech/api/graphnet/group/NetGroup.java +++ b/src/main/java/gregtech/api/graphnet/group/NetGroup.java @@ -1,9 +1,9 @@ package gregtech.api.graphnet.group; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.traverse.iter.EdgeDirection; import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; diff --git a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java index 5099c2ecc64..31c3dc70bac 100644 --- a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java +++ b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.group; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.path.PathBuilder; import gregtech.api.graphnet.path.SingletonNetPath; diff --git a/src/main/java/gregtech/api/graphnet/net/BlankNetNode.java b/src/main/java/gregtech/api/graphnet/net/BlankNetNode.java index 44c8ba62bd5..5ba8e48d8da 100644 --- a/src/main/java/gregtech/api/graphnet/net/BlankNetNode.java +++ b/src/main/java/gregtech/api/graphnet/net/BlankNetNode.java @@ -7,7 +7,8 @@ public final class BlankNetNode extends NetNode { - public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "BlankNode", BlankNetNode::new); + public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "BlankNode", + BlankNetNode::new); public BlankNetNode(@NotNull IGraphNet net) { super(net); diff --git a/src/main/java/gregtech/api/graphnet/net/BlockPosNode.java b/src/main/java/gregtech/api/graphnet/net/BlockPosNode.java index 358ca4f1242..69bc4ef54fb 100644 --- a/src/main/java/gregtech/api/graphnet/net/BlockPosNode.java +++ b/src/main/java/gregtech/api/graphnet/net/BlockPosNode.java @@ -10,7 +10,8 @@ public class BlockPosNode extends NetNode { - public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "BlockPosNode", BlockPosNode::new); + public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "BlockPosNode", + BlockPosNode::new); private BlockPos pos; diff --git a/src/main/java/gregtech/api/graphnet/net/WorldSavedNet.java b/src/main/java/gregtech/api/graphnet/net/WorldSavedNet.java index 74700cc0097..4c9dd204f9c 100644 --- a/src/main/java/gregtech/api/graphnet/net/WorldSavedNet.java +++ b/src/main/java/gregtech/api/graphnet/net/WorldSavedNet.java @@ -7,9 +7,6 @@ import gregtech.api.graphnet.graph.NetUndirectedGraph; import gregtech.api.graphnet.logic.WeightFactorLogic; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.net.NetNode; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.storage.WorldSavedData; diff --git a/src/main/java/gregtech/api/graphnet/path/NetPath.java b/src/main/java/gregtech/api/graphnet/path/NetPath.java index 2629cb13906..476cf2c3afb 100644 --- a/src/main/java/gregtech/api/graphnet/path/NetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/NetPath.java @@ -1,8 +1,8 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.net.NetNode; import com.google.common.collect.ImmutableCollection; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/path/PathBuilder.java b/src/main/java/gregtech/api/graphnet/path/PathBuilder.java index 5aa8956da80..c5c1f81371b 100644 --- a/src/main/java/gregtech/api/graphnet/path/PathBuilder.java +++ b/src/main/java/gregtech/api/graphnet/path/PathBuilder.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java b/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java index 35d26798190..7828fd498ca 100644 --- a/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java @@ -1,9 +1,9 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.net.NetNode; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableSet; diff --git a/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java b/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java index f69b29cf86e..9dec6fdc586 100644 --- a/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java @@ -1,8 +1,8 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.net.NetNode; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeWithCovers.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeWithCovers.java index cb2abf7a6c6..672039be8b4 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeWithCovers.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeWithCovers.java @@ -6,5 +6,6 @@ public interface NodeWithCovers { - @Nullable CoverableView getCoverableView(); + @Nullable + CoverableView getCoverableView(); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeWithFacingToOthers.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeWithFacingToOthers.java index 649fc55f083..df1fb9faab2 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeWithFacingToOthers.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeWithFacingToOthers.java @@ -9,5 +9,6 @@ public interface NodeWithFacingToOthers { - @Nullable EnumFacing getFacingToOther(@NotNull NetNode other); + @Nullable + EnumFacing getFacingToOther(@NotNull NetNode other); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java index cfc7577c547..00da7d3a722 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java @@ -4,16 +4,13 @@ import gregtech.api.graphnet.GraphClassType; import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.net.NetNode; - import gregtech.api.util.FacingPos; - import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; - import net.minecraftforge.common.capabilities.ICapabilityProvider; import org.jetbrains.annotations.NotNull; @@ -23,7 +20,8 @@ public class WorldPipeCapConnectionNode extends NetNode implements NodeWithFacin public static final int SORTING_KEY = 432; - public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "WorldPipeCapConnectionNode", + public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, + "WorldPipeCapConnectionNode", WorldPipeCapConnectionNode::resolve); private FacingPos posAndFacing; @@ -35,7 +33,8 @@ public WorldPipeCapConnectionNode(WorldPipeNet net) { private static WorldPipeCapConnectionNode resolve(IGraphNet net) { if (net instanceof WorldPipeNet w) return new WorldPipeCapConnectionNode(w); - GTLog.logger.fatal("Attempted to initialize a WorldPipeCapConnectionNode to a non-WorldPipeNet. If relevant NPEs occur later, this is most likely the cause."); + GTLog.logger.fatal( + "Attempted to initialize a WorldPipeCapConnectionNode to a non-WorldPipeNet. If relevant NPEs occur later, this is most likely the cause."); return null; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index f8c9683c40d..09d2482be58 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -3,11 +3,11 @@ import gregtech.api.cover.Cover; import gregtech.api.cover.CoverableView; import gregtech.api.graphnet.GraphClassType; -import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.MultiNodeHelper; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.net.WorldSavedNet; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; @@ -16,13 +16,10 @@ import gregtech.api.graphnet.predicate.EdgePredicate; import gregtech.api.graphnet.predicate.NetPredicateType; import gregtech.api.graphnet.traverse.iter.EdgeDirection; -import gregtech.api.util.GTUtility; import gregtech.api.util.IDirtyNotifiable; import gregtech.api.util.reference.WeakHashSet; import gregtech.common.covers.CoverShutter; -import it.unimi.dsi.fastutil.objects.Object2ObjectMap; - import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -38,7 +35,6 @@ import org.jetbrains.annotations.Nullable; import java.util.Collections; -import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -180,7 +176,8 @@ public IPipeCapabilityObject[] getNewCapabilityObjects(WorldPipeNode node) { return null; } - public abstract PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEntity owner, @NotNull WorldPipeNode node); + public abstract PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEntity owner, + @NotNull WorldPipeNode node); @Override public @NotNull GraphClassType getDefaultNodeType() { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNode.java index 0045db5d502..410ce2d37d0 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNode.java @@ -4,22 +4,18 @@ import gregtech.api.cover.CoverableView; import gregtech.api.graphnet.GraphClassType; import gregtech.api.graphnet.MultiNodeHelper; -import gregtech.api.graphnet.net.BlankNetNode; +import gregtech.api.graphnet.net.BlockPosNode; import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.net.BlockPosNode; - import gregtech.api.util.GTLog; - import gregtech.api.util.GTUtility; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; - import net.minecraftforge.common.capabilities.ICapabilityProvider; import org.jetbrains.annotations.NotNull; @@ -27,7 +23,8 @@ import java.lang.ref.WeakReference; -public class WorldPipeNode extends BlockPosNode implements NodeWithFacingToOthers, NodeWithCovers, NodeExposingCapabilities { +public class WorldPipeNode extends BlockPosNode + implements NodeWithFacingToOthers, NodeWithCovers, NodeExposingCapabilities { public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "WorldPipeNode", WorldPipeNode::resolve); @@ -45,7 +42,8 @@ public WorldPipeNode(WorldPipeNet net) { private static WorldPipeNode resolve(IGraphNet net) { if (net instanceof WorldPipeNet w) return new WorldPipeNode(w); - GTLog.logger.fatal("Attempted to initialize a WorldPipeNode to a non-WorldPipeNet. If relevant NPEs occur later, this is most likely the cause."); + GTLog.logger.fatal( + "Attempted to initialize a WorldPipeNode to a non-WorldPipeNet. If relevant NPEs occur later, this is most likely the cause."); return null; } @@ -117,7 +115,8 @@ public boolean traverse(long queryTick, boolean simulate) { @Override public @Nullable EnumFacing getFacingToOther(@NotNull NetNode other) { - return other instanceof WorldPipeNode n ? GTUtility.getFacingToNeighbor(this.getEquivalencyData(), n.getEquivalencyData()) : null; + return other instanceof WorldPipeNode n ? + GTUtility.getFacingToNeighbor(this.getEquivalencyData(), n.getEquivalencyData()) : null; } @Override diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index ad5f4b31eee..d49b90e9521 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -2,11 +2,11 @@ import gregtech.api.GTValues; import gregtech.api.graphnet.MultiNodeHelper; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.logic.INetLogicEntryListener; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.NetLogicType; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.IFreezable; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java index aea849a80ff..5e90e262d9d 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java @@ -5,9 +5,7 @@ import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; - import net.minecraftforge.common.capabilities.ICapabilityProvider; - import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java index e500e26690d..8685502d631 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java @@ -3,18 +3,14 @@ import gregtech.api.cover.CoverableView; import gregtech.api.graphnet.pipenet.WorldPipeNode; -import net.minecraft.entity.EntityLivingBase; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; -import net.minecraft.util.EnumParticleTypes; - import net.minecraftforge.common.capabilities.ICapabilityProvider; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.EnumMap; -import java.util.function.Consumer; public interface IWorldPipeNetTile extends ICapabilityProvider { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java index 890aa28504f..e5f81fefa1c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java @@ -3,16 +3,13 @@ import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.WorldPipeCapConnectionNode; import gregtech.api.graphnet.pipenet.WorldPipeNode; - import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.util.FacingPos; -import it.unimi.dsi.fastutil.objects.Object2ObjectMap; - import net.minecraft.util.EnumFacing; - import net.minecraftforge.common.capabilities.Capability; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java index 907b577619e..ac3eae52011 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java @@ -1,17 +1,13 @@ package gregtech.api.graphnet.pipenet.physical.tile; import gregtech.api.graphnet.pipenet.WorldPipeNode; - import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; -import it.unimi.dsi.fastutil.objects.Object2ObjectMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; - import net.minecraftforge.common.capabilities.ICapabilityProvider; +import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import org.jetbrains.annotations.NotNull; public class PipeCapabilityWrapper implements ICapabilityProvider { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index 64cceaedc83..a4265566caf 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -785,5 +785,4 @@ public void getCoverBoxes(Consumer consumer) { } } } - } diff --git a/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java index a1eabc1ee45..5d6de88f5ea 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java @@ -1,10 +1,9 @@ package gregtech.api.graphnet.traverse; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; - +import gregtech.api.graphnet.net.NetNode; import gregtech.api.util.GTUtility; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -86,6 +85,7 @@ public Function getNodeSupply() { protected abstract int getCapacity(NetEdge edge); public static class EvaluationResult { + public static final EvaluationResult EMPTY = new EvaluationResult(0, 0); protected final Object2IntOpenHashMap flowMap; diff --git a/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java index a8ff077e545..1ebcf241f58 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java @@ -1,17 +1,14 @@ package gregtech.api.graphnet.traverse; -import com.github.bsideup.jabel.Desugar; - -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; - +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.util.GTUtility; - import gregtech.api.util.function.ToBooleanFunction; +import com.github.bsideup.jabel.Desugar; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; @@ -30,7 +27,7 @@ public class EQTraverse extends AbstractMinCostTraverse { protected final ToIntFunction capacityFunction; protected final ToIntFunction supplyFunction; protected @Nullable ToBooleanFunction lossyNodes; - + protected final Set suppliers; protected final Set consumers; protected TestCase testCase; diff --git a/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java index d9949e7707b..44a6da84ab5 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java @@ -1,11 +1,10 @@ package gregtech.api.graphnet.traverse; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; - +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.util.function.ToBooleanFunction; import org.jetbrains.annotations.NotNull; @@ -31,7 +30,8 @@ public static void flood(@NotNull IGraphNet net, if (!net.getGraph().isDirected()) { throw new IllegalArgumentException("Cannot perform flood traverse logic on undirected graph!"); } - EvaluationResult result = new FDTraverse(net.getGraph(), capacityFunction, supplyFunction, lossyNodes).evaluate(); + EvaluationResult result = new FDTraverse(net.getGraph(), capacityFunction, supplyFunction, lossyNodes) + .evaluate(); if (result.isEmpty()) return; result.getFlowMap().forEach(flowReporterEdge::accept); result.getSupplyMap().forEach(flowReporterNode::accept); diff --git a/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java index bcbee5fe014..243cb5534ac 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java @@ -1,11 +1,10 @@ package gregtech.api.graphnet.traverse; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; - +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.util.function.ToBooleanFunction; import org.jetbrains.annotations.NotNull; @@ -26,7 +25,8 @@ public class RRTraverse extends AbstractMinCostTraverse { protected Pair nextPair; - public static void roundRobin(@NotNull IGraphNet net, Supplier<@Nullable Pair> nextNodePairSupplier, + public static void roundRobin(@NotNull IGraphNet net, + Supplier<@Nullable Pair> nextNodePairSupplier, @NotNull ObjIntConsumer flowReporterNode, @NotNull ObjIntConsumer flowReporterEdge, @NotNull ToIntFunction capacityFunction, diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java index 27c235544cd..fd73438fd41 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java @@ -1,10 +1,10 @@ package gregtech.api.graphnet.traverse.iter; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java index b20d1240fcd..e2a212c0d86 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java @@ -1,9 +1,9 @@ package gregtech.api.graphnet.traverse.iter; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java index fb3694ab073..71ce56077a8 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.traverse.iter; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java index b826b7bb297..4f0a6d06fa8 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java @@ -1,8 +1,8 @@ package gregtech.api.graphnet.traverseold; +import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java index 3351d1284ff..fb3c8ac41e9 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java index 0f5b8160ea3..442ac68eae2 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java @@ -1,9 +1,9 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import gregtech.api.graphnet.traverseold.util.ReversibleLossOperator; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java b/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java index 520fa25f779..82d8f1840ed 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; import net.minecraft.util.EnumFacing; diff --git a/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java index cd71e42f275..9ed31fbd28d 100644 --- a/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java +++ b/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java @@ -1,8 +1,8 @@ package gregtech.api.graphnet.traverseold; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.traverseold.util.FlowConsumptionStack; import gregtech.api.util.GTUtility; diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index dae73a4fc5b..9c832b0eb5c 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -933,9 +933,9 @@ public static EntityPlayer getSP() { } /** - * @param minValue the minimum possible succeeding value - * @param maxValue the maximum possible succeeding value - * @param test the predicate to query for success + * @param minValue the minimum possible succeeding value + * @param maxValue the maximum possible succeeding value + * @param test the predicate to query for success * @param ascending determines the direction of search * @return the smallest succeeding value if ascending, or the largest succeeding value if descending. */ @@ -1023,7 +1023,8 @@ public static int moveACloserTo0ByB(int a, int b) { public static void spawnParticles(World world, EnumFacing direction, EnumParticleTypes particleType, BlockPos pos, int particleCount) { - spawnParticles(world, direction, particleType, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, particleCount); + spawnParticles(world, direction, particleType, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, + particleCount); } public static void spawnParticles(World world, EnumFacing direction, EnumParticleTypes particleType, Entity entity, @@ -1032,7 +1033,8 @@ public static void spawnParticles(World world, EnumFacing direction, EnumParticl spawnParticles(world, direction, particleType, vec.x, vec.y, vec.y, particleCount); } - public static void spawnParticles(World world, EnumFacing direction, EnumParticleTypes particleType, double x, double y, double z, + public static void spawnParticles(World world, EnumFacing direction, EnumParticleTypes particleType, double x, + double y, double z, int particleCount) { if (world instanceof WorldServer server) { server.spawnParticle(particleType, diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 884442d54e8..3f463d0a64f 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -9,10 +9,9 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; -import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.graphnet.traverseold.TraverseHelpers; diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index ece1cf7264f..c4797f67228 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -3,8 +3,8 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.FluidTestObject; diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index 96fe5a92aec..ce13ce4a0aa 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -9,8 +9,8 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithFluidFilter; -import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.pipenet.transfer.TransferControl; import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 87a7e45c2b4..15f131cb6fc 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -3,8 +3,8 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; import gregtech.api.graphnet.predicate.test.ItemTestObject; diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index b4ebbabf3b3..308e255e855 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -3,9 +3,9 @@ import gregtech.api.GTValues; import gregtech.api.fluids.FluidBuilder; import gregtech.api.fluids.store.FluidStorageKeys; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index 6b5207e5dd7..c6f7378096d 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -4,11 +4,11 @@ import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index 42cbb7e076c..054f813d05b 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -1,10 +1,10 @@ package gregtech.common.pipelike.handlers.properties; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index e0700d8b830..074af38e057 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -2,10 +2,10 @@ import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.IEnergyContainer; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.group.PathCacheGroupData; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; @@ -80,7 +80,8 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage available -= allowed; if (!simulate) { flow.report(); - controller.insertToHandler(flow.voltageOut(), flow.amperageOut(), container, capability.getKey(), false); + controller.insertToHandler(flow.voltageOut(), flow.amperageOut(), container, + capability.getKey(), false); } } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java index aa83d9ed38c..ff22ea1ffe7 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java @@ -1,7 +1,7 @@ package gregtech.common.pipelike.net.energy; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.group.PathCacheGroupData; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.path.PathBuilder; import gregtech.api.graphnet.traverse.iter.NetIteratorSupplier; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java index cfefae11d9a..601c506aeed 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java @@ -1,10 +1,10 @@ package gregtech.common.pipelike.net.energy; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.PathBuilder; import gregtech.api.graphnet.path.SingletonNetPath; import gregtech.api.graphnet.path.StandardNetPath; @@ -272,7 +272,7 @@ public static final class StandardReport implements PathFlowReport { private final long voltage; private final Runnable[] report; - public StandardReport(long amperage, long voltage, @NotNull Runnable @NotNull ... report) { + public StandardReport(long amperage, long voltage, @NotNull Runnable @NotNull... report) { this.amperage = amperage; this.voltage = voltage; this.report = report; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java index 0085ba53f8c..55413b0cfa9 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java @@ -9,11 +9,10 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.traverse.iter.NetClosestIterator; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; public final class WorldEnergyNet extends WorldPipeNet { diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index 81007232a4a..2b590b432b2 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -1,7 +1,6 @@ package gregtech.common.pipelike.net.fluid; import gregtech.api.fluids.FluidState; -import gregtech.api.fluids.attribute.AttributedFluid; import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.NetEdge; @@ -16,7 +15,6 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.traverse.FDTraverse; - import gregtech.api.util.GTUtility; import net.minecraft.util.EnumFacing; @@ -25,7 +23,6 @@ import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidTankProperties; -import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -137,7 +134,8 @@ protected FluidStack drain(FluidStack resource, boolean doDrain, EnumFacing side return testObject.recombine(report.get()); } - protected void reportFlow(NetEdge edge, int flow, FluidTestObject testObject, SimulatorKey key, boolean sourceBias) { + protected void reportFlow(NetEdge edge, int flow, FluidTestObject testObject, SimulatorKey key, + boolean sourceBias) { if (edge instanceof AbstractNetFlowEdge n) n.consumeFlowLimit(testObject, node.getNet(), flow, getQueryTick(), key); if (key == null) { @@ -152,7 +150,6 @@ protected void reportFlow(NetEdge edge, int flow, FluidTestObject testObject, Si } } - protected void reportFlow(NetNode node, int flow, FluidTestObject testObject) { if (flow == 0) return; FluidContainmentLogic logic = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE); @@ -168,7 +165,8 @@ protected void reportFlow(NetNode node, int flow, FluidTestObject testObject) { FluidState state = FluidState.inferState(stack); if (!logic.contains(state)) state.handleFailure(tile.getWorld(), tile.getPos(), stack); } else if (node instanceof NodeExposingCapabilities exposer) { - IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, exposer.exposedFacing()); + IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + exposer.exposedFacing()); if (handler != null) { // positive flow is supply, aka we pulled flow from this node if (flow > 0) { @@ -182,7 +180,8 @@ protected void reportFlow(NetNode node, int flow, FluidTestObject testObject) { protected int getSupply(NetNode node, FluidTestObject testObject, boolean supply) { if (node instanceof NodeExposingCapabilities exposer) { - IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, exposer.exposedFacing()); + IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + exposer.exposedFacing()); if (handler != null) { if (supply) { FluidStack s = handler.drain(testObject.recombine(Integer.MAX_VALUE), false); diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java index e94a4241d97..735f32b39b4 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidContainmentLogic.java @@ -13,11 +13,9 @@ import net.minecraft.nbt.NBTTagString; import net.minecraft.network.PacketBuffer; import net.minecraft.util.ResourceLocation; - -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; - import net.minecraftforge.fluids.FluidStack; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 5c50bb2bb89..6aba5d44b6b 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -3,9 +3,9 @@ import gregtech.api.cover.Cover; import gregtech.api.cover.filter.CoverWithFluidFilter; import gregtech.api.graphnet.GraphClassType; -import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; @@ -18,12 +18,11 @@ import gregtech.common.covers.ManualImportExportMode; import gregtech.common.pipelike.net.item.WorldItemNet; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index c0cacba9f4a..3a0fd6b77f2 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -10,14 +10,10 @@ import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.graphnet.traverse.FDTraverse; - import gregtech.api.util.GTUtility; -import gregtech.common.pipelike.net.fluid.FluidFlowLogic; - import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; @@ -121,7 +117,8 @@ protected void reportFlow(NetEdge edge, int flow, ItemTestObject testObject, Sim protected void reportFlow(NetNode node, int flow, ItemTestObject testObject) { if (flow == 0) return; if (node instanceof NodeExposingCapabilities exposer) { - IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, exposer.exposedFacing()); + IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, + exposer.exposedFacing()); if (handler != null) { // positive flow is supply, aka we pulled flow from this node if (flow > 0) { @@ -134,7 +131,7 @@ protected void reportFlow(NetNode node, int flow, ItemTestObject testObject) { if (flow == 0) return; } } else { - for (int i = 0; i < handler.getSlots() ; i++) { + for (int i = 0; i < handler.getSlots(); i++) { ItemStack stack = testObject.recombineSafe(flow); flow -= stack.getCount() - handler.insertItem(i, stack, false).getCount(); if (flow == 0) return; @@ -146,18 +143,19 @@ protected void reportFlow(NetNode node, int flow, ItemTestObject testObject) { protected int getSupply(NetNode node, ItemTestObject testObject, boolean supply) { if (node instanceof NodeExposingCapabilities exposer) { - IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, exposer.exposedFacing()); + IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, + exposer.exposedFacing()); if (handler != null) { if (supply) { int sum = 0; - for (int i = 0; i < handler.getSlots() ; i++) { + for (int i = 0; i < handler.getSlots(); i++) { ItemStack stack = handler.extractItem(i, Integer.MAX_VALUE, true); if (testObject.test(stack)) sum += stack.getCount(); } return sum; } else { int sum = 0; - for (int i = 0; i < handler.getSlots() ; i++) { + for (int i = 0; i < handler.getSlots(); i++) { ItemStack stack = testObject.recombineSafe(Integer.MAX_VALUE); sum += stack.getCount() - handler.insertItem(i, stack, true).getCount(); } diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 2145b43380a..5953c8a5bf4 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -4,9 +4,9 @@ import gregtech.api.cover.filter.CoverWithItemFilter; import gregtech.api.graphnet.GraphClassType; import gregtech.api.graphnet.edge.FlowBufferTickProvider; -import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; @@ -19,12 +19,11 @@ import gregtech.common.covers.ManualImportExportMode; import gregtech.common.pipelike.net.fluid.WorldFluidNet; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.items.CapabilityItemHandler; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java index f7bcf02064d..65d67a6ca55 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java @@ -2,8 +2,8 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.ILaserRelay; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.group.PathCacheGroupData; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.path.SingletonNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNode; diff --git a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java index d943e514087..614b9d1c9f0 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java @@ -1,6 +1,5 @@ package gregtech.common.pipelike.net.laser; -import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.group.PathCacheGroupData; @@ -11,13 +10,10 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; -import gregtech.common.pipelike.net.energy.EnergyCapabilityObject; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index 4478dd69830..28ac7fcb0f7 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -4,8 +4,8 @@ import gregtech.api.capability.data.IDataAccess; import gregtech.api.capability.data.query.DataAccessFormat; import gregtech.api.capability.data.query.DataQueryObject; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.group.PathCacheGroupData; +import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.path.SingletonNetPath; import gregtech.api.graphnet.pipenet.WorldPipeNode; diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java index eb37ed63be0..85b7cc9202f 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -1,6 +1,5 @@ package gregtech.common.pipelike.net.optical; -import gregtech.api.capability.GregtechCapabilities; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.group.PathCacheGroupData; @@ -11,13 +10,10 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; -import gregtech.common.pipelike.net.energy.EnergyCapabilityObject; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; From b1fc4a9252ec337bea98bc28d991c7dab2ec6fdc Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Thu, 19 Dec 2024 20:46:31 -0700 Subject: [PATCH 150/157] covers & cleanup to compile :lets: --- .../api/capability/impl/ItemHandlerList.java | 2 +- .../api/graphnet/graph/GraphEdge.java | 7 + .../api/graphnet/pipenet/NodeLossCache.java | 77 --- .../api/graphnet/pipenet/NodeLossResult.java | 59 --- .../api/graphnet/pipenet/WorldPipeNet.java | 9 + .../pipenet/logic/TemperatureLogic.java | 55 +- .../physical/IPipeCapabilityObject.java | 5 - .../physical/tile/IWorldPipeNetTile.java | 6 + .../traverse/AbstractTileRoundRobinData.java | 73 --- .../pipenet/traverse/FlowManagerMap.java | 20 - .../pipenet/traverse/ITileFlowManager.java | 14 - .../traverse/LocalTransferInformation.java | 8 - .../pipenet/traverse/RoundRobinCache.java | 82 +++ .../traverse/SimpleTileRoundRobinData.java | 41 -- .../api/graphnet/traverse/EQTraverse.java | 35 +- .../api/graphnet/traverse/FDTraverse.java | 48 +- .../api/graphnet/traverse/RRTraverse.java | 69 +-- .../graphnet/traverse/iter/EdgeDirection.java | 3 +- .../graphnet/traverse/iter/EdgeSelector.java | 23 + .../traverse/iter/NetBreadthIterator.java | 4 +- .../traverse/iter/NetClosestIterator.java | 8 +- .../traverse/iter/NetIteratorSupplier.java | 2 +- .../traverseold/AbstractTraverseData.java | 49 -- .../traverseold/DistributorHelper.java | 24 - .../traverseold/IEqualizableTraverseData.java | 35 -- .../graphnet/traverseold/IRoundRobinData.java | 32 -- .../traverseold/IRoundRobinTraverseData.java | 52 -- .../graphnet/traverseold/ITraverseData.java | 78 --- .../traverseold/ITraverseGuideProvider.java | 15 - .../traverseold/TraverseDataProvider.java | 15 - .../graphnet/traverseold/TraverseGuide.java | 46 -- .../graphnet/traverseold/TraverseHelpers.java | 482 ------------------ .../util/CompleteLossOperator.java | 18 - .../util/CompositeLossOperator.java | 22 - .../traverseold/util/FlatLossOperator.java | 21 - .../util/FlowConsumptionStack.java | 49 -- .../traverseold/util/MultLossOperator.java | 34 -- .../util/ReversibleLossOperator.java | 21 - .../java/gregtech/api/util/GTUtility.java | 5 + .../gregtech/common/covers/CoverConveyor.java | 366 +++++++++---- .../common/covers/CoverFluidFilter.java | 36 +- .../common/covers/CoverFluidRegulator.java | 247 +-------- .../common/covers/CoverItemFilter.java | 35 +- .../gregtech/common/covers/CoverPump.java | 336 ++++++++---- .../common/covers/CoverRoboticArm.java | 253 ++------- .../gregtech/common/covers/CoverShutter.java | 11 +- .../net/energy/EnergyCapabilityObject.java | 17 +- .../net/energy/IEnergyTransferController.java | 47 -- .../net/energy/StandardEnergyPath.java | 7 + .../net/fluid/FluidCapabilityObject.java | 93 ++-- .../net/item/ItemCapabilityObject.java | 43 +- .../net/laser/ILaserTransferController.java | 43 -- .../net/laser/LaserCapabilityObject.java | 7 +- .../net/optical/DataCapabilityObject.java | 9 +- .../optical/IOpticalTransferController.java | 45 -- 55 files changed, 912 insertions(+), 2331 deletions(-) delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/ITileFlowManager.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/LocalTransferInformation.java create mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java create mode 100644 src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/DistributorHelper.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/IEqualizableTraverseData.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinTraverseData.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/ITraverseGuideProvider.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/TraverseGuide.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/util/CompleteLossOperator.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/util/CompositeLossOperator.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/util/FlatLossOperator.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/util/FlowConsumptionStack.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/util/MultLossOperator.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverseold/util/ReversibleLossOperator.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java delete mode 100644 src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java diff --git a/src/main/java/gregtech/api/capability/impl/ItemHandlerList.java b/src/main/java/gregtech/api/capability/impl/ItemHandlerList.java index c696ee00759..78e52c7c72b 100644 --- a/src/main/java/gregtech/api/capability/impl/ItemHandlerList.java +++ b/src/main/java/gregtech/api/capability/impl/ItemHandlerList.java @@ -18,7 +18,7 @@ public class ItemHandlerList implements IItemHandlerModifiable { private final Int2ObjectMap handlerBySlotIndex = new Int2ObjectOpenHashMap<>(); private final Map baseIndexOffset = new IdentityHashMap<>(); - public ItemHandlerList(List itemHandlerList) { + public ItemHandlerList(Iterable itemHandlerList) { int currentSlotIndex = 0; for (IItemHandler itemHandler : itemHandlerList) { if (baseIndexOffset.containsKey(itemHandler)) { diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java index a83af67b4eb..59d19932e61 100644 --- a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java +++ b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java @@ -3,6 +3,7 @@ import gregtech.api.graphnet.edge.NetEdge; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.graph.DefaultWeightedEdge; @@ -19,6 +20,12 @@ public GraphEdge(@NotNull NetEdge wrapped) { wrapped.wrapper = this; } + @Nullable + @Contract("null->null") + public static GraphEdge unwrap(NetEdge e) { + return e == null ? null : e.wrapper; + } + @ApiStatus.Internal public GraphEdge() { this.wrapped = null; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java deleted file mode 100644 index f803c429128..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossCache.java +++ /dev/null @@ -1,77 +0,0 @@ -package gregtech.api.graphnet.pipenet; - -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.api.graphnet.traverseold.ITraverseData; -import gregtech.api.util.TaskScheduler; -import gregtech.api.util.function.Task; - -import net.minecraft.world.World; - -import com.github.bsideup.jabel.Desugar; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; -import java.util.WeakHashMap; - -public class NodeLossCache implements Task { - - private static final WeakHashMap CACHE = new WeakHashMap<>(); - - public static void registerLossResult(Key key, NodeLossResult result, boolean simulating) { - NodeLossCache existing = CACHE.get(key.node().getNet()); - if (existing == null) { - existing = new NodeLossCache(key.node().getNet().getWorld()); - CACHE.put(key.node().getNet(), existing); - } - existing.registerResult(key, result, simulating); - } - - public static @Nullable NodeLossResult getLossResult(Key key, boolean simulating) { - NodeLossCache existing = CACHE.get(key.node().getNet()); - if (existing == null) { - existing = new NodeLossCache(key.node().getNet().getWorld()); - CACHE.put(key.node().getNet(), existing); - } - return existing.getResult(key, simulating); - } - - private final Map cache = new Object2ObjectOpenHashMap<>(); - - private NodeLossCache(World world) { - TaskScheduler.scheduleTask(world, TaskScheduler.weakTask(this)); - } - - public void registerResult(Key key, NodeLossResult result, boolean simulating) { - result.simulated = simulating; - cache.put(key, result); - } - - public @Nullable NodeLossResult getResult(Key key, boolean simulating) { - NodeLossResult result = cache.get(key); - if (!simulating && result != null && result.simulated) result.simulated = false; - return result; - } - - @Override - public boolean run() { - if (cache.isEmpty()) return true; - for (var result : cache.entrySet()) { - if (result.getValue().simulated) continue; - result.getValue().triggerPostAction(result.getKey().node()); - } - cache.clear(); - return true; - } - - public static Key key(WorldPipeNode node, IPredicateTestObject testObject) { - return new Key(node, testObject); - } - - public static Key key(WorldPipeNode node, ITraverseData data) { - return new Key(node, data.getTestObject()); - } - - @Desugar - public record Key(WorldPipeNode node, IPredicateTestObject testObject) {} -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java deleted file mode 100644 index 95e29333915..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeLossResult.java +++ /dev/null @@ -1,59 +0,0 @@ -package gregtech.api.graphnet.pipenet; - -import gregtech.api.graphnet.traverseold.util.CompositeLossOperator; -import gregtech.api.graphnet.traverseold.util.ReversibleLossOperator; - -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Consumer; - -public final class NodeLossResult { - - public static final NodeLossResult IDENTITY = new NodeLossResult(null, ReversibleLossOperator.IDENTITY); - - private final @Nullable Consumer postAction; - private final @NotNull ReversibleLossOperator lossFunction; - - boolean simulated = true; - - public NodeLossResult(@Nullable Consumer postAction, - @NotNull ReversibleLossOperator lossFunction) { - this.postAction = postAction; - this.lossFunction = lossFunction; - } - - @Contract("!null, !null -> new; !null, null -> param1; null, !null -> param2; null, null -> null") - public static NodeLossResult combine(@Nullable NodeLossResult a, @Nullable NodeLossResult b) { - if (a == null) return b; - if (b == null) return a; - Consumer postAction = a.postAction; - if (b.postAction != null) { - if (postAction == null) postAction = b.postAction; - else postAction = postAction.andThen(b.postAction); - } - return new NodeLossResult(postAction, new CompositeLossOperator(a.lossFunction, b.lossFunction)); - } - - public boolean hasPostAction() { - return postAction != null; - } - - public @Nullable Consumer getPostAction() { - return postAction; - } - - public NodeLossResult copy() { - return new NodeLossResult(postAction, lossFunction); - } - - public void triggerPostAction(WorldPipeNode node) { - if (postAction == null) return; - this.postAction.accept(node); - } - - public @NotNull ReversibleLossOperator getLossFunction() { - return lossFunction; - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 09d2482be58..4c754dee6e7 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -188,6 +188,15 @@ public abstract PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEn return (WorldPipeNode) getNode((Object) equivalencyData); } + public @NotNull WorldPipeNode getOrCreateNode(@NotNull BlockPos pos) { + WorldPipeNode node = getNode(pos); + if (node == null) { + node = new WorldPipeNode(this); + addNode(node); + } + return node; + } + protected Stream<@NotNull WorldPipeNet> sameDimensionNetsStream() { return dimensionNets.getOrDefault(this.getDimension(), Collections.emptySet()).stream() .filter(Objects::nonNull); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index d49b90e9521..f87784653ca 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -7,11 +7,9 @@ import gregtech.api.graphnet.logic.NetLogicEntry; import gregtech.api.graphnet.logic.NetLogicType; import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.pipenet.NodeLossResult; import gregtech.api.graphnet.pipenet.physical.IBurnable; import gregtech.api.graphnet.pipenet.physical.IFreezable; -import gregtech.api.graphnet.traverseold.util.CompleteLossOperator; -import gregtech.api.graphnet.traverseold.util.MultLossOperator; +import gregtech.api.util.GTUtility; import gregtech.client.particle.GTOverheatParticle; import net.minecraft.block.state.IBlockState; @@ -92,42 +90,27 @@ public boolean isUnderMinimum(int temperature) { return temperature < getTemperatureMinimum(); } - @Nullable - public NodeLossResult getLossResult(long tick) { - int temp = getTemperature(tick); + public void defaultHandleTemperature(World world, BlockPos pos) { + int temp = getTemperature(GTUtility.getTick()); if (isUnderMinimum(temp)) { - return new NodeLossResult(n -> { - World world = n.getNet().getWorld(); - BlockPos pos = n.getEquivalencyData(); - IBlockState state = world.getBlockState(pos); - if (state.getBlock() instanceof IFreezable freezable) { - freezable.fullyFreeze(state, world, pos); - } else { - world.setBlockToAir(pos); - } - }, CompleteLossOperator.INSTANCE); + IBlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof IFreezable freezable) { + freezable.fullyFreeze(state, world, pos); + } else { + world.setBlockToAir(pos); + } } else if (isOverMaximum(temp)) { - return new NodeLossResult(n -> { - World world = n.getNet().getWorld(); - BlockPos pos = n.getEquivalencyData(); - IBlockState state = world.getBlockState(pos); - if (state.getBlock() instanceof IBurnable burnable) { - burnable.fullyBurn(state, world, pos); - } else { - world.setBlockToAir(pos); - } - }, CompleteLossOperator.INSTANCE); + IBlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof IBurnable burnable) { + burnable.fullyBurn(state, world, pos); + } else { + world.setBlockToAir(pos); + } } else if (isOverPartialBurnThreshold(temp)) { - return new NodeLossResult(n -> { - World world = n.getNet().getWorld(); - BlockPos pos = n.getEquivalencyData(); - IBlockState state = world.getBlockState(pos); - if (state.getBlock() instanceof IBurnable burnable) { - burnable.partialBurn(state, world, pos); - } - }, MultLossOperator.TENTHS[5]); - } else { - return null; + IBlockState state = world.getBlockState(pos); + if (state.getBlock() instanceof IBurnable burnable) { + burnable.partialBurn(state, world, pos); + } } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java index 5e90e262d9d..e169f35808f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/IPipeCapabilityObject.java @@ -6,7 +6,6 @@ import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.fml.common.FMLCommonHandler; import org.jetbrains.annotations.NotNull; @@ -18,8 +17,4 @@ public interface IPipeCapabilityObject extends ICapabilityProvider { default boolean hasCapability(@NotNull Capability capability, EnumFacing facing) { return getCapability(capability, facing) != null; } - - default long getQueryTick() { - return FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java index 8685502d631..34c325e3e1c 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/IWorldPipeNetTile.java @@ -5,6 +5,8 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import net.minecraftforge.common.capabilities.ICapabilityProvider; import org.jetbrains.annotations.NotNull; @@ -24,4 +26,8 @@ public interface IWorldPipeNetTile extends ICapabilityProvider { @NotNull CoverableView getCoverHolder(); + + World getWorld(); + + BlockPos getPos(); } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java deleted file mode 100644 index 3fb7b81a0af..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/AbstractTileRoundRobinData.java +++ /dev/null @@ -1,73 +0,0 @@ -package gregtech.api.graphnet.pipenet.traverse; - -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.WorldPipeNode; -import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; -import gregtech.api.graphnet.traverseold.IRoundRobinData; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.EnumFacing; -import net.minecraftforge.common.capabilities.Capability; - -import org.apache.commons.lang3.mutable.MutableByte; -import org.jetbrains.annotations.MustBeInvokedByOverriders; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; -import java.util.WeakHashMap; - -public abstract class AbstractTileRoundRobinData implements IRoundRobinData { - - private final MutableByte pointer = new MutableByte(); - - // I'm sorry but a weak Object2Byte map doesn't exist - private final Map simulatorMap = new WeakHashMap<>(); - - @Override - @MustBeInvokedByOverriders - public void resetIfFinished(WorldPipeNode node, @Nullable SimulatorKey simulator) { - if (!hasNextInternalDestination(node, simulator)) getPointer(simulator).setValue(0); - } - - public @NotNull MutableByte getPointer(@Nullable SimulatorKey simulator) { - if (simulator == null) return pointer; - MutableByte value = simulatorMap.get(simulator); - if (value == null) { - value = new MutableByte(); - simulatorMap.put(simulator, value); - } - return value; - } - - public final boolean pointerFinished(@Nullable SimulatorKey simulator) { - return pointerFinished(getPointer(simulator)); - } - - public final boolean pointerFinished(@NotNull MutableByte pointer) { - return pointer.byteValue() >= EnumFacing.VALUES.length; - } - - public final EnumFacing getPointerFacing(SimulatorKey simulator) { - MutableByte pointer = getPointer(simulator); - if (pointerFinished(pointer)) throw new IllegalStateException("Pointer is finished!"); - return EnumFacing.VALUES[pointer.byteValue()]; - } - - public boolean hasCapabilityAtPointer(@NotNull Capability capability, WorldPipeNode node, - @Nullable SimulatorKey simulator) { - return getCapabilityAtPointer(capability, node, simulator) != null; - } - - @Nullable - public E getCapabilityAtPointer(@NotNull Capability capability, WorldPipeNode node, - @Nullable SimulatorKey simulator) { - if (pointerFinished(simulator)) return null; - PipeCapabilityWrapper wrapper = node.getTileEntity().getWrapperForNode(node); - EnumFacing pointer = getPointerFacing(simulator); - - if (!wrapper.isActive(pointer) || !wrapper.supports(capability)) return null; - TileEntity target = node.getTileEntity().getTargetWithCapabilities(node, pointer); - return target == null ? null : target.getCapability(capability, pointer.getOpposite()); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java deleted file mode 100644 index ac40dfb3751..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/FlowManagerMap.java +++ /dev/null @@ -1,20 +0,0 @@ -package gregtech.api.graphnet.pipenet.traverse; - -import gregtech.api.graphnet.pipenet.WorldPipeNode; - -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; - -import java.util.function.Function; - -public class FlowManagerMap extends Object2ObjectOpenHashMap { - - private final Function newSupplier; - - public FlowManagerMap(Function newSupplier) { - this.newSupplier = newSupplier; - } - - public ITileFlowManager access(WorldPipeNode node) { - return computeIfAbsent(node, newSupplier); - } -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/ITileFlowManager.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/ITileFlowManager.java deleted file mode 100644 index ae41ecc7af3..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/ITileFlowManager.java +++ /dev/null @@ -1,14 +0,0 @@ -package gregtech.api.graphnet.pipenet.traverse; - -public interface ITileFlowManager { - - default boolean canAcceptFlow() { - return getMaximumFlow() > 0; - } - - long getMaximumFlow(); - - void reportAttemptingFlow(long flow); - - long acceptFlow(long flow); -} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/LocalTransferInformation.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/LocalTransferInformation.java deleted file mode 100644 index e81dea469ae..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/LocalTransferInformation.java +++ /dev/null @@ -1,8 +0,0 @@ -package gregtech.api.graphnet.pipenet.traverse; - -import net.minecraft.util.EnumFacing; - -import com.github.bsideup.jabel.Desugar; - -@Desugar -public record LocalTransferInformation (EnumFacing facing, T controller, C container) {} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java new file mode 100644 index 00000000000..75829eff29c --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java @@ -0,0 +1,82 @@ +package gregtech.api.graphnet.pipenet.traverse; + +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.traverse.iter.NetIterator; + +import com.github.bsideup.jabel.Desugar; + +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.function.Predicate; +import java.util.function.Supplier; + +@Desugar +public record RoundRobinCache(LinkedHashSet sourceCache, LinkedHashSet destCache) { + + public static RoundRobinCache create() { + return new RoundRobinCache(new LinkedHashSet<>(), new LinkedHashSet<>()); + } + + public Supplier> buildSupplier(Collection sourceCandidates, + Collection destCandidates) { + return new CacheSupplier(sourceCandidates, destCandidates); + } + + public RoundRobinCache refresh(NetIterator sources, NetIterator targets) { + sourceCache.removeIf(n -> sources.getSpanningTreeEdge(n) == null); + destCache.removeIf(n -> targets.getSpanningTreeEdge(n) == null); + return this; + } + + public void filter(Predicate sourceFilter, Predicate destFilter) { + sourceCache.removeIf(sourceFilter); + destCache.removeIf(destFilter); + } + + public void clear() { + sourceCache.clear(); + destCache.clear(); + } + + public RoundRobinCache copy() { + return new RoundRobinCache(new LinkedHashSet<>(sourceCache), new LinkedHashSet<>(destCache)); + } + + private static final class CacheSupplier implements Supplier> { + + private final Iterator sourceIterator; + private final Collection destCandidates; + private NetNode nextSource; + private Iterator destIterator; + + public CacheSupplier(Collection sourceCandidates, Collection destCandidates) { + this.destCandidates = destCandidates; + this.destIterator = destCandidates.iterator(); + if (!destIterator.hasNext()) { + sourceIterator = Collections.emptyIterator(); + nextSource = null; + } else { + sourceIterator = sourceCandidates.iterator(); + this.nextSource = sourceIterator.hasNext() ? sourceIterator.next() : null; + } + } + + @Override + public Predicate get() { + if (nextSource == null) { + if (sourceIterator.hasNext()) nextSource = sourceIterator.next(); + if (nextSource == null) return null; + } + if (!destIterator.hasNext()) { + destIterator = destCandidates.iterator(); + if (!destIterator.hasNext()) return null; + nextSource = null; + return get(); + } + NetNode node = destIterator.next(); + return n -> n == nextSource || n == node; + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java deleted file mode 100644 index 0ed4bbe2f69..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/SimpleTileRoundRobinData.java +++ /dev/null @@ -1,41 +0,0 @@ -package gregtech.api.graphnet.pipenet.traverse; - -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.pipenet.WorldPipeNode; - -import net.minecraftforge.common.capabilities.Capability; - -import org.apache.commons.lang3.mutable.MutableByte; -import org.jetbrains.annotations.Nullable; - -public class SimpleTileRoundRobinData extends AbstractTileRoundRobinData { - - private final Capability cap; - - public SimpleTileRoundRobinData(Capability capability) { - this.cap = capability; - } - - @Override - public boolean hasNextInternalDestination(WorldPipeNode node, @Nullable SimulatorKey simulator) { - MutableByte pointer = getPointer(simulator); - byte val = pointer.byteValue(); - progressToNextInternalDestination(node, simulator); - boolean hasNext = !pointerFinished(pointer); - pointer.setValue(val); - return hasNext; - } - - @Override - public void progressToNextInternalDestination(WorldPipeNode node, @Nullable SimulatorKey simulator) { - MutableByte pointer = getPointer(simulator); - pointer.increment(); - while (!pointerFinished(pointer) && !hasCapabilityAtPointer(cap, node, simulator)) { - pointer.increment(); - } - } - - public @Nullable T getAtPointer(WorldPipeNode node, @Nullable SimulatorKey simulator) { - return getCapabilityAtPointer(cap, node, simulator); - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java index 1ebcf241f58..400624d72d1 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java @@ -32,12 +32,29 @@ public class EQTraverse extends AbstractMinCostTraverse { protected final Set consumers; protected TestCase testCase; - public static void equalDistribution(@NotNull IGraphNet net, - @NotNull ObjIntConsumer flowReporterNode, - @NotNull ObjIntConsumer flowReporterEdge, - @NotNull ToIntFunction capacityFunction, - @NotNull ToIntFunction supplyFunction, - @Nullable ToBooleanFunction lossyNodes) { + /** + * Perform equal distribution traverse. Equal distribution traverse draws the same amount from all sources, + * and deposits a separately calculated amount to all sinks. Drawn and deposited amounts will be maximized, + * and loss will be ignored until the final stage of traverse and reporting. + * + * @param net the net + * @param flowReporterNode flow reporter for nodes. Positive values mean draw, negative values mean sink. + * @param flowReporterEdge flow reporter for edges. Always positive. + * @param capacityFunction capacity function for edges. + * @param supplyFunction supply function for nodes. Positive values mean available draw, negative values mean + * available sink. + * @param lossyNodes optional function that marks nodes as lossy. Lossy nodes will eat up to + * {@link Short#MIN_VALUE} flow and their normal supply will be ignored. + * @param lossReporter optional reporter for loss. Always negative. Does nothing if lossy nodes is {@code null}. + * @return the total draw/sink after evaluation. + */ + public static int equalDistribution(@NotNull IGraphNet net, + @NotNull ObjIntConsumer flowReporterNode, + @NotNull ObjIntConsumer flowReporterEdge, + @NotNull ToIntFunction capacityFunction, + @NotNull ToIntFunction supplyFunction, + @Nullable ToBooleanFunction lossyNodes, + @Nullable ObjIntConsumer lossReporter) { if (!net.getGraph().isDirected()) { throw new IllegalArgumentException("Cannot perform equal distribution traverse logic on undirected graph!"); } @@ -57,7 +74,7 @@ public static void equalDistribution(@NotNull IGraphNet net, } } } - if (suppliers.size() == 0 || consumers.size() == 0) return; + if (suppliers.size() == 0 || consumers.size() == 0) return 0; // do some math to determine the working multiples that need to be tested // supplier count * test supply must equal consumer count * test consumption for all tests // naive brute force search for now @@ -88,9 +105,9 @@ public static void equalDistribution(@NotNull IGraphNet net, traverse.testCase = arr[solution]; traverse.lossyNodes = lossyNodes; EvaluationResult result = traverse.evaluate(); - if (result.isEmpty()) return; + if (result.isEmpty()) return 0; result.getFlowMap().forEach(flowReporterEdge::accept); - result.getSupplyMap().forEach(flowReporterNode::accept); + return FDTraverse.reportFlow(flowReporterNode, lossyNodes, lossReporter, result); } protected EQTraverse(Graph graph, ToIntFunction capacityFunction, diff --git a/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java index 44a6da84ab5..e10d84a2845 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java @@ -21,20 +21,35 @@ public class FDTraverse extends AbstractMinCostTraverse { protected final ToIntFunction supplyFunction; protected final ToBooleanFunction lossyNodes; - public static void flood(@NotNull IGraphNet net, - @NotNull ObjIntConsumer flowReporterNode, - @NotNull ObjIntConsumer flowReporterEdge, - @NotNull ToIntFunction capacityFunction, - @NotNull ToIntFunction supplyFunction, - @Nullable ToBooleanFunction lossyNodes) { + /** + * Perform flood traverse. Flood traverse takes the lowest cost (weight) paths while maximizing flow. + * + * @param net the net + * @param flowReporterNode flow reporter for nodes. Positive values mean draw, negative values mean sink. + * @param flowReporterEdge flow reporter for edges. Always positive. + * @param capacityFunction capacity function for edges. + * @param supplyFunction supply function for nodes. Positive values mean available draw, negative values mean + * available sink. + * @param lossyNodes optional function that marks nodes as lossy. Lossy nodes will eat up to + * {@link Short#MIN_VALUE} flow and their normal supply will be ignored. + * @param lossReporter optional reporter for loss. Always negative. Does nothing if lossy nodes is {@code null}. + * @return the total draw/sink after evaluation. + */ + public static int flood(@NotNull IGraphNet net, + @NotNull ObjIntConsumer flowReporterNode, + @NotNull ObjIntConsumer flowReporterEdge, + @NotNull ToIntFunction capacityFunction, + @NotNull ToIntFunction supplyFunction, + @Nullable ToBooleanFunction lossyNodes, + @Nullable ObjIntConsumer lossReporter) { if (!net.getGraph().isDirected()) { throw new IllegalArgumentException("Cannot perform flood traverse logic on undirected graph!"); } EvaluationResult result = new FDTraverse(net.getGraph(), capacityFunction, supplyFunction, lossyNodes) .evaluate(); - if (result.isEmpty()) return; + if (result.isEmpty()) return 0; result.getFlowMap().forEach(flowReporterEdge::accept); - result.getSupplyMap().forEach(flowReporterNode::accept); + return reportFlow(flowReporterNode, lossyNodes, lossReporter, result); } protected FDTraverse(Graph graph, ToIntFunction capacityFunction, @@ -45,6 +60,23 @@ protected FDTraverse(Graph graph, ToIntFunction this.lossyNodes = lossyNodes != null ? lossyNodes : n -> false; } + static int reportFlow(@NotNull ObjIntConsumer flowReporterNode, + @Nullable ToBooleanFunction lossyNodes, + @Nullable ObjIntConsumer lossReporter, @NotNull EvaluationResult result) { + int flow = 0; + for (var entry : result.getSupplyMap().object2IntEntrySet()) { + NetNode n = entry.getKey(); + int i = entry.getIntValue(); + if (lossyNodes != null && lossyNodes.applyAsBool(n)) { + if (lossReporter != null) lossReporter.accept(n, i); + } else { + flowReporterNode.accept(n, i); + } + if (i > 0) flow += i; + } + return flow; + } + @Override protected int getSupply(NetNode node) { if (lossyNodes.applyAsBool(node)) return Short.MIN_VALUE; diff --git a/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java index 243cb5534ac..66a6229c2a1 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java @@ -10,62 +10,67 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; -import org.jgrapht.alg.util.Pair; import java.util.function.ObjIntConsumer; +import java.util.function.Predicate; import java.util.function.Supplier; import java.util.function.ToIntFunction; -public class RRTraverse extends AbstractMinCostTraverse { +public class RRTraverse extends FDTraverse { - protected final Graph graph; - protected final ToIntFunction capacityFunction; - protected final ToIntFunction supplyFunction; - protected final ToBooleanFunction lossyNodes; + protected Predicate nextPredicate; - protected Pair nextPair; - - public static void roundRobin(@NotNull IGraphNet net, - Supplier<@Nullable Pair> nextNodePairSupplier, - @NotNull ObjIntConsumer flowReporterNode, - @NotNull ObjIntConsumer flowReporterEdge, - @NotNull ToIntFunction capacityFunction, - @NotNull ToIntFunction supplyFunction, - @Nullable ToBooleanFunction lossyNodes) { + /** + * Perform round robin traverse. Round robin traverse asks repeatedly for a node predicate; + * each predicate will be evaluated independently using flood traverse, where only nodes that match the predicate + * or have loss are allowed to have supply/demand. + * + * @param net the net + * @param nextNodePredicateSupplier supplier for next predicate. Will be repeatedly queried until it returns null, + * at which point the traverse will exit. + * @param flowReporterNode flow reporter for nodes. Positive values mean draw, negative values mean sink. + * @param flowReporterEdge flow reporter for edges. Always positive. + * @param capacityFunction capacity function for edges. + * @param supplyFunction supply function for nodes. Positive values mean available draw, negative values + * mean available sink. + * @param lossyNodes optional function that marks nodes as lossy. Lossy nodes will eat up to + * {@link Short#MIN_VALUE} flow and their normal supply will be ignored. + * @param lossReporter optional reporter for loss. Always negative. Does nothing if lossy nodes is + * {@code null}. + * @return the total draw/sink after evaluation. + */ + public static int roundRobin(@NotNull IGraphNet net, + Supplier<@Nullable Predicate> nextNodePredicateSupplier, + @NotNull ObjIntConsumer flowReporterNode, + @NotNull ObjIntConsumer flowReporterEdge, + @NotNull ToIntFunction capacityFunction, + @NotNull ToIntFunction supplyFunction, + @Nullable ToBooleanFunction lossyNodes, + @Nullable ObjIntConsumer lossReporter) { if (!net.getGraph().isDirected()) { throw new IllegalArgumentException("Cannot perform RR traverse logic on undirected graph!"); } RRTraverse traverse = new RRTraverse(net.getGraph(), capacityFunction, supplyFunction, lossyNodes); - while ((traverse.nextPair = nextNodePairSupplier.get()) != null) { + + int flow = 0; + while ((traverse.nextPredicate = nextNodePredicateSupplier.get()) != null) { EvaluationResult result = traverse.evaluate(); if (result.isEmpty()) continue; result.getFlowMap().forEach(flowReporterEdge::accept); - result.getSupplyMap().forEach(flowReporterNode::accept); + flow += reportFlow(flowReporterNode, lossyNodes, lossReporter, result); } + return flow; } protected RRTraverse(Graph graph, ToIntFunction capacityFunction, ToIntFunction supplyFunction, @Nullable ToBooleanFunction lossyNodes) { - this.graph = graph; - this.capacityFunction = capacityFunction; - this.supplyFunction = supplyFunction; - this.lossyNodes = lossyNodes != null ? lossyNodes : n -> false; + super(graph, capacityFunction, supplyFunction, lossyNodes); } @Override protected int getSupply(NetNode node) { if (lossyNodes.applyAsBool(node)) return Short.MIN_VALUE; - if (nextPair == null || nextPair.hasElement(node)) return 0; + if (nextPredicate == null || nextPredicate.test(node)) return 0; return supplyFunction.applyAsInt(node); } - - @Override - protected int getCapacity(NetEdge edge) { - return capacityFunction.applyAsInt(edge); - } - - @Override - public Graph getGraph() { - return graph; - } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java index 1081435b4a6..c32254598d3 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java @@ -4,12 +4,13 @@ import java.util.Set; -public enum EdgeDirection { +public enum EdgeDirection implements EdgeSelector { OUTGOING, INCOMING, ALL; + @Override public Set selectEdges(Graph graph, V vertex) { return switch (this) { case ALL -> graph.edgesOf(vertex); diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java new file mode 100644 index 00000000000..517eb6d8d28 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java @@ -0,0 +1,23 @@ +package gregtech.api.graphnet.traverse.iter; + +import org.jgrapht.Graph; + +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public interface EdgeSelector { + + Set selectEdges(Graph graph, V vertex); + + static EdgeSelector filtered(EdgeSelector prototype, Predicate edgeFilter) { + // can't create via lambda due to generics + return new EdgeSelector() { + + @Override + public Set selectEdges(Graph graph, V vertex) { + return prototype.selectEdges(graph, vertex).stream().filter(edgeFilter).collect(Collectors.toSet()); + } + }; + } +} diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java index fd73438fd41..a1c36f271a1 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java @@ -21,12 +21,12 @@ public class NetBreadthIterator implements NetIterator { * * @param origin the node to start at */ - public NetBreadthIterator(@NotNull NetNode origin, @NotNull EdgeDirection direction) { + public NetBreadthIterator(@NotNull NetNode origin, @NotNull EdgeSelector selector) { this.backer = new BreadthFirstIterator<>(origin.getNet().getGraph(), origin.wrapper) { @Override protected Set selectOutgoingEdges(GraphVertex vertex) { - return direction.selectEdges(graph, vertex); + return selector.selectEdges(graph, vertex); } }; } diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java index e2a212c0d86..6454efcde70 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java @@ -16,14 +16,14 @@ public class NetClosestIterator implements NetIterator { protected final ClosestFirstIterator backer; - protected final EdgeDirection direction; + protected final EdgeSelector selector; /** * Creates a closest-first iterator that traverses a connected component, starting at the given node. * * @param origin the node to start at */ - public NetClosestIterator(@NotNull NetNode origin, EdgeDirection direction) { + public NetClosestIterator(@NotNull NetNode origin, EdgeSelector selector) { this.backer = new ClosestFirstIterator<>(origin.getNet().getGraph(), origin.wrapper) { @Override @@ -31,7 +31,7 @@ protected Set selectOutgoingEdges(GraphVertex vertex) { return selectEdges(graph, vertex); } }; - this.direction = direction; + this.selector = selector; } public ClosestFirstIterator getBacker() { @@ -39,7 +39,7 @@ public ClosestFirstIterator getBacker() { } protected Set selectEdges(Graph graph, GraphVertex vertex) { - return direction.selectEdges(graph, vertex); + return selector.selectEdges(graph, vertex); } @Override diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java index 7f06c842a87..dae29ec1cc1 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java @@ -8,5 +8,5 @@ public interface NetIteratorSupplier { @NotNull - NetIterator create(@NotNull NetNode origin, @NotNull EdgeDirection direction); + NetIterator create(@NotNull NetNode origin, @NotNull EdgeSelector direction); } diff --git a/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java deleted file mode 100644 index 4f0a6d06fa8..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/AbstractTraverseData.java +++ /dev/null @@ -1,49 +0,0 @@ -package gregtech.api.graphnet.traverseold; - -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.path.NetPath; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import org.jetbrains.annotations.Nullable; - -public abstract class AbstractTraverseData> implements ITraverseData { - - private final IGraphNet net; - private final IPredicateTestObject testObject; - private final SimulatorKey simulator; - private final long queryTick; - - public AbstractTraverseData(IGraphNet net, IPredicateTestObject testObject, SimulatorKey simulator, - long queryTick) { - this.net = net; - this.testObject = testObject; - this.simulator = simulator; - this.queryTick = queryTick; - } - - @Override - public IGraphNet getGraphNet() { - return net; - } - - @Override - public IPredicateTestObject getTestObject() { - return testObject; - } - - @Override - public @Nullable SimulatorKey getSimulatorKey() { - return simulator; - } - - public boolean simulating() { - return simulator != null; - } - - @Override - public long getQueryTick() { - return queryTick; - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/DistributorHelper.java b/src/main/java/gregtech/api/graphnet/traverseold/DistributorHelper.java deleted file mode 100644 index cdbdcc23127..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/DistributorHelper.java +++ /dev/null @@ -1,24 +0,0 @@ -package gregtech.api.graphnet.traverseold; - -public class DistributorHelper { - - private final long maximum; - private long consumption; - - public DistributorHelper(long maximum, long consumption) { - this.maximum = maximum; - this.consumption = consumption; - } - - public void addConsumption(long consumption) { - this.consumption += consumption; - } - - public boolean supportsMult(long mult) { - return this.maximum >= this.consumption * mult; - } - - public long withMult(long mult) { - return this.consumption * mult; - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/IEqualizableTraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/IEqualizableTraverseData.java deleted file mode 100644 index 30deb02c815..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/IEqualizableTraverseData.java +++ /dev/null @@ -1,35 +0,0 @@ -package gregtech.api.graphnet.traverseold; - -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.path.NetPath; - -import org.jetbrains.annotations.NotNull; - -public interface IEqualizableTraverseData> extends ITraverseData { - - int getDestinationsAtNode(@NotNull N node); - - /** - * Whether a path should be skipped before running the collection process on it. - * The return of {@link ITraverseData#prepareForPathWalk(NetPath, long)} will be ignored during traversal. - */ - boolean shouldSkipPath(@NotNull P path); - - /** - * Should return how much flow the destination with the smallest maximum allowed flow among destinations at - * this node requires. - */ - long getMaxFlowToLeastDestination(@NotNull N destination); - - /** - * Called in preference to {@link ITraverseData#finalizeAtDestination(NetNode, long)} to provide the equalization. - */ - long finalizeAtDestination(@NotNull N node, long flowReachingNode, int expectedDestinations); - - /** - * @deprecated use {@link #finalizeAtDestination(NetNode, long, int)} instead. - */ - @Override - @Deprecated - long finalizeAtDestination(@NotNull N destination, long flowReachingDestination); -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java deleted file mode 100644 index fb3c8ac41e9..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinData.java +++ /dev/null @@ -1,32 +0,0 @@ -package gregtech.api.graphnet.traverseold; - -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.net.NetNode; - -import org.jetbrains.annotations.Nullable; - -import java.util.Iterator; - -public interface IRoundRobinData { - - /** - * Called to notify this {@link IRoundRobinData} to reset its internals to prepare for iteration over internal - * destinations. If this object has not finished progressing over its internal destinations, this should do nothing. - */ - void resetIfFinished(N node, @Nullable SimulatorKey simulator); - - /** - * Similar to {@link Iterator#hasNext()}, this method determines whether there is another internal destination in - * this {@link IRoundRobinData} to finalize at. When false is returned, the RR traversal will move on from - * this {@link IRoundRobinData} - * - * @return whether another internal destination is present - */ - boolean hasNextInternalDestination(N node, @Nullable SimulatorKey simulator); - - /** - * Similar to {@link Iterator#next()}, this is called to notify this {@link IRoundRobinData} that it should - * progress to the next internal destination. - */ - void progressToNextInternalDestination(N node, @Nullable SimulatorKey simulator); -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinTraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinTraverseData.java deleted file mode 100644 index bb1efb38ae8..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/IRoundRobinTraverseData.java +++ /dev/null @@ -1,52 +0,0 @@ -package gregtech.api.graphnet.traverseold; - -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.path.NetPath; - -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayDeque; - -public interface IRoundRobinTraverseData, N extends NetNode, P extends NetPath> - extends ITraverseData { - - /** - * The traversal cache must be cached and persistent between traversals, - * but not modified by anything external to {@link TraverseHelpers}. - * The traversal cache is (hopefully) modified deterministically between simulated and nonsimulated transfers, but - * remember that modification during simulation must not be reflected on the cache used for nonsimulation. - * The easiest way to accomplish this is to provide a cloned {@link ArrayDeque} during simulated transfers. - * - * @return the traversal cache. - */ - @NotNull - Object2ObjectLinkedOpenHashMap getTraversalCache(); - - /** - * Whether a path should be skipped before checking it against the round robin cache. - * The return of {@link ITraverseData#prepareForPathWalk(NetPath, long)} will be ignored during traversal. - */ - boolean shouldSkipPath(@NotNull P path); - - /** - * @return The {@link IRoundRobinData} for the particular destination. Will be mutated; should then be referenced - * in {@link ITraverseData#finalizeAtDestination(NetNode, long)} to do proper round robin within the - * destination. - */ - @NotNull - T createRRData(@NotNull N destination); - - /** - * Called in preference to {@link ITraverseData#finalizeAtDestination(NetNode, long)} to provide the round robin - * data for the destination. - */ - long finalizeAtDestination(@NotNull T data, @NotNull N destination, long flowReachingDestination); - - /** - * @deprecated use {@link #finalizeAtDestination(IRoundRobinData, NetNode, long)} instead. - */ - @Override - @Deprecated - long finalizeAtDestination(@NotNull N destination, long flowReachingDestination); -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java deleted file mode 100644 index 442ac68eae2..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/ITraverseData.java +++ /dev/null @@ -1,78 +0,0 @@ -package gregtech.api.graphnet.traverseold; - -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.path.NetPath; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; -import gregtech.api.graphnet.traverseold.util.ReversibleLossOperator; - -import org.jetbrains.annotations.MustBeInvokedByOverriders; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface ITraverseData> { - - IGraphNet getGraphNet(); - - IPredicateTestObject getTestObject(); - - @Nullable - SimulatorKey getSimulatorKey(); - - long getQueryTick(); - - /** - * Called before walking the next path. Should reset per-path logics to prepare. - * - * @param path the next path - * @param flow how much flow can be provided to the path. - * @return whether the path should be skipped - */ - boolean prepareForPathWalk(@NotNull P path, long flow); - - /** - * Reports that the traverse is traversing to a node, for additional logic to be run. - * - * @param node the node being traversed - * @param flowReachingNode the flow that has reached this node. - * @return the loss operator for the node. - */ - ReversibleLossOperator traverseToNode(@NotNull N node, long flowReachingNode); - - /** - * Reports that the traverse has finished a path walk, for finalization. - * - * @param destination the active node the path terminated at. - * @param flowReachingDestination the flow that reached the destination - * @return the amount of flow that should be consumed, before walking the next path. - */ - long finalizeAtDestination(@NotNull N destination, long flowReachingDestination); - - /** - * Allows for reporting a smaller capacity along an edge than it actually has. Do not report a larger capacity - * than the actual edge or things will break. - * - * @param edge the edge to get capacity for. - * @return a non-negative capacity that is less than or equal to the true capacity of the edge. - */ - default long getFlowLimit(@NotNull AbstractNetFlowEdge edge) { - return edge.getFlowLimit(this.getTestObject(), this.getGraphNet(), this.getQueryTick(), this.getSimulatorKey()); - } - - /** - * Allows for consuming more than just the edge flow limits on a consumption event. Must always consume the correct - * amount of edge flow or things will break. - * - * @param edge the edge to consume along. - * @param targetNode the target node of the edge. - * @param consumption the amount to consume from the edge's flow limit. - */ - @MustBeInvokedByOverriders - default void consumeFlowLimit(@NotNull AbstractNetFlowEdge edge, NetNode targetNode, - long consumption) { - edge.consumeFlowLimit(this.getTestObject(), this.getGraphNet(), consumption, this.getQueryTick(), - this.getSimulatorKey()); - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/ITraverseGuideProvider.java b/src/main/java/gregtech/api/graphnet/traverseold/ITraverseGuideProvider.java deleted file mode 100644 index 3f97ca91144..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/ITraverseGuideProvider.java +++ /dev/null @@ -1,15 +0,0 @@ -package gregtech.api.graphnet.traverseold; - -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.path.NetPath; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import org.jetbrains.annotations.Nullable; - -public interface ITraverseGuideProvider, T extends IPredicateTestObject> { - - @Nullable - > TraverseGuide getGuide( - TraverseDataProvider provider, T testObject, - long flow, boolean simulate); -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java b/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java deleted file mode 100644 index 82d8f1840ed..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/TraverseDataProvider.java +++ /dev/null @@ -1,15 +0,0 @@ -package gregtech.api.graphnet.traverseold; - -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; - -@FunctionalInterface -public interface TraverseDataProvider, T extends IPredicateTestObject> { - - D of(IGraphNet net, T testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing); -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/TraverseGuide.java b/src/main/java/gregtech/api/graphnet/traverseold/TraverseGuide.java deleted file mode 100644 index ff8a26a1fb8..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/TraverseGuide.java +++ /dev/null @@ -1,46 +0,0 @@ -package gregtech.api.graphnet.traverseold; - -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.path.NetPath; - -import org.jetbrains.annotations.Nullable; - -import java.util.Iterator; -import java.util.function.LongConsumer; -import java.util.function.Supplier; - -public class TraverseGuide, T extends ITraverseData> { - - private final T data; - private final Supplier> pathsSupplier; - private final long flow; - private final LongConsumer consumptionReport; - - public TraverseGuide(T data, Supplier> pathsSupplier, long flow, - @Nullable LongConsumer consumptionReport) { - this.data = data; - this.pathsSupplier = pathsSupplier; - this.flow = flow; - this.consumptionReport = consumptionReport; - } - - public void reportConsumedFlow(long consumedFlow) { - if (consumptionReport != null) consumptionReport.accept(consumedFlow); - } - - public T getData() { - return data; - } - - public Supplier> getPathsSupplier() { - return pathsSupplier; - } - - public Iterator

getPaths() { - return pathsSupplier.get(); - } - - public long getFlow() { - return flow; - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java b/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java deleted file mode 100644 index 9ed31fbd28d..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/TraverseHelpers.java +++ /dev/null @@ -1,482 +0,0 @@ -package gregtech.api.graphnet.traverseold; - -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.path.NetPath; -import gregtech.api.graphnet.traverseold.util.FlowConsumptionStack; -import gregtech.api.util.GTUtility; - -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jgrapht.alg.util.Pair; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.function.LongUnaryOperator; -import java.util.function.Predicate; -import java.util.function.Supplier; - -public final class TraverseHelpers { - - private TraverseHelpers() {} - - /** - * Provides logic for traversing a flow net in a 'flood' manner; - * specifically, find the lowest weight path, fill it to capacity, find the next lowest weight path, etc. - * Requires dynamic weights to function properly. - * - * @param data the traversal data. - * @param paths the paths to traverse. - * @param flowIn the flow to traverse with. - * @return the consumed flow. - */ - public static , - D extends ITraverseData> long traverseFlood( - @NotNull D data, - @NotNull Iterator

paths, - long flowIn) { - boolean simulate = data.getSimulatorKey() != null; - long availableFlow = flowIn; - pathloop: - while (paths.hasNext()) { - List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); - long pathFlow = availableFlow; - P path = paths.next(); - if (data.prepareForPathWalk(path, pathFlow)) continue; - - List nodes = path.getOrderedNodes().asList(); - List edges = path.getOrderedEdges().asList(); - assert nodes.size() == edges.size() + 1; - - FlowConsumptionStack stack = new FlowConsumptionStack(data.traverseToNode(nodes.get(0), pathFlow)); - pathFlow = stack.applyLatestLossFunction(pathFlow); - - for (int i = 0; i < edges.size(); i++) { - E edge = edges.get(i); - N sourceNode = nodes.get(i); - N targetNode = nodes.get(i + 1); - - if (targetNode.traverse(data.getQueryTick(), true)) { - if (!simulate) { - pathTraverseCalls.add(() -> targetNode.traverse(data.getQueryTick(), false)); - } - } else continue pathloop; - - pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); - stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), - data.traverseToNode(targetNode, pathFlow)); - pathFlow = stack.applyLatestLossFunction(pathFlow); - - if (pathFlow <= 0) continue pathloop; - } - - long accepted = data.finalizeAtDestination(nodes.get(nodes.size() - 1), pathFlow); - if (!simulate) pathTraverseCalls.forEach(Runnable::run); - availableFlow -= stack.consumeWithEndValue(accepted); - - if (availableFlow <= 0) break; - } - - return flowIn - availableFlow; - } - - /** - * Provides logic for traversing a net that simply finds the lowest weight path that it can traverse, - * and then traverses it. Optionally supports flow, in which case overflows will be reported - * and paths will be iterated over until flow or paths are exhausted. - * - * @param data the traversal data. - * @param paths the paths to traverse. - * @param overflowListener will be provided with a node and incoming overflow once a path is walked - * and the final overflows are calculated. If null, no overflow logic will be calculated. - * @param flowIn the flow to traverse with. - * @return the consumed flow. - */ - public static , - D extends ITraverseData> long traverseDumb( - @NotNull D data, - @NotNull Iterator

paths, - @Nullable BiConsumer overflowListener, - long flowIn) { - boolean simulate = data.getSimulatorKey() != null; - boolean isFlow = overflowListener != null; - long availableFlow = isFlow ? flowIn : 0; - pathloop: - while (paths.hasNext()) { - List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); - long pathFlow = isFlow ? availableFlow : 1; - P path = paths.next(); - if (data.prepareForPathWalk(path, pathFlow)) continue; - - List nodes = path.getOrderedNodes(); - List edges = path.getOrderedEdges(); - - List overflowReporters = isFlow ? new ObjectArrayList<>() : null; - assert nodes.size() == edges.size() + 1; - - FlowConsumptionStack stack = isFlow ? - new FlowConsumptionStack(data.traverseToNode(nodes.get(0), pathFlow)) : null; - if (isFlow) pathFlow = stack.applyLatestLossFunction(pathFlow); - - for (int i = 0; i < edges.size(); i++) { - E edge = edges.get(i); - N targetNode = nodes.get(i + 1); - - if (targetNode.traverse(data.getQueryTick(), true)) { - if (!simulate) { - pathTraverseCalls.add(() -> targetNode.traverse(data.getQueryTick(), false)); - } - } else continue pathloop; - - if (isFlow) { - AbstractNetFlowEdge flowEdge = (AbstractNetFlowEdge) edge; - long limit = data.getFlowLimit(flowEdge); - long overflow = pathFlow - limit; - if (overflow > 0) { - pathFlow = limit; - overflowReporters.add(reduction -> { - long finalOverflow = overflow - reduction; - if (finalOverflow > 0) { - overflowListener.accept(targetNode, finalOverflow); - return finalOverflow; - } - return 0; - }); - } - stack.add(flow -> data.consumeFlowLimit(flowEdge, targetNode, flow), - data.traverseToNode(targetNode, pathFlow)); - pathFlow = stack.applyLatestLossFunction(pathFlow); - } - } - long accepted = data.finalizeAtDestination(nodes.get(edges.size()), pathFlow); - long unaccepted = pathFlow - accepted; - if (isFlow) { - availableFlow -= stack.consumeWithEndValue(accepted) + - overflowReporters.stream().mapToLong(u -> u.applyAsLong(unaccepted)).sum(); - } - if (!simulate) pathTraverseCalls.forEach(Runnable::run); - - if (availableFlow <= 0) break; - } - - return flowIn - availableFlow; - } - - /** - * Provides logic for traversing a flow net in an equal distribution manner. Operates in the following stages: - *
- *
- * Stage One (collection) -- collect paths into a list while iterating, gathering a map of edges to flow info. - * Get numbers for what is needed to provide 1 flow per node destination per path, ignoring potential loss. - * If a path cannot be traversed, it is either trimmed or we abort based on {@code strict}. - *
- *
- * Stage Two (scaling) -- scale up the mult with a binary search until we get the largest mult where no edge - * capacities are exceeded. If this mult is 0, abort and return 0. - *
- *
- * Stage Three (traversal) -- traverse the collected paths and perform consumption and flow, using the multiplier - * from stage two. - * - * @param data the traversal data. - * @param paths the paths to traverse. - * @param flowIn the flow to traverse with. - * @param strict whether to abort if one of the destination paths cannot be traversed due to node restrictions, - * not edge restrictions. - * @return the consumed flow. - */ - public static , - D extends IEqualizableTraverseData> long traverseEqualDistribution( - @NotNull D data, - @NotNull Iterator

paths, - long flowIn, - boolean strict) { - // collection - Map, DistributorHelper> distributorHelperMap = new Object2ObjectOpenHashMap<>(); - Object2IntOpenHashMap

desiredMap = new Object2IntOpenHashMap<>(); - int totalDesired = 0; - long maxMult = flowIn; - pathsloop: - while (paths.hasNext()) { - P path = paths.next(); - if (data.shouldSkipPath(path)) continue; - - List nodes = path.getOrderedNodes(); - List edges = path.getOrderedEdges(); - assert nodes.size() == edges.size() + 1; - for (N node : nodes) { - if (!node.traverse(data.getQueryTick(), true)) { - if (strict) return 0; - else continue pathsloop; - } - } - N dest = nodes.get(nodes.size() - 1); - int desired = data.getDestinationsAtNode(dest); - totalDesired += desired; - desiredMap.put(path, desired); - maxMult = Math.min(maxMult, data.getMaxFlowToLeastDestination(dest)); - for (int i = 0; i < edges.size(); i++) { - E edge = edges.get(i); - N targetNode = nodes.get(i + 1); - distributorHelperMap.compute(Pair.of(edge, targetNode), (k, v) -> { - if (v == null) { - v = new DistributorHelper(k.getFirst().getFlowLimit(data.getTestObject(), - data.getGraphNet(), data.getQueryTick(), data.getSimulatorKey()), desired); - return v; - } else { - v.addConsumption(desired); - return v; - } - }); - } - } - if (totalDesired == 0) return 0; - maxMult = Math.min(maxMult, flowIn / totalDesired); - // scaling - long mult = GTUtility.binarySearch(0, maxMult, l -> { - for (DistributorHelper helper : distributorHelperMap.values()) { - if (!helper.supportsMult(l)) return false; - } - return true; - }, false); - if (mult == 0) return 0; - // traversal - boolean simulate = data.getSimulatorKey() != null; - long availableFlow = flowIn; - pathloop: - for (var entry : desiredMap.object2IntEntrySet()) { - List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); - long pathFlow = entry.getIntValue() * mult; - P path = entry.getKey(); - - // no skipping paths at this stage - data.prepareForPathWalk(path, pathFlow); - - List nodes = path.getOrderedNodes(); - List edges = path.getOrderedEdges(); - assert nodes.size() == edges.size() + 1; - - FlowConsumptionStack stack = new FlowConsumptionStack(data.traverseToNode(nodes.get(0), pathFlow)); - pathFlow = stack.applyLatestLossFunction(pathFlow); - - for (int i = 0; i < edges.size(); i++) { - E edge = edges.get(i); - N sourceNode = nodes.get(i); - N targetNode = nodes.get(i + 1); - - if (targetNode.traverse(data.getQueryTick(), true)) { - if (!simulate) { - pathTraverseCalls.add(() -> targetNode.traverse(data.getQueryTick(), false)); - } - } else continue pathloop; - - pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); - stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), - data.traverseToNode(targetNode, pathFlow)); - pathFlow = stack.applyLatestLossFunction(pathFlow); - - if (pathFlow <= 0) continue pathloop; - } - - long accepted = data.finalizeAtDestination(nodes.get(nodes.size() - 1), pathFlow, entry.getIntValue()); - if (!simulate) pathTraverseCalls.forEach(Runnable::run); - availableFlow -= stack.consumeWithEndValue(accepted); - - if (availableFlow <= 0) break; - } - - return flowIn - availableFlow; - } - - /** - * Provides logic for traversing a flow net in an equal distribution manner within a dynamic weights context. - * Calls {@link #traverseEqualDistribution(IEqualizableTraverseData, Iterator, long, boolean)} repeatedly, using a - * fresh - * collection of paths from the {@code pathsSupplier} until - * {@link #traverseEqualDistribution(IEqualizableTraverseData, Iterator, long, boolean)} returns 0 or 100 iterations - * are - * performed. - * - * @param data the traversal data. - * @param pathsSupplier the supplier for a fresh set of paths. - * @param flowIn the flow to traverse with. - * @param strict whether to abort if one of the destination paths cannot be traversed due to node - * restrictions, - * not edge restrictions. - * @return the consumed flow. - */ - public static , - D extends IEqualizableTraverseData> long traverseEqualDistribution( - @NotNull D data, - @NotNull Supplier> pathsSupplier, - long flowIn, - boolean strict) { - long availableFlow = flowIn; - byte iterationCount = 0; - while (iterationCount <= 100) { - iterationCount++; - Iterator

paths = pathsSupplier.get(); - long flow = traverseEqualDistribution(data, paths, availableFlow, strict); - if (flow == 0) break; - else availableFlow -= flow; - } - - return flowIn - availableFlow; - } - - /** - * Provides logic for traversing a flow net in a round robin manner. This implementation merely ensures that - * destinations will be walked to in a predictable manner through the use of a cache, any balancing must - * be done on the {@link ITraverseData}'s end. - * - * @param data the traversal data. - * @param paths the paths to traverse. - * @param flowIn the flow to traverse with. - * @param strict whether to abort if one of the destination paths cannot be traversed due to node restrictions, - * not edge restrictions. - * @return the consumed flow. - */ - public static , N extends NetNode, E extends AbstractNetFlowEdge, - P extends NetPath, D extends IRoundRobinTraverseData> long traverseRoundRobin( - @NotNull D data, - @NotNull Iterator

paths, - long flowIn, - boolean strict) { - long availableFlow = flowIn; - Object2ObjectLinkedOpenHashMap cache = data.getTraversalCache(); - Predicate invalidityCheck = null; - - Map skippedPaths = new Object2ObjectOpenHashMap<>(); - while (paths.hasNext()) { - P path = paths.next(); - if (data.shouldSkipPath(path)) continue; - N destinationNode = path.getTargetNode(); - if (invalidityCheck == null) { - invalidityCheck = d -> { - if (d == null) return false; - NetNode node = destinationNode.getNet().getNode(d); - return node == null || !node.isActive(); - }; - } - Object destIdentifier = destinationNode.getEquivalencyData(); - Object nextUp = cache.isEmpty() ? null : cache.firstKey(); - // filter out invalid equivalency data - while (invalidityCheck.test(nextUp)) { - cache.removeFirst(); - nextUp = cache.isEmpty() ? null : cache.firstKey(); - } - if (destIdentifier.equals(nextUp)) { - // keep iterating over paths in order to collect destinations into the cache - if (availableFlow <= 0) continue; - // path is next up in the ordering, we can traverse. - T rr = cache.get(destIdentifier); - long accepted = rrTraverse(data, path, rr, availableFlow, strict); - if (!rr.hasNextInternalDestination(destinationNode, data.getSimulatorKey())) { - cache.getAndMoveToLast(destIdentifier); - } - if (accepted == -1) return flowIn - availableFlow; - else availableFlow -= accepted; - } else { - // this path isn't the next one up, skip it unless it's a completely new destination. - if (cache.containsKey(destIdentifier)) { - // keep iterating over paths in order to collect destinations into the cache - if (availableFlow <= 0) continue; - skippedPaths.put(destIdentifier, path); - } else { - // keep iterating over paths in order to collect destinations into the cache - if (availableFlow <= 0) { - cache.putAndMoveToFirst(destIdentifier, data.createRRData(destinationNode)); - continue; - } - T rr = data.createRRData(destinationNode); - long accepted = rrTraverse(data, path, rr, availableFlow, strict); - if (rr.hasNextInternalDestination(destinationNode, data.getSimulatorKey())) { - cache.putAndMoveToFirst(destIdentifier, rr); - } else { - cache.putAndMoveToLast(destIdentifier, rr); - } - if (accepted == -1) return flowIn - availableFlow; - else availableFlow -= accepted; - } - } - } - // finally, try and work through skipped paths - while (availableFlow > 0) { - Object nextUp = cache.isEmpty() ? null : cache.firstKey(); - if (nextUp == null) break; - P path = skippedPaths.get(nextUp); - if (path == null) break; - assert invalidityCheck != null; // skipped paths would be empty if invalidity check is null - if (invalidityCheck.test(nextUp)) { - cache.removeFirst(); - continue; - } - T rr = data.createRRData(path.getTargetNode()); - long accepted = rrTraverse(data, path, rr, availableFlow, strict); - if (!rr.hasNextInternalDestination(path.getTargetNode(), data.getSimulatorKey())) { - cache.getAndMoveToLast(nextUp); - } - if (accepted == -1) return flowIn - availableFlow; - else availableFlow -= accepted; - } - - return flowIn - availableFlow; - } - - private static , N extends NetNode, E extends AbstractNetFlowEdge, - P extends NetPath, D extends ITraverseData & IRoundRobinTraverseData> long rrTraverse( - @NotNull D data, - @NotNull P path, - @NotNull T rr, - long flowIn, - boolean strict) { - boolean simulate = data.getSimulatorKey() != null; - List pathTraverseCalls = simulate ? null : new ObjectArrayList<>(); - long pathFlow = flowIn; - - data.prepareForPathWalk(path, pathFlow); - - List nodes = path.getOrderedNodes(); - List edges = path.getOrderedEdges(); - assert nodes.size() == edges.size() + 1; - - FlowConsumptionStack stack = new FlowConsumptionStack(data.traverseToNode(nodes.get(0), pathFlow)); - pathFlow = stack.applyLatestLossFunction(pathFlow); - - for (int i = 0; i < edges.size(); i++) { - E edge = edges.get(i); - N targetNode = nodes.get(i + 1); - - if (targetNode.traverse(data.getQueryTick(), true)) { - if (!simulate) { - pathTraverseCalls.add(() -> targetNode.traverse(data.getQueryTick(), false)); - } - } else return strict ? -1 : 0; - - pathFlow = Math.min(data.getFlowLimit(edge), pathFlow); - stack.add(flow -> data.consumeFlowLimit(edge, targetNode, flow), - data.traverseToNode(targetNode, pathFlow)); - pathFlow = stack.applyLatestLossFunction(pathFlow); - - if (pathFlow <= 0) return 0; - } - N dest = nodes.get(nodes.size() - 1); - rr.resetIfFinished(dest, data.getSimulatorKey()); - long accepted = 0; - while (rr.hasNextInternalDestination(dest, data.getSimulatorKey())) { - rr.progressToNextInternalDestination(dest, data.getSimulatorKey()); - accepted += data.finalizeAtDestination(rr, dest, pathFlow - accepted); - if (accepted == pathFlow) break; - } - if (!simulate) pathTraverseCalls.forEach(Runnable::run); - - return stack.consumeWithEndValue(accepted); - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/util/CompleteLossOperator.java b/src/main/java/gregtech/api/graphnet/traverseold/util/CompleteLossOperator.java deleted file mode 100644 index 5cb4b1b3236..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/util/CompleteLossOperator.java +++ /dev/null @@ -1,18 +0,0 @@ -package gregtech.api.graphnet.traverseold.util; - -public class CompleteLossOperator implements ReversibleLossOperator { - - public static final CompleteLossOperator INSTANCE = new CompleteLossOperator(); - - private CompleteLossOperator() {} - - @Override - public double applyLoss(double value) { - return 0; - } - - @Override - public double undoLoss(double value) { - return 0; - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/util/CompositeLossOperator.java b/src/main/java/gregtech/api/graphnet/traverseold/util/CompositeLossOperator.java deleted file mode 100644 index 8234e3a916d..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/util/CompositeLossOperator.java +++ /dev/null @@ -1,22 +0,0 @@ -package gregtech.api.graphnet.traverseold.util; - -public class CompositeLossOperator implements ReversibleLossOperator { - - private final ReversibleLossOperator first; - private final ReversibleLossOperator second; - - public CompositeLossOperator(ReversibleLossOperator first, ReversibleLossOperator second) { - this.first = first; - this.second = second; - } - - @Override - public double applyLoss(double value) { - return second.applyLoss(first.applyLoss(value)); - } - - @Override - public double undoLoss(double value) { - return first.undoLoss(second.undoLoss(value)); - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/util/FlatLossOperator.java b/src/main/java/gregtech/api/graphnet/traverseold/util/FlatLossOperator.java deleted file mode 100644 index 668f7295a50..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/util/FlatLossOperator.java +++ /dev/null @@ -1,21 +0,0 @@ -package gregtech.api.graphnet.traverseold.util; - -public class FlatLossOperator implements ReversibleLossOperator { - - private final double loss; - - public FlatLossOperator(double loss) { - assert loss > 0; - this.loss = loss; - } - - @Override - public double applyLoss(double value) { - return value - loss; - } - - @Override - public double undoLoss(double value) { - return value + loss; - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/util/FlowConsumptionStack.java b/src/main/java/gregtech/api/graphnet/traverseold/util/FlowConsumptionStack.java deleted file mode 100644 index 10ce63ed51e..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/util/FlowConsumptionStack.java +++ /dev/null @@ -1,49 +0,0 @@ -package gregtech.api.graphnet.traverseold.util; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; - -import java.util.List; -import java.util.function.LongConsumer; - -public class FlowConsumptionStack { - - private final List flowConsumers = new ObjectArrayList<>(); - - private final List operators = new ObjectArrayList<>(); - - private final ReversibleLossOperator initialOperator; - - public FlowConsumptionStack() { - this.initialOperator = ReversibleLossOperator.IDENTITY; - } - - public FlowConsumptionStack(ReversibleLossOperator initialOperator) { - this.initialOperator = initialOperator; - } - - public long applyLatestLossFunction(long value) { - if (operators.isEmpty()) return (long) Math.floor(initialOperator.applyLoss(value)); - else return (long) Math.floor(operators.get(operators.size() - 1).applyLoss(value)); - } - - public void add(LongConsumer flowConsumer, ReversibleLossOperator postLoss) { - flowConsumers.add(flowConsumer); - operators.add(postLoss); - } - - /** - * Walks backwards along the loss operators and applies consumption to flow consumers. - * - * @param endValue the target end value - * @return the value that needs to be pushed into the start of the stack to achieve the end value. - */ - public long consumeWithEndValue(long endValue) { - double value = endValue; - for (int i = operators.size() - 1; i >= 0; i--) { - ReversibleLossOperator operator = operators.get(i); - value = operator.undoLoss(value); - flowConsumers.get(i).accept((long) Math.ceil(value)); - } - return (long) Math.ceil(initialOperator.undoLoss(value)); - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/util/MultLossOperator.java b/src/main/java/gregtech/api/graphnet/traverseold/util/MultLossOperator.java deleted file mode 100644 index b3c778a62f3..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/util/MultLossOperator.java +++ /dev/null @@ -1,34 +0,0 @@ -package gregtech.api.graphnet.traverseold.util; - -public class MultLossOperator implements ReversibleLossOperator { - - public static final MultLossOperator[] TENTHS = new MultLossOperator[10]; - - public static final MultLossOperator[] EIGHTHS = new MultLossOperator[8]; - - static { - for (int i = 1; i < 10; i++) { - TENTHS[i] = new MultLossOperator(0.1d * i); - } - for (int i = 1; i < 8; i++) { - EIGHTHS[i] = new MultLossOperator(0.125d * i); - } - } - - private final double mult; - - public MultLossOperator(double mult) { - assert mult > 0 && mult <= 1; - this.mult = mult; - } - - @Override - public double applyLoss(double value) { - return value * mult; - } - - @Override - public double undoLoss(double value) { - return value / mult; - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverseold/util/ReversibleLossOperator.java b/src/main/java/gregtech/api/graphnet/traverseold/util/ReversibleLossOperator.java deleted file mode 100644 index 9fe0ff8b656..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverseold/util/ReversibleLossOperator.java +++ /dev/null @@ -1,21 +0,0 @@ -package gregtech.api.graphnet.traverseold.util; - -public interface ReversibleLossOperator { - - ReversibleLossOperator IDENTITY = new ReversibleLossOperator() { - - @Override - public double applyLoss(double value) { - return value; - } - - @Override - public double undoLoss(double value) { - return value; - } - }; - - double applyLoss(double value); - - double undoLoss(double value); -} diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 9c832b0eb5c..0c7a8721ff4 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -56,6 +56,7 @@ import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandlerItem; +import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.ReflectionHelper; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; @@ -1045,4 +1046,8 @@ public static void spawnParticles(World world, EnumFacing direction, EnumParticl 0.1); } } + + public static long getTick() { + return FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); + } } diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 3f463d0a64f..2d95b156803 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -4,19 +4,33 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; import gregtech.api.capability.impl.ItemHandlerDelegate; +import gregtech.api.capability.impl.ItemHandlerList; import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; +import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; +import gregtech.api.graphnet.pipenet.traverse.RoundRobinCache; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverseold.TraverseHelpers; +import gregtech.api.graphnet.traverse.EQTraverse; +import gregtech.api.graphnet.traverse.FDTraverse; +import gregtech.api.graphnet.traverse.RRTraverse; +import gregtech.api.graphnet.traverse.iter.EdgeDirection; +import gregtech.api.graphnet.traverse.iter.EdgeSelector; +import gregtech.api.graphnet.traverse.iter.NetClosestIterator; +import gregtech.api.graphnet.traverse.iter.NetIterator; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; +import gregtech.api.util.GTUtility; import gregtech.api.util.ItemStackHashStrategy; import gregtech.api.util.function.BiIntConsumer; import gregtech.client.renderer.pipe.cover.CoverRenderer; @@ -26,11 +40,7 @@ import gregtech.common.covers.filter.ItemFilterContainer; import gregtech.common.covers.filter.MatchResult; import gregtech.common.covers.filter.MergabilityInfo; -import gregtech.common.pipelike.net.itemold.IItemTransferController; -import gregtech.common.pipelike.net.itemold.IItemTraverseGuideProvider; -import gregtech.common.pipelike.net.itemold.ItemEQTraverseData; -import gregtech.common.pipelike.net.itemold.ItemRRTraverseData; -import gregtech.common.pipelike.net.itemold.ItemTraverseData; +import gregtech.common.pipelike.net.item.ItemCapabilityObject; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; @@ -45,7 +55,6 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.IStringSerializable; import net.minecraft.util.ITickable; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.common.capabilities.Capability; @@ -78,14 +87,14 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; -import org.jetbrains.annotations.Contract; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Map; import java.util.function.IntUnaryOperator; +import java.util.function.Predicate; public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithItemFilter { @@ -101,7 +110,7 @@ public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, private CoverableItemHandlerWrapper itemHandlerWrapper; protected boolean isWorkingAllowed = true; - protected final Object2ObjectLinkedOpenHashMap> roundRobinCache = new Object2ObjectLinkedOpenHashMap<>(); + protected final RoundRobinCache roundRobinCache = RoundRobinCache.create(); protected @Nullable CoverRenderer rendererInverted; @@ -163,6 +172,7 @@ public DistributionMode getDistributionMode() { public void setDistributionMode(DistributionMode distributionMode) { this.distributionMode = distributionMode; + this.roundRobinCache.clear(); markDirty(); } @@ -236,6 +246,231 @@ protected void performTransferOnUpdate(@NotNull IItemHandler sourceHandler, @Not protected int performTransfer(@NotNull IItemHandler sourceHandler, @NotNull IItemHandler destHandler, boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { + // if the source handler or the dest handler is a pipe, perform a pipenet transfer. Otherwise, do a simple one. + if (sourceHandler instanceof ItemCapabilityObject s) { + if (destHandler instanceof ItemCapabilityObject d) { + return transferWithinNet(s.getNode(), d.getNode(), byFilterSlot, minTransfer, maxTransfer, + transferReport); + } else { + PipeCapabilityWrapper wrapper = s.getNode().getTileEntity().getWrapperForNode(s.getNode()); + if (wrapper instanceof NodeManagingPCW managingPCW) { + // if export, we know we're on the pipe; otherwise, we're on the tile. + EnumFacing facing = conveyorMode == ConveyorMode.EXPORT ? getAttachedSide() : + getAttachedSide().getOpposite(); + NetNode node = managingPCW.getNodeForFacing(facing); + if (node == null) return 0; + return transferWithinNet(s.getNode(), node, byFilterSlot, minTransfer, maxTransfer, transferReport); + } + return 0; + } + } else { + if (destHandler instanceof ItemCapabilityObject d) { + PipeCapabilityWrapper wrapper = d.getNode().getTileEntity().getWrapperForNode(d.getNode()); + if (wrapper instanceof NodeManagingPCW managingPCW) { + // if import, we know we're on the pipe; otherwise, we're on the tile. + EnumFacing facing = conveyorMode == ConveyorMode.IMPORT ? getAttachedSide() : + getAttachedSide().getOpposite(); + NetNode node = managingPCW.getNodeForFacing(facing); + if (node == null) return 0; + return transferWithinNet(node, d.getNode(), byFilterSlot, minTransfer, maxTransfer, transferReport); + } + return 0; + } else { + return simpleTransfer(sourceHandler, destHandler, byFilterSlot, minTransfer, maxTransfer, + transferReport); + } + } + } + + protected RoundRobinCache getRoundRobinCache(boolean simulate) { + return simulate ? roundRobinCache.copy() : roundRobinCache; + } + + /** + * Performs transfer between two nodes of a pipenet. + * + * @param sourceNode the node to pull from + * @param destNode the node to push to + * @param byFilterSlot whether to perform the transfer by filter slot. + * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. + * Each filter slot will report its transfer before the next slot is calculated. + * @return how much was transferred in total. + */ + protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode destNode, + boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, + @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { + // first, evaluate whether we're the only bridge between two areas in a group + NetEdge bridge = sourceNode.getNet().getEdge(sourceNode, destNode); + GraphEdge b1 = GraphEdge.unwrap(bridge); + GraphEdge b2 = GraphEdge.unwrap(sourceNode.getNet().getEdge(destNode, sourceNode)); + Predicate predicate = g -> g != b1 && g != b2; + NetClosestIterator sourceFrontier = new NetClosestIterator(sourceNode, + EdgeSelector.filtered(EdgeDirection.INCOMING, predicate)); + NetClosestIterator destFrontier = new NetClosestIterator(destNode, + EdgeSelector.filtered(EdgeDirection.OUTGOING, predicate)); + Map sourceCandidates = new Object2ObjectOpenHashMap<>(); + Map destinationCandidates = new Object2ObjectOpenHashMap<>(); + // note that if we checked all edges instead of only incoming for one and outgoing for the other, + // we would be able to know that we're the only bridge once either frontier exhausted, not both. + while (sourceFrontier.hasNext() || destFrontier.hasNext()) { + if (sourceFrontier.hasNext()) { + NetNode next = sourceFrontier.next(); + // the dest frontier has seen the next node in the source frontier, we are not the only bridge. + if (destFrontier.getSpanningTreeEdge(next) != null) return 0; + if (next instanceof NodeExposingCapabilities cap) { + IItemHandler handler = cap.getProvider() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, cap.exposedFacing()); + if (handler != null && !(handler instanceof ItemCapabilityObject)) + sourceCandidates.put(next, handler); + } + } + if (destFrontier.hasNext()) { + NetNode next = destFrontier.next(); + // the source frontier has seen the next node in the dest frontier, we are not the only bridge. + if (sourceFrontier.getSpanningTreeEdge(next) != null) return 0; + if (next instanceof NodeExposingCapabilities cap) { + IItemHandler handler = cap.getProvider() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, cap.exposedFacing()); + if (handler != null && !(handler instanceof ItemCapabilityObject)) + destinationCandidates.put(next, handler); + } + } + } + // if we reach this point, we know we are the only bridge and can commence traverse. + ItemFilterContainer filter = this.getItemFilter(); + byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter + Int2IntArrayMap extractableByFilterSlot = new Int2IntArrayMap(); + Int2ObjectArrayMap> filterSlotToMergability = new Int2ObjectArrayMap<>(); + ItemHandlerList handlerSourceCandidates = new ItemHandlerList(sourceCandidates.values()); + for (int i = 0; i < handlerSourceCandidates.getSlots(); i++) { + ItemStack stack = handlerSourceCandidates.extractItem(i, Integer.MAX_VALUE, true); + int extracted = stack.getCount(); + if (extracted == 0) continue; + MatchResult match = null; + if (filter == null || (match = filter.match(stack)).isMatched()) { + int filterSlot = -1; + if (byFilterSlot) { + filterSlot = match.getFilterIndex(); + } + extractableByFilterSlot.merge(filterSlot, extracted, Integer::sum); + final int handlerSlot = i; + filterSlotToMergability.compute(filterSlot, (k, v) -> { + if (v == null) v = new MergabilityInfo<>(); + v.add(handlerSlot, new ItemTestObject(stack), extracted); + return v; + }); + } + } + var iter = extractableByFilterSlot.int2IntEntrySet().fastIterator(); + int totalTransfer = 0; + + while (iter.hasNext()) { + var next = iter.next(); + int filterSlot = next.getIntKey(); + int min = minTransfer.applyAsInt(filterSlot); + int max = maxTransfer.applyAsInt(filterSlot); + if (max < min || max <= 0) continue; + if (next.getIntValue() >= min) { + MergabilityInfo mergabilityInfo = filterSlotToMergability.get(filterSlot); + MergabilityInfo.Merge merge = mergabilityInfo.getLargestMerge(); + // since we can't guarantee the transferability of multiple stack types while just simulating, + // if the largest merge is not large enough we have to give up. + if (merge.getCount() >= min) { + int slotTransfer = 0; + int transfer = Math.min(merge.getCount(), max); + // only simulate to test min if necessary + if (min > 0) { + transfer = attemptNetTransfer(sourceNode.getNet(), bridge, transfer, merge.getTestObject(), + sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, + SimulatorKey.getNewSimulatorInstance()); + if (transfer < min) continue; + } + transfer = attemptNetTransfer(sourceNode.getNet(), bridge, transfer, merge.getTestObject(), + sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, null); + int remaining = max - transfer; + slotTransfer += transfer; + if (remaining <= 0) continue; + for (MergabilityInfo.Merge otherMerge : mergabilityInfo + .getNonLargestMerges(merge)) { + transfer = Math.min(otherMerge.getCount(), remaining); + // we don't have to simulate here since we no longer need to respect the min + transfer = attemptNetTransfer(sourceNode.getNet(), bridge, transfer, merge.getTestObject(), + sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, null); + remaining -= transfer; + slotTransfer += transfer; + if (remaining <= 0) break; + } + if (transferReport != null) transferReport.accept(filterSlot, slotTransfer); + totalTransfer += slotTransfer; + } + } + } + return totalTransfer; + } + + protected int attemptNetTransfer(IGraphNet net, NetEdge bridge, int limit, ItemTestObject testObject, + NetIterator sources, Map sourceCandidates, + NetIterator targets, Map destCandidates, + @Nullable SimulatorKey key) { + return switch (distributionMode) { + case FLOOD -> FDTraverse.flood(net, + (n, f) -> { + if (key == null) ItemCapabilityObject.reportFlow(n, f, testObject); + }, + (e, f) -> ItemCapabilityObject.reportFlow(e, f, testObject, key, true), + e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? + GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : 0, + n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), null, null); + case EQUALIZED -> EQTraverse.equalDistribution(net, + (n, f) -> { + if (key == null) ItemCapabilityObject.reportFlow(n, f, testObject); + }, + (e, f) -> ItemCapabilityObject.reportFlow(e, f, testObject, key, true), + e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? + GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : 0, + n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), null, null); + case ROUND_ROBIN -> { + roundRobinCache.refresh(sources, targets); + yield RRTraverse.roundRobin(net, getRoundRobinCache(key != null) + .buildSupplier(sourceCandidates.keySet(), destCandidates.keySet()), + (n, f) -> { + if (key == null) ItemCapabilityObject.reportFlow(n, f, testObject); + }, + (e, f) -> ItemCapabilityObject.reportFlow(e, f, testObject, key, true), + e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? + GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : + 0, + n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), + null, null); + } + }; + } + + protected int getSupply(NetNode node, ItemTestObject testObject, boolean supply) { + return ItemCapabilityObject.getSupply(node, testObject, supply); + } + + /** + * Performs transfer without involving the pipenet + * + * @param sourceHandler the handler to pull from + * @param destHandler the handler to push to + * @param byFilterSlot whether to perform the transfer by filter slot. + * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. + * Each filter slot will report its transfer before the next slot is calculated. + * @return how much was transferred in total. + */ + protected int simpleTransfer(@NotNull IItemHandler sourceHandler, @NotNull IItemHandler destHandler, + boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, + @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { ItemFilterContainer filter = this.getItemFilter(); byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter Int2IntArrayMap extractableByFilterSlot = new Int2IntArrayMap(); @@ -271,31 +506,31 @@ protected int performTransfer(@NotNull IItemHandler sourceHandler, @NotNull IIte if (next.getIntValue() >= min) { MergabilityInfo mergabilityInfo = filterSlotToMergability.get(filterSlot); MergabilityInfo.Merge merge = mergabilityInfo.getLargestMerge(); + // since we can't guarantee the transferability of multiple stack types while just simulating, + // if the largest merge is not large enough we have to give up. if (merge.getCount() >= min) { int transfer = Math.min(merge.getCount(), max); - transfer = insertToHandler(destHandler, merge.getTestObject(), transfer, true); - // since we can't guarantee the insertability of multiple stack types while just simulating, - // if the largest merge is not large enough we have to give up. + transfer = simpleInsert(destHandler, merge.getTestObject(), transfer, true); if (transfer < min) continue; int toExtract = transfer; for (int handlerSlot : merge.getHandlerSlots()) { toExtract -= sourceHandler.extractItem(handlerSlot, toExtract, false).getCount(); if (toExtract == 0) break; } - insertToHandler(destHandler, merge.getTestObject(), transfer - toExtract, false); + simpleInsert(destHandler, merge.getTestObject(), transfer - toExtract, false); int remaining = max - transfer + toExtract; slotTransfer += transfer; if (remaining <= 0) continue; for (MergabilityInfo.Merge otherMerge : mergabilityInfo .getNonLargestMerges(merge)) { transfer = Math.min(otherMerge.getCount(), remaining); - transfer = insertToHandler(destHandler, merge.getTestObject(), transfer, true); + transfer = simpleInsert(destHandler, merge.getTestObject(), transfer, true); toExtract = transfer; for (int handlerSlot : otherMerge.getHandlerSlots()) { toExtract -= sourceHandler.extractItem(handlerSlot, toExtract, false).getCount(); if (toExtract == 0) break; } - insertToHandler(destHandler, otherMerge.getTestObject(), transfer - toExtract, false); + simpleInsert(destHandler, otherMerge.getTestObject(), transfer - toExtract, false); remaining -= transfer; slotTransfer += transfer; if (remaining <= 0) break; @@ -308,67 +543,6 @@ protected int performTransfer(@NotNull IItemHandler sourceHandler, @NotNull IIte return totalTransfer; } - protected int insertToHandler(@NotNull IItemHandler destHandler, ItemTestObject testObject, int count, - boolean simulate) { - if (!(destHandler instanceof IItemTraverseGuideProvider provider)) { - return simpleInsert(destHandler, testObject, count, simulate); - } - switch (distributionMode) { - case FLOOD -> { - var guide = provider.getGuide(this::getTD, testObject, count, simulate); - if (guide == null) return 0; - int consumed = (int) TraverseHelpers.traverseFlood(guide.getData(), guide.getPaths(), guide.getFlow()); - guide.reportConsumedFlow(consumed); - return consumed; - } - case EQUALIZED -> { - var guide = provider.getGuide(this::getEQTD, testObject, count, simulate); - if (guide == null) return 0; - int consumed = (int) TraverseHelpers.traverseEqualDistribution(guide.getData(), - guide.getPathsSupplier(), guide.getFlow(), true); - guide.reportConsumedFlow(consumed); - return consumed; - } - case ROUND_ROBIN -> { - var guide = provider - .getGuide( - (net, testObject1, simulator, queryTick, sourcePos, inputFacing) -> getRRTD(net, - testObject1, simulator, queryTick, sourcePos, inputFacing, simulate), - testObject, count, simulate); - if (guide == null) return 0; - int consumed = (int) TraverseHelpers.traverseRoundRobin(guide.getData(), guide.getPaths(), - guide.getFlow(), true); - guide.reportConsumedFlow(consumed); - return consumed; - } - } - return 0; - } - - @Contract("_, _, _, _, _, _ -> new") - protected @NotNull ItemTraverseData getTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { - return new ItemTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - @Contract("_, _, _, _, _, _ -> new") - protected @NotNull ItemEQTraverseData getEQTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { - return new ItemEQTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - @Contract("_, _, _, _, _, _, _ -> new") - protected @NotNull ItemRRTraverseData getRRTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing, - boolean simulate) { - return new ItemRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, - getRoundRobinCache(simulate)); - } - - protected Object2ObjectLinkedOpenHashMap> getRoundRobinCache(boolean simulate) { - return simulate ? roundRobinCache.clone() : roundRobinCache; - } - protected int simpleInsert(@NotNull IItemHandler destHandler, ItemTestObject testObject, int count, boolean simulate) { int available = count; @@ -380,40 +554,6 @@ protected int simpleInsert(@NotNull IItemHandler destHandler, ItemTestObject tes return count - available; } - @Override - public @Nullable T getControllerForControl(TransferControl control) { - if (control == IItemTransferController.CONTROL) { - return control.cast(this); - } - return null; - } - - @Override - public int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, - boolean simulate) { - if (getManualImportExportMode() == ManualImportExportMode.DISABLED) return amount; - if (getManualImportExportMode() == ManualImportExportMode.UNFILTERED || - getFilterMode() == ItemFilterMode.FILTER_INSERT) // insert to handler is an extract from us - return IItemTransferController.super.insertToHandler(testObject, amount, destHandler, simulate); - ItemFilterContainer filter = getItemFilter(); - if (filter == null || filter.test(testObject.recombine())) { - return IItemTransferController.super.insertToHandler(testObject, amount, destHandler, simulate); - } else return amount; - } - - @Override - public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler sourceHandler, - boolean simulate) { - if (getManualImportExportMode() == ManualImportExportMode.DISABLED) return 0; - if (getManualImportExportMode() == ManualImportExportMode.UNFILTERED || - getFilterMode() == ItemFilterMode.FILTER_EXTRACT) // extract from handler is an insert to us - return IItemTransferController.super.extractFromHandler(testObject, amount, sourceHandler, simulate); - ItemFilterContainer filter = getItemFilter(); - if (filter == null || filter.test(testObject.recombine())) { - return IItemTransferController.super.extractFromHandler(testObject, amount, sourceHandler, simulate); - } else return 0; - } - protected static class TypeItemInfo { public final ItemStack itemStack; diff --git a/src/main/java/gregtech/common/covers/CoverFluidFilter.java b/src/main/java/gregtech/common/covers/CoverFluidFilter.java index f019bc6d183..ff057404493 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidFilter.java +++ b/src/main/java/gregtech/common/covers/CoverFluidFilter.java @@ -6,9 +6,6 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithFluidFilter; -import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; -import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; @@ -19,7 +16,6 @@ import gregtech.common.covers.filter.BaseFilter; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.FluidFilterContainer; -import gregtech.common.pipelike.net.fluidold.IFluidTransferController; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -53,8 +49,7 @@ import java.io.IOException; -public class CoverFluidFilter extends CoverBase implements CoverWithUI, CoverWithFluidFilter, TransferControlProvider, - IFluidTransferController { +public class CoverFluidFilter extends CoverBase implements CoverWithUI, CoverWithFluidFilter { protected final String titleLocale; protected final SimpleOverlayRenderer texture; @@ -228,35 +223,6 @@ public void readFromNBT(@NotNull NBTTagCompound tagCompound) { } } - @Override - public @Nullable T getControllerForControl(TransferControl control) { - if (control == IFluidTransferController.CONTROL) { - return control.cast(this); - } - return null; - } - - @Override - public int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, - boolean doFill) { - if (getFilterMode() == FluidFilterMode.FILTER_FILL) // insert to handler is a drain for us - return IFluidTransferController.super.insertToHandler(testObject, amount, destHandler, doFill); - if (getFluidFilter().test(testObject.recombine())) { - return IFluidTransferController.super.insertToHandler(testObject, amount, destHandler, doFill); - } else return 0; - } - - @Override - public @Nullable FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, - IFluidHandler sourceHandler, boolean doDrain) { - if (testObject == null || - getFilterMode() == FluidFilterMode.FILTER_DRAIN) // extract from handler is an insert to us - return IFluidTransferController.super.extractFromHandler(testObject, amount, sourceHandler, doDrain); - if (getFluidFilter().test(testObject.recombine())) { - return IFluidTransferController.super.extractFromHandler(testObject, amount, sourceHandler, doDrain); - } else return null; - } - private class FluidHandlerFiltered extends FluidHandlerDelegate { public FluidHandlerFiltered(@NotNull IFluidHandler delegate) { diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index c4797f67228..385b0f3cf56 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -3,24 +3,16 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.pipenet.WorldPipeNode; -import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.mui.GTGuiTextures; -import gregtech.api.util.GTUtility; import gregtech.common.covers.filter.FluidFilterContainer; import gregtech.common.covers.filter.SimpleFluidFilter; -import gregtech.common.pipelike.net.fluidold.FluidEQTraverseData; -import gregtech.common.pipelike.net.fluidold.FluidRRTraverseData; -import gregtech.common.pipelike.net.fluidold.FluidTraverseData; -import gregtech.common.pipelike.net.fluidold.IFluidTransferController; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -35,7 +27,6 @@ import com.cleanroommc.modularui.value.sync.StringSyncValue; import com.cleanroommc.modularui.widget.ParentWidget; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.jetbrains.annotations.NotNull; import java.util.function.IntUnaryOperator; @@ -71,54 +62,20 @@ protected void refreshBuffer(int transferRate) { @Override protected void performTransferOnUpdate(@NotNull IFluidHandler sourceHandler, @NotNull IFluidHandler destHandler) { - if (transferMode == TransferMode.TRANSFER_ANY) { + if (transferMode != TransferMode.TRANSFER_EXACT) { super.performTransferOnUpdate(sourceHandler, destHandler); return; } FluidFilterContainer filter = this.getFluidFilter(); if (filter == null) return; - if (transferMode == TransferMode.KEEP_EXACT) { - IntUnaryOperator maxflow = s -> Math.min(filter.getTransferLimit(s), getFluidsLeftToTransfer()); - reportFluidsTransfer(performTransfer(sourceHandler, destHandler, true, s -> 0, maxflow, null)); - } else if (transferMode == TransferMode.TRANSFER_EXACT) { - IntUnaryOperator maxflow = s -> { - int limit = filter.getTransferLimit(s); - if (getFluidsLeftToTransfer() < limit) { - noTransferDueToMinimum = true; - return 0; - } else return limit; - }; - performTransfer(sourceHandler, destHandler, true, maxflow, maxflow, (a, b) -> reportFluidsTransfer(b)); - } - } - - @Override - protected @NotNull FluidTraverseData getTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { - if (transferMode == TransferMode.KEEP_EXACT) { - return new KeepFluidTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - return super.getTD(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - @Override - protected @NotNull FluidEQTraverseData getEQTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { - if (transferMode == TransferMode.KEEP_EXACT) { - return new KeepFluidEQTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - return super.getEQTD(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - @Override - protected @NotNull FluidRRTraverseData getRRTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing, - boolean simulate) { - if (transferMode == TransferMode.KEEP_EXACT) { - return new KeepFluidRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, - getRoundRobinCache(simulate)); - } - return super.getRRTD(net, testObject, simulator, queryTick, sourcePos, inputFacing, simulate); + IntUnaryOperator maxflow = s -> { + int limit = filter.getTransferLimit(s); + if (getFluidsLeftToTransfer() < limit) { + noTransferDueToMinimum = true; + return 0; + } else return limit; + }; + performTransfer(sourceHandler, destHandler, true, maxflow, maxflow, (a, b) -> reportFluidsTransfer(b)); } @Override @@ -132,6 +89,22 @@ protected int simpleInsert(@NotNull IFluidHandler destHandler, FluidTestObject t return super.simpleInsert(destHandler, testObject, count, simulate); } + @Override + protected int getSupply(NetNode node, FluidTestObject testObject, boolean supply) { + if (transferMode != TransferMode.KEEP_EXACT || supply) return super.getSupply(node, testObject, supply); + if (node instanceof NodeExposingCapabilities exposer) { + IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + exposer.exposedFacing()); + if (handler != null) { + assert getFluidFilter() != null; + int kept = getFluidFilter().getTransferLimit(testObject.recombine()); + return -Math.min(handler.fill(testObject.recombine(Integer.MAX_VALUE), false), + kept - computeContained(handler, testObject)); + } + } + return 0; + } + public void setTransferMode(TransferMode transferMode) { if (this.transferMode != transferMode) { this.transferMode = transferMode; @@ -188,42 +161,6 @@ protected ParentWidget createUI(ModularPanel mainPanel, PanelSyncManager sync .setTextColor(Color.WHITE.darker(1)))); } - // @Override - // public int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, - // boolean doFill) { - // if (pumpMode == PumpMode.EXPORT) { - // if (transferMode == TransferMode.KEEP_EXACT) { - // int contained = computeContained(destHandler, testObject); - // assert getFluidFilter() != null; - // int keep = getFluidFilter().getTransferLimit(testObject.recombine()); - // if (contained >= keep) return 0; - // return super.insertToHandler(testObject, Math.min(keep - contained, amount), destHandler, doFill); - // } else if (transferMode == TransferMode.TRANSFER_EXACT) { - // assert getFluidFilter() != null; - // int required = getFluidFilter().getTransferLimit(testObject.recombine()); - // if (amount < required) return 0; - // return super.insertToHandler(testObject, required, destHandler, doFill); - // } - // } - // return super.insertToHandler(testObject, amount, destHandler, doFill); - // } - // - // @Override - // public @Nullable FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, - // IFluidHandler sourceHandler, boolean doDrain) { - // if (pumpMode == PumpMode.IMPORT) { - // // should extraction instead be ignored for transfer exact? - // if (transferMode == TransferMode.TRANSFER_EXACT) { - // assert getFluidFilter() != null; - // int required = testObject == null ? getFluidFilter().getTransferSize() : - // getFluidFilter().getTransferLimit(testObject.recombine()); - // if (amount < required) return null; - // else amount = required; - // } - // } - // return super.extractFromHandler(testObject, amount, sourceHandler, doDrain); - // } - @Override public int getMaxTransferRate() { return this.transferMode.maxFluidStackSize; @@ -282,134 +219,4 @@ protected int computeContained(@NotNull IFluidHandler handler, @NotNull FluidTes } return found; } - - protected class KeepFluidTraverseData extends FluidTraverseData { - - public KeepFluidTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing) { - super(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - @Override - public long finalizeAtDestination(@NotNull WorldPipeNode destination, long flowReachingDestination) { - long availableFlow = flowReachingDestination; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IFluidHandler container = capability.getValue() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - capability.getKey().getOpposite()); - if (container != null) { - int contained = computeContained(container, getTestObject()); - assert getFluidFilter() != null; - int kept = getFluidFilter().getTransferLimit(getTestObject().recombine()); - if (contained >= kept) continue; - availableFlow -= IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, !simulating()); - } - } - return flowReachingDestination - availableFlow; - } - } - - protected class KeepFluidEQTraverseData extends FluidEQTraverseData { - - public KeepFluidEQTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, - long queryTick, - BlockPos sourcePos, EnumFacing inputFacing) { - super(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - @Override - protected void compute(@NotNull WorldPipeNode destination) { - this.destCount = 0; - this.maxMinFlow = 0; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IFluidHandler container = capability.getValue() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - capability.getKey().getOpposite()); - if (container != null) { - int contained = computeContained(container, getTestObject()); - assert getFluidFilter() != null; - int kept = getFluidFilter().getTransferLimit(getTestObject().recombine()); - if (contained >= kept) continue; - if (destCount == 0) maxMinFlow = Integer.MAX_VALUE; - destCount += 1; - maxMinFlow = Math.min(maxMinFlow, - IFluidTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - kept - contained, - container, false)); - } - } - } - - @Override - public long finalizeAtDestination(@NotNull WorldPipeNode node, long flowReachingNode, - int expectedDestinations) { - long availableFlow = flowReachingNode; - long flowPerDestination = flowReachingNode / expectedDestinations; - if (flowPerDestination == 0) return 0; - for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { - if (GTUtility.arePosEqual(node.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IFluidHandler container = capability.getValue() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - capability.getKey().getOpposite()); - if (container != null) { - int contained = computeContained(container, getTestObject()); - assert getFluidFilter() != null; - int kept = getFluidFilter().getTransferLimit(getTestObject().recombine()); - if (contained >= kept) continue; - availableFlow -= IFluidTransferController.CONTROL.get(node.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, flowPerDestination), container, !simulating()); - } - } - return flowReachingNode - availableFlow; - } - } - - protected class KeepFluidRRTraverseData extends FluidRRTraverseData { - - public KeepFluidRRTraverseData(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing, - @NotNull Object2ObjectLinkedOpenHashMap> cache) { - super(net, testObject, simulator, queryTick, sourcePos, inputFacing, cache); - } - - @Override - public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData data, - @NotNull WorldPipeNode destination, long flowReachingDestination) { - long availableFlow = flowReachingDestination; - EnumFacing pointerFacing = data.getPointerFacing(getSimulatorKey()); - // anti insert-to-our-source logic - if (!GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) || - !(pointerFacing == inputFacing)) { - IFluidHandler container = data.getAtPointer(destination, getSimulatorKey()); - if (container != null) { - int contained = computeContained(container, getTestObject()); - assert getFluidFilter() != null; - int kept = getFluidFilter().getTransferLimit(getTestObject().recombine()); - if (contained < kept) { - availableFlow -= IFluidTransferController.CONTROL.get( - destination.getTileEntity().getCoverHolder() - .getCoverAtSide(pointerFacing)) - .insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, !simulating()); - } - } - } - return flowReachingDestination - availableFlow; - } - } } diff --git a/src/main/java/gregtech/common/covers/CoverItemFilter.java b/src/main/java/gregtech/common/covers/CoverItemFilter.java index df671597ef7..590cc91203e 100644 --- a/src/main/java/gregtech/common/covers/CoverItemFilter.java +++ b/src/main/java/gregtech/common/covers/CoverItemFilter.java @@ -6,9 +6,6 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; -import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; -import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.api.util.GTLog; import gregtech.api.util.GTUtility; @@ -19,7 +16,6 @@ import gregtech.common.covers.filter.BaseFilter; import gregtech.common.covers.filter.BaseFilterContainer; import gregtech.common.covers.filter.ItemFilterContainer; -import gregtech.common.pipelike.net.itemold.IItemTransferController; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -52,8 +48,7 @@ import java.io.IOException; -public class CoverItemFilter extends CoverBase implements CoverWithUI, CoverWithItemFilter, TransferControlProvider, - IItemTransferController { +public class CoverItemFilter extends CoverBase implements CoverWithUI, CoverWithItemFilter { protected final String titleLocale; protected final SimpleOverlayRenderer texture; @@ -231,34 +226,6 @@ public T getCapability(@NotNull Capability capability, T defaultValue) { return defaultValue; } - @Override - public @Nullable T getControllerForControl(TransferControl control) { - if (control == IItemTransferController.CONTROL) { - return control.cast(this); - } - return null; - } - - @Override - public int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, - boolean simulate) { - if (getFilterMode() == ItemFilterMode.FILTER_INSERT) // insert to handler is an extract from us - return IItemTransferController.super.insertToHandler(testObject, amount, destHandler, simulate); - if (getItemFilter().test(testObject.recombine())) { - return IItemTransferController.super.insertToHandler(testObject, amount, destHandler, simulate); - } else return amount; - } - - @Override - public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler sourceHandler, - boolean simulate) { - if (getFilterMode() == ItemFilterMode.FILTER_EXTRACT) // extract from handler is an insert to us - return IItemTransferController.super.extractFromHandler(testObject, amount, sourceHandler, simulate); - if (getItemFilter().test(testObject.recombine())) { - return IItemTransferController.super.extractFromHandler(testObject, amount, sourceHandler, simulate); - } else return 0; - } - private class ItemHandlerFiltered extends ItemHandlerDelegate { public ItemHandlerFiltered(IItemHandler delegate) { diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index ce13ce4a0aa..a0ffdcae8c5 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -9,15 +9,27 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithFluidFilter; +import gregtech.api.graphnet.edge.AbstractNetFlowEdge; +import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; -import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; +import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; +import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; +import gregtech.api.graphnet.pipenet.traverse.RoundRobinCache; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverseold.TraverseHelpers; +import gregtech.api.graphnet.traverse.EQTraverse; +import gregtech.api.graphnet.traverse.FDTraverse; +import gregtech.api.graphnet.traverse.RRTraverse; +import gregtech.api.graphnet.traverse.iter.EdgeDirection; +import gregtech.api.graphnet.traverse.iter.EdgeSelector; +import gregtech.api.graphnet.traverse.iter.NetClosestIterator; +import gregtech.api.graphnet.traverse.iter.NetIterator; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; +import gregtech.api.util.GTUtility; import gregtech.api.util.function.BiIntConsumer; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; @@ -25,11 +37,7 @@ import gregtech.client.renderer.texture.cube.SimpleSidedCubeRenderer; import gregtech.common.covers.filter.FluidFilterContainer; import gregtech.common.covers.filter.MatchResult; -import gregtech.common.pipelike.net.fluidold.FluidEQTraverseData; -import gregtech.common.pipelike.net.fluidold.FluidRRTraverseData; -import gregtech.common.pipelike.net.fluidold.FluidTraverseData; -import gregtech.common.pipelike.net.fluidold.IFluidTransferController; -import gregtech.common.pipelike.net.fluidold.IFluidTraverseGuideProvider; +import gregtech.common.pipelike.net.fluid.FluidCapabilityObject; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; @@ -43,7 +51,6 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.IStringSerializable; import net.minecraft.util.ITickable; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraftforge.common.capabilities.Capability; @@ -75,15 +82,15 @@ import com.cleanroommc.modularui.widgets.layout.Row; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import org.jetbrains.annotations.Contract; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Map; import java.util.function.IntUnaryOperator; +import java.util.function.Predicate; -public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithFluidFilter, - TransferControlProvider, IFluidTransferController { +public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithFluidFilter { public final int tier; public final int maxFluidTransferRate; @@ -97,7 +104,7 @@ public class CoverPump extends CoverBase implements CoverWithUI, ITickable, ICon protected FluidFilterContainer fluidFilterContainer; protected BucketMode bucketMode = BucketMode.MILLI_BUCKET; - protected final Object2ObjectLinkedOpenHashMap> roundRobinCache = new Object2ObjectLinkedOpenHashMap<>(); + protected final RoundRobinCache roundRobinCache = RoundRobinCache.create(); protected @Nullable CoverRenderer rendererInverted; @@ -170,6 +177,8 @@ public DistributionMode getDistributionMode() { public void setDistributionMode(DistributionMode distributionMode) { this.distributionMode = distributionMode; + this.roundRobinCache.clear(); + markDirty(); } public void setBucketMode(BucketMode bucketMode) { @@ -253,16 +262,114 @@ protected void performTransferOnUpdate(@NotNull IFluidHandler sourceHandler, @No protected int performTransfer(@NotNull IFluidHandler sourceHandler, @NotNull IFluidHandler destHandler, boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { + // if the source handler or the dest handler is a pipe, perform a pipenet transfer. Otherwise, do a simple one. + if (sourceHandler instanceof FluidCapabilityObject s) { + if (destHandler instanceof FluidCapabilityObject d) { + return transferWithinNet(s.getNode(), d.getNode(), byFilterSlot, minTransfer, maxTransfer, + transferReport); + } else { + PipeCapabilityWrapper wrapper = s.getNode().getTileEntity().getWrapperForNode(s.getNode()); + if (wrapper instanceof NodeManagingPCW managingPCW) { + // if export, we know we're on the pipe; otherwise, we're on the tile. + EnumFacing facing = pumpMode == PumpMode.EXPORT ? getAttachedSide() : + getAttachedSide().getOpposite(); + NetNode node = managingPCW.getNodeForFacing(facing); + if (node == null) return 0; + return transferWithinNet(s.getNode(), node, byFilterSlot, minTransfer, maxTransfer, transferReport); + } + return 0; + } + } else { + if (destHandler instanceof FluidCapabilityObject d) { + PipeCapabilityWrapper wrapper = d.getNode().getTileEntity().getWrapperForNode(d.getNode()); + if (wrapper instanceof NodeManagingPCW managingPCW) { + // if import, we know we're on the pipe; otherwise, we're on the tile. + EnumFacing facing = pumpMode == PumpMode.IMPORT ? getAttachedSide() : + getAttachedSide().getOpposite(); + NetNode node = managingPCW.getNodeForFacing(facing); + if (node == null) return 0; + return transferWithinNet(node, d.getNode(), byFilterSlot, minTransfer, maxTransfer, transferReport); + } + return 0; + } else { + return simpleTransfer(sourceHandler, destHandler, byFilterSlot, minTransfer, maxTransfer, + transferReport); + } + } + } + + protected RoundRobinCache getRoundRobinCache(boolean simulate) { + return simulate ? roundRobinCache.copy() : roundRobinCache; + } + + /** + * Performs transfer between two nodes of a pipenet. + * + * @param sourceNode the node to pull from + * @param destNode the node to push to + * @param byFilterSlot whether to perform the transfer by filter slot. + * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. + * Each filter slot will report its transfer before the next slot is calculated. + * @return how much was transferred in total. + */ + protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode destNode, + boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, + @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { + // first, evaluate whether we're the only bridge between two areas in a group + NetEdge bridge = sourceNode.getNet().getEdge(sourceNode, destNode); + GraphEdge b1 = GraphEdge.unwrap(bridge); + GraphEdge b2 = GraphEdge.unwrap(sourceNode.getNet().getEdge(destNode, sourceNode)); + Predicate predicate = g -> g != b1 && g != b2; + NetClosestIterator sourceFrontier = new NetClosestIterator(sourceNode, + EdgeSelector.filtered(EdgeDirection.INCOMING, predicate)); + NetClosestIterator destFrontier = new NetClosestIterator(destNode, + EdgeSelector.filtered(EdgeDirection.OUTGOING, predicate)); + Map sourceCandidates = new Object2ObjectOpenHashMap<>(); + Map destinationCandidates = new Object2ObjectOpenHashMap<>(); + // note that if we checked all edges instead of only incoming for one and outgoing for the other, + // we would be able to know that we're the only bridge once either frontier exhausted, not both. + while (sourceFrontier.hasNext() || destFrontier.hasNext()) { + if (sourceFrontier.hasNext()) { + NetNode next = sourceFrontier.next(); + // the dest frontier has seen the next node in the source frontier, we are not the only bridge. + if (destFrontier.getSpanningTreeEdge(next) != null) return 0; + if (next instanceof NodeExposingCapabilities cap) { + IFluidHandler handler = cap.getProvider() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, cap.exposedFacing()); + if (handler != null && !(handler instanceof FluidCapabilityObject)) + sourceCandidates.put(next, handler); + } + } + if (destFrontier.hasNext()) { + NetNode next = destFrontier.next(); + // the source frontier has seen the next node in the dest frontier, we are not the only bridge. + if (sourceFrontier.getSpanningTreeEdge(next) != null) return 0; + if (next instanceof NodeExposingCapabilities cap) { + IFluidHandler handler = cap.getProvider() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, cap.exposedFacing()); + if (handler != null && !(handler instanceof FluidCapabilityObject)) + destinationCandidates.put(next, handler); + } + } + } + // if we reach this point, we know we are the only bridge and can commence traverse. FluidFilterContainer filter = this.getFluidFilter(); byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter Object2IntOpenHashMap contained = new Object2IntOpenHashMap<>(); - var tanks = sourceHandler.getTankProperties(); - for (IFluidTankProperties tank : tanks) { - FluidStack contents = tank.getContents(); - if (contents != null) contained.merge(new FluidTestObject(contents), contents.amount, Integer::sum); + for (IFluidHandler handler : sourceCandidates.values()) { + var tanks = handler.getTankProperties(); + for (IFluidTankProperties tank : tanks) { + FluidStack contents = tank.getContents(); + if (contents != null) contained.merge(new FluidTestObject(contents), contents.amount, Integer::sum); + } } var iter = contained.object2IntEntrySet().fastIterator(); int totalTransfer = 0; + while (iter.hasNext()) { var content = iter.next(); FluidStack contents = content.getKey().recombine(content.getIntValue()); @@ -279,13 +386,14 @@ protected int performTransfer(@NotNull IFluidHandler sourceHandler, @NotNull IFl if (contents.amount < min) continue; int transfer = Math.min(contents.amount, max); - FluidStack extracted = sourceHandler.drain(content.getKey().recombine(transfer), false); - if (extracted == null || extracted.amount < min) continue; - transfer = insertToHandler(destHandler, content.getKey(), extracted.amount, true); - if (transfer <= 0 || transfer < min) continue; - extracted = sourceHandler.drain(content.getKey().recombine(transfer), true); - if (extracted == null) continue; - transfer = insertToHandler(destHandler, content.getKey(), extracted.amount, false); + if (min > 0) { + transfer = attemptNetTransfer(sourceNode.getNet(), bridge, transfer, content.getKey(), + sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, + SimulatorKey.getNewSimulatorInstance()); + if (transfer < min) continue; + } + transfer = attemptNetTransfer(sourceNode.getNet(), bridge, transfer, content.getKey(), + sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, null); if (transferReport != null) transferReport.accept(filterSlot, transfer); totalTransfer += transfer; } @@ -293,65 +401,103 @@ protected int performTransfer(@NotNull IFluidHandler sourceHandler, @NotNull IFl return totalTransfer; } - protected int insertToHandler(@NotNull IFluidHandler destHandler, FluidTestObject testObject, int count, - boolean simulate) { - if (!(destHandler instanceof IFluidTraverseGuideProvider provider)) { - return simpleInsert(destHandler, testObject, count, simulate); - } - switch (distributionMode) { - case FLOOD -> { - var guide = provider.getGuide(this::getTD, testObject, count, simulate); - if (guide == null) return 0; - int consumed = (int) TraverseHelpers.traverseFlood(guide.getData(), guide.getPaths(), guide.getFlow()); - guide.reportConsumedFlow(consumed); - return consumed; - } - case EQUALIZED -> { - var guide = provider.getGuide(this::getEQTD, testObject, count, simulate); - if (guide == null) return 0; - int consumed = (int) TraverseHelpers.traverseEqualDistribution(guide.getData(), - guide.getPathsSupplier(), guide.getFlow(), true); - guide.reportConsumedFlow(consumed); - return consumed; - } + protected int attemptNetTransfer(IGraphNet net, NetEdge bridge, int limit, FluidTestObject testObject, + NetIterator sources, Map sourceCandidates, + NetIterator targets, Map destCandidates, + @Nullable SimulatorKey key) { + return switch (distributionMode) { + case FLOOD -> FDTraverse.flood(net, + (n, f) -> { + if (key == null) FluidCapabilityObject.reportFlow(n, f, testObject); + }, + (e, f) -> FluidCapabilityObject.reportFlow(e, f, testObject, key, true), + e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? + GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : 0, + n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), null, null); + case EQUALIZED -> EQTraverse.equalDistribution(net, + (n, f) -> { + if (key == null) FluidCapabilityObject.reportFlow(n, f, testObject); + }, + (e, f) -> FluidCapabilityObject.reportFlow(e, f, testObject, key, true), + e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? + GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : 0, + n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), null, null); case ROUND_ROBIN -> { - var guide = provider - .getGuide( - (net, testObject1, simulator, queryTick, sourcePos, inputFacing) -> getRRTD(net, - testObject1, simulator, queryTick, sourcePos, inputFacing, simulate), - testObject, count, simulate); - if (guide == null) return 0; - int consumed = (int) TraverseHelpers.traverseRoundRobin(guide.getData(), guide.getPaths(), - guide.getFlow(), true); - guide.reportConsumedFlow(consumed); - return consumed; + roundRobinCache.refresh(sources, targets); + yield RRTraverse.roundRobin(net, getRoundRobinCache(key != null) + .buildSupplier(sourceCandidates.keySet(), destCandidates.keySet()), + (n, f) -> { + if (key == null) FluidCapabilityObject.reportFlow(n, f, testObject); + }, + (e, f) -> FluidCapabilityObject.reportFlow(e, f, testObject, key, true), + e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? + GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : + 0, + n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), + null, null); } - } - return 0; - } - - @Contract("_, _, _, _, _, _ -> new") - protected @NotNull FluidTraverseData getTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { - return new FluidTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); + }; } - @Contract("_, _, _, _, _, _ -> new") - protected @NotNull FluidEQTraverseData getEQTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { - return new FluidEQTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); + protected int getSupply(NetNode node, FluidTestObject testObject, boolean supply) { + return FluidCapabilityObject.getSupply(node, testObject, supply); } - @Contract("_, _, _, _, _, _, _ -> new") - protected @NotNull FluidRRTraverseData getRRTD(IGraphNet net, FluidTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing, - boolean simulate) { - return new FluidRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, - getRoundRobinCache(simulate)); - } + /** + * Performs transfer without involving the pipenet + * + * @param sourceHandler the handler to pull from + * @param destHandler the handler to push to + * @param byFilterSlot whether to perform the transfer by filter slot. + * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not + * transferring by slot, a filter slot of -1 will be passed in. + * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. + * Each filter slot will report its transfer before the next slot is calculated. + * @return how much was transferred in total. + */ + protected int simpleTransfer(@NotNull IFluidHandler sourceHandler, @NotNull IFluidHandler destHandler, + boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, + @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { + FluidFilterContainer filter = this.getFluidFilter(); + byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter + Object2IntOpenHashMap contained = new Object2IntOpenHashMap<>(); + var tanks = sourceHandler.getTankProperties(); + for (IFluidTankProperties tank : tanks) { + FluidStack contents = tank.getContents(); + if (contents != null) contained.merge(new FluidTestObject(contents), contents.amount, Integer::sum); + } + var iter = contained.object2IntEntrySet().fastIterator(); + int totalTransfer = 0; + while (iter.hasNext()) { + var content = iter.next(); + FluidStack contents = content.getKey().recombine(content.getIntValue()); + MatchResult match = null; + if (filter == null || (match = filter.match(contents)).isMatched()) { + int filterSlot = -1; + if (byFilterSlot) { + assert filter != null; // we know it is not null, because if it were byFilterSlot would be false. + filterSlot = match.getFilterIndex(); + } + int min = minTransfer.applyAsInt(filterSlot); + int max = maxTransfer.applyAsInt(filterSlot); + if (max < min || max <= 0) continue; - protected Object2ObjectLinkedOpenHashMap> getRoundRobinCache(boolean simulate) { - return simulate ? roundRobinCache.clone() : roundRobinCache; + if (contents.amount < min) continue; + int transfer = Math.min(contents.amount, max); + FluidStack extracted = sourceHandler.drain(content.getKey().recombine(transfer), false); + if (extracted == null || extracted.amount < min) continue; + transfer = simpleInsert(destHandler, content.getKey(), extracted.amount, true); + if (transfer <= 0 || transfer < min) continue; + extracted = sourceHandler.drain(content.getKey().recombine(transfer), true); + if (extracted == null) continue; + transfer = simpleInsert(destHandler, content.getKey(), extracted.amount, false); + if (transferReport != null) transferReport.accept(filterSlot, transfer); + totalTransfer += transfer; + } + } + return totalTransfer; } protected int simpleInsert(@NotNull IFluidHandler destHandler, FluidTestObject testObject, int count, @@ -632,40 +778,6 @@ public void readFromNBT(@NotNull NBTTagCompound tagCompound) { return Textures.VOLTAGE_CASINGS[this.tier].getSpriteOnSide(SimpleSidedCubeRenderer.RenderSide.SIDE); } - @Override - public @Nullable T getControllerForControl(TransferControl control) { - if (control == IFluidTransferController.CONTROL) { - return control.cast(this); - } - return null; - } - - @Override - public int insertToHandler(@NotNull FluidTestObject testObject, int amount, @NotNull IFluidHandler destHandler, - boolean doFill) { - if (getManualImportExportMode() == ManualImportExportMode.DISABLED) return 0; - if (getManualImportExportMode() == ManualImportExportMode.UNFILTERED || - getFilterMode() == FluidFilterMode.FILTER_FILL) // insert to handler is a drain for us - return IFluidTransferController.super.insertToHandler(testObject, amount, destHandler, doFill); - FluidFilterContainer filter = getFluidFilter(); - if (filter == null || filter.test(testObject.recombine())) { - return IFluidTransferController.super.insertToHandler(testObject, amount, destHandler, doFill); - } else return 0; - } - - @Override - public @Nullable FluidStack extractFromHandler(@Nullable FluidTestObject testObject, int amount, - IFluidHandler sourceHandler, boolean doDrain) { - if (getManualImportExportMode() == ManualImportExportMode.DISABLED) return null; - if (testObject == null || getManualImportExportMode() == ManualImportExportMode.UNFILTERED || - getFilterMode() == FluidFilterMode.FILTER_DRAIN) // extract from handler is an insert to us - return IFluidTransferController.super.extractFromHandler(testObject, amount, sourceHandler, doDrain); - FluidFilterContainer filter = getFluidFilter(); - if (filter == null || filter.test(testObject.recombine())) { - return IFluidTransferController.super.extractFromHandler(testObject, amount, sourceHandler, doDrain); - } else return null; - } - public enum PumpMode implements IStringSerializable, IIOMode { IMPORT("cover.pump.mode.import"), diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 15f131cb6fc..48a8b403896 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -3,28 +3,20 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.pipenet.WorldPipeNode; -import gregtech.api.graphnet.pipenet.traverse.SimpleTileRoundRobinData; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.mui.GTGuiTextures; -import gregtech.api.util.GTUtility; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; import gregtech.common.covers.filter.ItemFilterContainer; -import gregtech.common.pipelike.net.itemold.IItemTransferController; -import gregtech.common.pipelike.net.itemold.ItemEQTraverseData; -import gregtech.common.pipelike.net.itemold.ItemRRTraverseData; -import gregtech.common.pipelike.net.itemold.ItemTraverseData; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; @@ -42,7 +34,6 @@ import com.cleanroommc.modularui.widgets.layout.Column; import com.cleanroommc.modularui.widgets.layout.Row; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import org.jetbrains.annotations.NotNull; import java.util.function.IntUnaryOperator; @@ -98,54 +89,20 @@ protected void refreshBuffer(int transferRate) { @Override protected void performTransferOnUpdate(@NotNull IItemHandler sourceHandler, @NotNull IItemHandler destHandler) { - if (transferMode == TransferMode.TRANSFER_ANY) { + if (transferMode != TransferMode.TRANSFER_EXACT) { super.performTransferOnUpdate(sourceHandler, destHandler); return; } ItemFilterContainer filter = this.getItemFilter(); if (filter == null) return; - if (transferMode == TransferMode.KEEP_EXACT) { - IntUnaryOperator maxflow = s -> Math.min(filter.getTransferLimit(s), getItemsLeftToTransfer()); - reportItemsTransfer(performTransfer(sourceHandler, destHandler, true, s -> 0, maxflow, null)); - } else if (transferMode == TransferMode.TRANSFER_EXACT) { - IntUnaryOperator maxflow = s -> { - int limit = filter.getTransferLimit(s); - if (getItemsLeftToTransfer() < limit) { - noTransferDueToMinimum = true; - return 0; - } else return limit; - }; - performTransfer(sourceHandler, destHandler, true, maxflow, maxflow, (a, b) -> reportItemsTransfer(b)); - } - } - - @Override - protected @NotNull ItemTraverseData getTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { - if (transferMode == TransferMode.KEEP_EXACT) { - return new KeepItemTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - return super.getTD(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - @Override - protected @NotNull ItemEQTraverseData getEQTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing) { - if (transferMode == TransferMode.KEEP_EXACT) { - return new KeepItemEQTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - return super.getEQTD(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - @Override - protected @NotNull ItemRRTraverseData getRRTD(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, - long queryTick, BlockPos sourcePos, EnumFacing inputFacing, - boolean simulate) { - if (transferMode == TransferMode.KEEP_EXACT) { - return new KeepItemRRTraverseData(net, testObject, simulator, queryTick, sourcePos, inputFacing, - getRoundRobinCache(simulate)); - } - return super.getRRTD(net, testObject, simulator, queryTick, sourcePos, inputFacing, simulate); + IntUnaryOperator reqFlow = s -> { + int limit = filter.getTransferLimit(s); + if (getItemsLeftToTransfer() < limit) { + noTransferDueToMinimum = true; + return 0; + } else return limit; + }; + performTransfer(sourceHandler, destHandler, true, reqFlow, reqFlow, (a, b) -> reportItemsTransfer(b)); } @Override @@ -159,6 +116,31 @@ protected int simpleInsert(@NotNull IItemHandler destHandler, ItemTestObject tes return super.simpleInsert(destHandler, testObject, count, simulate); } + @Override + protected int getSupply(NetNode node, ItemTestObject testObject, boolean supply) { + if (transferMode != TransferMode.KEEP_EXACT || supply) return super.getSupply(node, testObject, supply); + if (node instanceof NodeExposingCapabilities exposer) { + IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, + exposer.exposedFacing()); + if (handler != null) { + int sum = 0; + assert getItemFilter() != null; + int kept = getItemFilter().getTransferLimit(testObject.recombine()); + ItemStack stack = testObject.recombineSafe(Integer.MAX_VALUE); + for (int i = 0; i < handler.getSlots(); i++) { + sum += stack.getCount() - handler.insertItem(i, stack, true).getCount(); + ItemStack contained = handler.getStackInSlot(i); + if (testObject.test(contained)) { + kept -= contained.getCount(); + if (kept <= 0) return 0; + } + } + return -Math.min(kept, sum); + } + } + return 0; + } + public void setTransferMode(TransferMode transferMode) { if (this.transferMode != transferMode) { this.transferMode = transferMode; @@ -210,43 +192,6 @@ protected ParentWidget createUI(ModularPanel mainPanel, PanelSyncManager .setTextColor(Color.WHITE.darker(1)))); } - // @Override - // public int insertToHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler destHandler, - // boolean simulate) { - // if (conveyorMode == ConveyorMode.EXPORT) { - // if (transferMode == TransferMode.KEEP_EXACT) { - // int contained = computeContained(destHandler, testObject); - // assert getItemFilter() != null; - // int keep = getItemFilter().getTransferLimit(testObject.recombine()); - // if (contained >= keep) return amount; - // int allowed = Math.min(keep - contained, amount); - // return (amount - allowed) + super.insertToHandler(testObject, allowed, destHandler, simulate); - // } else if (transferMode == TransferMode.TRANSFER_EXACT) { - // assert getItemFilter() != null; - // int required = getItemFilter().getTransferLimit(testObject.recombine()); - // if (amount < required) return amount; - // return (amount - required) + super.insertToHandler(testObject, required, destHandler, simulate); - // } - // } - // return super.insertToHandler(testObject, amount, destHandler, simulate); - // } - // - // @Override - // public int extractFromHandler(@NotNull ItemTestObject testObject, int amount, @NotNull IItemHandler - // sourceHandler, - // boolean simulate) { - // if (conveyorMode == ConveyorMode.IMPORT) { - // // should extraction instead be ignored for transfer exact? - // if (transferMode == TransferMode.TRANSFER_EXACT) { - // assert getItemFilter() != null; - // int required = getItemFilter().getTransferLimit(testObject.recombine()); - // if (amount < required) return 0; - // else amount = required; - // } - // } - // return super.extractFromHandler(testObject, amount, sourceHandler, simulate); - // } - @Override protected int getMaxStackSize() { return getTransferMode().maxStackSize; @@ -297,130 +242,4 @@ protected int computeContained(@NotNull IItemHandler handler, @NotNull ItemTestO } return found; } - - protected class KeepItemTraverseData extends ItemTraverseData { - - public KeepItemTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing) { - super(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - @Override - public long finalizeAtDestination(@NotNull WorldPipeNode destination, long flowReachingDestination) { - long availableFlow = flowReachingDestination; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IItemHandler container = capability.getValue() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, - capability.getKey().getOpposite()); - if (container != null) { - int contained = computeContained(container, getTestObject()); - assert getItemFilter() != null; - int kept = getItemFilter().getTransferLimit(getTestObject().recombine()); - if (contained >= kept) continue; - availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, simulating()); - } - } - return flowReachingDestination - availableFlow; - } - } - - protected class KeepItemEQTraverseData extends ItemEQTraverseData { - - public KeepItemEQTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing) { - super(net, testObject, simulator, queryTick, sourcePos, inputFacing); - } - - @Override - protected void compute(@NotNull WorldPipeNode destination) { - this.destCount = 0; - this.maxMinFlow = 0; - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IItemHandler container = capability.getValue() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, - capability.getKey().getOpposite()); - if (container != null) { - int contained = computeContained(container, getTestObject()); - assert getItemFilter() != null; - int kept = getItemFilter().getTransferLimit(getTestObject().recombine()); - if (contained >= kept) continue; - if (destCount == 0) maxMinFlow = Integer.MAX_VALUE; - destCount += 1; - int test = kept - contained; - maxMinFlow = Math.min(maxMinFlow, test - - IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), test, - container, true)); - } - } - } - - @Override - public long finalizeAtDestination(@NotNull WorldPipeNode node, long flowReachingNode, - int expectedDestinations) { - long availableFlow = flowReachingNode; - long flowPerDestination = flowReachingNode / expectedDestinations; - if (flowPerDestination == 0) return 0; - for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { - if (GTUtility.arePosEqual(node.getEquivalencyData(), sourcePos) && - capability.getKey() == inputFacing) - continue; // anti insert-to-our-source logic - - IItemHandler container = capability.getValue() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, - capability.getKey().getOpposite()); - if (container != null) { - int contained = computeContained(container, getTestObject()); - assert getItemFilter() != null; - int kept = getItemFilter().getTransferLimit(getTestObject().recombine()); - if (contained >= kept) continue; - availableFlow = IItemTransferController.CONTROL.get(node.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, flowPerDestination), container, simulating()); - } - } - return flowReachingNode - availableFlow; - } - } - - protected class KeepItemRRTraverseData extends ItemRRTraverseData { - - public KeepItemRRTraverseData(IGraphNet net, ItemTestObject testObject, SimulatorKey simulator, long queryTick, - BlockPos sourcePos, EnumFacing inputFacing, - @NotNull Object2ObjectLinkedOpenHashMap> cache) { - super(net, testObject, simulator, queryTick, sourcePos, inputFacing, cache); - } - - @Override - public long finalizeAtDestination(@NotNull SimpleTileRoundRobinData data, - @NotNull WorldPipeNode destination, - long flowReachingDestination) { - long availableFlow = flowReachingDestination; - EnumFacing pointerFacing = data.getPointerFacing(getSimulatorKey()); - if (GTUtility.arePosEqual(destination.getEquivalencyData(), sourcePos) && pointerFacing == inputFacing) - return 0; // anti insert-to-our-source logic - - IItemHandler container = data.getAtPointer(destination, getSimulatorKey()); - if (container != null) { - int contained = computeContained(container, getTestObject()); - assert getItemFilter() != null; - int kept = getItemFilter().getTransferLimit(getTestObject().recombine()); - if (contained >= kept) return 0; - availableFlow = IItemTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(pointerFacing)).insertToHandler(getTestObject(), - (int) Math.min(kept - contained, availableFlow), container, simulating()); - } - return flowReachingDestination - availableFlow; - } - } } diff --git a/src/main/java/gregtech/common/covers/CoverShutter.java b/src/main/java/gregtech/common/covers/CoverShutter.java index 2f2a29d409a..5f0dc1676f0 100644 --- a/src/main/java/gregtech/common/covers/CoverShutter.java +++ b/src/main/java/gregtech/common/covers/CoverShutter.java @@ -5,8 +5,6 @@ import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; import gregtech.client.renderer.texture.Textures; @@ -26,9 +24,8 @@ import codechicken.lib.vec.Cuboid6; import codechicken.lib.vec.Matrix4; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -public class CoverShutter extends CoverBase implements IControllable, TransferControlProvider { +public class CoverShutter extends CoverBase implements IControllable { private boolean isWorkingAllowed = true; @@ -119,10 +116,4 @@ public void readFromNBT(@NotNull NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); isWorkingAllowed = tagCompound.getBoolean("WorkingAllowed"); } - - @Override - public @Nullable T getControllerForControl(TransferControl control) { - if (!isWorkingEnabled()) return null; - else return control.getNoPassage(); - } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java index 074af38e057..709bc748550 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyCapabilityObject.java @@ -11,6 +11,7 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.util.GTLog; +import gregtech.common.covers.CoverShutter; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; @@ -66,22 +67,22 @@ public long acceptEnergyFromNetwork(EnumFacing side, long voltage, long amperage long available = amperage; for (EnergyPath path : paths) { NetNode target = path.getTargetNode(); - for (var capability : node.getTileEntity().getTargetsWithCapabilities(node).entrySet()) { - if (node == target && capability.getKey() == side) continue; // anti insert-to-our-source logic + if (!(target instanceof WorldPipeNode n)) continue; + for (var capability : n.getTileEntity().getTargetsWithCapabilities(n).entrySet()) { + if (n == node && capability.getKey() == side) continue; // anti insert-to-our-source logic IEnergyContainer container = capability.getValue().getCapability( GregtechCapabilities.CAPABILITY_ENERGY_CONTAINER, capability.getKey().getOpposite()); - if (container != null) { - IEnergyTransferController controller = IEnergyTransferController.CONTROL - .get(tile.getCoverHolder().getCoverAtSide(capability.getKey())); - long allowed = controller.insertToHandler(voltage, available, container, capability.getKey(), true); + if (container != null && !(n.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey()) instanceof CoverShutter)) { + long allowed = container.acceptEnergyFromNetwork(capability.getKey(), voltage, amperage, true); EnergyPath.PathFlowReport flow = path.traverse(voltage, allowed); if (flow.euOut() > 0) { available -= allowed; if (!simulate) { flow.report(); - controller.insertToHandler(flow.voltageOut(), flow.amperageOut(), container, - capability.getKey(), false); + container.acceptEnergyFromNetwork(capability.getKey(), flow.voltageOut(), + flow.amperageOut(), false); } } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java b/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java deleted file mode 100644 index 5c637f0c398..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/energy/IEnergyTransferController.java +++ /dev/null @@ -1,47 +0,0 @@ -package gregtech.common.pipelike.net.energy; - -import gregtech.api.capability.IEnergyContainer; -import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; - -import net.minecraft.util.EnumFacing; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface IEnergyTransferController { - - TransferControl CONTROL = new TransferControl<>("Energy") { - - @Override - public @NotNull IEnergyTransferController get(@Nullable Object potentialHolder) { - if (!(potentialHolder instanceof TransferControlProvider holder)) return DEFAULT; - IEnergyTransferController found = holder.getControllerForControl(CONTROL); - return found == null ? DEFAULT : found; - } - - @Override - public @NotNull IEnergyTransferController getNoPassage() { - return NO_PASSAGE; - } - }; - - IEnergyTransferController DEFAULT = new IEnergyTransferController() {}; - - IEnergyTransferController NO_PASSAGE = new IEnergyTransferController() { - - @Override - public long insertToHandler(long voltage, long amperage, @NotNull IEnergyContainer destHandler, - EnumFacing side, boolean simulate) { - return 0; - } - }; - - /** - * @return inserted amperes - */ - default long insertToHandler(long voltage, long amperage, @NotNull IEnergyContainer destHandler, EnumFacing side, - boolean simulate) { - return destHandler.acceptEnergyFromNetwork(side, voltage, amperage, simulate); - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java index 601c506aeed..20de26887cf 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java @@ -8,6 +8,7 @@ import gregtech.api.graphnet.path.PathBuilder; import gregtech.api.graphnet.path.SingletonNetPath; import gregtech.api.graphnet.path.StandardNetPath; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; @@ -99,6 +100,9 @@ public PathFlowReport traverse(final long voltage, final long amperage) { data.getLogicEntryDefaultable(VoltageLimitLogic.TYPE).getValue()); float heat = (float) computeHeat(voltage, endVoltage, finalResultAmperage, correctedAmperage); if (heat > 0) tempLogic.applyThermalEnergy(heat, tick); + if (node instanceof WorldPipeNode n) { + tempLogic.defaultHandleTemperature(n.getNet().getWorld(), n.getEquivalencyData()); + } } finalEnergyFlow.recordFlow(tick, new EnergyFlowData(correctedAmperage, finalResultVoltage)); }); @@ -238,6 +242,9 @@ else if (resultVoltage > voltageLimit) { data.getLogicEntryDefaultable(VoltageLimitLogic.TYPE).getValue()); float heat = (float) computeHeat(voltage, endVoltage, resultAmperage, resultAmperage); if (heat > 0) tempLogic.applyThermalEnergy(heat, tick); + if (node instanceof WorldPipeNode n) { + tempLogic.defaultHandleTemperature(n.getNet().getWorld(), n.getEquivalencyData()); + } } finalEnergyFlow.recordFlow(tick, new EnergyFlowData(resultAmperage, finalResultVoltage)); diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index 2b590b432b2..a730891cb56 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -9,7 +9,9 @@ import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.pipenet.WorldPipeNode; +import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; +import gregtech.api.graphnet.pipenet.physical.tile.IWorldPipeNetTile; import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; @@ -29,7 +31,6 @@ import java.util.Arrays; import java.util.EnumMap; -import java.util.concurrent.atomic.AtomicInteger; public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler, IFluidTankProperties { @@ -52,6 +53,10 @@ public FluidCapabilityObject(WorldPipeNode node) { } } + public WorldPipeNode getNode() { + return node; + } + @Override public void init(@NotNull PipeTileEntity tile, @NotNull PipeCapabilityWrapper wrapper) { this.tile = tile; @@ -88,20 +93,21 @@ protected int fill(FluidStack resource, boolean doFill, EnumFacing side) { int flow = resource.amount; SimulatorKey key = doFill ? null : SimulatorKey.getNewSimulatorInstance(); FluidTestObject testObject = new FluidTestObject(resource); - AtomicInteger report = new AtomicInteger(); - FDTraverse.flood(node.getNet(), + int report = FDTraverse.flood(node.getNet(), (n, f) -> { - if (n == node) report.addAndGet(f); - else if (doFill) reportFlow(n, f, testObject); + if (n != node && doFill) reportFlow(n, f, testObject); }, (e, f) -> reportFlow(e, f, testObject, key, true), e -> e instanceof AbstractNetFlowEdge n && e.test(testObject) ? - GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, node.getNet(), getQueryTick(), key)) : 0, + GTUtility.safeCastLongToInt( + n.getFlowLimit(testObject, node.getNet(), GTUtility.getTick(), key)) : + 0, n -> n == node ? flow : getSupply(n, testObject, false), - n -> n.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE).handles(testObject)); + n -> n.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE).handles(testObject), + (n, f) -> handleLoss(n, f, testObject)); this.transferring = false; - return report.get(); + return report; } protected FluidStack drain(int maxDrain, boolean doDrain, EnumFacing side) { @@ -118,42 +124,70 @@ protected FluidStack drain(FluidStack resource, boolean doDrain, EnumFacing side int flow = resource.amount; SimulatorKey key = doDrain ? null : SimulatorKey.getNewSimulatorInstance(); FluidTestObject testObject = new FluidTestObject(resource); - AtomicInteger report = new AtomicInteger(); - FDTraverse.flood(node.getNet(), + int report = FDTraverse.flood(node.getNet(), (n, f) -> { - if (n == node) report.addAndGet(f); - else if (doDrain) reportFlow(n, f, testObject); + if (n != node && doDrain) reportFlow(n, f, testObject); }, (e, f) -> reportFlow(e, f, testObject, key, false), e -> e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, node.getNet(), getQueryTick(), key)) : 0, + GTUtility.safeCastLongToInt( + n.getFlowLimit(testObject, node.getNet(), GTUtility.getTick(), key)) : + 0, n -> n == node ? flow : getSupply(n, testObject, true), - n -> n.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE).handles(testObject)); + n -> n.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE).handles(testObject), + (n, f) -> handleLoss(n, f, testObject)); this.transferring = false; - return testObject.recombine(report.get()); + return testObject.recombine(report); } - protected void reportFlow(NetEdge edge, int flow, FluidTestObject testObject, SimulatorKey key, - boolean sourceBias) { + public static void reportFlow(NetEdge edge, int flow, FluidTestObject testObject, SimulatorKey key, + boolean sourceBias) { + NetNode node = sourceBias ? edge.getSource() : edge.getTarget(); + if (node == null) return; if (edge instanceof AbstractNetFlowEdge n) - n.consumeFlowLimit(testObject, node.getNet(), flow, getQueryTick(), key); + n.consumeFlowLimit(testObject, node.getNet(), flow, GTUtility.getTick(), key); if (key == null) { - NetNode node = sourceBias ? edge.getSource() : edge.getTarget(); - if (node == null) return; FluidFlowLogic logic = node.getData().getLogicEntryNullable(FluidFlowLogic.TYPE); if (logic == null) { logic = FluidFlowLogic.TYPE.getNew(); node.getData().setLogicEntry(logic); } - logic.recordFlow(getQueryTick(), testObject.recombine(flow)); + FluidStack stack = testObject.recombine(flow); + logic.recordFlow(GTUtility.getTick(), stack); + TemperatureLogic temp = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); + if (temp != null) { + FluidContainmentLogic cont = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE); + int t = stack.getFluid().getTemperature(stack); + temp.moveTowardsTemperature(t, GTUtility.getTick(), stack.amount, cont.getMaximumTemperature() >= t); + if (node instanceof WorldPipeNode n) { + temp.defaultHandleTemperature(n.getNet().getWorld(), n.getEquivalencyData()); + } + } + } + } + + public static void reportFlow(NetNode node, int flow, FluidTestObject testObject) { + if (flow == 0) return; + if (node instanceof NodeExposingCapabilities exposer) { + IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + exposer.exposedFacing()); + if (handler != null) { + // positive flow is supply, aka we pulled flow from this node + if (flow > 0) { + handler.drain(testObject.recombine(flow), true); + } else { + handler.fill(testObject.recombine(flow), true); + } + } } } - protected void reportFlow(NetNode node, int flow, FluidTestObject testObject) { + public static void handleLoss(NetNode node, int flow, FluidTestObject testObject) { if (flow == 0) return; FluidContainmentLogic logic = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE); - if (!logic.handles(testObject)) { + if (node instanceof WorldPipeNode n) { + IWorldPipeNetTile tile = n.getTileEntity(); FluidStack stack = testObject.recombine(flow); // failing attributes take priority over state for (FluidAttribute attribute : FluidAttribute.inferAttributes(stack)) { @@ -164,21 +198,10 @@ protected void reportFlow(NetNode node, int flow, FluidTestObject testObject) { } FluidState state = FluidState.inferState(stack); if (!logic.contains(state)) state.handleFailure(tile.getWorld(), tile.getPos(), stack); - } else if (node instanceof NodeExposingCapabilities exposer) { - IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - exposer.exposedFacing()); - if (handler != null) { - // positive flow is supply, aka we pulled flow from this node - if (flow > 0) { - handler.drain(testObject.recombine(flow), true); - } else { - handler.fill(testObject.recombine(flow), true); - } - } } } - protected int getSupply(NetNode node, FluidTestObject testObject, boolean supply) { + public static int getSupply(NetNode node, FluidTestObject testObject, boolean supply) { if (node instanceof NodeExposingCapabilities exposer) { IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, exposer.exposedFacing()); diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index 3a0fd6b77f2..0dcc6f46bc4 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -17,7 +17,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; @@ -25,7 +24,6 @@ import org.jetbrains.annotations.Nullable; import java.util.EnumMap; -import java.util.concurrent.atomic.AtomicInteger; public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler { @@ -44,6 +42,10 @@ public ItemCapabilityObject(WorldPipeNode node) { } } + public WorldPipeNode getNode() { + return node; + } + @Override public void init(@NotNull PipeTileEntity tile, @NotNull PipeCapabilityWrapper wrapper) { this.tile = tile; @@ -76,22 +78,21 @@ public T getCapability(Capability capability, @Nullable EnumFacing facing this.transferring = true; int flow = stack.getCount(); - long queryTick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); SimulatorKey key = simulate ? SimulatorKey.getNewSimulatorInstance() : null; ItemTestObject testObject = new ItemTestObject(stack); - AtomicInteger report = new AtomicInteger(); - FDTraverse.flood(node.getNet(), + int report = FDTraverse.flood(node.getNet(), (n, f) -> { - if (n == node) report.addAndGet(f); - else if (!simulate) reportFlow(n, f, testObject); + if (n != node && !simulate) reportFlow(n, f, testObject); }, (e, f) -> reportFlow(e, f, testObject, key, true), e -> e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, node.getNet(), queryTick, key)) : 0, - n -> n == node ? flow : getSupply(n, testObject, false), null); + GTUtility.safeCastLongToInt( + n.getFlowLimit(testObject, node.getNet(), GTUtility.getTick(), key)) : + 0, + n -> n == node ? flow : getSupply(n, testObject, false), null, null); this.transferring = false; - return testObject.recombine(stack.getCount() - report.get()); + return testObject.recombine(stack.getCount() - report); } protected @NotNull ItemStack extractItem(int slot, int amount, boolean simulate, EnumFacing side) { @@ -99,22 +100,24 @@ public T getCapability(Capability capability, @Nullable EnumFacing facing return ItemStack.EMPTY; } - protected void reportFlow(NetEdge edge, int flow, ItemTestObject testObject, SimulatorKey key, boolean sourceBias) { - if (edge instanceof AbstractNetFlowEdge n) - n.consumeFlowLimit(testObject, node.getNet(), flow, getQueryTick(), key); + public static void reportFlow(NetEdge edge, int flow, ItemTestObject testObject, SimulatorKey key, + boolean sourceBias) { + NetNode node = sourceBias ? edge.getSource() : edge.getTarget(); + if (node == null) return; + if (edge instanceof AbstractNetFlowEdge n) { + n.consumeFlowLimit(testObject, node.getNet(), flow, GTUtility.getTick(), key); + } if (key == null) { - NetNode node = sourceBias ? edge.getSource() : edge.getTarget(); - if (node == null) return; ItemFlowLogic logic = node.getData().getLogicEntryNullable(ItemFlowLogic.TYPE); if (logic == null) { logic = ItemFlowLogic.TYPE.getNew(); node.getData().setLogicEntry(logic); } - logic.recordFlow(getQueryTick(), testObject.recombine(flow)); + logic.recordFlow(GTUtility.getTick(), testObject.recombine(flow)); } } - protected void reportFlow(NetNode node, int flow, ItemTestObject testObject) { + public static void reportFlow(NetNode node, int flow, ItemTestObject testObject) { if (flow == 0) return; if (node instanceof NodeExposingCapabilities exposer) { IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, @@ -141,7 +144,7 @@ protected void reportFlow(NetNode node, int flow, ItemTestObject testObject) { } } - protected int getSupply(NetNode node, ItemTestObject testObject, boolean supply) { + public static int getSupply(NetNode node, ItemTestObject testObject, boolean supply) { if (node instanceof NodeExposingCapabilities exposer) { IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, exposer.exposedFacing()); @@ -155,11 +158,11 @@ protected int getSupply(NetNode node, ItemTestObject testObject, boolean supply) return sum; } else { int sum = 0; + ItemStack stack = testObject.recombineSafe(Integer.MAX_VALUE); for (int i = 0; i < handler.getSlots(); i++) { - ItemStack stack = testObject.recombineSafe(Integer.MAX_VALUE); sum += stack.getCount() - handler.insertItem(i, stack, true).getCount(); } - return sum; + return -sum; } } } diff --git a/src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java b/src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java deleted file mode 100644 index 4ef8b2b87ab..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/laser/ILaserTransferController.java +++ /dev/null @@ -1,43 +0,0 @@ -package gregtech.common.pipelike.net.laser; - -import gregtech.api.capability.ILaserRelay; -import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface ILaserTransferController { - - TransferControl CONTROL = new TransferControl<>("Laser") { - - @Override - public @NotNull ILaserTransferController get(@Nullable Object potentialHolder) { - if (!(potentialHolder instanceof TransferControlProvider holder)) return DEFAULT; - ILaserTransferController found = holder.getControllerForControl(CONTROL); - return found == null ? DEFAULT : found; - } - - @Override - public @NotNull ILaserTransferController getNoPassage() { - return NO_PASSAGE; - } - }; - - ILaserTransferController DEFAULT = new ILaserTransferController() {}; - - ILaserTransferController NO_PASSAGE = new ILaserTransferController() { - - @Override - public long insertToHandler(long voltage, long amperage, @NotNull ILaserRelay destHandler) { - return 0; - } - }; - - /** - * @return inserted amperes - */ - default long insertToHandler(long voltage, long amperage, @NotNull ILaserRelay destHandler) { - return destHandler.receiveLaser(voltage, amperage); - } -} diff --git a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java index 65d67a6ca55..9c606613b2e 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java @@ -10,6 +10,7 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.common.covers.CoverShutter; import gregtech.common.pipelike.net.SlowActiveWalker; import net.minecraft.util.EnumFacing; @@ -76,9 +77,9 @@ else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { if (destination == node && capability.getKey() == facing) continue; // anti insert-to-our-source logic ILaserRelay laser = capability.getValue() .getCapability(GregtechTileCapabilities.CAPABILITY_LASER, capability.getKey().getOpposite()); - if (laser != null) { - long transmitted = ILaserTransferController.CONTROL.get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())).insertToHandler(laserVoltage, laserAmperage, laser); + if (laser != null && !(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey()) instanceof CoverShutter)) { + long transmitted = laser.receiveLaser(laserVoltage, laserAmperage); if (transmitted > 0) { SlowActiveWalker.dispatch(tile.getWorld(), path, 1, 2, 2); available -= transmitted; diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index 28ac7fcb0f7..2d6aa3c815c 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -12,6 +12,7 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; +import gregtech.common.covers.CoverShutter; import gregtech.common.pipelike.net.SlowActiveWalker; import net.minecraft.util.EnumFacing; @@ -76,12 +77,10 @@ else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { IDataAccess access = capability.getValue() .getCapability(GregtechTileCapabilities.CAPABILITY_DATA_ACCESS, capability.getKey().getOpposite()); - if (access != null) { + if (access != null && !(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey()) instanceof CoverShutter)) { queryObject.setShouldTriggerWalker(false); - boolean cancelled = IOpticalTransferController.CONTROL - .get(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey())) - .queryHandler(queryObject, access); + boolean cancelled = access.accessData(queryObject); if (queryObject.shouldTriggerWalker()) { SlowActiveWalker.dispatch(tile.getWorld(), path, 1); } diff --git a/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java b/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java deleted file mode 100644 index 94da6f4ce10..00000000000 --- a/src/main/java/gregtech/common/pipelike/net/optical/IOpticalTransferController.java +++ /dev/null @@ -1,45 +0,0 @@ -package gregtech.common.pipelike.net.optical; - -import gregtech.api.capability.data.IDataAccess; -import gregtech.api.capability.data.query.DataQueryObject; -import gregtech.api.graphnet.pipenet.transfer.TransferControl; -import gregtech.api.graphnet.pipenet.transfer.TransferControlProvider; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface IOpticalTransferController { - - TransferControl CONTROL = new TransferControl<>("Laser") { - - @Override - public @NotNull IOpticalTransferController get(@Nullable Object potentialHolder) { - if (!(potentialHolder instanceof TransferControlProvider holder)) return DEFAULT; - IOpticalTransferController found = holder.getControllerForControl(CONTROL); - return found == null ? DEFAULT : found; - } - - @Override - public @NotNull IOpticalTransferController getNoPassage() { - return NO_PASSAGE; - } - }; - - IOpticalTransferController DEFAULT = new IOpticalTransferController() {}; - - IOpticalTransferController NO_PASSAGE = new IOpticalTransferController() { - - @Override - public boolean queryHandler(DataQueryObject query, IDataAccess handler) { - return false; - } - }; - - /** - * @return whether the request should be cancelled - */ - default boolean queryHandler(DataQueryObject query, IDataAccess handler) { - if (query.traverseTo(handler)) return handler.accessData(query); - else return false; - } -} From 67552a81769a8e9c6f6bd27cc9e008ca267aa929 Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Fri, 20 Dec 2024 12:12:24 -0700 Subject: [PATCH 151/157] Fix issues I thought of in my sleep --- .../api/graphnet/GraphNetUtility.java | 59 +++++++++++++ .../api/graphnet/graph/GraphVertex.java | 8 ++ .../pipenet/traverse/RoundRobinCache.java | 83 ++++++++++++------- .../graphnet/traverse/iter/EdgeSelector.java | 13 --- .../gregtech/common/covers/CoverConveyor.java | 61 ++++++-------- .../gregtech/common/covers/CoverPump.java | 61 ++++++-------- 6 files changed, 171 insertions(+), 114 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/GraphNetUtility.java diff --git a/src/main/java/gregtech/api/graphnet/GraphNetUtility.java b/src/main/java/gregtech/api/graphnet/GraphNetUtility.java new file mode 100644 index 00000000000..ad260545767 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/GraphNetUtility.java @@ -0,0 +1,59 @@ +package gregtech.api.graphnet; + +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.traverse.iter.EdgeDirection; +import gregtech.api.graphnet.traverse.iter.EdgeSelector; +import gregtech.api.graphnet.traverse.iter.NetClosestIterator; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.NotNull; +import org.jgrapht.Graph; + +import java.util.Set; + +public final class GraphNetUtility { + + private GraphNetUtility() {} + + public static boolean isOnlyBridge(@NotNull NetEdge bridge) { + NetNode sourceNode = bridge.getSource(); + NetNode destNode = bridge.getTarget(); + if (sourceNode == null || destNode == null) return false; + EdgeSelector selector = bridgeFiltered(EdgeDirection.ALL, sourceNode, destNode); + NetClosestIterator sourceFrontier = new NetClosestIterator(sourceNode, selector); + NetClosestIterator destFrontier = new NetClosestIterator(destNode, selector); + // since we check all edges, if either frontier exhausts we know that they cannot coincide. + while (sourceFrontier.hasNext() && destFrontier.hasNext()) { + NetNode next = sourceFrontier.next(); + // the dest frontier has seen the next node in the source frontier, we are not the only bridge. + if (destFrontier.getSpanningTreeEdge(next) != null) return false; + next = destFrontier.next(); + // the source frontier has seen the next node in the dest frontier, we are not the only bridge. + if (sourceFrontier.getSpanningTreeEdge(next) != null) return false; + } + return true; + } + + public static EdgeSelector bridgeFiltered(@NotNull EdgeSelector basis, + @NotNull NetNode sourceNode, @NotNull NetNode destNode) { + GraphEdge e1 = GraphEdge.unwrap(sourceNode.getNet().getEdge(sourceNode, destNode)); + GraphEdge e2 = GraphEdge.unwrap(sourceNode.getNet().getEdge(destNode, sourceNode)); + GraphVertex v1 = GraphVertex.unwrap(sourceNode); + GraphVertex v2 = GraphVertex.unwrap(destNode); + return new EdgeSelector() { + + @Override + public Set selectEdges(Graph graph, V vertex) { + Set s = basis.selectEdges(graph, vertex); + if (vertex == v1 || vertex == v2) { + s = new ObjectOpenHashSet<>(s); + s.removeIf(e -> e == e1 || e == e2); + } + return s; + } + }; + } +} diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java b/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java index 36df5cea44b..58999c88d4d 100644 --- a/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java +++ b/src/main/java/gregtech/api/graphnet/graph/GraphVertex.java @@ -3,7 +3,9 @@ import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Objects; @@ -26,6 +28,12 @@ public NetNode getWrapped() { return wrapped; } + @Nullable + @Contract("null->null") + public static GraphVertex unwrap(NetNode n) { + return n == null ? null : n.wrapper; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java index 75829eff29c..824381386c9 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java @@ -4,24 +4,25 @@ import gregtech.api.graphnet.traverse.iter.NetIterator; import com.github.bsideup.jabel.Desugar; +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; +import java.util.ArrayDeque; import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.function.Predicate; import java.util.function.Supplier; @Desugar -public record RoundRobinCache(LinkedHashSet sourceCache, LinkedHashSet destCache) { +public record RoundRobinCache(ObjectLinkedOpenHashSet sourceCache, + ObjectLinkedOpenHashSet destCache) { public static RoundRobinCache create() { - return new RoundRobinCache(new LinkedHashSet<>(), new LinkedHashSet<>()); + return new RoundRobinCache(new ObjectLinkedOpenHashSet<>(), new ObjectLinkedOpenHashSet<>()); } public Supplier> buildSupplier(Collection sourceCandidates, Collection destCandidates) { - return new CacheSupplier(sourceCandidates, destCandidates); + return sourceCandidates.isEmpty() || destCandidates.isEmpty() ? () -> null : + new CacheSupplier(sourceCandidates, destCandidates); } public RoundRobinCache refresh(NetIterator sources, NetIterator targets) { @@ -41,42 +42,62 @@ public void clear() { } public RoundRobinCache copy() { - return new RoundRobinCache(new LinkedHashSet<>(sourceCache), new LinkedHashSet<>(destCache)); + return new RoundRobinCache(sourceCache.clone(), destCache.clone()); } - private static final class CacheSupplier implements Supplier> { + private final class CacheSupplier implements Supplier> { - private final Iterator sourceIterator; - private final Collection destCandidates; - private NetNode nextSource; - private Iterator destIterator; + private final ArrayDeque sources; + private ArrayDeque dests; + private ArrayDeque destBacklog; public CacheSupplier(Collection sourceCandidates, Collection destCandidates) { - this.destCandidates = destCandidates; - this.destIterator = destCandidates.iterator(); - if (!destIterator.hasNext()) { - sourceIterator = Collections.emptyIterator(); - nextSource = null; - } else { - sourceIterator = sourceCandidates.iterator(); - this.nextSource = sourceIterator.hasNext() ? sourceIterator.next() : null; - } + this.sources = new ArrayDeque<>(sourceCandidates); + this.dests = new ArrayDeque<>(destCandidates); + this.destBacklog = new ArrayDeque<>(destCandidates.size()); } @Override public Predicate get() { - if (nextSource == null) { - if (sourceIterator.hasNext()) nextSource = sourceIterator.next(); - if (nextSource == null) return null; + if (dests.isEmpty()) { + ArrayDeque queue = dests; + dests = destBacklog; + destBacklog = queue; + sources.removeFirst(); + if (sources.isEmpty()) return null; + int i = 0; + while (true) { + NetNode s = sources.peekFirst(); + // yeet the first if we've gone through the entire deque without a match + if (i >= sources.size()) { + sourceCache.removeFirst(); + i = 0; + } + if (!sourceCache.contains(s) || sourceCache.first() == s) break; + i++; + sources.addLast(sources.removeFirst()); + } } - if (!destIterator.hasNext()) { - destIterator = destCandidates.iterator(); - if (!destIterator.hasNext()) return null; - nextSource = null; - return get(); + NetNode s = sources.peekFirst(); + NetNode d; + int i = 0; + while (true) { + d = dests.removeFirst(); + // yeet the first if we've gone through the entire deque without a match + if (i >= dests.size()) { + destCache.removeFirst(); + i = 0; + } + if (!destCache.contains(d) || destCache.first() == d) break; + i++; + dests.addLast(d); + } - NetNode node = destIterator.next(); - return n -> n == nextSource || n == node; + destBacklog.addLast(d); + sourceCache.addAndMoveToLast(s); + destCache.addAndMoveToLast(d); + NetNode finalD = d; + return n -> n == s || n == finalD; } } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java index 517eb6d8d28..0841a5f4f21 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java @@ -3,21 +3,8 @@ import org.jgrapht.Graph; import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; public interface EdgeSelector { Set selectEdges(Graph graph, V vertex); - - static EdgeSelector filtered(EdgeSelector prototype, Predicate edgeFilter) { - // can't create via lambda due to generics - return new EdgeSelector() { - - @Override - public Set selectEdges(Graph graph, V vertex) { - return prototype.selectEdges(graph, vertex).stream().filter(edgeFilter).collect(Collectors.toSet()); - } - }; - } } diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 2d95b156803..667a95fae78 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -10,10 +10,10 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; +import gregtech.api.graphnet.GraphNetUtility; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; @@ -25,7 +25,6 @@ import gregtech.api.graphnet.traverse.FDTraverse; import gregtech.api.graphnet.traverse.RRTraverse; import gregtech.api.graphnet.traverse.iter.EdgeDirection; -import gregtech.api.graphnet.traverse.iter.EdgeSelector; import gregtech.api.graphnet.traverse.iter.NetClosestIterator; import gregtech.api.graphnet.traverse.iter.NetIterator; import gregtech.api.mui.GTGuiTextures; @@ -94,7 +93,6 @@ import java.util.Map; import java.util.function.IntUnaryOperator; -import java.util.function.Predicate; public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithItemFilter { @@ -305,42 +303,35 @@ protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode de @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { // first, evaluate whether we're the only bridge between two areas in a group NetEdge bridge = sourceNode.getNet().getEdge(sourceNode, destNode); - GraphEdge b1 = GraphEdge.unwrap(bridge); - GraphEdge b2 = GraphEdge.unwrap(sourceNode.getNet().getEdge(destNode, sourceNode)); - Predicate predicate = g -> g != b1 && g != b2; + if (bridge == null || !GraphNetUtility.isOnlyBridge(bridge)) return 0; + // second, build frontier information. If we have no candidates for either frontier, exit early. NetClosestIterator sourceFrontier = new NetClosestIterator(sourceNode, - EdgeSelector.filtered(EdgeDirection.INCOMING, predicate)); - NetClosestIterator destFrontier = new NetClosestIterator(destNode, - EdgeSelector.filtered(EdgeDirection.OUTGOING, predicate)); + GraphNetUtility.bridgeFiltered(EdgeDirection.INCOMING, sourceNode, destNode)); Map sourceCandidates = new Object2ObjectOpenHashMap<>(); - Map destinationCandidates = new Object2ObjectOpenHashMap<>(); - // note that if we checked all edges instead of only incoming for one and outgoing for the other, - // we would be able to know that we're the only bridge once either frontier exhausted, not both. - while (sourceFrontier.hasNext() || destFrontier.hasNext()) { - if (sourceFrontier.hasNext()) { - NetNode next = sourceFrontier.next(); - // the dest frontier has seen the next node in the source frontier, we are not the only bridge. - if (destFrontier.getSpanningTreeEdge(next) != null) return 0; - if (next instanceof NodeExposingCapabilities cap) { - IItemHandler handler = cap.getProvider() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, cap.exposedFacing()); - if (handler != null && !(handler instanceof ItemCapabilityObject)) - sourceCandidates.put(next, handler); - } + while (sourceFrontier.hasNext()) { + NetNode next = sourceFrontier.next(); + if (next instanceof NodeExposingCapabilities cap) { + IItemHandler handler = cap.getProvider() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, cap.exposedFacing()); + if (handler != null && !(handler instanceof ItemCapabilityObject)) + sourceCandidates.put(next, handler); } - if (destFrontier.hasNext()) { - NetNode next = destFrontier.next(); - // the source frontier has seen the next node in the dest frontier, we are not the only bridge. - if (sourceFrontier.getSpanningTreeEdge(next) != null) return 0; - if (next instanceof NodeExposingCapabilities cap) { - IItemHandler handler = cap.getProvider() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, cap.exposedFacing()); - if (handler != null && !(handler instanceof ItemCapabilityObject)) - destinationCandidates.put(next, handler); - } + } + if (sourceCandidates.isEmpty()) return 0; + NetClosestIterator destFrontier = new NetClosestIterator(destNode, + GraphNetUtility.bridgeFiltered(EdgeDirection.OUTGOING, sourceNode, destNode)); + Map destinationCandidates = new Object2ObjectOpenHashMap<>(); + while (destFrontier.hasNext()) { + NetNode next = destFrontier.next(); + if (next instanceof NodeExposingCapabilities cap) { + IItemHandler handler = cap.getProvider() + .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, cap.exposedFacing()); + if (handler != null && !(handler instanceof ItemCapabilityObject)) + destinationCandidates.put(next, handler); } } - // if we reach this point, we know we are the only bridge and can commence traverse. + if (destinationCandidates.isEmpty()) return 0; + // third, build merge information from source candidates ItemFilterContainer filter = this.getItemFilter(); byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter Int2IntArrayMap extractableByFilterSlot = new Int2IntArrayMap(); @@ -367,7 +358,7 @@ protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode de } var iter = extractableByFilterSlot.int2IntEntrySet().fastIterator(); int totalTransfer = 0; - + // fourth, perform transfer based on merge information while (iter.hasNext()) { var next = iter.next(); int filterSlot = next.getIntKey(); diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index a0ffdcae8c5..0383f6eb230 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -9,10 +9,10 @@ import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithFluidFilter; +import gregtech.api.graphnet.GraphNetUtility; import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; @@ -24,7 +24,6 @@ import gregtech.api.graphnet.traverse.FDTraverse; import gregtech.api.graphnet.traverse.RRTraverse; import gregtech.api.graphnet.traverse.iter.EdgeDirection; -import gregtech.api.graphnet.traverse.iter.EdgeSelector; import gregtech.api.graphnet.traverse.iter.NetClosestIterator; import gregtech.api.graphnet.traverse.iter.NetIterator; import gregtech.api.mui.GTGuiTextures; @@ -88,7 +87,6 @@ import java.util.Map; import java.util.function.IntUnaryOperator; -import java.util.function.Predicate; public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithFluidFilter { @@ -321,42 +319,35 @@ protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode de @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { // first, evaluate whether we're the only bridge between two areas in a group NetEdge bridge = sourceNode.getNet().getEdge(sourceNode, destNode); - GraphEdge b1 = GraphEdge.unwrap(bridge); - GraphEdge b2 = GraphEdge.unwrap(sourceNode.getNet().getEdge(destNode, sourceNode)); - Predicate predicate = g -> g != b1 && g != b2; + if (bridge == null || !GraphNetUtility.isOnlyBridge(bridge)) return 0; + // second, build frontier information. If we have no candidates for either frontier, exit early. NetClosestIterator sourceFrontier = new NetClosestIterator(sourceNode, - EdgeSelector.filtered(EdgeDirection.INCOMING, predicate)); - NetClosestIterator destFrontier = new NetClosestIterator(destNode, - EdgeSelector.filtered(EdgeDirection.OUTGOING, predicate)); + GraphNetUtility.bridgeFiltered(EdgeDirection.INCOMING, sourceNode, destNode)); Map sourceCandidates = new Object2ObjectOpenHashMap<>(); - Map destinationCandidates = new Object2ObjectOpenHashMap<>(); - // note that if we checked all edges instead of only incoming for one and outgoing for the other, - // we would be able to know that we're the only bridge once either frontier exhausted, not both. - while (sourceFrontier.hasNext() || destFrontier.hasNext()) { - if (sourceFrontier.hasNext()) { - NetNode next = sourceFrontier.next(); - // the dest frontier has seen the next node in the source frontier, we are not the only bridge. - if (destFrontier.getSpanningTreeEdge(next) != null) return 0; - if (next instanceof NodeExposingCapabilities cap) { - IFluidHandler handler = cap.getProvider() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, cap.exposedFacing()); - if (handler != null && !(handler instanceof FluidCapabilityObject)) - sourceCandidates.put(next, handler); - } + while (sourceFrontier.hasNext()) { + NetNode next = sourceFrontier.next(); + if (next instanceof NodeExposingCapabilities cap) { + IFluidHandler handler = cap.getProvider() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, cap.exposedFacing()); + if (handler != null && !(handler instanceof FluidCapabilityObject)) + sourceCandidates.put(next, handler); } - if (destFrontier.hasNext()) { - NetNode next = destFrontier.next(); - // the source frontier has seen the next node in the dest frontier, we are not the only bridge. - if (sourceFrontier.getSpanningTreeEdge(next) != null) return 0; - if (next instanceof NodeExposingCapabilities cap) { - IFluidHandler handler = cap.getProvider() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, cap.exposedFacing()); - if (handler != null && !(handler instanceof FluidCapabilityObject)) - destinationCandidates.put(next, handler); - } + } + if (sourceCandidates.isEmpty()) return 0; + NetClosestIterator destFrontier = new NetClosestIterator(destNode, + GraphNetUtility.bridgeFiltered(EdgeDirection.OUTGOING, sourceNode, destNode)); + Map destinationCandidates = new Object2ObjectOpenHashMap<>(); + while (destFrontier.hasNext()) { + NetNode next = destFrontier.next(); + if (next instanceof NodeExposingCapabilities cap) { + IFluidHandler handler = cap.getProvider() + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, cap.exposedFacing()); + if (handler != null && !(handler instanceof FluidCapabilityObject)) + destinationCandidates.put(next, handler); } } - // if we reach this point, we know we are the only bridge and can commence traverse. + if (destinationCandidates.isEmpty()) return 0; + // third, build merge information from source candidates FluidFilterContainer filter = this.getFluidFilter(); byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter Object2IntOpenHashMap contained = new Object2IntOpenHashMap<>(); @@ -369,7 +360,7 @@ protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode de } var iter = contained.object2IntEntrySet().fastIterator(); int totalTransfer = 0; - + // fourth, perform transfer based on merge information while (iter.hasNext()) { var content = iter.next(); FluidStack contents = content.getKey().recombine(content.getIntValue()); From eb88875ba293bf07f8f7a441714ae02d29341804 Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Fri, 20 Dec 2024 21:34:51 -0700 Subject: [PATCH 152/157] pain --- dependencies.gradle | 2 + .../graphnet/GraphClassRegistrationEvent.java | 3 +- .../api/graphnet/GraphClassRegistry.java | 10 +- .../api/graphnet/GraphNetUtility.java | 4 +- .../gregtech/api/graphnet/edge/NetEdge.java | 7 + .../api/graphnet/edge/NetFlowEdge.java | 5 + .../api/graphnet/edge/NetFlowSharedEdge.java | 12 + .../api/graphnet/graph/GraphEdge.java | 2 +- .../api/graphnet/graph/INetGraph.java | 4 +- .../api/graphnet/graph/NetDirectedGraph.java | 5 - .../graphnet/graph/NetUndirectedGraph.java | 5 - .../api/graphnet/graph/TweakedCSMCF.java | 825 ++++++++++++++++++ .../api/graphnet/group/GroupGraphView.java | 264 ++++++ .../gregtech/api/graphnet/group/NetGroup.java | 14 +- .../graphnet/group/PathCacheGroupData.java | 4 +- .../graphnet/logic/AbstractByteLogicData.java | 69 ++ .../api/graphnet/logic/NetLogicRegistry.java | 17 +- .../api/graphnet/net/BlockPosNode.java | 3 +- .../gregtech/api/graphnet/net/NetNode.java | 7 + .../pipenet/NodeExposingCapabilities.java | 3 + .../pipenet/WorldPipeCapConnectionNode.java | 23 +- .../api/graphnet/pipenet/WorldPipeNet.java | 1 + .../api/graphnet/pipenet/WorldPipeNode.java | 2 +- .../physical/tile/NodeManagingPCW.java | 8 + .../physical/tile/PipeCapabilityWrapper.java | 10 + .../pipenet/physical/tile/PipeTileEntity.java | 31 +- .../pipenet/traverse/RoundRobinCache.java | 4 +- .../predicate/NetPredicateRegistry.java | 10 +- .../traverse/AbstractMinCostTraverse.java | 16 +- .../api/graphnet/traverse/EQTraverse.java | 23 +- .../api/graphnet/traverse/FDTraverse.java | 30 +- .../api/graphnet/traverse/RRTraverse.java | 21 +- .../traverse/iter/NetBreadthIterator.java | 45 +- .../traverse/iter/NetClosestIterator.java | 43 +- .../graphnet/traverse/iter/NetIterator.java | 2 + .../api/unification/material/Material.java | 4 +- .../materials/FirstDegreeMaterials.java | 18 +- .../java/gregtech/api/util/FacingPos.java | 2 + .../api/util/function/ToBooleanFunction.java | 7 - .../java/gregtech/common/CommonProxy.java | 21 + .../gregtech/common/covers/CoverConveyor.java | 35 +- .../gregtech/common/covers/CoverPump.java | 35 +- .../properties/MaterialEnergyProperties.java | 40 +- .../net/energy/SuperconductorLogic.java | 16 +- .../net/fluid/FluidCapabilityObject.java | 54 +- .../net/item/ItemCapabilityObject.java | 8 +- .../net/laser/LaserCapabilityObject.java | 96 +- .../material/CTMaterialBuilder.java | 4 +- .../material/MaterialPropertyExpansion.java | 4 +- .../groovy/MaterialPropertyExpansion.java | 10 +- .../resources/assets/gregtech/lang/en_us.lang | 1 - 51 files changed, 1606 insertions(+), 283 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/graph/TweakedCSMCF.java create mode 100644 src/main/java/gregtech/api/graphnet/group/GroupGraphView.java create mode 100644 src/main/java/gregtech/api/graphnet/logic/AbstractByteLogicData.java delete mode 100644 src/main/java/gregtech/api/util/function/ToBooleanFunction.java diff --git a/dependencies.gradle b/dependencies.gradle index 4b069b8ce06..6b60e9ec1ce 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -63,6 +63,8 @@ dependencies { compileOnly rfg.deobf("curse.maven:littletiles-257818:4750222") // LittleTiles 1.5.82-1.12.2 compileOnly rfg.deobf("curse.maven:creativecore-257814:4722163") // Creative Core 1.10.71 + runtimeOnly rfg.deobf("curse.maven:spark-361579:3542217") + // Mods with Soft compat but which have no need to be in code, such as isModLoaded() checks and getModItem() recipes. // Uncomment any of these to test them in-game. diff --git a/src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java b/src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java index 95eeac71c5c..8e00f7bed4d 100644 --- a/src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java +++ b/src/main/java/gregtech/api/graphnet/GraphClassRegistrationEvent.java @@ -13,7 +13,8 @@ public final class GraphClassRegistrationEvent extends Event { public void accept(GraphClassType type) { if (!gather.add(type)) - throw new IllegalStateException("Detected a name collision during Graph Class registration!"); + throw new IllegalStateException( + "Detected a name collision during Graph Class registration! Collision on name: " + type.getName()); } ObjectRBTreeSet> getGather() { diff --git a/src/main/java/gregtech/api/graphnet/GraphClassRegistry.java b/src/main/java/gregtech/api/graphnet/GraphClassRegistry.java index 6f843b4f041..80a8b8fc06e 100644 --- a/src/main/java/gregtech/api/graphnet/GraphClassRegistry.java +++ b/src/main/java/gregtech/api/graphnet/GraphClassRegistry.java @@ -4,13 +4,13 @@ import gregtech.api.graphnet.logic.NetLogicType; import net.minecraft.client.Minecraft; -import net.minecraft.util.IntIdentityHashBiMap; import net.minecraft.util.text.TextComponentTranslation; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -20,13 +20,13 @@ public final class GraphClassRegistry { private static final Int2ObjectArrayMap> REGISTRY; - private static final IntIdentityHashBiMap NAMES_TO_NETWORK_IDS; + private static final Object2IntOpenHashMap NAMES_TO_NETWORK_IDS; static { GraphClassRegistrationEvent event = new GraphClassRegistrationEvent(); MinecraftForge.EVENT_BUS.post(event); Set> gather = event.getGather(); - NAMES_TO_NETWORK_IDS = new IntIdentityHashBiMap<>(gather.size()); + NAMES_TO_NETWORK_IDS = new Object2IntOpenHashMap<>(gather.size()); REGISTRY = new Int2ObjectArrayMap<>(gather.size()); int id = 1; for (GraphClassType type : gather) { @@ -37,11 +37,11 @@ public final class GraphClassRegistry { } public static String getName(int networkID) { - return NAMES_TO_NETWORK_IDS.get(networkID); + return REGISTRY.get(networkID).getName(); } public static int getNetworkID(@NotNull String name) { - return NAMES_TO_NETWORK_IDS.getId(name); + return NAMES_TO_NETWORK_IDS.getInt(name); } public static int getNetworkID(@NotNull NetLogicType type) { diff --git a/src/main/java/gregtech/api/graphnet/GraphNetUtility.java b/src/main/java/gregtech/api/graphnet/GraphNetUtility.java index ad260545767..c996c41e678 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetUtility.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetUtility.java @@ -29,10 +29,10 @@ public static boolean isOnlyBridge(@NotNull NetEdge bridge) { while (sourceFrontier.hasNext() && destFrontier.hasNext()) { NetNode next = sourceFrontier.next(); // the dest frontier has seen the next node in the source frontier, we are not the only bridge. - if (destFrontier.getSpanningTreeEdge(next) != null) return false; + if (destFrontier.hasSeen(next)) return false; next = destFrontier.next(); // the source frontier has seen the next node in the dest frontier, we are not the only bridge. - if (sourceFrontier.getSpanningTreeEdge(next) != null) return false; + if (sourceFrontier.hasSeen(next)) return false; } return true; } diff --git a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java index 44a22746b09..e44691fef92 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetEdge.java @@ -13,6 +13,7 @@ import net.minecraftforge.common.util.INBTSerializable; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,6 +32,12 @@ public class NetEdge implements INBTSerializable { private @Nullable NetLogicData data; + @Nullable + @Contract("null->null") + public static NetEdge unwrap(GraphEdge e) { + return e == null ? null : e.wrapped; + } + public @Nullable NetNode getSource() { if (wrapper == null) return null; return wrapper.getSource().wrapped; diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java index ca3238d7f47..ac67f7926db 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java @@ -162,4 +162,9 @@ Set getActiveChannels(long queryTick) { return map.keySet(); } } + + @Override + public GraphClassType getType() { + return TYPE; + } } diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java index 6ce462f1fd0..2652908b6c7 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java +++ b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java @@ -1,5 +1,7 @@ package gregtech.api.graphnet.edge; +import gregtech.api.GTValues; +import gregtech.api.graphnet.GraphClassType; import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; @@ -14,6 +16,11 @@ public class NetFlowSharedEdge extends AbstractNetFlowEdge { + public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, + "NetFlowSharedEdge", + n -> n instanceof FlowBufferTickProvider p ? + new NetFlowSharedEdge(p.getFlowBufferTicks(), p.getRegenerationTime()) : new NetFlowSharedEdge(10)); + private final int flowBufferTicks; private final int regenerationTime; @@ -166,4 +173,9 @@ Set getActiveChannels(long queryTick) { return map.keySet(); } } + + @Override + public GraphClassType getType() { + return TYPE; + } } diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java index 59d19932e61..08b6e9b1c73 100644 --- a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java +++ b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java @@ -67,7 +67,7 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; GraphEdge graphEdge = (GraphEdge) o; - return Objects.equals(wrapped, graphEdge.wrapped); + return Objects.equals(getSource(), graphEdge.getSource()) && Objects.equals(getTarget(), graphEdge.getTarget()); } @Override diff --git a/src/main/java/gregtech/api/graphnet/graph/INetGraph.java b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java index da7af889543..d55032f4c87 100644 --- a/src/main/java/gregtech/api/graphnet/graph/INetGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/INetGraph.java @@ -4,5 +4,7 @@ public interface INetGraph extends Graph { - boolean isDirected(); + default boolean isDirected() { + return getType().isDirected(); + } } diff --git a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java index 44f1128e704..d2937a6c6a9 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetDirectedGraph.java @@ -13,11 +13,6 @@ public NetDirectedGraph(Supplier vertexSupplier, Supplier standardBuilder() { return iGraphNet -> new NetDirectedGraph( () -> new GraphVertex(iGraphNet.getDefaultNodeType().getNew(iGraphNet)), diff --git a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java index 7ab4b4dd732..974c9325059 100644 --- a/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java +++ b/src/main/java/gregtech/api/graphnet/graph/NetUndirectedGraph.java @@ -13,11 +13,6 @@ public NetUndirectedGraph(Supplier vertexSupplier, Supplier standardBuilder() { return iGraphNet -> new NetUndirectedGraph( () -> new GraphVertex(iGraphNet.getDefaultNodeType().getNew(iGraphNet)), diff --git a/src/main/java/gregtech/api/graphnet/graph/TweakedCSMCF.java b/src/main/java/gregtech/api/graphnet/graph/TweakedCSMCF.java new file mode 100644 index 00000000000..7ad785cb1c9 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/graph/TweakedCSMCF.java @@ -0,0 +1,825 @@ +package gregtech.api.graphnet.graph; + +import org.jgrapht.Graph; +import org.jgrapht.alg.flow.mincost.CapacityScalingMinimumCostFlow; +import org.jgrapht.alg.flow.mincost.MinimumCostFlowProblem; +import org.jgrapht.alg.interfaces.MinimumCostFlowAlgorithm; +import org.jgrapht.alg.util.Pair; +import org.jgrapht.util.CollectionUtil; +import org.jheaps.AddressableHeap; +import org.jheaps.tree.PairingHeap; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * Copy of {@link CapacityScalingMinimumCostFlow} from JGraphT with edits made for optimization within GT's application. + */ +public class TweakedCSMCF implements MinimumCostFlowAlgorithm { + + /** + * A capacity which is considered to be infinite. Every arc, which has upper capacity greater + * that or equal to this value is considered to be an infinite capacity arc. + */ + public static final int CAP_INF = 1000 * 1000 * 1000; + /** + * A cost which is considered to be infinite. This value is used internally for flow network + * transformation. That is why arcs with cost magnitude greater than or equal to this value are + * not allowed. + */ + public static final double COST_INF = 1e9; + /** + * Default scaling factor + */ + public static final int DEFAULT_SCALING_FACTOR = 8; + /** + * Debug variable + */ + private static final boolean DEBUG = false; + /** + * Scaling factor of this algorithm + */ + private final int scalingFactor; + /** + * Number of vertices in the network + */ + private int n; + /** + * Number of edges in the network + */ + private int m; + /** + * Variable that is used to determine whether a vertex has been labeled temporarily or + * permanently during Dijkstra's algorithm + */ + private int counter = 1; + /** + * Specified minimum cost flow problem + */ + private MinimumCostFlowProblem problem; + /** + * Computed minimum cost flow + */ + private MinimumCostFlow minimumCostFlow; + /** + * Array of internal nodes used by the algorithm. Node: these nodes are stored in the same order + * as vertices of the specified flow network. This allows to determine quickly their + * counterparts in the network. + */ + private Node[] nodes; + /** + * Array of internal arcs. Note: these arcs are stored in the same order as edges of the + * specified flow network. This allows to determine quickly their counterparts in the network. + */ + private Arc[] arcs; + /** + * List of vertices of the flow network. + */ + private List graphVertices; + /** + * List of edges of the flow network. + */ + private List graphEdges; + + /** + * Constructs a new instance of the algorithm which uses default scaling factor. + */ + public TweakedCSMCF() { + this(DEFAULT_SCALING_FACTOR); + } + + /** + * Constructs a new instance of the algorithm with custom {@code scalingFactor}. If the + * {@code scalingFactor} is less than 2, the algorithm doesn't use scaling. + * + * @param scalingFactor custom scaling factor + */ + public TweakedCSMCF(int scalingFactor) { + this.scalingFactor = scalingFactor; + Node.ID = 0; // for debug + } + + /** + * Returns mapping from edge to flow value through this particular edge + * + * @return maximum flow mapping, or null if a MinimumCostFlowProblem has not yet been solved. + */ + @Override + public Map getFlowMap() { + return minimumCostFlow == null ? null : this.minimumCostFlow.getFlowMap(); + } + + /** + * {@inheritDoc} + */ + @Override + public GraphVertex getFlowDirection(GraphEdge edge) { + return problem.getGraph().getEdgeTarget(edge); + } + + /** + * {@inheritDoc} + */ + @Override + public MinimumCostFlow getMinimumCostFlow( + final MinimumCostFlowProblem minimumCostFlowProblem) { + this.problem = Objects.requireNonNull(minimumCostFlowProblem); + if (problem.getGraph().getType().isUndirected()) { + throw new IllegalArgumentException( + "The algorithm doesn't support undirected flow networks"); + } + n = problem.getGraph().vertexSet().size(); + m = problem.getGraph().edgeSet().size(); + calculateMinimumCostFlow(); + + return minimumCostFlow; + } + + /** + * Returns solution to the dual linear program formulated on the network. Serves as a + * certificate of optimality. + *

+ * It is represented as a mapping from graph nodes to their potentials (dual variables). Reduced + * cost of a arc $(a, b)$ is defined as $cost((a, b)) + potential(b) - potential(b)$. According + * to the reduced cost optimality conditions, a feasible solution to the minimum cost flow + * problem is optimal if and only if reduced cost of every non-saturated arc is greater than or + * equal to $0$. + * + * @return solution to the dual linear program formulated on the network, or null if a + * MinimumCostFlowProblem has not yet been solved. + */ + public Map getDualSolution() { + if (minimumCostFlow == null) + return null; + + Map dualVariables = new HashMap<>(); + for (int i = 0; i < n; i++) { + dualVariables.put(graphVertices.get(i), nodes[i].potential); + } + return dualVariables; + } + + /** + * Calculated a solution to the specified minimum cost flow problem. If the scaling factor is + * greater than 1, performs scaling phases, otherwise uses simple capacity scaling algorithm. + */ + private void calculateMinimumCostFlow() { + init(); + if (scalingFactor > 1) { + // run with scaling + int U = getU(); + int delta = scalingFactor; + while (U >= delta) { + delta *= scalingFactor; + } + delta /= scalingFactor; + while (delta >= 1) { + Pair, Set> pair = scale(delta); + pushAllFlow(pair.getFirst(), pair.getSecond(), delta); + delta /= scalingFactor; + } + } else { + // run without scaling + Pair, Set> pair = scale(1); + pushAllFlow(pair.getFirst(), pair.getSecond(), 1); + } + minimumCostFlow = finish(); + } + + /** + * Converts the flow network in the form convenient for the algorithm. Validated the arc + * capacities and costs. + *

+ * Also, adds a dummy node to the network and arcs from every node to this dummy node, and from + * this dummy node to every other node. These added arcs have infinite capacities + * {@link CapacityScalingMinimumCostFlow#CAP_INF} and infinite costs + * {@link CapacityScalingMinimumCostFlow#COST_INF}. This ensures, that every search for an + * augmenting path to send at least $\Delta$ units of flow succeeds. + *

+ * If the flow network has a feasible solution, at the end there will be no flow on the added + * arcs. Otherwise, the specified problem has no feasible solution. + */ + private void init() { + int supplySum = 0; + + // initialize data structures + nodes = new Node[n + 1]; + nodes[n] = new Node(0); // dummy node + arcs = new Arc[m]; + graphEdges = new ArrayList<>(m); + graphVertices = new ArrayList<>(n); + + Map nodeMap = CollectionUtil.newHashMapWithExpectedSize(n); + Graph graph = problem.getGraph(); + + // convert vertices into internal nodes + int i = 0; + for (GraphVertex vertex : graph.vertexSet()) { + graphVertices.add(vertex); + int supply = problem.getNodeSupply().apply(vertex); + supplySum += supply; + nodes[i] = new Node(supply); + nodeMap.put(vertex, nodes[i]); + // reduction + nodes[i].addArcTo(nodes[n], CAP_INF, COST_INF); + nodes[n].addArcTo(nodes[i], CAP_INF, COST_INF); + ++i; + } + if (Math.abs(supplySum) > 0) { + throw new IllegalArgumentException("Total node supply isn't equal to 0"); + } + i = 0; + // convert edges into their internal counterparts + for (GraphEdge edge : graph.edgeSet()) { + graphEdges.add(edge); + Node node = nodeMap.get(graph.getEdgeSource(edge)); + Node opposite = nodeMap.get(graph.getEdgeTarget(edge)); + int upperCap = problem.getArcCapacityUpperBounds().apply(edge); + int lowerCap = problem.getArcCapacityLowerBounds().apply(edge); + double cost = graph.getEdgeWeight(edge); + + if (upperCap < 0) { + throw new IllegalArgumentException("Negative edge capacities are not allowed"); + } else if (lowerCap > upperCap) { + throw new IllegalArgumentException( + "Lower edge capacity must not exceed upper edge capacity"); + } else if (lowerCap >= CAP_INF) { + throw new IllegalArgumentException( + "The problem is unbounded due to the infinite lower capacity"); + } else if (upperCap >= CAP_INF && cost < 0) { + throw new IllegalArgumentException( + "The algorithm doesn't support infinite capacity arcs with negative cost"); + } else if (Math.abs(cost) >= COST_INF) { + throw new IllegalArgumentException( + "Specified flow network contains an edge of infinite cost"); + } else if (node == opposite) { + throw new IllegalArgumentException("Self-loops aren't allowed"); + } + // remove non-zero lower capacity + node.excess -= lowerCap; + opposite.excess += lowerCap; + if (cost < 0) { + // removing negative edge costs + node.excess -= upperCap - lowerCap; + opposite.excess += upperCap - lowerCap; + Node t = node; + node = opposite; + opposite = t; + cost *= -1; + } + arcs[i] = node.addArcTo(opposite, upperCap - lowerCap, cost); + if (DEBUG) { + System.out.println(arcs[i]); + } + ++i; + } + if (DEBUG) { + System.out.println("Printing mapping"); + for (Map.Entry entry : nodeMap.entrySet()) { + System.out.println(entry + " -> " + entry); + } + } + } + + /** + * Returns the largest magnitude of any supply/demand or finite arc capacity. + * + * @return the largest magnitude of any supply/demand or finite arc capacity. + */ + private int getU() { + int result = 0; + for (Node node : nodes) { + result = Math.max(result, Math.abs(node.excess)); + } + for (Arc arc : arcs) { + if (!arc.isInfiniteCapacityArc()) { + result = Math.max(result, arc.residualCapacity); + } + } + return result; + } + + /** + * Performs a scaling phase by saturating all negative reduced cost arcs with residual capacity + * greater than or equal to the {@code delta}, so that they don't belong to the + * $\Delta$-residual network and, hence, don't violate optimality conditions. After that this + * method computes and returns nodes with positive excess greater than or equal to the + * {@code delta} and nodes with negative excesses that are less than or equal to {@code delta} + * + * @param delta current value of $\Delta$ + * @return the nodes with excesses no less than {@code delta} and no greater than {@code -delta} + */ + private Pair, Set> scale(int delta) { + if (DEBUG) { + System.out.println(String.format("Current delta = %d", delta)); + } + + // saturate all non-saturated arcs with negative edge costs in the delta-residual network + for (Node node : nodes) { + Arc nextArc = node.firstNonSaturated; + for (Arc arc = nextArc; arc != null; arc = nextArc) { + nextArc = nextArc.next; + int residualCapacity = arc.residualCapacity; + if (arc.residualCapacity >= delta && arc.getReducedCost() < 0) { + if (DEBUG) { + System.out.println("Saturating arc " + arc); + } + arc.sendFlow(residualCapacity); + arc.head.excess += residualCapacity; + arc.revArc.head.excess -= residualCapacity; + } + } + } + + // finding all nodes with excess magnitude no less than delta + List positiveExcessNodes = new ArrayList<>(); + Set negativeExcessNodes = new HashSet<>(); + for (Node node : nodes) { + if (node.excess >= delta) { + positiveExcessNodes.add(node); + } else if (node.excess <= -delta) { + negativeExcessNodes.add(node); + } + } + return new Pair<>(positiveExcessNodes, negativeExcessNodes); + } + + /** + * For every node in the {@code positiveExcessNodes} pushes all flow away from it until its + * excess is less than {@code delta}. This is always possible due to the performed flow network + * reduction during the initialization phase. + * + * @param positiveExcessNodes nodes from the network with positive excesses no less than + * {@code delta} + * @param negativeExcessNodes nodes from the network with negative excesses no greater than + * {@code delta} + * @param delta the current value of $\Delta$ + */ + private void pushAllFlow( + List positiveExcessNodes, Set negativeExcessNodes, int delta) { + for (Node node : positiveExcessNodes) { + while (node.excess >= delta) { + if (negativeExcessNodes.isEmpty()) { + return; + } + pushDijkstra(node, negativeExcessNodes, delta); + } + } + } + + /** + * Runs the Dijkstra's algorithm in the residual network using {@link Arc#getReducedCost()} as + * arc distances. + *

+ * After reaching a node with excess no greater than {@code -delta}, augments it. Since the + * search is performed in the $\Delta$-residual network, the augmentation carries at least + * {@code delta} units of flow. The search always succeeds due to the flow network reduction + * performed during the initialization phase. + *

+ * Updates the potentials of the nodes so that they: + *

    + *
  • Satisfy optimality conditions in the $\Delta$-residual network
  • + *
  • The reduced cost of the augmented path is equal to $0$
  • + *
+ *

+ * Let us denote some permanently labeled vertex as $u$, and the first + * permanently labeled vertex with negative excess as $v$. Let $dist(x)$ be the + * distance function in the residual network. Then we use the following formula to update the + * node potentials: $v.potential = v.potential + dist(v) - dist(u)$. The potentials of the + * temporarily labeled and unvisited vertices stay unchanged. + * + * @param start the start node for Dijkstra's algorithm + * @param negativeExcessNodes nodes from the network with negative excesses no greater than + * {@code delta} + * @param delta the current value of $\Delta$ + */ + private void pushDijkstra(Node start, Set negativeExcessNodes, int delta) { + int TEMPORARILY_LABELED = counter++; + int PERMANENTLY_LABELED = counter++; + AddressableHeap.Handle currentFibNode; + AddressableHeap heap = new PairingHeap<>(); + List permanentlyLabeled = new LinkedList<>(); + start.parentArc = null; + start.handle = heap.insert(0d, start); + + while (!heap.isEmpty()) { + currentFibNode = heap.deleteMin(); + double distance = currentFibNode.getKey(); + Node currentNode = currentFibNode.getValue(); + if (negativeExcessNodes.contains(currentNode)) { + // the path to push at least delta units of flow is found + augmentPath(start, currentNode); + if (currentNode.excess > -delta) { + negativeExcessNodes.remove(currentNode); + } + // updating potentials + for (Node node : permanentlyLabeled) { + node.potential += distance; + } + if (DEBUG) { + System.out.println(String.format("Distance = %.1f", distance)); + for (Node node : nodes) { + System.out.println( + String.format("Id = %d, potential = %.1f", node.id, node.potential)); + } + } + return; + } + currentNode.labelType = PERMANENTLY_LABELED; // currentNode becomes permanently labeled + permanentlyLabeled.add(currentNode); + for (Arc currentArc = currentNode.firstNonSaturated; currentArc != null; currentArc = currentArc.next) { + // looking only for arcs with residual capacity greater than delta + if (currentArc.residualCapacity < delta) { + continue; + } + Node opposite = currentArc.head; + if (opposite.labelType != PERMANENTLY_LABELED) { + if (opposite.labelType == TEMPORARILY_LABELED) { + // opposite has been labeled already + if (distance + currentArc.getReducedCost() < opposite.handle.getKey()) { + opposite.handle.decreaseKey(distance + currentArc.getReducedCost()); + opposite.parentArc = currentArc; + } + } else { + // opposite is encountered for the first time + opposite.labelType = TEMPORARILY_LABELED; + opposite.handle = heap.insert(distance + currentArc.getReducedCost(), opposite); + opposite.parentArc = currentArc; + } + } + } + currentNode.potential -= distance; // allows not to store the distances of the nodes + } + } + + /** + * Augments the path from {@code start} to the {@code end} sending as much flow as possible. + * Uses {@link Node#parentArc} computed by the Dijkstra's algorithm. Updates the excesses of the + * {@code start} and the {@code end} nodes. + * + * @param start the start of the augmenting path + * @param end the end of the augmenting path + */ + private void augmentPath(Node start, Node end) { + // compute delta to augment + int valueToAugment = Math.min(start.excess, -end.excess); + for (Arc arc = end.parentArc; arc != null; arc = arc.revArc.head.parentArc) { + valueToAugment = Math.min(valueToAugment, arc.residualCapacity); + } + if (DEBUG) { + ArrayList stack = new ArrayList<>(); + for (Arc arc = end.parentArc; arc != null; arc = arc.revArc.head.parentArc) { + stack.add(arc.head); + } + stack.add(start); + System.out.println("Printing augmenting path"); + for (int i = stack.size() - 1; i > 0; i--) { + System.out.print(stack.get(i).id + " -> "); + } + System.out.println(stack.get(0).id + ", delta = " + valueToAugment); + } + // augmenting the flow + end.excess += valueToAugment; + for (Arc arc = end.parentArc; arc != null; arc = arc.revArc.head.parentArc) { + arc.sendFlow(valueToAugment); + } + start.excess -= valueToAugment; + } + + /** + * Finishes the computation by checking the flow feasibility, computing arc flows, and creating + * an instance of {@link MinimumCostFlow}. The resulting flow mapping contains all edges of the + * specified minimum cost flow problem. + * + * @return the solution to the minimum cost flow problem + */ + private MinimumCostFlow finish() { + Map flowMap = CollectionUtil.newHashMapWithExpectedSize(m); + double totalCost = 0; + // check feasibility + for (Arc arc = nodes[n].firstNonSaturated; arc != null; arc = arc.next) { + if (arc.revArc.residualCapacity > 0) { + throw new IllegalArgumentException( + "Specified flow network problem has no feasible solution"); + } + } + // create the solution object + for (int i = 0; i < m; i++) { + GraphEdge graphEdge = graphEdges.get(i); + Arc arc = arcs[i]; + double flowOnArc = arc.revArc.residualCapacity; // this value equals to the flow on the + // initial arc + if (problem.getGraph().getEdgeWeight(graphEdge) < 0) { + // the initial arc goes in the opposite direction + flowOnArc = problem.getArcCapacityUpperBounds().apply(graphEdge) - + problem.getArcCapacityLowerBounds().apply(graphEdge) - flowOnArc; + } + flowOnArc += problem.getArcCapacityLowerBounds().apply(graphEdge); + flowMap.put(graphEdge, flowOnArc); + totalCost += flowOnArc * problem.getGraph().getEdgeWeight(graphEdge); + } + return new MinimumCostFlowImpl<>(totalCost, flowMap); + } + + /** + * Tests the optimality conditions after a flow of minimum cost has been computed. + *

+ * More precisely, tests, whether the reduced cost of every non-saturated arc in the residual + * network is non-negative. This validation is performed with precision of {@code eps}. If the + * solution doesn't meet this condition, returns, false. + *

+ * In general, this method should always return true unless the algorithm implementation has a + * bug. + * + * @param eps the precision to use + * @return true, if the computed solution is optimal, false otherwise. + */ + public boolean testOptimality(double eps) { + if (minimumCostFlow == null) + throw new RuntimeException( + "Cannot return a dual solution before getMinimumCostFlow(MinimumCostFlowProblem minimumCostFlowProblem) is invoked!"); + + for (Node node : nodes) { + for (Arc arc = node.firstNonSaturated; arc != null; arc = arc.next) { + if (arc.getReducedCost() < -eps) { + return false; + } + } + } + return true; + } + + /** + * Supporting data structure for the {@link CapacityScalingMinimumCostFlow}. + *

+ * Is used as an internal representation of the vertices of the flow network. Contains all + * information needed during the computation. + * + * @author Timofey Chudakov + * @since July 2018 + */ + private static class Node { + + /** + * Variable for debug purposes + */ + private static int ID = 0; + /** + * Reference to the {@link } this node is contained in + */ + AddressableHeap.Handle handle; + /** + * An arc on the augmenting path which head is this node. + */ + Arc parentArc; + /** + * The label of this node. Is used to distinguish temporarily and permanently labeled nodes + * during the Dijkstra's algorithm + */ + int labelType; + /** + * The excess of this node. If this value is positive, then this is a source node. If this + * value is 0, than this is a transhipment node. If this value if negative, this is a sink + * node. + */ + int excess; + /** + * The dual variable of this node. This is used to search for an augmenting path in the + * residual network using the reduced costs of the arcs as arc lengths. + */ + double potential; + /** + * Reference of the first outgoing saturated arc (with zero residual capacity) + * incident to this node + */ + Arc firstSaturated; + /** + * Reference of the first outgoing non-saturated arc (with positive residual + * capacity) incident to this node. + */ + Arc firstNonSaturated; + /** + * Variable for debug purposes + */ + private int id = ID++; + + /** + * Constructs a new node with {@code excess} + * + * @param excess the excess of this node + */ + public Node(int excess) { + this.excess = excess; + } + + /** + * Adds a new arc with {@code capacity}, {@code cost} to the {@code opposite}. This method + * also creates a reverse arc with zero capacity and {@code -cost}. + * + * @param opposite the head of the resulting arc. + * @param capacity the capacity of the resulting arc. + * @param cost the cost of the resulting arc + * @return the resulting arc to the {@code opposite} node + */ + Arc addArcTo(Node opposite, int capacity, double cost) { + Arc forwardArc = new Arc(opposite, capacity, cost); + if (capacity > 0) { + // forward arc becomes the first arc in the linked list of non-saturated arcs + if (firstNonSaturated != null) { + firstNonSaturated.prev = forwardArc; + } + forwardArc.next = firstNonSaturated; + firstNonSaturated = forwardArc; + } else { + // forward arc becomes the first arc in the linked list of saturated arcs + if (firstSaturated != null) { + firstSaturated.prev = forwardArc; + } + forwardArc.next = firstSaturated; + firstSaturated = forwardArc; + } + Arc reverseArc = new Arc(this, 0, -cost); + if (opposite.firstSaturated != null) { + opposite.firstSaturated.prev = reverseArc; + } + reverseArc.next = opposite.firstSaturated; + opposite.firstSaturated = reverseArc; + + forwardArc.revArc = reverseArc; + reverseArc.revArc = forwardArc; + + return forwardArc; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return String.format("Id = %d, excess = %d, potential = %.1f", id, excess, potential); + } + } + + /** + * Supporting data structure for the {@link CapacityScalingMinimumCostFlow}. + *

+ * Represents a directed edge (arc) in the residual flow network. Contains all information + * needed during the computation. + * + * @author Timofey Chudakov + * @since July 2018 + */ + private static class Arc { + + /** + * The head (target) of this arc. + */ + final Node head; + /** + * The cost of sending one unit of flow across this arc. This value is positive for initial + * network arcs, negative - for the reverse residual arcs, and equals to the + * {@link CapacityScalingMinimumCostFlow#COST_INF} for the arcs used for the reduction. + */ + final double cost; + /** + * The reverse counterpart of this arc. + */ + Arc revArc; + /** + * The previous arc. This variable is used to maintain the presence of this arc in the + * linked list of arc which are either saturated or not. + */ + Arc prev; + /** + * The next arc. This variable is used to maintain the presence of this arc in the linked + * list of arc which are either saturated or not. + */ + Arc next; + /** + * The residual capacity of this arc. For forward arcs $(i, j)$ it equals $c_{i, j} - x_{i, + * j}$ where $x_{i, j}$ is the flow on this arc. For reverse arcs it equals $x_{i,j}$. + */ + int residualCapacity; + + /** + * Creates a new arc + * + * @param head the head (target) of this arc + * @param residualCapacity its residual capacity + * @param cost its cost + */ + Arc(Node head, int residualCapacity, double cost) { + this.head = head; + this.cost = cost; + this.residualCapacity = residualCapacity; + } + + /** + * Returns reduced cost of this arc. + * + * @return reduced cost of this arc. + */ + double getReducedCost() { + return cost + head.potential - revArc.head.potential; + } + + /** + * Sends {@code value units of flow across this arc}. + * + * @param value how many units of flow to send + */ + void sendFlow(int value) { + decreaseResidualCapacity(value); + revArc.increaseResidualCapacity(value); + } + + /** + * Decreases residual capacity of this arc by {@code value} units of flow. Moves this arc + * from list of non-saturated arc to the list of saturated arcs if necessary. + * + * @param value the value to subtract from the residual capacity of this arc + */ + private void decreaseResidualCapacity(int value) { + if (residualCapacity >= CAP_INF) { + return; + } + residualCapacity -= value; + if (residualCapacity == 0) { + // need to move this arc from list of non-saturated arcs to list of saturated arcs + Node tail = revArc.head; + if (next != null) { + next.prev = prev; + } + if (prev != null) { + prev.next = next; + } else { + tail.firstNonSaturated = next; + } + next = tail.firstSaturated; + if (tail.firstSaturated != null) { + tail.firstSaturated.prev = this; + } + tail.firstSaturated = this; + prev = null; + } + } + + /** + * Increases residual capacity of this arc by {@code value} units of flow. Moves this arc + * from list of saturated arc to the list of non-saturated arcs if necessary. + * + * @param value the value to add to the residual capacity of this arc + */ + private void increaseResidualCapacity(int value) { + if (residualCapacity >= CAP_INF) { + return; + } + if (residualCapacity == 0) { + // need to move this arc from list of saturated arcs to list of non-saturated arcs + Node tail = revArc.head; + if (next != null) { + next.prev = prev; + } + if (prev != null) { + prev.next = next; + } else { + tail.firstSaturated = next; + } + next = tail.firstNonSaturated; + if (tail.firstNonSaturated != null) { + tail.firstNonSaturated.prev = this; + } + tail.firstNonSaturated = this; + prev = null; + } + residualCapacity += value; + } + + /** + * Returns true if the arc has infinite capacity, false otherwise. + * + * @return true if the arc has infinite capacity, false otherwise. + */ + public boolean isInfiniteCapacityArc() { + return residualCapacity >= CAP_INF; + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return String.format( + "(%d, %d), residual capacity = %s, reduced cost = %.1f, cost = %.1f", + revArc.head.id, head.id, + residualCapacity >= CAP_INF ? "INF" : String.valueOf(residualCapacity), + getReducedCost(), cost); + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/group/GroupGraphView.java b/src/main/java/gregtech/api/graphnet/group/GroupGraphView.java new file mode 100644 index 00000000000..afea04ddf48 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/group/GroupGraphView.java @@ -0,0 +1,264 @@ +package gregtech.api.graphnet.group; + +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.graph.INetGraph; +import gregtech.api.graphnet.net.NetNode; + +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.NotNull; +import org.jgrapht.Graph; +import org.jgrapht.GraphType; + +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.function.Supplier; + +public class GroupGraphView implements Graph { + + protected final @NotNull NetGroup group; + + protected final EdgeSetView edgeView = new EdgeSetView(); + + protected final Set addedVertices = new ObjectOpenHashSet<>(); + + public GroupGraphView(@NotNull NetGroup group) { + this.group = group; + } + + protected INetGraph backer() { + return group.net.getGraph(); + } + + @Override + public Set getAllEdges(GraphVertex sourceVertex, GraphVertex targetVertex) { + return backer().getAllEdges(sourceVertex, targetVertex); + } + + @Override + public GraphEdge getEdge(GraphVertex sourceVertex, GraphVertex targetVertex) { + return backer().getEdge(sourceVertex, targetVertex); + } + + @Override + public Supplier getVertexSupplier() { + return backer().getVertexSupplier(); + } + + @Override + public Supplier getEdgeSupplier() { + return backer().getEdgeSupplier(); + } + + @Override + public GraphEdge addEdge(GraphVertex sourceVertex, GraphVertex targetVertex) { + return backer().addEdge(sourceVertex, targetVertex); + } + + @Override + public boolean addEdge(GraphVertex sourceVertex, GraphVertex targetVertex, GraphEdge graphEdge) { + return backer().addEdge(sourceVertex, targetVertex, graphEdge); + } + + @Override + public GraphVertex addVertex() { + GraphVertex vertex = backer().addVertex(); + addedVertices.add(vertex); + return vertex; + } + + @Override + public boolean addVertex(GraphVertex vertex) { + addedVertices.add(vertex); + return backer().addVertex(vertex); + } + + @Override + public boolean containsEdge(GraphVertex sourceVertex, GraphVertex targetVertex) { + return containsVertex(sourceVertex) && containsVertex(targetVertex) && + backer().containsEdge(sourceVertex, targetVertex); + } + + @Override + public boolean containsEdge(GraphEdge graphEdge) { + return containsVertex(graphEdge.getSource()) && containsVertex(graphEdge.getTarget()) && + backer().containsEdge(graphEdge); + } + + @Override + public boolean containsVertex(GraphVertex vertex) { + return addedVertices.contains(vertex) || group.getNodes().contains(NetNode.unwrap(vertex)); + } + + @Override + public Set edgeSet() { + return edgeView; + } + + @Override + public int degreeOf(GraphVertex vertex) { + if (backer().isDirected()) return inDegreeOf(vertex) + outDegreeOf(vertex); + int degree = 0; + Set edges = backer().edgesOf(vertex); + for (GraphEdge e : edges) { + if (!containsEdge(e)) continue; + if (backer().getEdgeSource(e).equals(backer().getEdgeTarget(e))) { + degree += 2; + } else { + degree += 1; + } + } + return degree; + } + + @Override + public Set edgesOf(GraphVertex vertex) { + Set s = new ObjectOpenHashSet<>(backer().edgesOf(vertex)); + s.removeIf(e -> !containsEdge(e)); + return s; + } + + @Override + public int inDegreeOf(GraphVertex vertex) { + if (!backer().isDirected()) return degreeOf(vertex); + return incomingEdgesOf(vertex).size(); + } + + @Override + public Set incomingEdgesOf(GraphVertex vertex) { + Set s = new ObjectOpenHashSet<>(backer().incomingEdgesOf(vertex)); + s.removeIf(e -> !containsEdge(e)); + return s; + } + + @Override + public int outDegreeOf(GraphVertex vertex) { + if (!backer().isDirected()) return degreeOf(vertex); + return outgoingEdgesOf(vertex).size(); + } + + @Override + public Set outgoingEdgesOf(GraphVertex vertex) { + Set s = new ObjectOpenHashSet<>(backer().outgoingEdgesOf(vertex)); + s.removeIf(e -> !containsEdge(e)); + return s; + } + + @Override + public boolean removeAllEdges(Collection edges) { + return backer().removeAllEdges(edges); + } + + @Override + public Set removeAllEdges(GraphVertex sourceVertex, GraphVertex targetVertex) { + return backer().removeAllEdges(sourceVertex, targetVertex); + } + + @Override + public boolean removeAllVertices(Collection vertices) { + return backer().removeAllVertices(vertices) | addedVertices.removeAll(vertices); + } + + @Override + public GraphEdge removeEdge(GraphVertex sourceVertex, GraphVertex targetVertex) { + return backer().removeEdge(sourceVertex, targetVertex); + } + + @Override + public boolean removeEdge(GraphEdge graphEdge) { + return backer().removeEdge(graphEdge); + } + + @Override + public boolean removeVertex(GraphVertex vertex) { + return backer().removeVertex(vertex) | addedVertices.remove(vertex); + } + + @Override + public Set vertexSet() { + Set set = new ObjectOpenHashSet<>(group.getNodes().size() + addedVertices.size()); + set.addAll(addedVertices); + for (NetNode node : group.getNodes()) { + set.add(GraphVertex.unwrap(node)); + } + return set; + } + + @Override + public GraphVertex getEdgeSource(GraphEdge graphEdge) { + return backer().getEdgeSource(graphEdge); + } + + @Override + public GraphVertex getEdgeTarget(GraphEdge graphEdge) { + return backer().getEdgeTarget(graphEdge); + } + + @Override + public GraphType getType() { + return backer().getType(); + } + + @Override + public double getEdgeWeight(GraphEdge graphEdge) { + return backer().getEdgeWeight(graphEdge); + } + + @Override + public void setEdgeWeight(GraphEdge graphEdge, double weight) { + backer().setEdgeWeight(graphEdge, weight); + } + + @Override + public void setEdgeWeight(GraphVertex sourceVertex, GraphVertex targetVertex, double weight) { + backer().setEdgeWeight(sourceVertex, targetVertex, weight); + } + + private final class EdgeSetView extends AbstractSet { + + @Override + public @NotNull Iterator iterator() { + return new Iterator<>() { + + final Iterator backer = group.net.getGraph().edgeSet().iterator(); + GraphEdge next; + + @Override + public boolean hasNext() { + if (next != null) return true; + return calcNext(); + } + + @Override + public GraphEdge next() { + if (next == null) { + if (!calcNext()) throw new NoSuchElementException(); + } + GraphEdge e = next; + next = null; + return e; + } + + private boolean calcNext() { + do { + if (!backer.hasNext()) return false; + next = backer.next(); + } while (!containsEdge(next)); + return true; + } + }; + } + + @Override + public int size() { + int size = 0; + for (GraphEdge ignored : this) { + size++; + } + return size; + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/group/NetGroup.java b/src/main/java/gregtech/api/graphnet/group/NetGroup.java index b9789d210f3..c8812e0257a 100644 --- a/src/main/java/gregtech/api/graphnet/group/NetGroup.java +++ b/src/main/java/gregtech/api/graphnet/group/NetGroup.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.Collections; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -28,12 +29,14 @@ public final class NetGroup { public final IGraphNet net; - private final @NotNull Set nodes; + final @NotNull Set nodes; private final @NotNull Int2ObjectMap> sortingNodes; private @Nullable GroupData data; + private GroupGraphView graphView; + public NetGroup(IGraphNet net) { this(net, new ObjectOpenHashSet<>(), new Int2ObjectOpenHashMap<>()); } @@ -117,8 +120,7 @@ public static MergeDirection isEdgeAllowed(@NotNull NetNode source, @NotNull Net NetGroup sourceGroup = source.getGroupUnsafe(); NetGroup targetGroup = target.getGroupUnsafe(); - if (sourceGroup == null || targetGroup == null) return MergeDirection.NULL; - + if (sourceGroup == null || targetGroup == null || sourceGroup == targetGroup) return MergeDirection.NULL; return GroupData.mergeAllowed(sourceGroup.getData(), targetGroup.getData()); } @@ -174,6 +176,7 @@ public void splitNode(NetNode source) { if (data != null) stream = stream.peek(e -> data.notifyOfRemovedEdge(e.wrapped)); ObjectLinkedOpenHashSet targets = stream .map(a -> Graphs.getOppositeVertex(net.getGraph(), a, source.wrapper).getWrapped()) + .filter(Objects::nonNull) .collect(Collectors.toCollection(ObjectLinkedOpenHashSet::new)); this.net.getBacker().removeVertex(source.wrapper); this.removeNode(source); @@ -254,4 +257,9 @@ public Int2ObjectMap> getSortingNodes() { public @Nullable GroupData getData() { return this.data; } + + public GroupGraphView getGraphView() { + if (graphView == null) graphView = new GroupGraphView(this); + return graphView; + } } diff --git a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java index 31c3dc70bac..b8b20eb131b 100644 --- a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java +++ b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java @@ -78,7 +78,7 @@ public NetPath getOrCompute(@NotNull NetNode target) { while (frontierPosition < this.frontierPosition && targetFrontier.hasNext()) { NetNode node = targetFrontier.next(); frontierPosition++; - if (searchFrontier.getSpanningTreeEdge(node) != null) { + if (searchFrontier.hasSeen(node)) { NetPath built = buildPath(node, targetFrontier, searchFrontier); this.put(target, built); return built; @@ -89,7 +89,7 @@ public NetPath getOrCompute(@NotNull NetNode target) { searchFrontier.next(); NetNode node = targetFrontier.next(); this.frontierPosition++; - if (searchFrontier.getSpanningTreeEdge(node) != null) { + if (searchFrontier.hasSeen(node)) { NetPath built = buildPath(node, targetFrontier, searchFrontier); this.put(target, built); return built; diff --git a/src/main/java/gregtech/api/graphnet/logic/AbstractByteLogicData.java b/src/main/java/gregtech/api/graphnet/logic/AbstractByteLogicData.java new file mode 100644 index 00000000000..8a590aa5b00 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/logic/AbstractByteLogicData.java @@ -0,0 +1,69 @@ +package gregtech.api.graphnet.logic; + +import net.minecraft.nbt.NBTTagByte; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.ResourceLocation; + +import org.jetbrains.annotations.NotNull; + +import java.util.function.Supplier; + +public abstract class AbstractByteLogicData> extends NetLogicEntry { + + private byte value; + + protected AbstractByteLogicData() {} + + protected AbstractByteLogicData(byte init) { + this.value = init; + } + + protected T setValue(byte value) { + this.value = value; + return (T) this; + } + + public byte getValue() { + return this.value; + } + + @Override + public NBTTagByte serializeNBT() { + return new NBTTagByte(this.value); + } + + @Override + public void deserializeNBT(NBTTagByte nbt) { + this.value = nbt.getByte(); + } + + @Override + public void encode(PacketBuffer buf, boolean fullChange) { + buf.writeByte(this.value); + } + + @Override + public void decode(PacketBuffer buf, boolean fullChange) { + this.value = buf.readByte(); + } + + @Override + public abstract @NotNull AbstractByteLogicData.ByteLogicType getType(); + + public static class ByteLogicType> extends NetLogicType { + + public ByteLogicType(@NotNull ResourceLocation name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + super(name, supplier, defaultable); + } + + public ByteLogicType(@NotNull String namespace, @NotNull String name, @NotNull Supplier<@NotNull T> supplier, + @NotNull T defaultable) { + super(namespace, name, supplier, defaultable); + } + + public T getWith(byte value) { + return getNew().setValue(value); + } + } +} diff --git a/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java b/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java index ed07079e990..7c10c62c559 100644 --- a/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java +++ b/src/main/java/gregtech/api/graphnet/logic/NetLogicRegistry.java @@ -1,13 +1,13 @@ package gregtech.api.graphnet.logic; import net.minecraft.client.Minecraft; -import net.minecraft.util.IntIdentityHashBiMap; import net.minecraft.util.text.TextComponentTranslation; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -17,13 +17,13 @@ public final class NetLogicRegistry { private static final Int2ObjectArrayMap> REGISTRY; - private static final IntIdentityHashBiMap NAMES_TO_NETWORK_IDS; + private static final Object2IntOpenHashMap NAMES_TO_NETWORK_IDS; static { NetLogicRegistrationEvent event = new NetLogicRegistrationEvent(); MinecraftForge.EVENT_BUS.post(event); Set> gather = event.getGather(); - NAMES_TO_NETWORK_IDS = new IntIdentityHashBiMap<>(gather.size()); + NAMES_TO_NETWORK_IDS = new Object2IntOpenHashMap<>(gather.size()); REGISTRY = new Int2ObjectArrayMap<>(gather.size()); int id = 1; for (NetLogicType type : gather) { @@ -34,11 +34,13 @@ public final class NetLogicRegistry { } public static String getName(int networkID) { - return NAMES_TO_NETWORK_IDS.get(networkID); + return REGISTRY.get(networkID).getName(); } public static int getNetworkID(@NotNull String name) { - return NAMES_TO_NETWORK_IDS.getId(name); + int id = NAMES_TO_NETWORK_IDS.getInt(name); + if (id == -1) throwUnregisteredError(name); + return id; } public static int getNetworkID(@NotNull NetLogicType type) { @@ -80,6 +82,11 @@ public static void throwDecodingError() { "This suggests that the server and client have different GT versions or modifications."); } + public static void throwUnregisteredError(String n) { + throw new RuntimeException("Could not determine the network ID of a to-encode NetLogicEntry. " + + "This suggests that the NetLogicEntry does not have a registered type. The offending name is: " + n); + } + private static void disconnect() { if (Minecraft.getMinecraft().getConnection() != null) Minecraft.getMinecraft().getConnection() diff --git a/src/main/java/gregtech/api/graphnet/net/BlockPosNode.java b/src/main/java/gregtech/api/graphnet/net/BlockPosNode.java index 69bc4ef54fb..d2b055f2e12 100644 --- a/src/main/java/gregtech/api/graphnet/net/BlockPosNode.java +++ b/src/main/java/gregtech/api/graphnet/net/BlockPosNode.java @@ -13,10 +13,11 @@ public class BlockPosNode extends NetNode { public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "BlockPosNode", BlockPosNode::new); - private BlockPos pos; + private @NotNull BlockPos pos; public BlockPosNode(IGraphNet net) { super(net); + pos = BlockPos.ORIGIN; } public BlockPosNode setPos(BlockPos pos) { diff --git a/src/main/java/gregtech/api/graphnet/net/NetNode.java b/src/main/java/gregtech/api/graphnet/net/NetNode.java index 85bc95fa361..88ffa7fe6b1 100644 --- a/src/main/java/gregtech/api/graphnet/net/NetNode.java +++ b/src/main/java/gregtech/api/graphnet/net/NetNode.java @@ -10,6 +10,7 @@ import net.minecraftforge.common.util.INBTSerializable; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -64,6 +65,12 @@ public boolean traverse(long queryTick, boolean simulate) { return true; } + @Nullable + @Contract("null->null") + public static NetNode unwrap(GraphVertex n) { + return n == null ? null : n.wrapped; + } + @NotNull public NetGroup getGroupSafe() { if (this.group == null) { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/NodeExposingCapabilities.java b/src/main/java/gregtech/api/graphnet/pipenet/NodeExposingCapabilities.java index 80aee2ec274..df45c95647a 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/NodeExposingCapabilities.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/NodeExposingCapabilities.java @@ -3,8 +3,11 @@ import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.ICapabilityProvider; +import org.jetbrains.annotations.NotNull; + public interface NodeExposingCapabilities { + @NotNull ICapabilityProvider getProvider(); default EnumFacing exposedFacing() { diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java index 00da7d3a722..62f9eba17c2 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeCapConnectionNode.java @@ -11,6 +11,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import org.jetbrains.annotations.NotNull; @@ -24,11 +25,12 @@ public class WorldPipeCapConnectionNode extends NetNode implements NodeWithFacin "WorldPipeCapConnectionNode", WorldPipeCapConnectionNode::resolve); - private FacingPos posAndFacing; + private @NotNull FacingPos posAndFacing; public WorldPipeCapConnectionNode(WorldPipeNet net) { super(net); sortingKey = SORTING_KEY; + posAndFacing = FacingPos.ORIGIN; } private static WorldPipeCapConnectionNode resolve(IGraphNet net) { @@ -85,13 +87,28 @@ public void deserializeNBT(NBTTagCompound nbt) { } @Override - public ICapabilityProvider getProvider() { + public @NotNull ICapabilityProvider getProvider() { WorldPipeNode parent = getParent(); - return parent.getTileEntity().getTargetWithCapabilities(parent, posAndFacing.getFacing()); + if (parent == null) return EMPTY; + ICapabilityProvider prov = parent.getTileEntity().getTargetWithCapabilities(parent, posAndFacing.getFacing()); + return prov != null ? prov : EMPTY; } @Override public EnumFacing exposedFacing() { return posAndFacing.getFacing().getOpposite(); } + + private static final ICapabilityProvider EMPTY = new ICapabilityProvider() { + + @Override + public boolean hasCapability(Capability capability, EnumFacing facing) { + return false; + } + + @Override + public T getCapability(Capability capability, EnumFacing facing) { + return null; + } + }; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 4c754dee6e7..b0d7c376928 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -192,6 +192,7 @@ public abstract PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEn WorldPipeNode node = getNode(pos); if (node == null) { node = new WorldPipeNode(this); + node.setPos(pos); addNode(node); } return node; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNode.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNode.java index 410ce2d37d0..eb103b724ee 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNode.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNode.java @@ -125,7 +125,7 @@ public boolean traverse(long queryTick, boolean simulate) { } @Override - public ICapabilityProvider getProvider() { + public @NotNull ICapabilityProvider getProvider() { return getTileEntity(); } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java index e5f81fefa1c..2a7551de98f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/NodeManagingPCW.java @@ -25,6 +25,13 @@ public NodeManagingPCW(@NotNull PipeTileEntity owner, @NotNull WorldPipeNode nod super(owner, node, capabilities, inactiveKey, activeKey); } + @Override + public void invalidate() { + for (WorldPipeCapConnectionNode n : managed.values()) { + n.getNet().removeNode(n); + } + } + @Override protected void setActiveInternal(@NotNull EnumFacing facing) { super.setActiveInternal(facing); @@ -35,6 +42,7 @@ protected void setActiveInternal(@NotNull EnumFacing facing) { connectionNode = c; } else { connectionNode = new WorldPipeCapConnectionNode(node.getNet()); + connectionNode.setPosAndFacing(pos); connectionNode.getNet().addNode(connectionNode); } managed.put(facing, connectionNode); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java index ac3eae52011..5e2f660e7e9 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java @@ -9,6 +9,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class PipeCapabilityWrapper implements ICapabilityProvider { @@ -34,6 +35,8 @@ public PipeCapabilityWrapper(@NotNull PipeTileEntity owner, @NotNull WorldPipeNo } } + public void invalidate() {} + public void setActive(@NotNull EnumFacing facing) { if (!isActive(facing)) { setActiveInternal(facing); @@ -62,6 +65,13 @@ public boolean isActive(@NotNull EnumFacing facing) { return (this.activeMask & 1 << facing.ordinal()) > 0; } + public T getCapabilityCoverQuery(@NotNull Capability capability, @Nullable EnumFacing facing) { + // covers have access to the capability objects no matter the connection status + IPipeCapabilityObject object = capabilities.get(capability); + if (object == null) return null; + return object.getCapability(capability, facing); + } + @Override public boolean hasCapability(@NotNull Capability capability, EnumFacing facing) { if (facing != null && !isActive(facing)) return false; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index a4265566caf..a365016b4be 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -12,7 +12,6 @@ import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.IInsulatable; -import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; import gregtech.api.graphnet.pipenet.physical.block.PipeBlock; import gregtech.api.graphnet.pipenet.physical.block.RayTraceAABB; @@ -48,7 +47,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.MustBeInvokedByOverriders; @@ -86,7 +84,6 @@ public class PipeTileEntity extends NeighborCacheTileEntityBase implements ITick private final Set tickers = new ObjectOpenHashSet<>(); protected final PipeCoverHolder covers = new PipeCoverHolder(this); - private final Object2ObjectOpenHashMap, IPipeCapabilityObject> capabilities = new Object2ObjectOpenHashMap<>(); private final Object2ObjectOpenCustomHashMap netCapabilities = WorldPipeNet .getSensitiveHashMap(); @@ -123,9 +120,11 @@ public void validate() { @Override public void invalidate() { super.invalidate(); - if (!getWorld().isRemote) getBlockType().getHandler(this) - .removeFromNets(this.getWorld(), this.getPos(), this.getStructure()); - else killOverheatParticle(); + if (!getWorld().isRemote) { + getBlockType().getHandler(this) + .removeFromNets(this.getWorld(), this.getPos(), this.getStructure()); + netCapabilities.values().forEach(PipeCapabilityWrapper::invalidate); + } else killOverheatParticle(); // TODO I hate this so much can someone please make it so that covers go through getDrops()? getCoverHolder().dropAllCovers(); } @@ -415,9 +414,11 @@ private void setAllIdle(EnumFacing facing) { // capability // public T getCapabilityCoverQuery(@NotNull Capability capability, @Nullable EnumFacing facing) { - // covers have access to the capability objects no matter the connection status - IPipeCapabilityObject object = capabilities.get(capability); - return object == null ? null : object.getCapability(capability, facing); + for (PipeCapabilityWrapper wrapper : netCapabilities.values()) { + T cap = wrapper.getCapabilityCoverQuery(capability, facing); + if (cap != null) return cap; + } + return null; } @Override @@ -430,11 +431,11 @@ public T getCapability(@NotNull Capability capability, @Nullable EnumFaci if (capability == GregtechTileCapabilities.CAPABILITY_COVER_HOLDER) { return GregtechTileCapabilities.CAPABILITY_COVER_HOLDER.cast(getCoverHolder()); } - T pipeCapability; - IPipeCapabilityObject object = capabilities.get(capability); - if (object == null || (pipeCapability = object.getCapability(capability, facing)) == null) - pipeCapability = super.getCapability(capability, facing); - + T pipeCapability = null; + for (PipeCapabilityWrapper wrapper : netCapabilities.values()) { + if ((pipeCapability = wrapper.getCapability(capability, facing)) != null) break; + } + if (pipeCapability == null) pipeCapability = super.getCapability(capability, facing); Cover cover = facing == null ? null : getCoverHolder().getCoverAtSide(facing); if (cover == null) { if (facing == null || isConnected(facing)) { @@ -481,7 +482,6 @@ public void setWorld(@NotNull World worldIn) { public void initialize() { if (!getWorld().isRemote) { this.netLogicDatas.clear(); - this.capabilities.clear(); this.netCapabilities.clear(); this.listeners.clear(); for (WorldPipeNode node : PipeBlock.getNodesForTile(this)) { @@ -514,7 +514,6 @@ public void initialize() { this.legacy = false; } this.netLogicDatas.trim(); - this.capabilities.trim(); this.netCapabilities.trim(); this.listeners.trim(); updateActiveStatus(null, false); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java index 824381386c9..aa7f1e61c3a 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java @@ -26,8 +26,8 @@ public Supplier> buildSupplier(Collection sourceCand } public RoundRobinCache refresh(NetIterator sources, NetIterator targets) { - sourceCache.removeIf(n -> sources.getSpanningTreeEdge(n) == null); - destCache.removeIf(n -> targets.getSpanningTreeEdge(n) == null); + sourceCache.removeIf(n -> !sources.hasSeen(n)); + destCache.removeIf(n -> !targets.hasSeen(n)); return this; } diff --git a/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java index 46715e6f34c..84ba9851260 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java +++ b/src/main/java/gregtech/api/graphnet/predicate/NetPredicateRegistry.java @@ -1,13 +1,13 @@ package gregtech.api.graphnet.predicate; import net.minecraft.client.Minecraft; -import net.minecraft.util.IntIdentityHashBiMap; import net.minecraft.util.text.TextComponentTranslation; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -17,13 +17,13 @@ public final class NetPredicateRegistry { private static final Int2ObjectArrayMap> REGISTRY; - private static final IntIdentityHashBiMap NAMES_TO_NETWORK_IDS; + private static final Object2IntOpenHashMap NAMES_TO_NETWORK_IDS; static { NetPredicateRegistrationEvent event = new NetPredicateRegistrationEvent(); MinecraftForge.EVENT_BUS.post(event); Set> gather = event.getGather(); - NAMES_TO_NETWORK_IDS = new IntIdentityHashBiMap<>(gather.size()); + NAMES_TO_NETWORK_IDS = new Object2IntOpenHashMap<>(gather.size()); REGISTRY = new Int2ObjectArrayMap<>(gather.size()); int id = 1; for (NetPredicateType type : gather) { @@ -34,11 +34,11 @@ public final class NetPredicateRegistry { } public static String getName(int networkID) { - return NAMES_TO_NETWORK_IDS.get(networkID); + return REGISTRY.get(networkID).getName(); } public static int getNetworkID(@NotNull String name) { - return NAMES_TO_NETWORK_IDS.getId(name); + return NAMES_TO_NETWORK_IDS.getInt(name); } public static int getNetworkID(@NotNull NetPredicateType type) { diff --git a/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java index 5d6de88f5ea..42f54fb1a24 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java @@ -3,6 +3,7 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.graph.TweakedCSMCF; import gregtech.api.graphnet.net.NetNode; import gregtech.api.util.GTUtility; @@ -16,7 +17,7 @@ public abstract class AbstractMinCostTraverse implements MinimumCostFlowProblem { - protected static final CapacityScalingMinimumCostFlow MINCOST = new CapacityScalingMinimumCostFlow<>(); + protected static final TweakedCSMCF MINCOST = new TweakedCSMCF(); protected static final GraphVertex CORRECTOR = new GraphVertex(); @@ -34,9 +35,15 @@ public abstract class AbstractMinCostTraverse implements MinimumCostFlowProblem< correction -= supply; GraphEdge e = new GraphEdge(); if (supply < 0) { - getGraph().addEdge(CORRECTOR, v, e); + if (!getGraph().addEdge(CORRECTOR, v, e)) { + getGraph().removeEdge(CORRECTOR, v); + getGraph().addEdge(CORRECTOR, v, e); + } } else { - getGraph().addEdge(v, CORRECTOR, e); + if (!getGraph().addEdge(v, CORRECTOR, e)) { + getGraph().removeEdge(v, CORRECTOR); + getGraph().addEdge(v, CORRECTOR, e); + } } getGraph().setEdgeWeight(e, CapacityScalingMinimumCostFlow.COST_INF - 1); count++; @@ -58,10 +65,11 @@ public abstract class AbstractMinCostTraverse implements MinimumCostFlowProblem< result.reportFlow(e, entry.getValue().intValue()); } } - getGraph().removeVertex(CORRECTOR); return result; } catch (Exception ignored) { return EvaluationResult.EMPTY; + } finally { + getGraph().removeVertex(CORRECTOR); } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java index 400624d72d1..52afd63e029 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java @@ -3,10 +3,9 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.net.NetNode; import gregtech.api.util.GTUtility; -import gregtech.api.util.function.ToBooleanFunction; import com.github.bsideup.jabel.Desugar; import it.unimi.dsi.fastutil.objects.Object2IntMap; @@ -19,6 +18,7 @@ import java.util.Comparator; import java.util.Set; import java.util.function.ObjIntConsumer; +import java.util.function.Predicate; import java.util.function.ToIntFunction; public class EQTraverse extends AbstractMinCostTraverse { @@ -26,7 +26,7 @@ public class EQTraverse extends AbstractMinCostTraverse { protected final Graph graph; protected final ToIntFunction capacityFunction; protected final ToIntFunction supplyFunction; - protected @Nullable ToBooleanFunction lossyNodes; + protected @Nullable Predicate lossyNodes; protected final Set suppliers; protected final Set consumers; @@ -37,7 +37,7 @@ public class EQTraverse extends AbstractMinCostTraverse { * and deposits a separately calculated amount to all sinks. Drawn and deposited amounts will be maximized, * and loss will be ignored until the final stage of traverse and reporting. * - * @param net the net + * @param group the net group the traverse takes place in * @param flowReporterNode flow reporter for nodes. Positive values mean draw, negative values mean sink. * @param flowReporterEdge flow reporter for edges. Always positive. * @param capacityFunction capacity function for edges. @@ -48,21 +48,21 @@ public class EQTraverse extends AbstractMinCostTraverse { * @param lossReporter optional reporter for loss. Always negative. Does nothing if lossy nodes is {@code null}. * @return the total draw/sink after evaluation. */ - public static int equalDistribution(@NotNull IGraphNet net, + public static int equalDistribution(@NotNull NetGroup group, @NotNull ObjIntConsumer flowReporterNode, @NotNull ObjIntConsumer flowReporterEdge, @NotNull ToIntFunction capacityFunction, @NotNull ToIntFunction supplyFunction, - @Nullable ToBooleanFunction lossyNodes, + @Nullable Predicate lossyNodes, @Nullable ObjIntConsumer lossReporter) { - if (!net.getGraph().isDirected()) { + if (!group.getGraphView().getType().isDirected()) { throw new IllegalArgumentException("Cannot perform equal distribution traverse logic on undirected graph!"); } int minSupplier = Integer.MAX_VALUE; Set suppliers = new ObjectOpenHashSet<>(); int minConsumer = Integer.MIN_VALUE; Set consumers = new ObjectOpenHashSet<>(); - for (GraphVertex v : net.getGraph().vertexSet()) { + for (GraphVertex v : group.getGraphView().vertexSet()) { if (v.getWrapped() != null) { int supply = supplyFunction.applyAsInt(v.getWrapped()); if (supply > 0) { @@ -89,7 +89,8 @@ public static int equalDistribution(@NotNull IGraphNet net, TestCase[] arr = cases.stream().sorted(Comparator.comparingInt(c -> suppliers.size() * c.supply)) .toArray(TestCase[]::new); // execute binary searching on test cases - EQTraverse traverse = new EQTraverse(net.getGraph(), capacityFunction, supplyFunction, suppliers, consumers); + EQTraverse traverse = new EQTraverse(group.getGraphView(), capacityFunction, supplyFunction, suppliers, + consumers); int solution = (int) GTUtility.binarySearch(0, arr.length - 1, l -> { traverse.testCase = arr[(int) l]; EvaluationResult result = traverse.evaluate(); @@ -107,7 +108,7 @@ public static int equalDistribution(@NotNull IGraphNet net, EvaluationResult result = traverse.evaluate(); if (result.isEmpty()) return 0; result.getFlowMap().forEach(flowReporterEdge::accept); - return FDTraverse.reportFlow(flowReporterNode, lossyNodes, lossReporter, result); + return FDTraverse.reportSupply(flowReporterNode, lossyNodes, lossReporter, result); } protected EQTraverse(Graph graph, ToIntFunction capacityFunction, @@ -121,7 +122,7 @@ protected EQTraverse(Graph graph, ToIntFunction @Override protected int getSupply(NetNode node) { - if (lossyNodes != null && lossyNodes.applyAsBool(node)) return Short.MIN_VALUE; + if (lossyNodes != null && lossyNodes.test(node)) return Short.MIN_VALUE; if (suppliers.contains(node)) return testCase.supply; if (consumers.contains(node)) return testCase.consumption; return 0; diff --git a/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java index e10d84a2845..339c8b6c01d 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java @@ -3,15 +3,15 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.net.NetNode; -import gregtech.api.util.function.ToBooleanFunction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jgrapht.Graph; import java.util.function.ObjIntConsumer; +import java.util.function.Predicate; import java.util.function.ToIntFunction; public class FDTraverse extends AbstractMinCostTraverse { @@ -19,12 +19,12 @@ public class FDTraverse extends AbstractMinCostTraverse { protected final Graph graph; protected final ToIntFunction capacityFunction; protected final ToIntFunction supplyFunction; - protected final ToBooleanFunction lossyNodes; + protected final Predicate lossyNodes; /** * Perform flood traverse. Flood traverse takes the lowest cost (weight) paths while maximizing flow. * - * @param net the net + * @param group the net group the traverse takes place in * @param flowReporterNode flow reporter for nodes. Positive values mean draw, negative values mean sink. * @param flowReporterEdge flow reporter for edges. Always positive. * @param capacityFunction capacity function for edges. @@ -35,39 +35,39 @@ public class FDTraverse extends AbstractMinCostTraverse { * @param lossReporter optional reporter for loss. Always negative. Does nothing if lossy nodes is {@code null}. * @return the total draw/sink after evaluation. */ - public static int flood(@NotNull IGraphNet net, + public static int flood(@NotNull NetGroup group, @NotNull ObjIntConsumer flowReporterNode, @NotNull ObjIntConsumer flowReporterEdge, @NotNull ToIntFunction capacityFunction, @NotNull ToIntFunction supplyFunction, - @Nullable ToBooleanFunction lossyNodes, + @Nullable Predicate lossyNodes, @Nullable ObjIntConsumer lossReporter) { - if (!net.getGraph().isDirected()) { + if (!group.getGraphView().getType().isDirected()) { throw new IllegalArgumentException("Cannot perform flood traverse logic on undirected graph!"); } - EvaluationResult result = new FDTraverse(net.getGraph(), capacityFunction, supplyFunction, lossyNodes) + EvaluationResult result = new FDTraverse(group.getGraphView(), capacityFunction, supplyFunction, lossyNodes) .evaluate(); if (result.isEmpty()) return 0; result.getFlowMap().forEach(flowReporterEdge::accept); - return reportFlow(flowReporterNode, lossyNodes, lossReporter, result); + return reportSupply(flowReporterNode, lossyNodes, lossReporter, result); } protected FDTraverse(Graph graph, ToIntFunction capacityFunction, - ToIntFunction supplyFunction, @Nullable ToBooleanFunction lossyNodes) { + ToIntFunction supplyFunction, @Nullable Predicate lossyNodes) { this.graph = graph; this.capacityFunction = capacityFunction; this.supplyFunction = supplyFunction; this.lossyNodes = lossyNodes != null ? lossyNodes : n -> false; } - static int reportFlow(@NotNull ObjIntConsumer flowReporterNode, - @Nullable ToBooleanFunction lossyNodes, - @Nullable ObjIntConsumer lossReporter, @NotNull EvaluationResult result) { + static int reportSupply(@NotNull ObjIntConsumer flowReporterNode, + @Nullable Predicate lossyNodes, + @Nullable ObjIntConsumer lossReporter, @NotNull EvaluationResult result) { int flow = 0; for (var entry : result.getSupplyMap().object2IntEntrySet()) { NetNode n = entry.getKey(); int i = entry.getIntValue(); - if (lossyNodes != null && lossyNodes.applyAsBool(n)) { + if (lossyNodes != null && lossyNodes.test(n)) { if (lossReporter != null) lossReporter.accept(n, i); } else { flowReporterNode.accept(n, i); @@ -79,7 +79,7 @@ static int reportFlow(@NotNull ObjIntConsumer flowReporterNode, @Override protected int getSupply(NetNode node) { - if (lossyNodes.applyAsBool(node)) return Short.MIN_VALUE; + if (lossyNodes.test(node)) return Short.MIN_VALUE; else return supplyFunction.applyAsInt(node); } diff --git a/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java index 66a6229c2a1..c0f299dbd61 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java @@ -3,9 +3,8 @@ import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.net.NetNode; -import gregtech.api.util.function.ToBooleanFunction; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -18,14 +17,14 @@ public class RRTraverse extends FDTraverse { - protected Predicate nextPredicate; + protected java.util.function.Predicate nextPredicate; /** * Perform round robin traverse. Round robin traverse asks repeatedly for a node predicate; * each predicate will be evaluated independently using flood traverse, where only nodes that match the predicate * or have loss are allowed to have supply/demand. * - * @param net the net + * @param group the net group the traverse takes place in * @param nextNodePredicateSupplier supplier for next predicate. Will be repeatedly queried until it returns null, * at which point the traverse will exit. * @param flowReporterNode flow reporter for nodes. Positive values mean draw, negative values mean sink. @@ -39,37 +38,37 @@ public class RRTraverse extends FDTraverse { * {@code null}. * @return the total draw/sink after evaluation. */ - public static int roundRobin(@NotNull IGraphNet net, + public static int roundRobin(@NotNull NetGroup group, Supplier<@Nullable Predicate> nextNodePredicateSupplier, @NotNull ObjIntConsumer flowReporterNode, @NotNull ObjIntConsumer flowReporterEdge, @NotNull ToIntFunction capacityFunction, @NotNull ToIntFunction supplyFunction, - @Nullable ToBooleanFunction lossyNodes, + @Nullable Predicate lossyNodes, @Nullable ObjIntConsumer lossReporter) { - if (!net.getGraph().isDirected()) { + if (!group.getGraphView().getType().isDirected()) { throw new IllegalArgumentException("Cannot perform RR traverse logic on undirected graph!"); } - RRTraverse traverse = new RRTraverse(net.getGraph(), capacityFunction, supplyFunction, lossyNodes); + RRTraverse traverse = new RRTraverse(group.getGraphView(), capacityFunction, supplyFunction, lossyNodes); int flow = 0; while ((traverse.nextPredicate = nextNodePredicateSupplier.get()) != null) { EvaluationResult result = traverse.evaluate(); if (result.isEmpty()) continue; result.getFlowMap().forEach(flowReporterEdge::accept); - flow += reportFlow(flowReporterNode, lossyNodes, lossReporter, result); + flow += reportSupply(flowReporterNode, lossyNodes, lossReporter, result); } return flow; } protected RRTraverse(Graph graph, ToIntFunction capacityFunction, - ToIntFunction supplyFunction, @Nullable ToBooleanFunction lossyNodes) { + ToIntFunction supplyFunction, @Nullable Predicate lossyNodes) { super(graph, capacityFunction, supplyFunction, lossyNodes); } @Override protected int getSupply(NetNode node) { - if (lossyNodes.applyAsBool(node)) return Short.MIN_VALUE; + if (lossyNodes.test(node)) return Short.MIN_VALUE; if (nextPredicate == null || nextPredicate.test(node)) return 0; return supplyFunction.applyAsInt(node); } diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java index a1c36f271a1..2e98bbe71c2 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java @@ -8,13 +8,14 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; import org.jgrapht.traverse.BreadthFirstIterator; import java.util.Set; public class NetBreadthIterator implements NetIterator { - protected BreadthFirstIterator backer; + protected Iter backer; /** * Creates a breadth-first iterator that traverses a connected component, starting at the given node. @@ -22,13 +23,7 @@ public class NetBreadthIterator implements NetIterator { * @param origin the node to start at */ public NetBreadthIterator(@NotNull NetNode origin, @NotNull EdgeSelector selector) { - this.backer = new BreadthFirstIterator<>(origin.getNet().getGraph(), origin.wrapper) { - - @Override - protected Set selectOutgoingEdges(GraphVertex vertex) { - return selector.selectEdges(graph, vertex); - } - }; + this.backer = new Iter(origin.getNet().getGraph(), origin.wrapper, selector); } /** @@ -37,13 +32,7 @@ protected Set selectOutgoingEdges(GraphVertex vertex) { * @param graphNet the graph to traverse. */ public NetBreadthIterator(@NotNull IGraphNet graphNet) { - this.backer = new BreadthFirstIterator<>(graphNet.getGraph(), (GraphVertex) null) { - - @Override - protected Set selectOutgoingEdges(GraphVertex vertex) { - return graph.edgesOf(vertex); - } - }; + this.backer = new Iter(graphNet.getGraph(), (GraphVertex) null, EdgeDirection.ALL); } public BreadthFirstIterator getBacker() { @@ -64,11 +53,35 @@ public NetNode next() { return backer.getParent(node.wrapper).getWrapped(); } + public boolean hasSeen(@NotNull NetNode node) { + return backer.hasSeen(node.wrapper); + } + public @Nullable NetEdge getSpanningTreeEdge(@NotNull NetNode node) { - return backer.getSpanningTreeEdge(node.wrapper).getWrapped(); + if (!backer.hasSeen(node.wrapper)) return null; + return NetEdge.unwrap(backer.getSpanningTreeEdge(node.wrapper)); } public int getDepth(@NotNull NetNode node) { return backer.getDepth(node.wrapper); } + + protected static final class Iter extends BreadthFirstIterator { + + private final EdgeSelector selector; + + public Iter(Graph g, GraphVertex startVertex, EdgeSelector selector) { + super(g, startVertex); + this.selector = selector; + } + + @Override + protected Set selectOutgoingEdges(GraphVertex vertex) { + return selector.selectEdges(graph, vertex); + } + + public boolean hasSeen(GraphVertex vertex) { + return getSeenData(vertex) != null; + } + } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java index 6454efcde70..8a5fbf94155 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java @@ -14,9 +14,7 @@ public class NetClosestIterator implements NetIterator { - protected final ClosestFirstIterator backer; - - protected final EdgeSelector selector; + protected final Iter backer; /** * Creates a closest-first iterator that traverses a connected component, starting at the given node. @@ -24,24 +22,13 @@ public class NetClosestIterator implements NetIterator { * @param origin the node to start at */ public NetClosestIterator(@NotNull NetNode origin, EdgeSelector selector) { - this.backer = new ClosestFirstIterator<>(origin.getNet().getGraph(), origin.wrapper) { - - @Override - protected Set selectOutgoingEdges(GraphVertex vertex) { - return selectEdges(graph, vertex); - } - }; - this.selector = selector; + this.backer = new Iter(origin.getNet().getGraph(), origin.wrapper, selector); } public ClosestFirstIterator getBacker() { return backer; } - protected Set selectEdges(Graph graph, GraphVertex vertex) { - return selector.selectEdges(graph, vertex); - } - @Override public boolean hasNext() { return backer.hasNext(); @@ -56,7 +43,31 @@ public double getShortestPathLength(@NotNull NetNode node) { return backer.getShortestPathLength(node.wrapper); } + public boolean hasSeen(@NotNull NetNode node) { + return backer.hasSeen(node.wrapper); + } + public @Nullable NetEdge getSpanningTreeEdge(@NotNull NetNode node) { - return backer.getSpanningTreeEdge(node.wrapper).getWrapped(); + if (!backer.hasSeen(node.wrapper)) return null; + return NetEdge.unwrap(backer.getSpanningTreeEdge(node.wrapper)); + } + + protected static final class Iter extends ClosestFirstIterator { + + private final EdgeSelector selector; + + public Iter(Graph g, GraphVertex startVertex, EdgeSelector selector) { + super(g, startVertex); + this.selector = selector; + } + + @Override + protected Set selectOutgoingEdges(GraphVertex vertex) { + return selector.selectEdges(graph, vertex); + } + + public boolean hasSeen(GraphVertex vertex) { + return getSeenData(vertex) != null; + } } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java index 71ce56077a8..1c5dcca4dad 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java @@ -10,6 +10,8 @@ public interface NetIterator extends Iterator { + boolean hasSeen(@NotNull NetNode node); + @Nullable NetEdge getSpanningTreeEdge(@NotNull NetNode node); } diff --git a/src/main/java/gregtech/api/unification/material/Material.java b/src/main/java/gregtech/api/unification/material/Material.java index fc261c305d9..d98734d9d8d 100644 --- a/src/main/java/gregtech/api/unification/material/Material.java +++ b/src/main/java/gregtech/api/unification/material/Material.java @@ -1050,9 +1050,9 @@ public Builder cableProperties(long voltage, long amperage, long loss) { return this; } - public Builder cableProperties(long voltage, long amperage, long loss, int superconductorTemperature) { + public Builder cableProperties(long voltage, long amperage, long loss, boolean superconductor) { getOrCreatePipeNetProperties() - .setProperty(MaterialEnergyProperties.create(voltage, amperage, loss, superconductorTemperature)); + .setProperty(MaterialEnergyProperties.create(voltage, amperage, loss, superconductor)); return this; } diff --git a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java index 614f772b8ff..3bd09c2028a 100644 --- a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java @@ -1341,7 +1341,7 @@ public static void register() { .color(0xE1B454).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Manganese, 1, Phosphorus, 1) - .cableProperties(GTValues.V[GTValues.LV], 2, GTValues.V[GTValues.ULV], Integer.MAX_VALUE) + .cableProperties(GTValues.V[GTValues.LV], 2, 0, true) .blast(1200, GasTier.LOW) .build(); @@ -1351,7 +1351,7 @@ public static void register() { .color(0x331900).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Magnesium, 1, Boron, 2) - .cableProperties(GTValues.V[GTValues.MV], 4, GTValues.V[GTValues.LV], Integer.MAX_VALUE) + .cableProperties(GTValues.V[GTValues.MV], 4, 0, true) .blast(b -> b .temp(2500, GasTier.LOW) .blastStats(VA[HV], 1000) @@ -1364,7 +1364,7 @@ public static void register() { .color(0x555555).iconSet(SHINY) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Mercury, 1, Barium, 2, Calcium, 2, Copper, 3, Oxygen, 8) - .cableProperties(GTValues.V[GTValues.HV], 4, GTValues.V[GTValues.MV], Integer.MAX_VALUE) + .cableProperties(GTValues.V[GTValues.HV], 4, 0, true) .blast(b -> b .temp(3300, GasTier.LOW) .blastStats(VA[HV], 1500) @@ -1377,7 +1377,7 @@ public static void register() { .color(0x008700).iconSet(SHINY) .flags(DECOMPOSITION_BY_CENTRIFUGING) .components(Uranium, 1, Platinum, 3) - .cableProperties(GTValues.V[GTValues.EV], 6, GTValues.V[GTValues.HV], Integer.MAX_VALUE) + .cableProperties(GTValues.V[GTValues.EV], 6, 0, true) .blast(b -> b .temp(4400, GasTier.MID) .blastStats(VA[EV], 1000) @@ -1390,7 +1390,7 @@ public static void register() { .color(0x330033).iconSet(SHINY) .flags(DECOMPOSITION_BY_CENTRIFUGING) .components(Samarium, 1, Iron, 1, Arsenic, 1, Oxygen, 1) - .cableProperties(GTValues.V[GTValues.IV], 6, GTValues.V[GTValues.EV], Integer.MAX_VALUE) + .cableProperties(GTValues.V[GTValues.IV], 6, 0, true) .blast(b -> b .temp(5200, GasTier.MID) .blastStats(VA[EV], 1500) @@ -1403,7 +1403,7 @@ public static void register() { .color(0x994C00).iconSet(METALLIC) .flags(DECOMPOSITION_BY_ELECTROLYZING, GENERATE_FINE_WIRE) .components(Indium, 4, Tin, 2, Barium, 2, Titanium, 1, Copper, 7, Oxygen, 14) - .cableProperties(GTValues.V[GTValues.LuV], 8, GTValues.V[GTValues.IV], Integer.MAX_VALUE) + .cableProperties(GTValues.V[GTValues.LuV], 8, 0, true) .blast(b -> b .temp(6000, GasTier.HIGH) .blastStats(VA[IV], 1000) @@ -1416,7 +1416,7 @@ public static void register() { .color(0x0A0A0A) .flags(DECOMPOSITION_BY_CENTRIFUGING, GENERATE_FINE_WIRE) .components(Uranium, 1, Rhodium, 1, Naquadah, 2) - .cableProperties(GTValues.V[GTValues.ZPM], 8, GTValues.V[LuV], Integer.MAX_VALUE) + .cableProperties(GTValues.V[GTValues.ZPM], 8, 0, true) .blast(b -> b .temp(9000, GasTier.HIGH) .blastStats(VA[IV], 1500) @@ -1430,7 +1430,7 @@ public static void register() { .color(0x7D9673).iconSet(METALLIC) .flags(DECOMPOSITION_BY_CENTRIFUGING, GENERATE_FINE_WIRE) .components(NaquadahEnriched, 4, Trinium, 3, Europium, 2, Duranium, 1) - .cableProperties(GTValues.V[GTValues.UV], 16, GTValues.V[GTValues.ZPM], Integer.MAX_VALUE) + .cableProperties(GTValues.V[GTValues.UV], 16, 0, true) .blast(b -> b .temp(9900, GasTier.HIGH) .blastStats(VA[LuV], 1200) @@ -1444,7 +1444,7 @@ public static void register() { .color(0xFFFFFF).iconSet(BRIGHT) .flags(DECOMPOSITION_BY_ELECTROLYZING) .components(Ruthenium, 1, Trinium, 2, Americium, 1, Neutronium, 2, Oxygen, 8) - .cableProperties(GTValues.V[GTValues.UHV], 24, GTValues.V[GTValues.UV], Integer.MAX_VALUE) + .cableProperties(GTValues.V[GTValues.UHV], 24, 0, true) .blast(b -> b .temp(10800, GasTier.HIGHER) .blastStats(VA[ZPM], 1000) diff --git a/src/main/java/gregtech/api/util/FacingPos.java b/src/main/java/gregtech/api/util/FacingPos.java index 3227e34f14b..7aea1060261 100644 --- a/src/main/java/gregtech/api/util/FacingPos.java +++ b/src/main/java/gregtech/api/util/FacingPos.java @@ -7,6 +7,8 @@ public class FacingPos { + public static final FacingPos ORIGIN = new FacingPos(BlockPos.ORIGIN, null); + private final BlockPos pos; private final EnumFacing facing; private final int hashCode; diff --git a/src/main/java/gregtech/api/util/function/ToBooleanFunction.java b/src/main/java/gregtech/api/util/function/ToBooleanFunction.java deleted file mode 100644 index 6c39546c0a8..00000000000 --- a/src/main/java/gregtech/api/util/function/ToBooleanFunction.java +++ /dev/null @@ -1,7 +0,0 @@ -package gregtech.api.util.function; - -@FunctionalInterface -public interface ToBooleanFunction { - - boolean applyAsBool(T value); -} diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index 666a548f8b7..fbfeccab803 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -4,10 +4,18 @@ import gregtech.api.GregTechAPI; import gregtech.api.block.VariantItemBlock; import gregtech.api.block.machines.MachineItemBlock; +import gregtech.api.graphnet.GraphClassRegistrationEvent; +import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.edge.NetFlowEdge; +import gregtech.api.graphnet.edge.NetFlowSharedEdge; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.NetLogicRegistrationEvent; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.net.BlankNetNode; +import gregtech.api.graphnet.net.BlockPosNode; +import gregtech.api.graphnet.pipenet.WorldPipeCapConnectionNode; +import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; import gregtech.api.graphnet.pipenet.physical.PipeStructureRegistrationEvent; import gregtech.api.graphnet.pipenet.physical.block.ItemPipeBlock; @@ -53,6 +61,7 @@ import gregtech.common.pipelike.block.optical.OpticalStructure; import gregtech.common.pipelike.block.pipe.MaterialPipeBlock; import gregtech.common.pipelike.block.pipe.MaterialPipeStructure; +import gregtech.common.pipelike.net.energy.AmperageLimitLogic; import gregtech.common.pipelike.net.energy.EnergyFlowLogic; import gregtech.common.pipelike.net.energy.SuperconductorLogic; import gregtech.common.pipelike.net.energy.VoltageLimitLogic; @@ -405,6 +414,18 @@ public static void registerNetLogics(NetLogicRegistrationEvent event) { event.accept(WeightFactorLogic.TYPE); event.accept(VoltageLimitLogic.TYPE); event.accept(VoltageLossLogic.TYPE); + event.accept(AmperageLimitLogic.TYPE); + } + + @SubscribeEvent + public static void registerGraphClasses(GraphClassRegistrationEvent event) { + event.accept(NetEdge.TYPE); + event.accept(NetFlowEdge.TYPE); + event.accept(NetFlowSharedEdge.TYPE); + event.accept(WorldPipeNode.TYPE); + event.accept(WorldPipeCapConnectionNode.TYPE); + event.accept(BlockPosNode.TYPE); + event.accept(BlankNetNode.TYPE); } @SubscribeEvent diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 667a95fae78..461dfd07d55 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -14,7 +14,7 @@ import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; @@ -375,12 +375,13 @@ protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode de int transfer = Math.min(merge.getCount(), max); // only simulate to test min if necessary if (min > 0) { - transfer = attemptNetTransfer(sourceNode.getNet(), bridge, transfer, merge.getTestObject(), + transfer = attemptNetTransfer(sourceNode.getGroupSafe(), bridge, transfer, + merge.getTestObject(), sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, SimulatorKey.getNewSimulatorInstance()); if (transfer < min) continue; } - transfer = attemptNetTransfer(sourceNode.getNet(), bridge, transfer, merge.getTestObject(), + transfer = attemptNetTransfer(sourceNode.getGroupSafe(), bridge, transfer, merge.getTestObject(), sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, null); int remaining = max - transfer; slotTransfer += transfer; @@ -389,7 +390,8 @@ protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode de .getNonLargestMerges(merge)) { transfer = Math.min(otherMerge.getCount(), remaining); // we don't have to simulate here since we no longer need to respect the min - transfer = attemptNetTransfer(sourceNode.getNet(), bridge, transfer, merge.getTestObject(), + transfer = attemptNetTransfer(sourceNode.getGroupSafe(), bridge, transfer, + merge.getTestObject(), sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, null); remaining -= transfer; slotTransfer += transfer; @@ -403,39 +405,44 @@ protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode de return totalTransfer; } - protected int attemptNetTransfer(IGraphNet net, NetEdge bridge, int limit, ItemTestObject testObject, + protected int attemptNetTransfer(NetGroup group, NetEdge bridge, int limit, ItemTestObject testObject, NetIterator sources, Map sourceCandidates, NetIterator targets, Map destCandidates, @Nullable SimulatorKey key) { return switch (distributionMode) { - case FLOOD -> FDTraverse.flood(net, + case FLOOD -> FDTraverse.flood(group, (n, f) -> { if (key == null) ItemCapabilityObject.reportFlow(n, f, testObject); }, (e, f) -> ItemCapabilityObject.reportFlow(e, f, testObject, key, true), e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : 0, - n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), null, null); - case EQUALIZED -> EQTraverse.equalDistribution(net, + GTUtility.safeCastLongToInt( + n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : + 0, + n -> getSupply(n, testObject, sources.hasSeen(n)), null, null); + case EQUALIZED -> EQTraverse.equalDistribution(group, (n, f) -> { if (key == null) ItemCapabilityObject.reportFlow(n, f, testObject); }, (e, f) -> ItemCapabilityObject.reportFlow(e, f, testObject, key, true), e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : 0, - n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), null, null); + GTUtility.safeCastLongToInt( + n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : + 0, + n -> getSupply(n, testObject, sources.hasSeen(n)), null, null); case ROUND_ROBIN -> { roundRobinCache.refresh(sources, targets); - yield RRTraverse.roundRobin(net, getRoundRobinCache(key != null) + yield RRTraverse.roundRobin(group, getRoundRobinCache(key != null) .buildSupplier(sourceCandidates.keySet(), destCandidates.keySet()), (n, f) -> { if (key == null) ItemCapabilityObject.reportFlow(n, f, testObject); }, (e, f) -> ItemCapabilityObject.reportFlow(e, f, testObject, key, true), e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : + GTUtility.safeCastLongToInt( + n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : 0, - n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), + n -> getSupply(n, testObject, sources.hasSeen(n)), null, null); } }; diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index 0383f6eb230..7e34363c204 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -13,7 +13,7 @@ import gregtech.api.graphnet.edge.AbstractNetFlowEdge; import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; @@ -378,12 +378,12 @@ protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode de if (contents.amount < min) continue; int transfer = Math.min(contents.amount, max); if (min > 0) { - transfer = attemptNetTransfer(sourceNode.getNet(), bridge, transfer, content.getKey(), + transfer = attemptNetTransfer(sourceNode.getGroupSafe(), bridge, transfer, content.getKey(), sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, SimulatorKey.getNewSimulatorInstance()); if (transfer < min) continue; } - transfer = attemptNetTransfer(sourceNode.getNet(), bridge, transfer, content.getKey(), + transfer = attemptNetTransfer(sourceNode.getGroupSafe(), bridge, transfer, content.getKey(), sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, null); if (transferReport != null) transferReport.accept(filterSlot, transfer); totalTransfer += transfer; @@ -392,40 +392,47 @@ protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode de return totalTransfer; } - protected int attemptNetTransfer(IGraphNet net, NetEdge bridge, int limit, FluidTestObject testObject, + protected int attemptNetTransfer(NetGroup group, NetEdge bridge, int limit, FluidTestObject testObject, NetIterator sources, Map sourceCandidates, NetIterator targets, Map destCandidates, @Nullable SimulatorKey key) { return switch (distributionMode) { - case FLOOD -> FDTraverse.flood(net, + case FLOOD -> FDTraverse.flood(group, (n, f) -> { if (key == null) FluidCapabilityObject.reportFlow(n, f, testObject); }, (e, f) -> FluidCapabilityObject.reportFlow(e, f, testObject, key, true), e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : 0, - n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), null, null); - case EQUALIZED -> EQTraverse.equalDistribution(net, + GTUtility.safeCastLongToInt( + n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : + 0, + n -> getSupply(n, testObject, sources.hasSeen(n)), FluidCapabilityObject.isLossyNode(testObject), + FluidCapabilityObject.handleLoss(testObject)); + case EQUALIZED -> EQTraverse.equalDistribution(group, (n, f) -> { if (key == null) FluidCapabilityObject.reportFlow(n, f, testObject); }, (e, f) -> FluidCapabilityObject.reportFlow(e, f, testObject, key, true), e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : 0, - n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), null, null); + GTUtility.safeCastLongToInt( + n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : + 0, + n -> getSupply(n, testObject, sources.hasSeen(n)), FluidCapabilityObject.isLossyNode(testObject), + FluidCapabilityObject.handleLoss(testObject)); case ROUND_ROBIN -> { roundRobinCache.refresh(sources, targets); - yield RRTraverse.roundRobin(net, getRoundRobinCache(key != null) + yield RRTraverse.roundRobin(group, getRoundRobinCache(key != null) .buildSupplier(sourceCandidates.keySet(), destCandidates.keySet()), (n, f) -> { if (key == null) FluidCapabilityObject.reportFlow(n, f, testObject); }, (e, f) -> FluidCapabilityObject.reportFlow(e, f, testObject, key, true), e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt(n.getFlowLimit(testObject, net, GTUtility.getTick(), key)) : + GTUtility.safeCastLongToInt( + n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : 0, - n -> getSupply(n, testObject, sources.getSpanningTreeEdge(n) != null), - null, null); + n -> getSupply(n, testObject, sources.hasSeen(n)), + FluidCapabilityObject.isLossyNode(testObject), FluidCapabilityObject.handleLoss(testObject)); } }; } diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 308e255e855..20f7aaa5cde 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -54,25 +54,22 @@ public final class MaterialEnergyProperties implements PipeNetProperties.IPipeNe private final long amperageLimit; private int materialMeltTemperature; private final long lossPerAmp; - private final int superconductorCriticalTemperature; + private final boolean superconductor; /** * Generate a MaterialEnergyProperties * - * @param voltageLimit the voltage limit for the cable - * @param amperageLimit the base amperage for the cable. - * @param lossPerAmp the base loss per amp per block traveled. - * @param superconductorCriticalTemperature the superconductor temperature. When the temperature is at or below - * superconductor temperature, loss will be treated as zero. A - * superconductor - * temperature of 0 or less will be treated as not a superconductor. + * @param voltageLimit the voltage limit for the cable + * @param amperageLimit the base amperage for the cable. + * @param lossPerAmp the base loss per amp per block traveled. + * @param superconductor whether the material will be treated as a superconductor. Does not override loss. */ public MaterialEnergyProperties(long voltageLimit, long amperageLimit, long lossPerAmp, - int superconductorCriticalTemperature) { + boolean superconductor) { this.voltageLimit = voltageLimit; this.amperageLimit = amperageLimit; this.lossPerAmp = lossPerAmp; - this.superconductorCriticalTemperature = superconductorCriticalTemperature; + this.superconductor = superconductor; } public long getVoltageLimit() { @@ -80,13 +77,12 @@ public long getVoltageLimit() { } public static MaterialEnergyProperties create(long voltageLimit, long amperageLimit, long lossPerAmp, - int superconductorCriticalTemperature) { - return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, - superconductorCriticalTemperature); + boolean superconductor) { + return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, superconductor); } public static MaterialEnergyProperties create(long voltageLimit, long amperageLimit, long lossPerAmp) { - return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, 0); + return new MaterialEnergyProperties(voltageLimit, amperageLimit, lossPerAmp, false); } public static IOreRegistrationHandler registrationHandler(TriConsumer handler) { @@ -100,7 +96,7 @@ public static IOreRegistrationHandler registrationHandler(TriConsumer 1; + return superconductor; } @Override @@ -117,12 +113,8 @@ public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull Lis tooltip.add(I18n.format("gregtech.cable.voltage", voltageLimit, GTValues.VNF[tier])); tooltip.add(I18n.format("gregtech.cable.amperage", getAmperage(structure))); - long loss = isSuperconductor() && superconductorCriticalTemperature == Integer.MAX_VALUE ? 0 : - getLoss(structure); + long loss = getLoss(structure); tooltip.add(I18n.format("gregtech.cable.loss_per_block", loss)); - if (isSuperconductor() && superconductorCriticalTemperature != Integer.MAX_VALUE) { - tooltip.add(I18n.format("gregtech.cable.superconductor_loss", superconductorCriticalTemperature)); - } } @Override @@ -193,8 +185,8 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { 1, 100 * cable.material(), cable.partialBurnThreshold()) .setInitialThermalEnergy(energy)); - if (superconductorCriticalTemperature > 0) { - data.setLogicEntry(SuperconductorLogic.TYPE.getWith(superconductorCriticalTemperature)); + if (superconductor) { + data.setLogicEntry(SuperconductorLogic.TYPE.getNew()); } } else if (structure instanceof MaterialPipeStructure pipe) { long amperage = getAmperage(structure); @@ -211,8 +203,8 @@ public void mutateData(NetLogicData data, IPipeStructure structure) { .getWith(TemperatureLossFunction.getOrCreatePipe(coolingFactor), materialMeltTemperature, 1, 50 * pipe.material(), null) .setInitialThermalEnergy(energy)); - if (superconductorCriticalTemperature > 0) { - data.setLogicEntry(SuperconductorLogic.TYPE.getWith(superconductorCriticalTemperature)); + if (superconductor) { + data.setLogicEntry(SuperconductorLogic.TYPE.getNew()); } } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java b/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java index dc5885c6eb8..332268f94f8 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/SuperconductorLogic.java @@ -1,21 +1,19 @@ package gregtech.common.pipelike.net.energy; import gregtech.api.GTValues; -import gregtech.api.graphnet.logic.AbstractIntLogicData; +import gregtech.api.graphnet.logic.AbstractByteLogicData; import org.jetbrains.annotations.NotNull; -public final class SuperconductorLogic extends AbstractIntLogicData { +public final class SuperconductorLogic extends AbstractByteLogicData { - public static final IntLogicType TYPE = new IntLogicType<>(GTValues.MODID, "Superconductor", - SuperconductorLogic::new, new SuperconductorLogic()); + public static final SuperconductorLogic INSTANCE = new SuperconductorLogic(); + + public static final ByteLogicType TYPE = new ByteLogicType<>(GTValues.MODID, "Superconductor", + () -> INSTANCE, INSTANCE); @Override - public @NotNull IntLogicType getType() { + public @NotNull ByteLogicType getType() { return TYPE; } - - public boolean canSuperconduct(int temp) { - return this.getValue() > temp; - } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index a730891cb56..f5d965aecea 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -31,6 +31,8 @@ import java.util.Arrays; import java.util.EnumMap; +import java.util.function.ObjIntConsumer; +import java.util.function.Predicate; public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler, IFluidTankProperties { @@ -93,7 +95,7 @@ protected int fill(FluidStack resource, boolean doFill, EnumFacing side) { int flow = resource.amount; SimulatorKey key = doFill ? null : SimulatorKey.getNewSimulatorInstance(); FluidTestObject testObject = new FluidTestObject(resource); - int report = FDTraverse.flood(node.getNet(), + int report = FDTraverse.flood(node.getGroupSafe(), (n, f) -> { if (n != node && doFill) reportFlow(n, f, testObject); }, @@ -103,9 +105,7 @@ protected int fill(FluidStack resource, boolean doFill, EnumFacing side) { n.getFlowLimit(testObject, node.getNet(), GTUtility.getTick(), key)) : 0, n -> n == node ? flow : getSupply(n, testObject, false), - n -> n.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE).handles(testObject), - (n, f) -> handleLoss(n, f, testObject)); - + isLossyNode(testObject), handleLoss(testObject)); this.transferring = false; return report; } @@ -124,7 +124,7 @@ protected FluidStack drain(FluidStack resource, boolean doDrain, EnumFacing side int flow = resource.amount; SimulatorKey key = doDrain ? null : SimulatorKey.getNewSimulatorInstance(); FluidTestObject testObject = new FluidTestObject(resource); - int report = FDTraverse.flood(node.getNet(), + int report = FDTraverse.flood(node.getGroupSafe(), (n, f) -> { if (n != node && doDrain) reportFlow(n, f, testObject); }, @@ -134,13 +134,19 @@ protected FluidStack drain(FluidStack resource, boolean doDrain, EnumFacing side n.getFlowLimit(testObject, node.getNet(), GTUtility.getTick(), key)) : 0, n -> n == node ? flow : getSupply(n, testObject, true), - n -> n.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE).handles(testObject), - (n, f) -> handleLoss(n, f, testObject)); + isLossyNode(testObject), handleLoss(testObject)); this.transferring = false; return testObject.recombine(report); } + public static Predicate isLossyNode(FluidTestObject testObject) { + return n -> { + FluidContainmentLogic containmentLogic = n.getData().getLogicEntryNullable(FluidContainmentLogic.TYPE); + return containmentLogic != null && !containmentLogic.handles(testObject); + }; + } + public static void reportFlow(NetEdge edge, int flow, FluidTestObject testObject, SimulatorKey key, boolean sourceBias) { NetNode node = sourceBias ? edge.getSource() : edge.getTarget(); @@ -177,35 +183,37 @@ public static void reportFlow(NetNode node, int flow, FluidTestObject testObject if (flow > 0) { handler.drain(testObject.recombine(flow), true); } else { - handler.fill(testObject.recombine(flow), true); + handler.fill(testObject.recombine(-flow), true); } } } } - public static void handleLoss(NetNode node, int flow, FluidTestObject testObject) { - if (flow == 0) return; - FluidContainmentLogic logic = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE); - if (node instanceof WorldPipeNode n) { - IWorldPipeNetTile tile = n.getTileEntity(); - FluidStack stack = testObject.recombine(flow); - // failing attributes take priority over state - for (FluidAttribute attribute : FluidAttribute.inferAttributes(stack)) { - if (!logic.contains(attribute)) { - attribute.handleFailure(tile.getWorld(), tile.getPos(), stack); - return; + public static ObjIntConsumer handleLoss(FluidTestObject testObject) { + return (node, f) -> { + if (f == 0) return; + FluidContainmentLogic logic = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE); + if (node instanceof WorldPipeNode n) { + IWorldPipeNetTile tile = n.getTileEntity(); + FluidStack stack = testObject.recombine(f); + // failing attributes take priority over state + for (FluidAttribute attribute : FluidAttribute.inferAttributes(stack)) { + if (!logic.contains(attribute)) { + attribute.handleFailure(tile.getWorld(), tile.getPos(), stack); + return; + } } + FluidState state = FluidState.inferState(stack); + if (!logic.contains(state)) state.handleFailure(tile.getWorld(), tile.getPos(), stack); } - FluidState state = FluidState.inferState(stack); - if (!logic.contains(state)) state.handleFailure(tile.getWorld(), tile.getPos(), stack); - } + }; } public static int getSupply(NetNode node, FluidTestObject testObject, boolean supply) { if (node instanceof NodeExposingCapabilities exposer) { IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, exposer.exposedFacing()); - if (handler != null) { + if (handler != null && !(handler instanceof FluidCapabilityObject)) { if (supply) { FluidStack s = handler.drain(testObject.recombine(Integer.MAX_VALUE), false); return s == null ? 0 : s.amount; diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index 0dcc6f46bc4..5197e917375 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -80,7 +80,7 @@ public T getCapability(Capability capability, @Nullable EnumFacing facing int flow = stack.getCount(); SimulatorKey key = simulate ? SimulatorKey.getNewSimulatorInstance() : null; ItemTestObject testObject = new ItemTestObject(stack); - int report = FDTraverse.flood(node.getNet(), + int report = FDTraverse.flood(node.getGroupSafe(), (n, f) -> { if (n != node && !simulate) reportFlow(n, f, testObject); }, @@ -135,8 +135,8 @@ public static void reportFlow(NetNode node, int flow, ItemTestObject testObject) } } else { for (int i = 0; i < handler.getSlots(); i++) { - ItemStack stack = testObject.recombineSafe(flow); - flow -= stack.getCount() - handler.insertItem(i, stack, false).getCount(); + ItemStack stack = testObject.recombineSafe(-flow); + flow += stack.getCount() - handler.insertItem(i, stack, false).getCount(); if (flow == 0) return; } } @@ -148,7 +148,7 @@ public static int getSupply(NetNode node, ItemTestObject testObject, boolean sup if (node instanceof NodeExposingCapabilities exposer) { IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, exposer.exposedFacing()); - if (handler != null) { + if (handler != null && !(handler instanceof ItemCapabilityObject)) { if (supply) { int sum = 0; for (int i = 0; i < handler.getSlots(); i++) { diff --git a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java index 9c606613b2e..f43304fccdd 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/LaserCapabilityObject.java @@ -51,48 +51,72 @@ public long receiveLaser(long laserVoltage, long laserAmperage) { } protected long receiveLaser(long laserVoltage, long laserAmperage, EnumFacing facing) { - if (tile == null || this.transmitting) return 0; - this.transmitting = true; - - NetPath path; - if (node.getGroupUnsafe() == null || node.getGroupSafe().getNodes().size() == 1) - path = new SingletonNetPath(node); - else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { - Set actives = node.getGroupSafe().getNodesUnderKey(ACTIVE_KEY); - if (actives.size() > 2) return 0; // single-destination contract violated - var iter = actives.iterator(); - NetNode target = iter.next(); - if (target == node) { - if (!iter.hasNext()) return 0; // no destinations - target = iter.next(); + long result = 0; + boolean earlyReturn = false; + if (tile != null && !this.transmitting) { + this.transmitting = true; + NetPath path = null; + if (node.getGroupUnsafe() == null || node.getGroupSafe().getNodes().size() == 1) + path = new SingletonNetPath(node); + else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { + Set actives = node.getGroupSafe().getNodesUnderKey(ACTIVE_KEY); + if (actives.size() > 2) { + earlyReturn = true;// single-destination contract violated + } else { + var iter = actives.iterator(); + NetNode target = iter.next(); + if (target == node) { + if (!iter.hasNext()) { + earlyReturn = true;// no destinations + } else { + target = iter.next(); + } + } + if (!earlyReturn) { + if (!(target instanceof WorldPipeNode)) { + earlyReturn = true;// useless target + } else { + path = cache.getOrCreate(node).getOrCompute(target); + if (path == null) { + earlyReturn = true;// no path + } + } + } + } + } else { + earlyReturn = true;// no cache to lookup with } - if (!(target instanceof WorldPipeNode)) return 0; // useless target - path = cache.getOrCreate(node).getOrCompute(target); - if (path == null) return 0; // no path - } else return 0; // no cache to lookup with - - long available = laserAmperage; - WorldPipeNode destination = (WorldPipeNode) path.getTargetNode(); - for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { - if (destination == node && capability.getKey() == facing) continue; // anti insert-to-our-source logic - ILaserRelay laser = capability.getValue() - .getCapability(GregtechTileCapabilities.CAPABILITY_LASER, capability.getKey().getOpposite()); - if (laser != null && !(destination.getTileEntity().getCoverHolder() - .getCoverAtSide(capability.getKey()) instanceof CoverShutter)) { - long transmitted = laser.receiveLaser(laserVoltage, laserAmperage); - if (transmitted > 0) { - SlowActiveWalker.dispatch(tile.getWorld(), path, 1, 2, 2); - available -= transmitted; - if (available <= 0) { - this.transmitting = false; - return laserAmperage; + if (!earlyReturn) { + long available = laserAmperage; + WorldPipeNode destination = (WorldPipeNode) path.getTargetNode(); + for (var capability : destination.getTileEntity().getTargetsWithCapabilities(destination).entrySet()) { + if (destination == node && capability.getKey() == facing) + continue; // anti insert-to-our-source logic + ILaserRelay laser = capability.getValue() + .getCapability(GregtechTileCapabilities.CAPABILITY_LASER, + capability.getKey().getOpposite()); + if (laser != null && !(destination.getTileEntity().getCoverHolder() + .getCoverAtSide(capability.getKey()) instanceof CoverShutter)) { + long transmitted = laser.receiveLaser(laserVoltage, laserAmperage); + if (transmitted > 0) { + SlowActiveWalker.dispatch(tile.getWorld(), path, 1, 2, 2); + available -= transmitted; + if (available <= 0) { + result = laserAmperage; + earlyReturn = true; + break; + } + } } } + if (!earlyReturn) { + result = laserAmperage - available; + } } + this.transmitting = false; } - this.transmitting = false; - return laserAmperage - available; + return result; } @Override diff --git a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java index 67c86b81532..8fb2f5cdcfc 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/CTMaterialBuilder.java @@ -240,8 +240,8 @@ public CTMaterialBuilder ingotSmeltInto(Material m) { @ZenMethod public CTMaterialBuilder cableProperties(long voltage, int amperage, int loss, - @Optional int superConTemperature) { - backingBuilder.cableProperties(voltage, amperage, loss, superConTemperature); + @Optional boolean superconductor) { + backingBuilder.cableProperties(voltage, amperage, loss, superconductor); return this; } diff --git a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java index d27118d708a..377e136596c 100644 --- a/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/crafttweaker/material/MaterialPropertyExpansion.java @@ -259,7 +259,7 @@ public static void addItemPipes(Material m, int priority, float transferRate) { @ZenMethod public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock, - @Optional int superconductorTemp) { + @Optional boolean superconductor) { if (checkFrozen("add Wires to a material")) return; PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); if (properties == null) { @@ -267,6 +267,6 @@ public static void addWires(Material m, long voltage, long baseAmperage, long lo m.setProperty(PropertyKey.PIPENET_PROPERTIES, properties); } properties.setProperty(MaterialEnergyProperties.create(voltage, baseAmperage, lossPerBlock, - superconductorTemp)); + superconductor)); } } diff --git a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java index beb2883b791..1bbdf829ced 100644 --- a/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java +++ b/src/main/java/gregtech/integration/groovy/MaterialPropertyExpansion.java @@ -331,11 +331,11 @@ public static void addItemPipes(Material m, int priority, float transferRate) { } public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock) { - addWires(m, voltage, baseAmperage, lossPerBlock, 0); + addWires(m, voltage, baseAmperage, lossPerBlock, false); } public static void addWires(Material m, long voltage, long baseAmperage, long lossPerBlock, - int superconductorTemp) { + boolean superconductor) { if (checkFrozen("add Wires to a material")) return; PipeNetProperties properties = m.getProperty(PropertyKey.PIPENET_PROPERTIES); if (properties == null) { @@ -343,7 +343,7 @@ public static void addWires(Material m, long voltage, long baseAmperage, long lo m.setProperty(PropertyKey.PIPENET_PROPERTIES, properties); } properties.setProperty(MaterialEnergyProperties.create(voltage, baseAmperage, lossPerBlock, - superconductorTemp)); + superconductor)); } public static void addCables(Material m, long voltage, long baseAmperage, long lossPerBlock) { @@ -351,7 +351,7 @@ public static void addCables(Material m, long voltage, long baseAmperage, long l } public static void addCables(Material m, int voltage, int baseAmperage, int lossPerBlock, - int superconductorTemp) { - addWires(m, voltage, baseAmperage, lossPerBlock, superconductorTemp); + boolean superconductor) { + addWires(m, voltage, baseAmperage, lossPerBlock, superconductor); } } diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index d3582f169f7..8224c92412c 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -5591,7 +5591,6 @@ gregtech.item_filter.footer=§eClick with item to override gregtech.cable.voltage=§aMax Voltage: §f%,d §f(%s§f) gregtech.cable.amperage=§eMax Amperage: §f%,d gregtech.cable.loss_per_block=§cLoss/Meter/Ampere: §f%,d§f EU-Volt -gregtech.cable.superconductor_loss=§cLoss is §f0§c under critical temperature §f%,d§f K gregtech.cable.superconductor=§d%s Superconductor gregtech.fluid_pipe.max_temperature=§cMax Temperature: §f%,d K From ed3324ab5a5d1bebd5d54a973671da6a60a7aea2 Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Fri, 20 Dec 2024 21:52:18 -0700 Subject: [PATCH 153/157] Yeet some streams --- .../api/graphnet/path/StandardNetPath.java | 34 +++++++++++++++---- .../net/energy/StandardEnergyPath.java | 22 +++++++++--- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java b/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java index 9dec6fdc586..336ffae97e3 100644 --- a/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java @@ -86,8 +86,17 @@ public NetLogicData getUnifiedNodeData() { } else if (nodes.size() == 2) { unifiedNodeData = NetLogicData.union(nodesList.get(0).getData(), nodesList.get(1).getData()); } else { - unifiedNodeData = NetLogicData.union(nodesList.get(0).getData(), - nodes.stream().skip(1).map(NetNode::getData).toArray(NetLogicData[]::new)); + ObjectArrayList list = new ObjectArrayList<>(nodes.size()); + boolean first = true; + for (NetNode node : nodes) { + if (first) { + first = false; + continue; + } + NetLogicData data = node.getData(); + list.add(data); + } + unifiedNodeData = NetLogicData.union(nodesList.get(0).getData(), list.elements()); } } return unifiedNodeData; @@ -105,8 +114,17 @@ public NetLogicData getUnifiedEdgeData() { } else if (edges.size() == 2) { unifiedEdgeData = NetLogicData.union(edgesList.get(0).getData(), edgesList.get(1).getData()); } else { - unifiedEdgeData = NetLogicData.union(edgesList.get(0).getData(), - edges.stream().skip(1).map(NetEdge::getData).toArray(NetLogicData[]::new)); + ObjectArrayList list = new ObjectArrayList<>(); + boolean first = true; + for (NetEdge edge : edges) { + if (first) { + first = false; + continue; + } + NetLogicData data = edge.getData(); + list.add(data); + } + unifiedEdgeData = NetLogicData.union(edgesList.get(0).getData(), list.elements()); } } return unifiedEdgeData; @@ -176,8 +194,12 @@ public Builder reverse() { @Override public StandardNetPath build() { - return new StandardNetPath(ImmutableSet.copyOf(nodes), ImmutableSet.copyOf(edges), - edges.stream().mapToDouble(NetEdge::getWeight).sum()); + double sum = 0.0; + for (NetEdge edge : edges) { + double edgeWeight = edge.getWeight(); + sum += edgeWeight; + } + return new StandardNetPath(ImmutableSet.copyOf(nodes), ImmutableSet.copyOf(edges), sum); } } } diff --git a/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java index 20de26887cf..d070397709c 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java @@ -87,8 +87,13 @@ public PathFlowReport traverse(final long voltage, final long amperage) { energyFlow = new EnergyFlowLogic(); data.setLogicEntry(energyFlow); } + long sum = 0L; + for (EnergyFlowData energyFlowData : energyFlow.getFlow(tick)) { + long amperaged = energyFlowData.amperage(); + sum += amperaged; + } long correctedAmperage = Math.min(data.getLogicEntryDefaultable(AmperageLimitLogic.TYPE).getValue() - - energyFlow.getFlow(tick).stream().mapToLong(EnergyFlowData::amperage).sum(), resultAmperage); + sum, resultAmperage); EnergyFlowLogic finalEnergyFlow = energyFlow; long finalResultVoltage = resultVoltage; @@ -190,8 +195,13 @@ public Builder reverse() { @Override public StandardEnergyPath build() { + double sum = 0.0; + for (NetEdge edge : edges) { + double edgeWeight = edge.getWeight(); + sum += edgeWeight; + } return new StandardEnergyPath(ImmutableSet.copyOf(nodes), ImmutableSet.copyOf(edges), - edges.stream().mapToDouble(NetEdge::getWeight).sum(), voltageLimitInfo, (long) Math.ceil(loss)); + sum, voltageLimitInfo, (long) Math.ceil(loss)); } } @@ -230,8 +240,12 @@ else if (resultVoltage > voltageLimit) { data.setLogicEntry(energyFlow); } long tick = FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter(); - long resultAmperage = Math.min(amperageLimit - - energyFlow.getFlow(tick).stream().mapToLong(EnergyFlowData::amperage).sum(), amperage); + long sum = 0L; + for (EnergyFlowData energyFlowData : energyFlow.getFlow(tick)) { + long amperaged = energyFlowData.amperage(); + sum += amperaged; + } + long resultAmperage = Math.min(amperageLimit - sum, amperage); EnergyFlowLogic finalEnergyFlow = energyFlow; long finalResultVoltage = resultVoltage; From 559ff499bd31877732224ba10410c7d8027d84c9 Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Sat, 21 Dec 2024 21:44:42 -0700 Subject: [PATCH 154/157] Breakthrough on flood traverse; covers soon.tm --- .../gregtech/api/graphnet/GraphNetBacker.java | 2 +- .../api/graphnet/GraphNetUtility.java | 19 +- .../graphnet/edge/AbstractNetFlowEdge.java | 95 ------ .../graphnet/edge/FlowBufferTickProvider.java | 10 - .../api/graphnet/edge/NetFlowEdge.java | 170 ----------- .../api/graphnet/edge/NetFlowSharedEdge.java | 181 ----------- .../api/graphnet/edge/SimulatorKey.java | 25 -- .../api/graphnet/graph/GraphEdge.java | 2 +- .../api/graphnet/group/GroupData.java | 4 +- .../gregtech/api/graphnet/group/NetGroup.java | 2 +- .../graphnet/group/PathCacheGroupData.java | 2 +- .../gregtech/api/graphnet/net/IGraphNet.java | 1 - .../api/graphnet/{edge => net}/NetEdge.java | 9 +- .../api/graphnet/net/WorldSavedNet.java | 1 - .../gregtech/api/graphnet/path/NetPath.java | 2 +- .../api/graphnet/path/PathBuilder.java | 2 +- .../api/graphnet/path/SingletonNetPath.java | 2 +- .../api/graphnet/path/StandardNetPath.java | 2 +- .../api/graphnet/pipenet/WorldPipeNet.java | 2 +- .../pipenet/physical/block/PipeBlock.java | 6 +- .../physical/block/PipeMaterialBlock.java | 2 +- .../pipenet/physical/tile/PipeTileEntity.java | 18 +- .../traverse/AbstractMinCostTraverse.java | 3 +- .../api/graphnet/traverse/EQTraverse.java | 2 +- .../api/graphnet/traverse/FDTraverse.java | 2 +- .../api/graphnet/traverse/RRTraverse.java | 2 +- .../{graph => traverse}/TweakedCSMCF.java | 5 +- .../graphnet/traverse/iter/EdgeDirection.java | 9 + .../graphnet/traverse/iter/EdgeSelector.java | 23 ++ .../traverse/iter/NetBreadthIterator.java | 2 +- .../traverse/iter/NetClosestIterator.java | 2 +- .../graphnet/traverse/iter/NetIterator.java | 10 +- .../iter/ResilientNetClosestIterator.java | 252 ++++++++++++++++ src/main/java/gregtech/api/util/MapUtil.java | 37 +++ .../java/gregtech/common/CommonProxy.java | 6 +- .../gregtech/common/covers/CoverConveyor.java | 281 ++---------------- .../gregtech/common/covers/CoverPump.java | 50 +--- .../common/covers/CoverRoboticArm.java | 10 +- .../properties/MaterialEnergyProperties.java | 2 +- .../properties/MaterialFluidProperties.java | 23 +- .../properties/MaterialItemProperties.java | 15 +- .../net/energy/StandardEnergyPath.java | 2 +- .../net/fluid/FluidCapabilityObject.java | 260 +++++++++++----- .../pipelike/net/fluid/FluidFlowLogic.java | 46 ++- .../pipelike/net/fluid/WorldFluidNet.java | 9 +- .../net/item/ItemCapabilityObject.java | 119 +++++--- .../pipelike/net/item/ItemFlowLogic.java | 47 ++- .../pipelike/net/item/WorldItemNet.java | 20 +- .../net/optical/DataCapabilityObject.java | 3 +- .../provider/PipeTileInfoProvider.java | 24 +- .../debug/DebugPipeNetInfoProvider.java | 2 +- 51 files changed, 790 insertions(+), 1037 deletions(-) delete mode 100644 src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java delete mode 100644 src/main/java/gregtech/api/graphnet/edge/FlowBufferTickProvider.java delete mode 100644 src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java delete mode 100644 src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java delete mode 100644 src/main/java/gregtech/api/graphnet/edge/SimulatorKey.java rename src/main/java/gregtech/api/graphnet/{edge => net}/NetEdge.java (93%) rename src/main/java/gregtech/api/graphnet/{graph => traverse}/TweakedCSMCF.java (99%) create mode 100644 src/main/java/gregtech/api/graphnet/traverse/iter/ResilientNetClosestIterator.java create mode 100644 src/main/java/gregtech/api/util/MapUtil.java diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index dc80c207b21..a3215188dbf 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -1,12 +1,12 @@ package gregtech.api.graphnet; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.group.MergeDirection; import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.traverse.iter.EdgeDirection; diff --git a/src/main/java/gregtech/api/graphnet/GraphNetUtility.java b/src/main/java/gregtech/api/graphnet/GraphNetUtility.java index c996c41e678..73885bb8220 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetUtility.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetUtility.java @@ -1,18 +1,14 @@ package gregtech.api.graphnet; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.traverse.iter.EdgeDirection; import gregtech.api.graphnet.traverse.iter.EdgeSelector; import gregtech.api.graphnet.traverse.iter.NetClosestIterator; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; -import org.jgrapht.Graph; - -import java.util.Set; public final class GraphNetUtility { @@ -43,17 +39,6 @@ public static EdgeSelector bridgeFiltered(@NotNull EdgeSelector basis, GraphEdge e2 = GraphEdge.unwrap(sourceNode.getNet().getEdge(destNode, sourceNode)); GraphVertex v1 = GraphVertex.unwrap(sourceNode); GraphVertex v2 = GraphVertex.unwrap(destNode); - return new EdgeSelector() { - - @Override - public Set selectEdges(Graph graph, V vertex) { - Set s = basis.selectEdges(graph, vertex); - if (vertex == v1 || vertex == v2) { - s = new ObjectOpenHashSet<>(s); - s.removeIf(e -> e == e1 || e == e2); - } - return s; - } - }; + return null; } } diff --git a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java deleted file mode 100644 index cf89034c41d..00000000000 --- a/src/main/java/gregtech/api/graphnet/edge/AbstractNetFlowEdge.java +++ /dev/null @@ -1,95 +0,0 @@ -package gregtech.api.graphnet.edge; - -import gregtech.api.graphnet.logic.ChannelCountLogic; -import gregtech.api.graphnet.logic.ThroughputLogic; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import org.jetbrains.annotations.Nullable; - -import java.lang.ref.WeakReference; -import java.util.Set; -import java.util.WeakHashMap; - -public abstract class AbstractNetFlowEdge extends NetEdge { - - private final AbstractChannelsHolder channels; - private final WeakHashMap simulatedChannels; - - public AbstractNetFlowEdge() { - this.channels = getNewHolder(null, null); - this.simulatedChannels = new WeakHashMap<>(9); - } - - public boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick, - @Nullable SimulatorKey simulator) { - if (!this.test(channel)) return false; - else return getChannels(simulator).cannotSupportChannel(channel, queryTick); - } - - protected AbstractChannelsHolder getChannels(@Nullable SimulatorKey simulator) { - if (simulator == null) return this.channels; - else { - AbstractChannelsHolder channels = simulatedChannels.get(simulator); - if (channels == null) { - channels = getNewHolder(this.channels, simulator); - simulatedChannels.put(simulator, channels); - } - return channels; - } - } - - protected int getChannelCount() { - return getData().getLogicEntryDefaultable(ChannelCountLogic.TYPE).getValue(); - } - - public long getThroughput() { - return getData().getLogicEntryDefaultable(ThroughputLogic.TYPE).getValue(); - } - - public long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick, - @Nullable SimulatorKey simulator) { - return getChannels(simulator).getFlowLimit(channel, graph, queryTick); - } - - protected long getConsumedLimit(IPredicateTestObject channel, long queryTick, @Nullable SimulatorKey simulator) { - return getChannels(simulator).getConsumedLimit(channel, queryTick); - } - - public void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick, - @Nullable SimulatorKey simulator) { - getChannels(simulator).consumeFlowLimit(channel, graph, amount, queryTick); - } - - public Set getActiveChannels(@Nullable SimulatorKey simulator, long queryTick) { - return getChannels(simulator).getActiveChannels(queryTick); - } - - protected abstract AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, - SimulatorKey simulator); - - protected abstract static class AbstractChannelsHolder { - - private final WeakReference simulator; - - public AbstractChannelsHolder(SimulatorKey simulator) { - this.simulator = new WeakReference<>(simulator); - } - - public SimulatorKey getSimulator() { - return simulator.get(); - } - - abstract void recalculateFlowLimits(long queryTick); - - abstract boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick); - - abstract long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick); - - abstract long getConsumedLimit(IPredicateTestObject channel, long queryTick); - - abstract void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick); - - abstract Set getActiveChannels(long queryTick); - } -} diff --git a/src/main/java/gregtech/api/graphnet/edge/FlowBufferTickProvider.java b/src/main/java/gregtech/api/graphnet/edge/FlowBufferTickProvider.java deleted file mode 100644 index 4fe9fee1c6e..00000000000 --- a/src/main/java/gregtech/api/graphnet/edge/FlowBufferTickProvider.java +++ /dev/null @@ -1,10 +0,0 @@ -package gregtech.api.graphnet.edge; - -public interface FlowBufferTickProvider { - - int getFlowBufferTicks(); - - default int getRegenerationTime() { - return 1; - } -} diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java deleted file mode 100644 index ac67f7926db..00000000000 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowEdge.java +++ /dev/null @@ -1,170 +0,0 @@ -package gregtech.api.graphnet.edge; - -import gregtech.api.GTValues; -import gregtech.api.graphnet.GraphClassType; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Set; - -public class NetFlowEdge extends AbstractNetFlowEdge { - - public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "NetFlowEdge", - n -> n instanceof FlowBufferTickProvider p ? - new NetFlowEdge(p.getFlowBufferTicks(), p.getRegenerationTime()) : new NetFlowEdge(10)); - - private final int flowBufferTicks; - private final int regenerationTime; - - /** - * NetEdge that provides standard flow behavior handling - * - * @param flowBufferTicks Determines how many ticks of 'buffer' flow capacity can be built up along edges. Allows - * for once-an-interval push/pull operations instead of needing them every tick for maximum - * throughput. - */ - public NetFlowEdge(int flowBufferTicks) { - this.flowBufferTicks = Math.max(flowBufferTicks, 1); - this.regenerationTime = 1; - } - - /** - * NetEdge that provides standard flow behavior handling - * - * @param flowBufferMult Determines maximum mult of 'buffer' flow capacity that can be built up along edges. - * Allows for once-an-interval push/pull operations instead of needing them every unit of - * time for maximum throughput. - * @param regenerationTime Ticks required for flow to regenerate once. Allows slowing down the rate of regeneration. - */ - public NetFlowEdge(int flowBufferMult, int regenerationTime) { - this.flowBufferTicks = Math.max(flowBufferMult, 1); - this.regenerationTime = Math.max(regenerationTime, 1); - } - - @Override - protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, - SimulatorKey simulator) { - if (prototype instanceof ChannelsHolder holder) return new ChannelsHolder(holder, simulator); - return new ChannelsHolder(simulator); - } - - @Nullable - private NetFlowEdge getInverse(IGraphNet graph) { - if (getTarget() == null || getSource() == null) return null; - NetEdge edge = graph.getEdge(getTarget(), getSource()); - if (edge instanceof NetFlowEdge i && i != this) { - return i; - } - return null; - } - - private final class ChannelsHolder extends AbstractChannelsHolder { - - private final Object2LongOpenHashMap map; - private long lastQueryTick; - private boolean init; - - public ChannelsHolder(SimulatorKey simulator) { - super(simulator); - this.map = new Object2LongOpenHashMap<>(9); - } - - public ChannelsHolder(ChannelsHolder prototype, SimulatorKey simulator) { - super(simulator); - this.map = prototype.map.clone(); - this.lastQueryTick = prototype.lastQueryTick; - } - - @Override - boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick) { - recalculateFlowLimits(queryTick); - if (map.containsKey(channel)) return map.getLong(channel) <= 0; - else return map.size() >= getChannelCount(); - } - - @Override - long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick) { - if (cannotSupportChannel(channel, queryTick)) return 0; - long limit = map.getLong(channel); - - NetFlowEdge inverse = getInverse(graph); - if (inverse != null) { - if (inverse.cannotSupportChannel(channel, queryTick, getSimulator())) return 0; - limit += inverse.getConsumedLimit(channel, queryTick, getSimulator()); - } - - return limit; - } - - @Override - long getConsumedLimit(IPredicateTestObject channel, long queryTick) { - recalculateFlowLimits(queryTick); - long limit = map.defaultReturnValue(); - return limit - map.getLong(channel); - } - - @Override - void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick) { - if (amount == 0) return; - recalculateFlowLimits(queryTick); - - // check against reverse edge - NetFlowEdge inverse = getInverse(graph); - if (inverse != null) { - long inverseConsumed = inverse.getConsumedLimit(channel, queryTick, getSimulator()); - if (inverseConsumed != 0) { - long toFreeUp = Math.min(inverseConsumed, amount); - inverse.consumeFlowLimit(channel, graph, -toFreeUp, queryTick, getSimulator()); - if (toFreeUp == amount) return; - amount -= toFreeUp; - } - } - - long finalAmount = amount; - map.compute(channel, (k, v) -> { - long d = map.defaultReturnValue(); - if (v == null) v = d; - v -= finalAmount; - if (v >= d) return null; - return v; - }); - } - - @Override - public void recalculateFlowLimits(long queryTick) { - if (!this.init) { - this.map.defaultReturnValue(getThroughput() * flowBufferTicks); - this.init = true; - } - int regenerationUnits = (int) (queryTick - this.lastQueryTick) / regenerationTime; - if (regenerationUnits < 0) { - this.map.clear(); - } else if (regenerationUnits > 0) { - List toRemove = new ObjectArrayList<>(); - this.map.replaceAll((k, v) -> { - v += (long) regenerationUnits * getThroughput(); - if (v >= map.defaultReturnValue()) toRemove.add(k); - return v; - }); - toRemove.forEach(this.map::removeLong); - this.lastQueryTick += (long) regenerationUnits * regenerationTime; - } - } - - @Override - Set getActiveChannels(long queryTick) { - recalculateFlowLimits(queryTick); - return map.keySet(); - } - } - - @Override - public GraphClassType getType() { - return TYPE; - } -} diff --git a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java b/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java deleted file mode 100644 index 2652908b6c7..00000000000 --- a/src/main/java/gregtech/api/graphnet/edge/NetFlowSharedEdge.java +++ /dev/null @@ -1,181 +0,0 @@ -package gregtech.api.graphnet.edge; - -import gregtech.api.GTValues; -import gregtech.api.graphnet.GraphClassType; -import gregtech.api.graphnet.net.IGraphNet; -import gregtech.api.graphnet.predicate.test.IPredicateTestObject; - -import net.minecraft.util.math.MathHelper; - -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Set; - -public class NetFlowSharedEdge extends AbstractNetFlowEdge { - - public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, - "NetFlowSharedEdge", - n -> n instanceof FlowBufferTickProvider p ? - new NetFlowSharedEdge(p.getFlowBufferTicks(), p.getRegenerationTime()) : new NetFlowSharedEdge(10)); - - private final int flowBufferTicks; - private final int regenerationTime; - - /** - * NetEdge that provides flow behavior where the capacity along an edge is shared by all channels. - * - * @param flowBufferTicks Determines how many ticks of 'buffer' flow capacity can be built up along edges. Allows - * for once-an-interval push/pull operations instead of needing them every tick for maximum - * throughput. - */ - public NetFlowSharedEdge(int flowBufferTicks) { - this.flowBufferTicks = Math.max(flowBufferTicks, 1); - this.regenerationTime = 1; - } - - /** - * NetEdge that provides flow behavior where the capacity along an edge is shared by all channels. - * - * @param flowBufferTicks Determines how many ticks of 'buffer' flow capacity can be built up along edges. Allows - * for once-an-interval push/pull operations instead of needing them every tick for maximum - * throughput. - * @param regenerationTime Ticks required for flow to regenerate once. Allows slowing down the rate of regeneration. - */ - public NetFlowSharedEdge(int flowBufferTicks, int regenerationTime) { - this.flowBufferTicks = Math.max(flowBufferTicks, 1); - this.regenerationTime = Math.max(regenerationTime, 1); - } - - @Override - protected AbstractChannelsHolder getNewHolder(AbstractChannelsHolder prototype, - SimulatorKey simulator) { - if (prototype instanceof ChannelsHolder holder) return new ChannelsHolder(holder, simulator); - return new ChannelsHolder(simulator); - } - - @Nullable - private NetFlowSharedEdge getInverse(IGraphNet graph) { - if (getTarget() == null || getSource() == null) return null; - NetEdge edge = graph.getEdge(getTarget(), getSource()); - if (edge instanceof NetFlowSharedEdge i && i != this) { - return i; - } - return null; - } - - private final class ChannelsHolder extends AbstractChannelsHolder { - - private long maxCapacity; - private long sharedCapacity; - private final Object2LongOpenHashMap map; - private long lastQueryTick; - private boolean init; - - public ChannelsHolder(SimulatorKey simulator) { - super(simulator); - this.map = new Object2LongOpenHashMap<>(9); - this.map.defaultReturnValue(0); - } - - public ChannelsHolder(ChannelsHolder prototype, SimulatorKey simulator) { - super(simulator); - this.map = prototype.map.clone(); - this.lastQueryTick = prototype.lastQueryTick; - } - - @Override - public boolean cannotSupportChannel(IPredicateTestObject channel, long queryTick) { - recalculateFlowLimits(queryTick); - if (sharedCapacity <= 0) return true; - else return map.size() >= getChannelCount(); - } - - @Override - long getFlowLimit(IPredicateTestObject channel, IGraphNet graph, long queryTick) { - if (cannotSupportChannel(channel, queryTick)) return 0; - - NetFlowSharedEdge inverse = getInverse(graph); - if (inverse != null) { - if (inverse.cannotSupportChannel(channel, queryTick, getSimulator())) return 0; - return sharedCapacity + inverse.getConsumedLimit(channel, queryTick, getSimulator()); - } else return sharedCapacity; - } - - @Override - long getConsumedLimit(IPredicateTestObject channel, long queryTick) { - recalculateFlowLimits(queryTick); - return map.getLong(channel); - } - - @Override - void consumeFlowLimit(IPredicateTestObject channel, IGraphNet graph, long amount, long queryTick) { - if (amount == 0) return; - recalculateFlowLimits(queryTick); - - // check against reverse edge - NetFlowSharedEdge inverse = getInverse(graph); - if (inverse != null) { - long inverseConsumed = inverse.getConsumedLimit(channel, queryTick, getSimulator()); - if (inverseConsumed != 0) { - long toFreeUp = Math.min(inverseConsumed, amount); - inverse.consumeFlowLimit(channel, graph, -toFreeUp, queryTick, getSimulator()); - if (toFreeUp == amount) return; - amount -= toFreeUp; - } - } - - long finalAmount = amount; - map.compute(channel, (k, v) -> { - if (v == null) v = 0L; - v += finalAmount; - if (v <= 0) return null; - return v; - }); - sharedCapacity -= finalAmount; - boundCapacity(); - } - - @Override - public void recalculateFlowLimits(long queryTick) { - if (!this.init) { - this.maxCapacity = getThroughput() * flowBufferTicks; - this.init = true; - } - int regenerationUnits = (int) (queryTick - this.lastQueryTick) / regenerationTime; - if (regenerationUnits < 0) { - this.map.clear(); - } else { - List toRemove = new ObjectArrayList<>(); - long regenerationPer = MathHelper.ceil((double) regenerationUnits * getThroughput() / map.size()); - map.replaceAll((k, v) -> { - v -= regenerationPer; - if (v <= 0) toRemove.add(k); - return v; - }); - sharedCapacity += regenerationPer * map.size(); - boundCapacity(); - toRemove.forEach(map::removeLong); - this.lastQueryTick += (long) regenerationUnits * regenerationTime; - } - } - - private void boundCapacity() { - if (this.sharedCapacity > this.maxCapacity) this.sharedCapacity = this.maxCapacity; - else if (this.sharedCapacity < 0) this.sharedCapacity = 0; - } - - @Override - Set getActiveChannels(long queryTick) { - recalculateFlowLimits(queryTick); - return map.keySet(); - } - } - - @Override - public GraphClassType getType() { - return TYPE; - } -} diff --git a/src/main/java/gregtech/api/graphnet/edge/SimulatorKey.java b/src/main/java/gregtech/api/graphnet/edge/SimulatorKey.java deleted file mode 100644 index 6d14d29849f..00000000000 --- a/src/main/java/gregtech/api/graphnet/edge/SimulatorKey.java +++ /dev/null @@ -1,25 +0,0 @@ -package gregtech.api.graphnet.edge; - -public final class SimulatorKey { - - private static int ID; - private final int id; - - private SimulatorKey() { - this.id = ID++; - } - - /** - * Claims a new, unique simulator instance for properly simulating flow edge limits without actually changing them. - *
- * This simulator must be discarded after use so that the garbage collector can clean up. - */ - public static SimulatorKey getNewSimulatorInstance() { - return new SimulatorKey(); - } - - @Override - public int hashCode() { - return id; - } -} diff --git a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java index 08b6e9b1c73..56f88a0b1e8 100644 --- a/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java +++ b/src/main/java/gregtech/api/graphnet/graph/GraphEdge.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.graph; -import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.net.NetEdge; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; diff --git a/src/main/java/gregtech/api/graphnet/group/GroupData.java b/src/main/java/gregtech/api/graphnet/group/GroupData.java index 14966bfb461..e24bd086ccd 100644 --- a/src/main/java/gregtech/api/graphnet/group/GroupData.java +++ b/src/main/java/gregtech/api/graphnet/group/GroupData.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.group; -import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -50,7 +50,7 @@ protected boolean mergeAllowed(@Nullable GroupData other) { public static MergeDirection mergeAllowed(@Nullable GroupData source, @Nullable GroupData target) { if (source != null && source.mergeAllowed(target)) return MergeDirection.SOURCE; if (target != null && target.mergeAllowed(source)) return MergeDirection.TARGET; - return MergeDirection.NONE; + return (source == null && target == null) ? MergeDirection.NULL : MergeDirection.NONE; } /** diff --git a/src/main/java/gregtech/api/graphnet/group/NetGroup.java b/src/main/java/gregtech/api/graphnet/group/NetGroup.java index c8812e0257a..118d73eaa37 100644 --- a/src/main/java/gregtech/api/graphnet/group/NetGroup.java +++ b/src/main/java/gregtech/api/graphnet/group/NetGroup.java @@ -1,8 +1,8 @@ package gregtech.api.graphnet.group; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.traverse.iter.EdgeDirection; import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; diff --git a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java index b8b20eb131b..b02f7172217 100644 --- a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java +++ b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.group; -import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.path.PathBuilder; diff --git a/src/main/java/gregtech/api/graphnet/net/IGraphNet.java b/src/main/java/gregtech/api/graphnet/net/IGraphNet.java index b17d676b639..90a0e6d42f3 100644 --- a/src/main/java/gregtech/api/graphnet/net/IGraphNet.java +++ b/src/main/java/gregtech/api/graphnet/net/IGraphNet.java @@ -3,7 +3,6 @@ import gregtech.api.graphnet.GraphClassType; import gregtech.api.graphnet.GraphNetBacker; import gregtech.api.graphnet.MultiNodeHelper; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.logic.NetLogicData; diff --git a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java b/src/main/java/gregtech/api/graphnet/net/NetEdge.java similarity index 93% rename from src/main/java/gregtech/api/graphnet/edge/NetEdge.java rename to src/main/java/gregtech/api/graphnet/net/NetEdge.java index e44691fef92..ce20217a004 100644 --- a/src/main/java/gregtech/api/graphnet/edge/NetEdge.java +++ b/src/main/java/gregtech/api/graphnet/net/NetEdge.java @@ -1,10 +1,9 @@ -package gregtech.api.graphnet.edge; +package gregtech.api.graphnet.net; import gregtech.api.GTValues; import gregtech.api.graphnet.GraphClassType; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.logic.NetLogicData; -import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.predicate.EdgePredicateHandler; import gregtech.api.graphnet.predicate.test.IPredicateTestObject; @@ -17,6 +16,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.function.Predicate; + public class NetEdge implements INBTSerializable { public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "NetEdge", @@ -109,4 +110,8 @@ public void deserializeNBT(NBTTagCompound nbt) { public GraphClassType getType() { return TYPE; } + + public static Predicate standardBlacklist(IPredicateTestObject testObject) { + return o -> o instanceof NetEdge e && !e.test(testObject); + } } diff --git a/src/main/java/gregtech/api/graphnet/net/WorldSavedNet.java b/src/main/java/gregtech/api/graphnet/net/WorldSavedNet.java index 4c9dd204f9c..a75a841eb6b 100644 --- a/src/main/java/gregtech/api/graphnet/net/WorldSavedNet.java +++ b/src/main/java/gregtech/api/graphnet/net/WorldSavedNet.java @@ -1,7 +1,6 @@ package gregtech.api.graphnet.net; import gregtech.api.graphnet.GraphNetBacker; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.graph.NetDirectedGraph; import gregtech.api.graphnet.graph.NetUndirectedGraph; diff --git a/src/main/java/gregtech/api/graphnet/path/NetPath.java b/src/main/java/gregtech/api/graphnet/path/NetPath.java index 476cf2c3afb..d74ce6f2875 100644 --- a/src/main/java/gregtech/api/graphnet/path/NetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/NetPath.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import com.google.common.collect.ImmutableCollection; diff --git a/src/main/java/gregtech/api/graphnet/path/PathBuilder.java b/src/main/java/gregtech/api/graphnet/path/PathBuilder.java index c5c1f81371b..5e9956bd2de 100644 --- a/src/main/java/gregtech/api/graphnet/path/PathBuilder.java +++ b/src/main/java/gregtech/api/graphnet/path/PathBuilder.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.Contract; diff --git a/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java b/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java index 7828fd498ca..0d12ac2fa56 100644 --- a/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/SingletonNetPath.java @@ -1,8 +1,8 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import com.google.common.collect.ImmutableCollection; diff --git a/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java b/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java index 336ffae97e3..9c769e0d786 100644 --- a/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java +++ b/src/main/java/gregtech/api/graphnet/path/StandardNetPath.java @@ -1,7 +1,7 @@ package gregtech.api.graphnet.path; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.logic.NetLogicData; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import com.google.common.collect.ImmutableCollection; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index b0d7c376928..884e8b138b9 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -4,9 +4,9 @@ import gregtech.api.cover.CoverableView; import gregtech.api.graphnet.GraphClassType; import gregtech.api.graphnet.MultiNodeHelper; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.INetGraph; import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.net.WorldSavedNet; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java index 26d7b68eea7..ba1c0238772 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeBlock.java @@ -129,7 +129,7 @@ public void doPlacementLogic(PipeTileEntity tile, EnumFacing placedBlockSearchSi connectTile(tile, null, facing); } // second check -- connect to matching mark pipes if side matches or config allows. - else if (tile.getPaintingColor() == other.getPaintingColor() && (facing == placedBlockSearchSide || + else if (tile.getPaintedColor() == other.getPaintedColor() && (facing == placedBlockSearchSide || !ConfigHolder.machines.gt6StylePipesCables)) { if (coverCheck(tile, other, facing)) connectTile(tile, other, facing); } @@ -446,7 +446,7 @@ public boolean recolorBlock(@NotNull World world, @NotNull BlockPos pos, @NotNul @NotNull EnumDyeColor color) { if (getStructure().isPaintable()) { PipeTileEntity tile = getTileEntity(world, pos); - if (tile != null && tile.getPaintingColor() != color.colorValue) { + if (tile != null && tile.getVisualColor() != color.colorValue) { tile.setPaintingColor(color.colorValue, false); return true; } @@ -463,7 +463,7 @@ public boolean canRenderInLayer(@NotNull IBlockState state, @NotNull BlockRender protected Pair getParticleTexture(World world, BlockPos blockPos) { PipeTileEntity tile = getTileEntity(world, blockPos); if (tile != null) { - return getStructure().getModel().getParticleTexture(tile.getPaintingColor(), null); + return getStructure().getModel().getParticleTexture(tile.getVisualColor(), null); } return null; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java index 80e8557e9a2..411a74092e5 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/block/PipeMaterialBlock.java @@ -128,7 +128,7 @@ public Class getTileClass(@NotNull World world protected Pair getParticleTexture(World world, BlockPos blockPos) { PipeMaterialTileEntity tile = getTileEntity(world, blockPos); if (tile != null) { - return getStructure().getModel().getParticleTexture(tile.getPaintingColor(), tile.getMaterial()); + return getStructure().getModel().getParticleTexture(tile.getVisualColor(), tile.getMaterial()); } return null; } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index a365016b4be..a684f20d871 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -191,6 +191,15 @@ public boolean isConnectedCoverAdjusted(EnumFacing facing) { (cover = getCoverHolder().getCoverAtSide(facing)) != null && cover.forcePipeRenderConnection(); } + public void setRenderClosed(EnumFacing facing, boolean closed) { + if (closed) { + this.renderMask |= 1 << facing.ordinal(); + } else { + this.renderMask &= ~(1 << facing.ordinal()); + } + syncConnected(); + } + public boolean renderClosed(EnumFacing facing) { return (this.renderMask & 1 << facing.ordinal()) > 0; } @@ -237,7 +246,11 @@ public byte getBlockedMask() { // paint // - public int getPaintingColor() { + public int getPaintedColor() { + return paintingColor; + } + + public int getVisualColor() { return isPainted() ? paintingColor : getDefaultPaintingColor(); } @@ -388,6 +401,7 @@ public void updateActiveStatus(@Nullable EnumFacing facing, boolean canOpenConne TileEntity tile = getNeighbor(facing); if (tile == null || tile instanceof PipeTileEntity) { + if (tile == null) setRenderClosed(facing, false); setAllIdle(facing); return; } @@ -747,7 +761,7 @@ public IExtendedBlockState getRenderInformation(IExtendedBlockState state) { return state.withProperty(AbstractPipeModel.THICKNESS_PROPERTY, this.getStructure().getRenderThickness()) .withProperty(AbstractPipeModel.CLOSED_MASK_PROPERTY, renderMask) .withProperty(AbstractPipeModel.BLOCKED_MASK_PROPERTY, blockedMask) - .withProperty(AbstractPipeModel.COLOR_PROPERTY, getPaintingColor()) + .withProperty(AbstractPipeModel.COLOR_PROPERTY, getVisualColor()) .withProperty(AbstractPipeModel.FRAME_MATERIAL_PROPERTY, frameMaterial) .withProperty(AbstractPipeModel.FRAME_MASK_PROPERTY, frameMask) .withProperty(CoverRendererPackage.PROPERTY, getCoverHolder().createPackage()); diff --git a/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java index 42f54fb1a24..e18414a065e 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java @@ -1,9 +1,8 @@ package gregtech.api.graphnet.traverse; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.graph.TweakedCSMCF; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.util.GTUtility; diff --git a/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java index 52afd63e029..4d89679826b 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java @@ -1,9 +1,9 @@ package gregtech.api.graphnet.traverse; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.group.NetGroup; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.util.GTUtility; diff --git a/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java index 339c8b6c01d..81b66a355da 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java @@ -1,9 +1,9 @@ package gregtech.api.graphnet.traverse; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.group.NetGroup; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java index c0f299dbd61..1fe6176af39 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java +++ b/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java @@ -1,9 +1,9 @@ package gregtech.api.graphnet.traverse; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.group.NetGroup; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/graph/TweakedCSMCF.java b/src/main/java/gregtech/api/graphnet/traverse/TweakedCSMCF.java similarity index 99% rename from src/main/java/gregtech/api/graphnet/graph/TweakedCSMCF.java rename to src/main/java/gregtech/api/graphnet/traverse/TweakedCSMCF.java index 7ad785cb1c9..acadfd5a276 100644 --- a/src/main/java/gregtech/api/graphnet/graph/TweakedCSMCF.java +++ b/src/main/java/gregtech/api/graphnet/traverse/TweakedCSMCF.java @@ -1,4 +1,7 @@ -package gregtech.api.graphnet.graph; +package gregtech.api.graphnet.traverse; + +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; import org.jgrapht.Graph; import org.jgrapht.alg.flow.mincost.CapacityScalingMinimumCostFlow; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java index c32254598d3..c798fbc042e 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java @@ -18,4 +18,13 @@ public Set selectEdges(Graph graph, V vertex) { case OUTGOING -> graph.outgoingEdgesOf(vertex); }; } + + @Override + public Set selectReversedEdges(Graph graph, V vertex) { + return switch (this) { + case ALL -> graph.edgesOf(vertex); + case OUTGOING -> graph.incomingEdgesOf(vertex); + case INCOMING -> graph.outgoingEdgesOf(vertex); + }; + } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java index 0841a5f4f21..7cf07519d32 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java @@ -1,10 +1,33 @@ package gregtech.api.graphnet.traverse.iter; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jgrapht.Graph; import java.util.Set; +import java.util.function.Predicate; public interface EdgeSelector { Set selectEdges(Graph graph, V vertex); + + Set selectReversedEdges(Graph graph, V vertex); + + static EdgeSelector filtered(EdgeSelector basis, Predicate blacklist) { + return new EdgeSelector() { + + @Override + public Set selectEdges(Graph graph, V vertex) { + Set set = new ObjectOpenHashSet<>(basis.selectEdges(graph, vertex)); + set.removeIf(blacklist); + return set; + } + + @Override + public Set selectReversedEdges(Graph graph, V vertex) { + Set set = new ObjectOpenHashSet<>(basis.selectReversedEdges(graph, vertex)); + set.removeIf(blacklist); + return set; + } + }; + } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java index 2e98bbe71c2..dc61f0f085a 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java @@ -1,9 +1,9 @@ package gregtech.api.graphnet.traverse.iter; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java index 8a5fbf94155..c2cad5be484 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java @@ -1,8 +1,8 @@ package gregtech.api.graphnet.traverse.iter; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java index 1c5dcca4dad..758322731a9 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java @@ -1,6 +1,6 @@ package gregtech.api.graphnet.traverse.iter; -import gregtech.api.graphnet.edge.NetEdge; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import org.jetbrains.annotations.NotNull; @@ -10,8 +10,16 @@ public interface NetIterator extends Iterator { + /** + * @param node the node in question. + * @return Whether this iterator has encountered the node in question. + */ boolean hasSeen(@NotNull NetNode node); + /** + * @param node the node in question. + * @return the next edge along the lowest weight path to the origin node for the node in question. + */ @Nullable NetEdge getSpanningTreeEdge(@NotNull NetNode node); } diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/ResilientNetClosestIterator.java b/src/main/java/gregtech/api/graphnet/traverse/iter/ResilientNetClosestIterator.java new file mode 100644 index 00000000000..900449d0862 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/traverse/iter/ResilientNetClosestIterator.java @@ -0,0 +1,252 @@ +package gregtech.api.graphnet.traverse.iter; + +import gregtech.api.graphnet.graph.GraphEdge; +import gregtech.api.graphnet.graph.GraphVertex; +import gregtech.api.graphnet.net.NetEdge; +import gregtech.api.graphnet.net.NetNode; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jgrapht.Graph; +import org.jgrapht.traverse.ClosestFirstIterator; +import org.jgrapht.traverse.CrossComponentIterator; +import org.jheaps.AddressableHeap; +import org.jheaps.tree.PairingHeap; + +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.function.Consumer; + +/** + * A specialized net closest iterator that allows nodes to be marked invalid for iteration retroactively, + * without requiring a new iterator to be declared, leading to its resilience. + */ +public class ResilientNetClosestIterator implements NetIterator { + + protected final @NotNull InternalIterator internal; + + public ResilientNetClosestIterator(@NotNull NetNode origin, @NotNull EdgeSelector selector) { + internal = new InternalIterator(origin.getNet().getGraph(), origin.wrapper, selector, + origin.getGroupSafe().getNodes().size()); + } + + public ResilientNetClosestIterator(@NotNull NetNode origin, @NotNull EdgeSelector selector, double radius) { + internal = new InternalIterator(origin.getNet().getGraph(), origin.wrapper, selector, + origin.getGroupSafe().getNodes().size(), radius); + } + + /** + * Marks a node as no longer valid for traversal. When applied to a node with children, the entire "branch" of the + * seen "tree" will be cut off, and previous inferior connections to the branch will be considered again, allowing + * further iteration to potentially revisit nodes within the removed "branch". + * + * @param node the node to mark invalid + * @return this object, for convenience. + */ + @Contract("_->this") + public ResilientNetClosestIterator markInvalid(@NotNull NetNode node) { + if (node.wrapper != null) internal.invalidate(node.wrapper); + return this; + } + + @Override + public boolean hasSeen(@NotNull NetNode node) { + return internal.seen.containsKey(node.wrapper); + } + + @Override + public @Nullable NetEdge getSpanningTreeEdge(@NotNull NetNode node) { + return NetEdge.unwrap(internal.getSpanningTreeEdge(node.wrapper)); + } + + @Override + public boolean hasNext() { + return internal.hasNext(); + } + + @Override + public NetNode next() { + return internal.next().getWrapped(); + } + + /** + * See {@link ClosestFirstIterator} and {@link CrossComponentIterator} + */ + protected static final class InternalIterator implements Iterator { + + public final Graph graph; + + public final EdgeSelector selector; + + public final AddressableHeap heap; + + public final Map> seen; + + public final double radius; + + public final Set invalidated = new ObjectOpenHashSet<>(); + + public InternalIterator(Graph graph, GraphVertex startVertex, EdgeSelector selector, + int expectedSize) { + this(graph, startVertex, selector, expectedSize, Double.POSITIVE_INFINITY); + } + + public InternalIterator(Graph graph, GraphVertex startVertex, EdgeSelector selector, + int expectedSize, double radius) { + this.graph = graph; + this.selector = selector; + this.radius = radius; + this.heap = new PairingHeap<>(); + this.seen = new Object2ObjectOpenHashMap<>(expectedSize); + encounterVertexFirst(startVertex, null); + } + + @Override + public boolean hasNext() { + return !isConnectedComponentExhausted(); + } + + @Override + public GraphVertex next() { + if (hasNext()) { + AddressableHeap.Handle node; + do { + node = heap.deleteMin(); + node.getValue().foundMinimum = true; + } while (node.getValue().outdated && hasNext()); + + addUnseenChildrenOf(node.getValue().vertex); + return node.getValue().vertex; + } else { + throw new NoSuchElementException(); + } + } + + private void addUnseenChildrenOf(GraphVertex vertex) { + for (GraphEdge edge : selector.selectEdges(graph, vertex)) { + + GraphVertex oppositeV = edge.getOppositeVertex(vertex); + encounterVertex(oppositeV, edge); + } + } + + public void invalidate(GraphVertex vertex) { + if (!invalidated.add(vertex)) return; + AddressableHeap.Handle handle = seen.get(vertex); + if (handle != null) { + Set regenerationCandidates = new ObjectOpenHashSet<>(); + handle.getValue().applySelfAndChildren(c -> { + seen.remove(c.vertex); + c.outdated = true; + regenerationCandidates.addAll(selector.selectReversedEdges(graph, c.vertex)); + }); + for (GraphEdge candidate : regenerationCandidates) { + if (seen.containsKey(candidate.getSource())) { + encounterVertex(candidate.getTarget(), candidate); + } else if (seen.containsKey(candidate.getTarget())) { + encounterVertex(candidate.getSource(), candidate); + } + } + } + } + + public GraphEdge getSpanningTreeEdge(GraphVertex vertex) { + AddressableHeap.Handle node = seen.get(vertex); + return node == null ? null : node.getValue().spanningTreeEdge; + } + + private boolean isConnectedComponentExhausted() { + if (heap.size() == 0) { + return true; + } else { + if (heap.findMin().getKey() > radius) { + heap.clear(); + return true; + } else { + return false; + } + } + } + + private void encounterVertex(GraphVertex vertex, GraphEdge edge) { + if (invalidated.contains(vertex)) return; + if (seen.containsKey(vertex)) { + encounterVertexAgain(vertex, edge); + } else { + encounterVertexFirst(vertex, edge); + } + } + + private void encounterVertexFirst(GraphVertex vertex, GraphEdge edge) { + double shortestPathLength; + SeenData data; + if (edge == null) { + shortestPathLength = 0; + data = new SeenData(vertex, null, null); + } else { + GraphVertex otherVertex = edge.getOppositeVertex(vertex); + AddressableHeap.Handle otherEntry = seen.get(otherVertex); + if (otherEntry == null) return; + shortestPathLength = otherEntry.getKey() + graph.getEdgeWeight(edge); + + data = new SeenData(vertex, edge, otherEntry.getValue()); + otherEntry.getValue().spanningChildren.add(data); + } + AddressableHeap.Handle handle = heap.insert(shortestPathLength, data); + seen.put(vertex, handle); + } + + private void encounterVertexAgain(GraphVertex vertex, GraphEdge edge) { + AddressableHeap.Handle node = seen.get(vertex); + + if (node.getValue().foundMinimum) { + // no improvement for this vertex possible + return; + } + GraphVertex otherVertex = edge.getOppositeVertex(vertex); + AddressableHeap.Handle otherEntry = seen.get(otherVertex); + + double candidatePathLength = otherEntry.getKey() + graph.getEdgeWeight(edge); + if (candidatePathLength < node.getKey()) { + node.getValue().parent = otherEntry.getValue(); + node.getValue().spanningTreeEdge = edge; + node.decreaseKey(candidatePathLength); + } + } + } + + protected static final class SeenData { + + public final GraphVertex vertex; + + // the next edge along the lowest weight path to the origin node + public GraphEdge spanningTreeEdge; + + public SeenData parent; + + public boolean foundMinimum = false; + + public boolean outdated = false; + + // all nodes whose spanning tree edges point at this node + public final Set spanningChildren = new ObjectOpenHashSet<>(6); + + public SeenData(GraphVertex vertex, GraphEdge spanningTreeEdge, SeenData parent) { + this.vertex = vertex; + this.spanningTreeEdge = spanningTreeEdge; + this.parent = parent; + } + + public void applySelfAndChildren(Consumer c) { + c.accept(this); + for (SeenData data : spanningChildren) { + data.applySelfAndChildren(c); + } + } + } +} diff --git a/src/main/java/gregtech/api/util/MapUtil.java b/src/main/java/gregtech/api/util/MapUtil.java new file mode 100644 index 00000000000..c1f15a617dc --- /dev/null +++ b/src/main/java/gregtech/api/util/MapUtil.java @@ -0,0 +1,37 @@ +package gregtech.api.util; + +import gregtech.api.graphnet.net.NetNode; + +import it.unimi.dsi.fastutil.objects.Object2BooleanMap; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Predicate; +import java.util.function.ToIntFunction; + +public class MapUtil { + + public static int computeIfAbsent(@NotNull Object2IntMap map, @NotNull NetNode key, + @NotNull ToIntFunction compute) { + int val; + if (map.containsKey(key)) { + val = map.getInt(key); + } else { + val = compute.applyAsInt(key); + map.put(key, val); + } + return val; + } + + public static boolean computeIfAbsent(@NotNull Object2BooleanMap map, @NotNull NetNode key, + @NotNull Predicate compute) { + boolean val; + if (map.containsKey(key)) { + val = map.getBoolean(key); + } else { + val = compute.test(key); + map.put(key, val); + } + return val; + } +} diff --git a/src/main/java/gregtech/common/CommonProxy.java b/src/main/java/gregtech/common/CommonProxy.java index fbfeccab803..8108222b9c7 100644 --- a/src/main/java/gregtech/common/CommonProxy.java +++ b/src/main/java/gregtech/common/CommonProxy.java @@ -5,15 +5,13 @@ import gregtech.api.block.VariantItemBlock; import gregtech.api.block.machines.MachineItemBlock; import gregtech.api.graphnet.GraphClassRegistrationEvent; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.NetFlowEdge; -import gregtech.api.graphnet.edge.NetFlowSharedEdge; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.NetLogicRegistrationEvent; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.logic.WeightFactorLogic; import gregtech.api.graphnet.net.BlankNetNode; import gregtech.api.graphnet.net.BlockPosNode; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.pipenet.WorldPipeCapConnectionNode; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.logic.TemperatureLogic; @@ -420,8 +418,6 @@ public static void registerNetLogics(NetLogicRegistrationEvent event) { @SubscribeEvent public static void registerGraphClasses(GraphClassRegistrationEvent event) { event.accept(NetEdge.TYPE); - event.accept(NetFlowEdge.TYPE); - event.accept(NetFlowSharedEdge.TYPE); event.accept(WorldPipeNode.TYPE); event.accept(WorldPipeCapConnectionNode.TYPE); event.accept(BlockPosNode.TYPE); diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 461dfd07d55..9431d684446 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -4,32 +4,16 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; import gregtech.api.capability.impl.ItemHandlerDelegate; -import gregtech.api.capability.impl.ItemHandlerList; import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; -import gregtech.api.graphnet.GraphNetUtility; -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.SimulatorKey; -import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; -import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; -import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.traverse.RoundRobinCache; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverse.EQTraverse; -import gregtech.api.graphnet.traverse.FDTraverse; -import gregtech.api.graphnet.traverse.RRTraverse; -import gregtech.api.graphnet.traverse.iter.EdgeDirection; -import gregtech.api.graphnet.traverse.iter.NetClosestIterator; -import gregtech.api.graphnet.traverse.iter.NetIterator; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; -import gregtech.api.util.GTUtility; import gregtech.api.util.ItemStackHashStrategy; import gregtech.api.util.function.BiIntConsumer; import gregtech.client.renderer.pipe.cover.CoverRenderer; @@ -87,7 +71,6 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -244,237 +227,12 @@ protected void performTransferOnUpdate(@NotNull IItemHandler sourceHandler, @Not protected int performTransfer(@NotNull IItemHandler sourceHandler, @NotNull IItemHandler destHandler, boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { - // if the source handler or the dest handler is a pipe, perform a pipenet transfer. Otherwise, do a simple one. - if (sourceHandler instanceof ItemCapabilityObject s) { - if (destHandler instanceof ItemCapabilityObject d) { - return transferWithinNet(s.getNode(), d.getNode(), byFilterSlot, minTransfer, maxTransfer, - transferReport); - } else { - PipeCapabilityWrapper wrapper = s.getNode().getTileEntity().getWrapperForNode(s.getNode()); - if (wrapper instanceof NodeManagingPCW managingPCW) { - // if export, we know we're on the pipe; otherwise, we're on the tile. - EnumFacing facing = conveyorMode == ConveyorMode.EXPORT ? getAttachedSide() : - getAttachedSide().getOpposite(); - NetNode node = managingPCW.getNodeForFacing(facing); - if (node == null) return 0; - return transferWithinNet(s.getNode(), node, byFilterSlot, minTransfer, maxTransfer, transferReport); - } - return 0; - } - } else { - if (destHandler instanceof ItemCapabilityObject d) { - PipeCapabilityWrapper wrapper = d.getNode().getTileEntity().getWrapperForNode(d.getNode()); - if (wrapper instanceof NodeManagingPCW managingPCW) { - // if import, we know we're on the pipe; otherwise, we're on the tile. - EnumFacing facing = conveyorMode == ConveyorMode.IMPORT ? getAttachedSide() : - getAttachedSide().getOpposite(); - NetNode node = managingPCW.getNodeForFacing(facing); - if (node == null) return 0; - return transferWithinNet(node, d.getNode(), byFilterSlot, minTransfer, maxTransfer, transferReport); - } - return 0; - } else { - return simpleTransfer(sourceHandler, destHandler, byFilterSlot, minTransfer, maxTransfer, - transferReport); - } - } - } - - protected RoundRobinCache getRoundRobinCache(boolean simulate) { - return simulate ? roundRobinCache.copy() : roundRobinCache; - } - - /** - * Performs transfer between two nodes of a pipenet. - * - * @param sourceNode the node to pull from - * @param destNode the node to push to - * @param byFilterSlot whether to perform the transfer by filter slot. - * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. - * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. - * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. - * Each filter slot will report its transfer before the next slot is calculated. - * @return how much was transferred in total. - */ - protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode destNode, - boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, - @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { - // first, evaluate whether we're the only bridge between two areas in a group - NetEdge bridge = sourceNode.getNet().getEdge(sourceNode, destNode); - if (bridge == null || !GraphNetUtility.isOnlyBridge(bridge)) return 0; - // second, build frontier information. If we have no candidates for either frontier, exit early. - NetClosestIterator sourceFrontier = new NetClosestIterator(sourceNode, - GraphNetUtility.bridgeFiltered(EdgeDirection.INCOMING, sourceNode, destNode)); - Map sourceCandidates = new Object2ObjectOpenHashMap<>(); - while (sourceFrontier.hasNext()) { - NetNode next = sourceFrontier.next(); - if (next instanceof NodeExposingCapabilities cap) { - IItemHandler handler = cap.getProvider() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, cap.exposedFacing()); - if (handler != null && !(handler instanceof ItemCapabilityObject)) - sourceCandidates.put(next, handler); - } - } - if (sourceCandidates.isEmpty()) return 0; - NetClosestIterator destFrontier = new NetClosestIterator(destNode, - GraphNetUtility.bridgeFiltered(EdgeDirection.OUTGOING, sourceNode, destNode)); - Map destinationCandidates = new Object2ObjectOpenHashMap<>(); - while (destFrontier.hasNext()) { - NetNode next = destFrontier.next(); - if (next instanceof NodeExposingCapabilities cap) { - IItemHandler handler = cap.getProvider() - .getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, cap.exposedFacing()); - if (handler != null && !(handler instanceof ItemCapabilityObject)) - destinationCandidates.put(next, handler); - } - } - if (destinationCandidates.isEmpty()) return 0; - // third, build merge information from source candidates ItemFilterContainer filter = this.getItemFilter(); byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter - Int2IntArrayMap extractableByFilterSlot = new Int2IntArrayMap(); - Int2ObjectArrayMap> filterSlotToMergability = new Int2ObjectArrayMap<>(); - ItemHandlerList handlerSourceCandidates = new ItemHandlerList(sourceCandidates.values()); - for (int i = 0; i < handlerSourceCandidates.getSlots(); i++) { - ItemStack stack = handlerSourceCandidates.extractItem(i, Integer.MAX_VALUE, true); - int extracted = stack.getCount(); - if (extracted == 0) continue; - MatchResult match = null; - if (filter == null || (match = filter.match(stack)).isMatched()) { - int filterSlot = -1; - if (byFilterSlot) { - filterSlot = match.getFilterIndex(); - } - extractableByFilterSlot.merge(filterSlot, extracted, Integer::sum); - final int handlerSlot = i; - filterSlotToMergability.compute(filterSlot, (k, v) -> { - if (v == null) v = new MergabilityInfo<>(); - v.add(handlerSlot, new ItemTestObject(stack), extracted); - return v; - }); - } - } - var iter = extractableByFilterSlot.int2IntEntrySet().fastIterator(); - int totalTransfer = 0; - // fourth, perform transfer based on merge information - while (iter.hasNext()) { - var next = iter.next(); - int filterSlot = next.getIntKey(); - int min = minTransfer.applyAsInt(filterSlot); - int max = maxTransfer.applyAsInt(filterSlot); - if (max < min || max <= 0) continue; - if (next.getIntValue() >= min) { - MergabilityInfo mergabilityInfo = filterSlotToMergability.get(filterSlot); - MergabilityInfo.Merge merge = mergabilityInfo.getLargestMerge(); - // since we can't guarantee the transferability of multiple stack types while just simulating, - // if the largest merge is not large enough we have to give up. - if (merge.getCount() >= min) { - int slotTransfer = 0; - int transfer = Math.min(merge.getCount(), max); - // only simulate to test min if necessary - if (min > 0) { - transfer = attemptNetTransfer(sourceNode.getGroupSafe(), bridge, transfer, - merge.getTestObject(), - sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, - SimulatorKey.getNewSimulatorInstance()); - if (transfer < min) continue; - } - transfer = attemptNetTransfer(sourceNode.getGroupSafe(), bridge, transfer, merge.getTestObject(), - sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, null); - int remaining = max - transfer; - slotTransfer += transfer; - if (remaining <= 0) continue; - for (MergabilityInfo.Merge otherMerge : mergabilityInfo - .getNonLargestMerges(merge)) { - transfer = Math.min(otherMerge.getCount(), remaining); - // we don't have to simulate here since we no longer need to respect the min - transfer = attemptNetTransfer(sourceNode.getGroupSafe(), bridge, transfer, - merge.getTestObject(), - sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, null); - remaining -= transfer; - slotTransfer += transfer; - if (remaining <= 0) break; - } - if (transferReport != null) transferReport.accept(filterSlot, slotTransfer); - totalTransfer += slotTransfer; - } - } - } - return totalTransfer; - } - - protected int attemptNetTransfer(NetGroup group, NetEdge bridge, int limit, ItemTestObject testObject, - NetIterator sources, Map sourceCandidates, - NetIterator targets, Map destCandidates, - @Nullable SimulatorKey key) { - return switch (distributionMode) { - case FLOOD -> FDTraverse.flood(group, - (n, f) -> { - if (key == null) ItemCapabilityObject.reportFlow(n, f, testObject); - }, - (e, f) -> ItemCapabilityObject.reportFlow(e, f, testObject, key, true), - e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt( - n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : - 0, - n -> getSupply(n, testObject, sources.hasSeen(n)), null, null); - case EQUALIZED -> EQTraverse.equalDistribution(group, - (n, f) -> { - if (key == null) ItemCapabilityObject.reportFlow(n, f, testObject); - }, - (e, f) -> ItemCapabilityObject.reportFlow(e, f, testObject, key, true), - e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt( - n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : - 0, - n -> getSupply(n, testObject, sources.hasSeen(n)), null, null); - case ROUND_ROBIN -> { - roundRobinCache.refresh(sources, targets); - yield RRTraverse.roundRobin(group, getRoundRobinCache(key != null) - .buildSupplier(sourceCandidates.keySet(), destCandidates.keySet()), - (n, f) -> { - if (key == null) ItemCapabilityObject.reportFlow(n, f, testObject); - }, - (e, f) -> ItemCapabilityObject.reportFlow(e, f, testObject, key, true), - e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt( - n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : - 0, - n -> getSupply(n, testObject, sources.hasSeen(n)), - null, null); - } - }; - } - - protected int getSupply(NetNode node, ItemTestObject testObject, boolean supply) { - return ItemCapabilityObject.getSupply(node, testObject, supply); - } - - /** - * Performs transfer without involving the pipenet - * - * @param sourceHandler the handler to pull from - * @param destHandler the handler to push to - * @param byFilterSlot whether to perform the transfer by filter slot. - * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. - * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. - * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. - * Each filter slot will report its transfer before the next slot is calculated. - * @return how much was transferred in total. - */ - protected int simpleTransfer(@NotNull IItemHandler sourceHandler, @NotNull IItemHandler destHandler, - boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, - @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { - ItemFilterContainer filter = this.getItemFilter(); - byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter - Int2IntArrayMap extractableByFilterSlot = new Int2IntArrayMap(); + Int2IntArrayMap containedByFilterSlot = new Int2IntArrayMap(); Int2ObjectArrayMap> filterSlotToMergability = new Int2ObjectArrayMap<>(); for (int i = 0; i < sourceHandler.getSlots(); i++) { - ItemStack stack = sourceHandler.extractItem(i, Integer.MAX_VALUE, true); + ItemStack stack = sourceHandler.getStackInSlot(i); int extracted = stack.getCount(); if (extracted == 0) continue; MatchResult match = null; @@ -483,7 +241,7 @@ protected int simpleTransfer(@NotNull IItemHandler sourceHandler, @NotNull IItem if (byFilterSlot) { filterSlot = match.getFilterIndex(); } - extractableByFilterSlot.merge(filterSlot, extracted, Integer::sum); + containedByFilterSlot.merge(filterSlot, extracted, Integer::sum); final int handlerSlot = i; filterSlotToMergability.compute(filterSlot, (k, v) -> { if (v == null) v = new MergabilityInfo<>(); @@ -492,7 +250,7 @@ protected int simpleTransfer(@NotNull IItemHandler sourceHandler, @NotNull IItem }); } } - var iter = extractableByFilterSlot.int2IntEntrySet().fastIterator(); + var iter = containedByFilterSlot.int2IntEntrySet().fastIterator(); int totalTransfer = 0; while (iter.hasNext()) { var next = iter.next(); @@ -508,27 +266,27 @@ protected int simpleTransfer(@NotNull IItemHandler sourceHandler, @NotNull IItem // if the largest merge is not large enough we have to give up. if (merge.getCount() >= min) { int transfer = Math.min(merge.getCount(), max); - transfer = simpleInsert(destHandler, merge.getTestObject(), transfer, true); + transfer = doInsert(destHandler, merge.getTestObject(), transfer, true); if (transfer < min) continue; int toExtract = transfer; for (int handlerSlot : merge.getHandlerSlots()) { toExtract -= sourceHandler.extractItem(handlerSlot, toExtract, false).getCount(); if (toExtract == 0) break; } - simpleInsert(destHandler, merge.getTestObject(), transfer - toExtract, false); + doInsert(destHandler, merge.getTestObject(), transfer - toExtract, false); int remaining = max - transfer + toExtract; slotTransfer += transfer; if (remaining <= 0) continue; for (MergabilityInfo.Merge otherMerge : mergabilityInfo .getNonLargestMerges(merge)) { transfer = Math.min(otherMerge.getCount(), remaining); - transfer = simpleInsert(destHandler, merge.getTestObject(), transfer, true); + transfer = doInsert(destHandler, merge.getTestObject(), transfer, true); toExtract = transfer; for (int handlerSlot : otherMerge.getHandlerSlots()) { toExtract -= sourceHandler.extractItem(handlerSlot, toExtract, false).getCount(); if (toExtract == 0) break; } - simpleInsert(destHandler, otherMerge.getTestObject(), transfer - toExtract, false); + doInsert(destHandler, otherMerge.getTestObject(), transfer - toExtract, false); remaining -= transfer; slotTransfer += transfer; if (remaining <= 0) break; @@ -541,12 +299,27 @@ protected int simpleTransfer(@NotNull IItemHandler sourceHandler, @NotNull IItem return totalTransfer; } - protected int simpleInsert(@NotNull IItemHandler destHandler, ItemTestObject testObject, int count, + protected RoundRobinCache getRoundRobinCache(boolean simulate) { + return simulate ? roundRobinCache.copy() : roundRobinCache; + } + + protected int getSupplyOrDemand(NetNode node, ItemTestObject testObject, boolean supply) { + return ItemCapabilityObject.getSupplyOrDemand(node, testObject, supply); + } + + protected int doExtract(@NotNull IItemHandler handler, ItemTestObject testObject, int count, boolean simulate) {} + + protected int simpleExtract(@NotNull IItemHandler handler, ItemTestObject testObject, int count, + boolean simulate) {} + + protected int doInsert(@NotNull IItemHandler handler, ItemTestObject testObject, int count, boolean simulate) {} + + protected int simpleInsert(@NotNull IItemHandler handler, ItemTestObject testObject, int count, boolean simulate) { int available = count; - for (int i = 0; i < destHandler.getSlots(); i++) { - ItemStack toInsert = testObject.recombine(Math.min(available, destHandler.getSlotLimit(i))); - available -= toInsert.getCount() - destHandler.insertItem(i, toInsert, simulate).getCount(); + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack toInsert = testObject.recombine(Math.min(available, handler.getSlotLimit(i))); + available -= toInsert.getCount() - handler.insertItem(i, toInsert, simulate).getCount(); if (available == 0) return count; } return count - available; diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index 7e34363c204..f7a40246eea 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -10,25 +10,19 @@ import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithFluidFilter; import gregtech.api.graphnet.GraphNetUtility; -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.group.NetGroup; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.traverse.RoundRobinCache; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverse.EQTraverse; -import gregtech.api.graphnet.traverse.FDTraverse; -import gregtech.api.graphnet.traverse.RRTraverse; import gregtech.api.graphnet.traverse.iter.EdgeDirection; import gregtech.api.graphnet.traverse.iter.NetClosestIterator; import gregtech.api.graphnet.traverse.iter.NetIterator; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; -import gregtech.api.util.GTUtility; import gregtech.api.util.function.BiIntConsumer; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; @@ -396,49 +390,11 @@ protected int attemptNetTransfer(NetGroup group, NetEdge bridge, int limit, Flui NetIterator sources, Map sourceCandidates, NetIterator targets, Map destCandidates, @Nullable SimulatorKey key) { - return switch (distributionMode) { - case FLOOD -> FDTraverse.flood(group, - (n, f) -> { - if (key == null) FluidCapabilityObject.reportFlow(n, f, testObject); - }, - (e, f) -> FluidCapabilityObject.reportFlow(e, f, testObject, key, true), - e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt( - n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : - 0, - n -> getSupply(n, testObject, sources.hasSeen(n)), FluidCapabilityObject.isLossyNode(testObject), - FluidCapabilityObject.handleLoss(testObject)); - case EQUALIZED -> EQTraverse.equalDistribution(group, - (n, f) -> { - if (key == null) FluidCapabilityObject.reportFlow(n, f, testObject); - }, - (e, f) -> FluidCapabilityObject.reportFlow(e, f, testObject, key, true), - e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt( - n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : - 0, - n -> getSupply(n, testObject, sources.hasSeen(n)), FluidCapabilityObject.isLossyNode(testObject), - FluidCapabilityObject.handleLoss(testObject)); - case ROUND_ROBIN -> { - roundRobinCache.refresh(sources, targets); - yield RRTraverse.roundRobin(group, getRoundRobinCache(key != null) - .buildSupplier(sourceCandidates.keySet(), destCandidates.keySet()), - (n, f) -> { - if (key == null) FluidCapabilityObject.reportFlow(n, f, testObject); - }, - (e, f) -> FluidCapabilityObject.reportFlow(e, f, testObject, key, true), - e -> e == bridge ? limit : e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt( - n.getFlowLimit(testObject, group.net, GTUtility.getTick(), key)) : - 0, - n -> getSupply(n, testObject, sources.hasSeen(n)), - FluidCapabilityObject.isLossyNode(testObject), FluidCapabilityObject.handleLoss(testObject)); - } - }; + return 0; } protected int getSupply(NetNode node, FluidTestObject testObject, boolean supply) { - return FluidCapabilityObject.getSupply(node, testObject, supply); + return FluidCapabilityObject.getSupplyOrDemand(node, testObject, supply); } /** diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 48a8b403896..61abdaa240c 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -106,19 +106,19 @@ protected void performTransferOnUpdate(@NotNull IItemHandler sourceHandler, @Not } @Override - protected int simpleInsert(@NotNull IItemHandler destHandler, ItemTestObject testObject, int count, + protected int simpleInsert(@NotNull IItemHandler handler, ItemTestObject testObject, int count, boolean simulate) { if (transferMode == TransferMode.KEEP_EXACT) { assert getItemFilter() != null; int kept = getItemFilter().getTransferLimit(testObject.recombine()); - count = Math.min(count, kept - computeContained(destHandler, testObject)); + count = Math.min(count, kept - computeContained(handler, testObject)); } - return super.simpleInsert(destHandler, testObject, count, simulate); + return super.simpleInsert(handler, testObject, count, simulate); } @Override - protected int getSupply(NetNode node, ItemTestObject testObject, boolean supply) { - if (transferMode != TransferMode.KEEP_EXACT || supply) return super.getSupply(node, testObject, supply); + protected int getSupplyOrDemand(NetNode node, ItemTestObject testObject, boolean supply) { + if (transferMode != TransferMode.KEEP_EXACT || supply) return super.getSupplyOrDemand(node, testObject, supply); if (node instanceof NodeExposingCapabilities exposer) { IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, exposer.exposedFacing()); diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java index 20f7aaa5cde..c1e24296dab 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialEnergyProperties.java @@ -131,7 +131,7 @@ public void verifyProperty(MaterialProperties properties) { this.materialMeltTemperature = computeMaterialMeltTemperature(properties); } - public static int computeMaterialMeltTemperature(@NotNull MaterialProperties properties) { + private static int computeMaterialMeltTemperature(@NotNull MaterialProperties properties) { if (properties.hasProperty(PropertyKey.FLUID)) { // autodetermine melt temperature from registered fluid FluidProperty prop = properties.getProperty(PropertyKey.FLUID); diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java index c6f7378096d..1430c525f38 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialFluidProperties.java @@ -1,9 +1,11 @@ package gregtech.common.pipelike.handlers.properties; import gregtech.api.capability.IPropertyFluidFilter; +import gregtech.api.fluids.FluidBuilder; import gregtech.api.fluids.FluidConstants; import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; +import gregtech.api.fluids.store.FluidStorageKeys; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.ThroughputLogic; @@ -14,6 +16,7 @@ import gregtech.api.graphnet.pipenet.logic.TemperatureLossFunction; import gregtech.api.graphnet.pipenet.physical.IPipeMaterialStructure; import gregtech.api.graphnet.pipenet.physical.IPipeStructure; +import gregtech.api.unification.material.properties.FluidProperty; import gregtech.api.unification.material.properties.MaterialProperties; import gregtech.api.unification.material.properties.PipeNetProperties; import gregtech.api.unification.material.properties.PropertyKey; @@ -27,6 +30,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fluids.Fluid; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; @@ -162,7 +166,24 @@ public void verifyProperty(MaterialProperties properties) { if (!properties.hasProperty(PropertyKey.WOOD)) { properties.ensureSet(PropertyKey.INGOT, true); } - this.materialMeltTemperature = MaterialEnergyProperties.computeMaterialMeltTemperature(properties); + this.materialMeltTemperature = computeMaterialMeltTemperature(properties, maxFluidTemperature); + } + + public static int computeMaterialMeltTemperature(@NotNull MaterialProperties properties, int fallback) { + if (properties.hasProperty(PropertyKey.FLUID)) { + // autodetermine melt temperature from registered fluid + FluidProperty prop = properties.getProperty(PropertyKey.FLUID); + Fluid fluid = prop.get(FluidStorageKeys.LIQUID); + if (fluid == null) { + FluidBuilder builder = prop.getQueuedBuilder(FluidStorageKeys.LIQUID); + if (builder != null) { + return builder.getDeterminedTemperature(properties.getMaterial(), FluidStorageKeys.LIQUID); + } + } else { + return fluid.getTemperature(); + } + } + return fallback; } @Override diff --git a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java index 054f813d05b..d2eeb8ee006 100644 --- a/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java +++ b/src/main/java/gregtech/common/pipelike/handlers/properties/MaterialItemProperties.java @@ -51,17 +51,22 @@ public MaterialPropertyKey getKey() { public void addInformation(@NotNull ItemStack stack, World worldIn, @NotNull List tooltip, @NotNull ITooltipFlag flagIn, IPipeMaterialStructure structure) { tooltip.add(I18n.format("gregtech.item_pipe")); - if (baseItemsPer5Ticks % 16 != 0) { - tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate", - baseItemsPer5Ticks * 4)); + long items = getThroughput(structure); + if (items % 16 != 0) { + tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate", items * 4)); } else { - tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate_stacks", - baseItemsPer5Ticks / 16)); + tooltip.add(I18n.format("gregtech.universal.tooltip.item_transfer_rate_stacks", items / 16)); } tooltip.add(I18n.format("gregtech.pipe.priority", TextFormattingUtil.formatNumbers(getFlowPriority(structure)))); } + private long getThroughput(IPipeStructure structure) { + if (structure instanceof MaterialPipeStructure pipe) { + return baseItemsPer5Ticks * pipe.material(); + } else return baseItemsPer5Ticks; + } + @Override public void verifyProperty(MaterialProperties properties) { if (!properties.hasProperty(PropertyKey.WOOD)) { diff --git a/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java index d070397709c..414f9310799 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/StandardEnergyPath.java @@ -1,9 +1,9 @@ package gregtech.common.pipelike.net.energy; -import gregtech.api.graphnet.edge.NetEdge; import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.logic.NetLogicData; import gregtech.api.graphnet.logic.WeightFactorLogic; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.PathBuilder; import gregtech.api.graphnet.path.SingletonNetPath; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index f5d965aecea..98978f39c06 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -2,10 +2,9 @@ import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.SimulatorKey; import gregtech.api.graphnet.logic.ChannelCountLogic; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.pipenet.WorldPipeNode; @@ -16,8 +15,11 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverse.FDTraverse; +import gregtech.api.graphnet.traverse.iter.EdgeDirection; +import gregtech.api.graphnet.traverse.iter.EdgeSelector; +import gregtech.api.graphnet.traverse.iter.ResilientNetClosestIterator; import gregtech.api.util.GTUtility; +import gregtech.api.util.MapUtil; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; @@ -26,13 +28,17 @@ import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidTankProperties; +import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2LongMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayDeque; import java.util.Arrays; import java.util.EnumMap; -import java.util.function.ObjIntConsumer; -import java.util.function.Predicate; +import java.util.List; public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandler, IFluidTankProperties { @@ -93,21 +99,66 @@ protected int fill(FluidStack resource, boolean doFill, EnumFacing side) { this.transferring = true; int flow = resource.amount; - SimulatorKey key = doFill ? null : SimulatorKey.getNewSimulatorInstance(); FluidTestObject testObject = new FluidTestObject(resource); - int report = FDTraverse.flood(node.getGroupSafe(), - (n, f) -> { - if (n != node && doFill) reportFlow(n, f, testObject); - }, - (e, f) -> reportFlow(e, f, testObject, key, true), - e -> e instanceof AbstractNetFlowEdge n && e.test(testObject) ? - GTUtility.safeCastLongToInt( - n.getFlowLimit(testObject, node.getNet(), GTUtility.getTick(), key)) : - 0, - n -> n == node ? flow : getSupply(n, testObject, false), - isLossyNode(testObject), handleLoss(testObject)); + ResilientNetClosestIterator iter = new ResilientNetClosestIterator(node, + EdgeSelector.filtered(EdgeDirection.OUTGOING, e -> e instanceof NetEdge n && !n.test(testObject))); + Object2IntOpenHashMap availableDemandCache = new Object2IntOpenHashMap<>(); + Object2IntOpenHashMap flowLimitCache = new Object2IntOpenHashMap<>(); + Object2BooleanOpenHashMap lossyCache = new Object2BooleanOpenHashMap<>(); + List postActions = new ObjectArrayList<>(); + int total = 0; + main: + while (iter.hasNext()) { + if (flow <= 0) break; + final NetNode next = iter.next(); + int limit = Math.min(MapUtil.computeIfAbsent(flowLimitCache, next, n -> getFlowLimit(n, testObject)), flow); + if (limit <= 0) { + iter.markInvalid(next); + continue; + } + int supply = MapUtil.computeIfAbsent(availableDemandCache, next, + n -> getSupplyOrDemand(n, testObject, false)); + if (supply <= 0) continue; + supply = Math.min(supply, limit); + NetEdge span; + NetNode trace = next; + ArrayDeque seen = new ArrayDeque<>(); + seen.add(next); + while ((span = iter.getSpanningTreeEdge(trace)) != null) { + trace = span.getOppositeNode(trace); + if (trace == null) continue main; + int l = MapUtil.computeIfAbsent(flowLimitCache, trace, n -> getFlowLimit(n, testObject)); + if (l == 0) { + iter.markInvalid(node); + continue main; + } + supply = Math.min(supply, l); + seen.addFirst(trace); + } + total += supply; + flow -= supply; + int finalSupply = supply; + for (NetNode n : seen) { + // reporting flow can cause temperature pipe destruction which causes graph modification while + // iterating. + if (doFill) postActions.add(() -> reportFlow(n, finalSupply, testObject)); + int remaining = flowLimitCache.getInt(n) - supply; + flowLimitCache.put(n, remaining); + if (remaining <= 0) { + iter.markInvalid(n); + } + if (MapUtil.computeIfAbsent(lossyCache, n, a -> isLossyNode(a, testObject))) { + // reporting loss can cause misc pipe destruction which causes graph modification while iterating. + if (doFill) postActions.add(() -> handleLoss(n, finalSupply, testObject)); + continue main; + } + } + if (doFill) reportExtractedInserted(next, supply, testObject, false); + availableDemandCache.put(next, availableDemandCache.getInt(next) - supply); + } + postActions.forEach(Runnable::run); this.transferring = false; - return report; + return total; } protected FluidStack drain(int maxDrain, boolean doDrain, EnumFacing side) { @@ -122,94 +173,141 @@ protected FluidStack drain(FluidStack resource, boolean doDrain, EnumFacing side this.transferring = true; int flow = resource.amount; - SimulatorKey key = doDrain ? null : SimulatorKey.getNewSimulatorInstance(); FluidTestObject testObject = new FluidTestObject(resource); - int report = FDTraverse.flood(node.getGroupSafe(), - (n, f) -> { - if (n != node && doDrain) reportFlow(n, f, testObject); - }, - (e, f) -> reportFlow(e, f, testObject, key, false), - e -> e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt( - n.getFlowLimit(testObject, node.getNet(), GTUtility.getTick(), key)) : - 0, - n -> n == node ? flow : getSupply(n, testObject, true), - isLossyNode(testObject), handleLoss(testObject)); - + ResilientNetClosestIterator iter = new ResilientNetClosestIterator(node, + EdgeSelector.filtered(EdgeDirection.INCOMING, e -> e instanceof NetEdge n && !n.test(testObject))); + Object2IntOpenHashMap availableSupplyCache = new Object2IntOpenHashMap<>(); + Object2IntOpenHashMap flowLimitCache = new Object2IntOpenHashMap<>(); + Object2BooleanOpenHashMap lossyCache = new Object2BooleanOpenHashMap<>(); + List postActions = new ObjectArrayList<>(); + int total = 0; + main: + while (iter.hasNext()) { + if (flow <= 0) break; + final NetNode next = iter.next(); + int limit = Math.min(MapUtil.computeIfAbsent(flowLimitCache, next, n -> getFlowLimit(n, testObject)), flow); + if (limit <= 0) { + iter.markInvalid(next); + continue; + } + int supply = MapUtil.computeIfAbsent(availableSupplyCache, next, + n -> getSupplyOrDemand(n, testObject, true)); + if (supply <= 0) continue; + supply = Math.min(supply, limit); + NetEdge span; + NetNode trace = next; + ArrayDeque seen = new ArrayDeque<>(); + seen.add(next); + while ((span = iter.getSpanningTreeEdge(trace)) != null) { + trace = span.getOppositeNode(trace); + if (trace == null) continue main; + int l = MapUtil.computeIfAbsent(flowLimitCache, trace, n -> getFlowLimit(n, testObject)); + if (l == 0) { + iter.markInvalid(node); + continue main; + } + supply = Math.min(supply, l); + seen.addFirst(trace); + } + total += supply; + flow -= supply; + int finalSupply = supply; + for (NetNode n : seen) { + // reporting flow can cause temperature pipe destruction which causes graph modification while + // iterating. + if (doDrain) postActions.add(() -> reportFlow(n, finalSupply, testObject)); + int remaining = flowLimitCache.getInt(n) - supply; + flowLimitCache.put(n, remaining); + if (remaining <= 0) { + iter.markInvalid(n); + } + if (MapUtil.computeIfAbsent(lossyCache, n, a -> isLossyNode(a, testObject))) { + // reporting loss can cause misc pipe destruction which causes graph modification while iterating. + if (doDrain) postActions.add(() -> handleLoss(n, finalSupply, testObject)); + continue main; + } + } + if (doDrain) reportExtractedInserted(next, supply, testObject, true); + availableSupplyCache.put(next, availableSupplyCache.getInt(next) - supply); + } + postActions.forEach(Runnable::run); this.transferring = false; - return testObject.recombine(report); + return testObject.recombine(total); } - public static Predicate isLossyNode(FluidTestObject testObject) { - return n -> { - FluidContainmentLogic containmentLogic = n.getData().getLogicEntryNullable(FluidContainmentLogic.TYPE); - return containmentLogic != null && !containmentLogic.handles(testObject); - }; + protected int getFlowLimit(NetNode node, FluidTestObject testObject) { + ThroughputLogic throughput = node.getData().getLogicEntryNullable(ThroughputLogic.TYPE); + if (throughput == null) return Integer.MAX_VALUE; + FluidFlowLogic history = node.getData().getLogicEntryNullable(FluidFlowLogic.TYPE); + if (history == null) return GTUtility.safeCastLongToInt(throughput.getValue() * FluidFlowLogic.MEMORY_TICKS); + Object2LongMap sum = history.getSum(); + if (sum.isEmpty()) return GTUtility.safeCastLongToInt(throughput.getValue() * FluidFlowLogic.MEMORY_TICKS); + if (sum.size() < node.getData().getLogicEntryDefaultable(ChannelCountLogic.TYPE).getValue() || + sum.containsKey(testObject)) { + return GTUtility + .safeCastLongToInt(throughput.getValue() * FluidFlowLogic.MEMORY_TICKS - sum.getLong(testObject)); + } + return 0; } - public static void reportFlow(NetEdge edge, int flow, FluidTestObject testObject, SimulatorKey key, - boolean sourceBias) { - NetNode node = sourceBias ? edge.getSource() : edge.getTarget(); - if (node == null) return; - if (edge instanceof AbstractNetFlowEdge n) - n.consumeFlowLimit(testObject, node.getNet(), flow, GTUtility.getTick(), key); - if (key == null) { - FluidFlowLogic logic = node.getData().getLogicEntryNullable(FluidFlowLogic.TYPE); - if (logic == null) { - logic = FluidFlowLogic.TYPE.getNew(); - node.getData().setLogicEntry(logic); - } + public static boolean isLossyNode(NetNode node, FluidTestObject testObject) { + FluidContainmentLogic containmentLogic = node.getData().getLogicEntryNullable(FluidContainmentLogic.TYPE); + return containmentLogic != null && !containmentLogic.handles(testObject); + } + + public static void reportFlow(NetNode node, int flow, FluidTestObject testObject) { + FluidFlowLogic logic = node.getData().getLogicEntryNullable(FluidFlowLogic.TYPE); + if (logic == null) { + logic = FluidFlowLogic.TYPE.getNew(); + node.getData().setLogicEntry(logic); + } + logic.recordFlow(GTUtility.getTick(), testObject, flow); + TemperatureLogic temp = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); + if (temp != null) { FluidStack stack = testObject.recombine(flow); - logic.recordFlow(GTUtility.getTick(), stack); - TemperatureLogic temp = node.getData().getLogicEntryNullable(TemperatureLogic.TYPE); - if (temp != null) { - FluidContainmentLogic cont = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE); - int t = stack.getFluid().getTemperature(stack); - temp.moveTowardsTemperature(t, GTUtility.getTick(), stack.amount, cont.getMaximumTemperature() >= t); - if (node instanceof WorldPipeNode n) { - temp.defaultHandleTemperature(n.getNet().getWorld(), n.getEquivalencyData()); - } + FluidContainmentLogic cont = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE); + int t = stack.getFluid().getTemperature(stack); + temp.moveTowardsTemperature(t, GTUtility.getTick(), stack.amount, cont.getMaximumTemperature() >= t); + if (node instanceof WorldPipeNode n) { + temp.defaultHandleTemperature(n.getNet().getWorld(), n.getEquivalencyData()); } } } - public static void reportFlow(NetNode node, int flow, FluidTestObject testObject) { + public static void reportExtractedInserted(NetNode node, int flow, FluidTestObject testObject, boolean extracted) { if (flow == 0) return; if (node instanceof NodeExposingCapabilities exposer) { IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, exposer.exposedFacing()); if (handler != null) { - // positive flow is supply, aka we pulled flow from this node - if (flow > 0) { + if (extracted) { handler.drain(testObject.recombine(flow), true); } else { - handler.fill(testObject.recombine(-flow), true); + handler.fill(testObject.recombine(flow), true); } } } } - public static ObjIntConsumer handleLoss(FluidTestObject testObject) { - return (node, f) -> { - if (f == 0) return; - FluidContainmentLogic logic = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE); - if (node instanceof WorldPipeNode n) { - IWorldPipeNetTile tile = n.getTileEntity(); - FluidStack stack = testObject.recombine(f); - // failing attributes take priority over state - for (FluidAttribute attribute : FluidAttribute.inferAttributes(stack)) { - if (!logic.contains(attribute)) { - attribute.handleFailure(tile.getWorld(), tile.getPos(), stack); - return; - } + public static void handleLoss(NetNode node, int flow, FluidTestObject testObject) { + if (flow == 0) return; + FluidContainmentLogic logic = node.getData().getLogicEntryDefaultable(FluidContainmentLogic.TYPE); + if (node instanceof WorldPipeNode n) { + IWorldPipeNetTile tile = n.getTileEntity(); + FluidStack stack = testObject.recombine(flow); + // failing attributes take priority over state + for (FluidAttribute attribute : FluidAttribute.inferAttributes(stack)) { + if (!logic.contains(attribute)) { + attribute.handleFailure(tile.getWorld(), tile.getPos(), stack); + return; } - FluidState state = FluidState.inferState(stack); - if (!logic.contains(state)) state.handleFailure(tile.getWorld(), tile.getPos(), stack); } - }; + FluidState state = FluidState.inferState(stack); + if (!logic.contains(state)) state.handleFailure(tile.getWorld(), tile.getPos(), stack); + } } - public static int getSupply(NetNode node, FluidTestObject testObject, boolean supply) { + public static int getSupplyOrDemand(NetNode node, FluidTestObject testObject, boolean supply) { if (node instanceof NodeExposingCapabilities exposer) { IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, exposer.exposedFacing()); @@ -218,7 +316,7 @@ public static int getSupply(NetNode node, FluidTestObject testObject, boolean su FluidStack s = handler.drain(testObject.recombine(Integer.MAX_VALUE), false); return s == null ? 0 : s.amount; } else { - return -handler.fill(testObject.recombine(Integer.MAX_VALUE), false); + return handler.fill(testObject.recombine(Integer.MAX_VALUE), false); } } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java index 229cdacca95..ae1e2c5c9e0 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidFlowLogic.java @@ -3,26 +3,25 @@ import gregtech.api.GTValues; import gregtech.api.graphnet.logic.AbstractTransientLogicData; import gregtech.api.graphnet.logic.NetLogicType; +import gregtech.api.graphnet.predicate.test.FluidTestObject; +import gregtech.api.util.GTUtility; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fml.common.FMLCommonHandler; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.Object2LongArrayMap; +import it.unimi.dsi.fastutil.objects.Object2LongMap; +import it.unimi.dsi.fastutil.objects.Object2LongMaps; import org.jetbrains.annotations.NotNull; -import java.util.Collections; -import java.util.List; - public class FluidFlowLogic extends AbstractTransientLogicData { public static final NetLogicType TYPE = new NetLogicType<>(GTValues.MODID, "FluidFlow", FluidFlowLogic::new, new FluidFlowLogic()); - public static final int MEMORY_TICKS = 10; + public static final int MEMORY_TICKS = WorldFluidNet.getBufferTicks(); - private final Long2ObjectOpenHashMap> memory = new Long2ObjectOpenHashMap<>(); + private final Long2ObjectOpenHashMap> memory = new Long2ObjectOpenHashMap<>(); private FluidStack last; @Override @@ -30,20 +29,35 @@ public class FluidFlowLogic extends AbstractTransientLogicData { return TYPE; } - public @NotNull Long2ObjectOpenHashMap> getMemory() { - updateMemory(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); + public @NotNull Long2ObjectOpenHashMap> getMemory() { + updateMemory(GTUtility.getTick()); return memory; } - public @NotNull List getFlow(long tick) { + public @NotNull Object2LongMap getSum() { + Object2LongMap sum = new Object2LongArrayMap<>(); + for (Object2LongMap list : getMemory().values()) { + for (var entry : list.object2LongEntrySet()) { + sum.put(entry.getKey(), sum.getLong(entry.getKey()) + entry.getLongValue()); + } + } + return sum; + } + + public @NotNull Object2LongMap getFlow(long tick) { updateMemory(tick); - return memory.getOrDefault(tick, Collections.emptyList()); + return memory.getOrDefault(tick, Object2LongMaps.emptyMap()); + } + + public void recordFlow(long tick, @NotNull FluidStack flow) { + recordFlow(tick, new FluidTestObject(flow), flow.amount); } - public void recordFlow(long tick, FluidStack flow) { + public void recordFlow(long tick, @NotNull FluidTestObject testObject, int amount) { updateMemory(tick); - memory.computeIfAbsent(tick, k -> new ObjectArrayList<>()).add(flow); - last = flow; + Object2LongMap map = memory.computeIfAbsent(tick, k -> new Object2LongArrayMap<>()); + map.put(testObject, map.getLong(testObject) + amount); + last = testObject.recombine(amount); } public FluidStack getLast() { @@ -53,7 +67,7 @@ public FluidStack getLast() { private void updateMemory(long tick) { var iter = memory.long2ObjectEntrySet().fastIterator(); while (iter.hasNext()) { - Long2ObjectMap.Entry> entry = iter.next(); + var entry = iter.next(); if (entry.getLongKey() + MEMORY_TICKS < tick) { iter.remove(); } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 6aba5d44b6b..9dfb478d613 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -2,10 +2,8 @@ import gregtech.api.cover.Cover; import gregtech.api.cover.filter.CoverWithFluidFilter; -import gregtech.api.graphnet.GraphClassType; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; @@ -90,9 +88,8 @@ public PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEntity owne return new NodeManagingPCW(owner, node, map, 0, 0); } - @Override - public @NotNull GraphClassType getDefaultEdgeType() { - return NetFlowEdge.TYPE; + public static int getBufferTicks() { + return 10; } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index 5197e917375..3563ddb49fe 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -1,8 +1,8 @@ package gregtech.common.pipelike.net.item; -import gregtech.api.graphnet.edge.AbstractNetFlowEdge; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.SimulatorKey; +import gregtech.api.graphnet.logic.ChannelCountLogic; +import gregtech.api.graphnet.logic.ThroughputLogic; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.pipenet.WorldPipeNode; @@ -11,8 +11,11 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverse.FDTraverse; +import gregtech.api.graphnet.traverse.iter.EdgeDirection; +import gregtech.api.graphnet.traverse.iter.EdgeSelector; +import gregtech.api.graphnet.traverse.iter.ResilientNetClosestIterator; import gregtech.api.util.GTUtility; +import gregtech.api.util.MapUtil; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; @@ -20,9 +23,12 @@ import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2LongMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayDeque; import java.util.EnumMap; public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler { @@ -78,21 +84,53 @@ public T getCapability(Capability capability, @Nullable EnumFacing facing this.transferring = true; int flow = stack.getCount(); - SimulatorKey key = simulate ? SimulatorKey.getNewSimulatorInstance() : null; ItemTestObject testObject = new ItemTestObject(stack); - int report = FDTraverse.flood(node.getGroupSafe(), - (n, f) -> { - if (n != node && !simulate) reportFlow(n, f, testObject); - }, - (e, f) -> reportFlow(e, f, testObject, key, true), - e -> e instanceof AbstractNetFlowEdge n ? - GTUtility.safeCastLongToInt( - n.getFlowLimit(testObject, node.getNet(), GTUtility.getTick(), key)) : - 0, - n -> n == node ? flow : getSupply(n, testObject, false), null, null); - + ResilientNetClosestIterator iter = new ResilientNetClosestIterator(node, + EdgeSelector.filtered(EdgeDirection.OUTGOING, NetEdge.standardBlacklist(testObject))); + Object2IntOpenHashMap availableDemandCache = new Object2IntOpenHashMap<>(); + Object2IntOpenHashMap flowLimitCache = new Object2IntOpenHashMap<>(); + main: + while (iter.hasNext()) { + if (flow <= 0) break; + final NetNode next = iter.next(); + int limit = Math.min(MapUtil.computeIfAbsent(flowLimitCache, next, n -> getFlowLimit(n, testObject)), flow); + if (limit <= 0) { + iter.markInvalid(next); + continue; + } + int demand = MapUtil.computeIfAbsent(availableDemandCache, next, + n -> getSupplyOrDemand(n, testObject, false)); + if (demand <= 0) continue; + demand = Math.min(demand, limit); + NetEdge span; + NetNode trace = next; + ArrayDeque seen = new ArrayDeque<>(); + seen.add(next); + while ((span = iter.getSpanningTreeEdge(trace)) != null) { + trace = span.getOppositeNode(trace); + if (trace == null) continue main; + int l = MapUtil.computeIfAbsent(flowLimitCache, trace, n -> getFlowLimit(n, testObject)); + if (l == 0) { + iter.markInvalid(node); + continue main; + } + demand = Math.min(demand, l); + seen.addFirst(trace); + } + flow -= demand; + for (NetNode n : seen) { + if (!simulate) reportFlow(n, demand, testObject); + int remaining = flowLimitCache.getInt(n) - demand; + flowLimitCache.put(n, remaining); + if (remaining <= 0) { + iter.markInvalid(n); + } + } + if (!simulate) reportExtractedInserted(next, demand, testObject, false); + availableDemandCache.put(next, availableDemandCache.getInt(next) - demand); + } this.transferring = false; - return testObject.recombine(stack.getCount() - report); + return testObject.recombine(flow); } protected @NotNull ItemStack extractItem(int slot, int amount, boolean simulate, EnumFacing side) { @@ -100,31 +138,38 @@ public T getCapability(Capability capability, @Nullable EnumFacing facing return ItemStack.EMPTY; } - public static void reportFlow(NetEdge edge, int flow, ItemTestObject testObject, SimulatorKey key, - boolean sourceBias) { - NetNode node = sourceBias ? edge.getSource() : edge.getTarget(); - if (node == null) return; - if (edge instanceof AbstractNetFlowEdge n) { - n.consumeFlowLimit(testObject, node.getNet(), flow, GTUtility.getTick(), key); - } - if (key == null) { - ItemFlowLogic logic = node.getData().getLogicEntryNullable(ItemFlowLogic.TYPE); - if (logic == null) { - logic = ItemFlowLogic.TYPE.getNew(); - node.getData().setLogicEntry(logic); - } - logic.recordFlow(GTUtility.getTick(), testObject.recombine(flow)); + protected int getFlowLimit(NetNode node, ItemTestObject testObject) { + ThroughputLogic throughput = node.getData().getLogicEntryNullable(ThroughputLogic.TYPE); + if (throughput == null) return Integer.MAX_VALUE; + ItemFlowLogic history = node.getData().getLogicEntryNullable(ItemFlowLogic.TYPE); + if (history == null) return GTUtility.safeCastLongToInt(throughput.getValue() * ItemFlowLogic.BUFFER_MULT); + Object2LongMap sum = history.getSum(); + if (sum.isEmpty()) return GTUtility.safeCastLongToInt(throughput.getValue() * ItemFlowLogic.BUFFER_MULT); + if (sum.size() < node.getData().getLogicEntryDefaultable(ChannelCountLogic.TYPE).getValue() || + sum.containsKey(testObject)) { + return GTUtility + .safeCastLongToInt(throughput.getValue() * ItemFlowLogic.BUFFER_MULT - sum.getLong(testObject)); } + return 0; } public static void reportFlow(NetNode node, int flow, ItemTestObject testObject) { + ItemFlowLogic logic = node.getData().getLogicEntryNullable(ItemFlowLogic.TYPE); + if (logic == null) { + logic = ItemFlowLogic.TYPE.getNew(); + node.getData().setLogicEntry(logic); + } + logic.recordFlow(GTUtility.getTick(), testObject.recombine(flow)); + } + + public static void reportExtractedInserted(NetNode node, int flow, ItemTestObject testObject, boolean extracted) { if (flow == 0) return; if (node instanceof NodeExposingCapabilities exposer) { IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, exposer.exposedFacing()); if (handler != null) { // positive flow is supply, aka we pulled flow from this node - if (flow > 0) { + if (extracted) { for (int i = 0; i < handler.getSlots(); i++) { ItemStack stack = handler.extractItem(i, flow, true); if (testObject.test(stack)) { @@ -135,16 +180,16 @@ public static void reportFlow(NetNode node, int flow, ItemTestObject testObject) } } else { for (int i = 0; i < handler.getSlots(); i++) { - ItemStack stack = testObject.recombineSafe(-flow); - flow += stack.getCount() - handler.insertItem(i, stack, false).getCount(); - if (flow == 0) return; + ItemStack stack = testObject.recombineSafe(flow); + flow -= stack.getCount() - handler.insertItem(i, stack, false).getCount(); + if (flow <= 0) return; } } } } } - public static int getSupply(NetNode node, ItemTestObject testObject, boolean supply) { + public static int getSupplyOrDemand(NetNode node, ItemTestObject testObject, boolean supply) { if (node instanceof NodeExposingCapabilities exposer) { IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, exposer.exposedFacing()); @@ -162,7 +207,7 @@ public static int getSupply(NetNode node, ItemTestObject testObject, boolean sup for (int i = 0; i < handler.getSlots(); i++) { sum += stack.getCount() - handler.insertItem(i, stack, true).getCount(); } - return -sum; + return sum; } } } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java b/src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java index b7471316f94..5fa9fab6d01 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemFlowLogic.java @@ -3,26 +3,26 @@ import gregtech.api.GTValues; import gregtech.api.graphnet.logic.AbstractTransientLogicData; import gregtech.api.graphnet.logic.NetLogicType; +import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.util.GTUtility; import net.minecraft.item.ItemStack; -import net.minecraftforge.fml.common.FMLCommonHandler; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.Object2LongArrayMap; +import it.unimi.dsi.fastutil.objects.Object2LongMap; +import it.unimi.dsi.fastutil.objects.Object2LongMaps; import org.jetbrains.annotations.NotNull; -import java.util.Collections; -import java.util.List; - public class ItemFlowLogic extends AbstractTransientLogicData { public static final NetLogicType TYPE = new NetLogicType<>(GTValues.MODID, "ItemFlow", ItemFlowLogic::new, new ItemFlowLogic()); - public static final int MEMORY_TICKS = 10; + public static final int MEMORY_TICKS = WorldItemNet.getBufferTicks(); + public static final int BUFFER_MULT = MEMORY_TICKS / WorldItemNet.getBufferRegenerationFactor(); - private final Long2ObjectOpenHashMap> memory = new Long2ObjectOpenHashMap<>(); + private final Long2ObjectOpenHashMap> memory = new Long2ObjectOpenHashMap<>(); private ItemStack last; @Override @@ -30,20 +30,35 @@ public class ItemFlowLogic extends AbstractTransientLogicData { return TYPE; } - public @NotNull Long2ObjectOpenHashMap> getMemory() { - updateMemory(FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter()); + public @NotNull Long2ObjectOpenHashMap> getMemory() { + updateMemory(GTUtility.getTick()); return memory; } - public @NotNull List getFlow(long tick) { + public @NotNull Object2LongMap getSum() { + Object2LongMap sum = new Object2LongArrayMap<>(); + for (Object2LongMap list : getMemory().values()) { + for (var entry : list.object2LongEntrySet()) { + sum.put(entry.getKey(), sum.getLong(entry.getKey()) + entry.getLongValue()); + } + } + return sum; + } + + public @NotNull Object2LongMap getFlow(long tick) { updateMemory(tick); - return memory.getOrDefault(tick, Collections.emptyList()); + return memory.getOrDefault(tick, Object2LongMaps.emptyMap()); + } + + public void recordFlow(long tick, @NotNull ItemStack flow) { + recordFlow(tick, new ItemTestObject(flow), flow.getCount()); } - public void recordFlow(long tick, ItemStack flow) { + public void recordFlow(long tick, @NotNull ItemTestObject testObject, int amount) { updateMemory(tick); - memory.computeIfAbsent(tick, k -> new ObjectArrayList<>()).add(flow); - last = flow; + Object2LongMap map = memory.computeIfAbsent(tick, k -> new Object2LongArrayMap<>()); + map.put(testObject, map.getLong(testObject) + amount); + last = testObject.recombine(amount); } public ItemStack getLast() { @@ -53,7 +68,7 @@ public ItemStack getLast() { private void updateMemory(long tick) { var iter = memory.long2ObjectEntrySet().fastIterator(); while (iter.hasNext()) { - Long2ObjectMap.Entry> entry = iter.next(); + var entry = iter.next(); if (entry.getLongKey() + MEMORY_TICKS < tick) { iter.remove(); } diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 5953c8a5bf4..6f8212abc47 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -2,11 +2,8 @@ import gregtech.api.cover.Cover; import gregtech.api.cover.filter.CoverWithItemFilter; -import gregtech.api.graphnet.GraphClassType; -import gregtech.api.graphnet.edge.FlowBufferTickProvider; -import gregtech.api.graphnet.edge.NetEdge; -import gregtech.api.graphnet.edge.NetFlowEdge; import gregtech.api.graphnet.net.IGraphNet; +import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.pipenet.WorldPipeNet; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; @@ -27,7 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class WorldItemNet extends WorldPipeNet implements FlowBufferTickProvider { +public class WorldItemNet extends WorldPipeNet { public static final Capability[] CAPABILITIES = new Capability[] { CapabilityItemHandler.ITEM_HANDLER_CAPABILITY }; @@ -91,18 +88,11 @@ public PipeCapabilityWrapper buildCapabilityWrapper(@NotNull PipeTileEntity owne return new NodeManagingPCW(owner, node, map, 0, 0); } - @Override - public @NotNull GraphClassType getDefaultEdgeType() { - return NetFlowEdge.TYPE; - } - - @Override - public int getFlowBufferTicks() { - return 2; + public static int getBufferTicks() { + return 10; } - @Override - public int getRegenerationTime() { + public static int getBufferRegenerationFactor() { return 5; } diff --git a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java index 2d6aa3c815c..f82319ce383 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/DataCapabilityObject.java @@ -82,7 +82,8 @@ else if (node.getGroupSafe().getData() instanceof PathCacheGroupData cache) { queryObject.setShouldTriggerWalker(false); boolean cancelled = access.accessData(queryObject); if (queryObject.shouldTriggerWalker()) { - SlowActiveWalker.dispatch(tile.getWorld(), path, 1); + // since we are a pull-based system, we need to reverse the path for it to look correct + SlowActiveWalker.dispatch(tile.getWorld(), path.reversed(), 1, 1, 5); } if (cancelled) return true; } diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java index f868ad6b133..20dd590ae92 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/PipeTileInfoProvider.java @@ -21,7 +21,7 @@ import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2LongMap; import mcjty.theoneprobe.api.ElementAlignment; import mcjty.theoneprobe.api.IProbeHitData; import mcjty.theoneprobe.api.IProbeInfo; @@ -92,16 +92,11 @@ private void addFluidFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, .text(" " + logic.getLast().getLocalizedName()); } - Object2IntOpenHashMap counts = new Object2IntOpenHashMap<>(); - for (var memory : logic.getMemory().values()) { - for (FluidStack stack : memory) { - counts.merge(new FluidTestObject(stack), stack.amount, Integer::sum); - } - } + Object2LongMap counts = logic.getSum(); - for (var entry : counts.object2IntEntrySet()) { + for (var entry : counts.object2LongEntrySet()) { FluidStack stack = entry.getKey().recombine(); - String value = TextFormattingUtil.formatNumbers(entry.getIntValue() * 20L / FluidFlowLogic.MEMORY_TICKS); + String value = TextFormattingUtil.formatNumbers(20 * entry.getLongValue() / FluidFlowLogic.MEMORY_TICKS); iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) .element(new FluidStackElement(stack)) .text(" §b" + value + " L/s §f" + stack.getLocalizedName()); @@ -119,16 +114,11 @@ private void addItemFlowInformation(ProbeMode probeMode, IProbeInfo iProbeInfo, .text(" " + logic.getLast().getDisplayName()); } - Object2IntOpenHashMap counts = new Object2IntOpenHashMap<>(); - for (var memory : logic.getMemory().values()) { - for (ItemStack stack : memory) { - counts.merge(new ItemTestObject(stack), stack.getCount(), Integer::sum); - } - } + Object2LongMap counts = logic.getSum(); - for (var entry : counts.object2IntEntrySet()) { + for (var entry : counts.object2LongEntrySet()) { ItemStack stack = entry.getKey().recombine(); - String value = TextFormattingUtil.formatNumbers(entry.getIntValue() * 20L / ItemFlowLogic.MEMORY_TICKS); + String value = TextFormattingUtil.formatNumbers(20 * entry.getLongValue() / ItemFlowLogic.MEMORY_TICKS); iProbeInfo.horizontal(iProbeInfo.defaultLayoutStyle().alignment(ElementAlignment.ALIGN_CENTER)) .item(stack) .text(" §b" + value + " /s §f" + stack.getDisplayName()); diff --git a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java index d7491a25a06..3d7e7dc8e0c 100644 --- a/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java +++ b/src/main/java/gregtech/integration/theoneprobe/provider/debug/DebugPipeNetInfoProvider.java @@ -42,7 +42,7 @@ public void addProbeInfo(@NotNull ProbeMode mode, @NotNull IProbeInfo probeInfo, } if (tileEntity instanceof PipeTileEntity pipeTile) { String builder = "{" + - ", mark: " + pipeTile.getPaintingColor() + + ", mark: " + pipeTile.getVisualColor() + ", open: " + pipeTile.getConnectionMask() + ", blocked: " + pipeTile.getBlockedMask() + "}"; From 8e0b84cedbac0ed5557e373fd25e195797428959 Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Mon, 23 Dec 2024 17:57:15 -0700 Subject: [PATCH 155/157] covers working and misc bugs patched --- .../api/capability/impl/FluidHandlerList.java | 84 ++ .../api/capability/impl/ItemHandlerList.java | 38 +- .../gregtech/api/graphnet/GraphNetBacker.java | 37 +- .../api/graphnet/GraphNetUtility.java | 109 ++- .../gregtech/api/graphnet/group/NetGroup.java | 4 +- .../graphnet/group/PathCacheGroupData.java | 6 +- .../gregtech/api/graphnet/net/NetEdge.java | 6 - .../api/graphnet/pipenet/WorldPipeNet.java | 14 +- .../physical/tile/PipeCapabilityWrapper.java | 10 - .../pipenet/physical/tile/PipeTileEntity.java | 2 +- .../pipenet/traverse/RoundRobinCache.java | 103 --- .../predicate/EdgePredicateHandler.java | 5 +- .../traverse/AbstractMinCostTraverse.java | 127 --- .../api/graphnet/traverse/EQTraverse.java | 143 --- .../traverse/{iter => }/EdgeDirection.java | 2 +- .../traverse/{iter => }/EdgeSelector.java | 2 +- .../api/graphnet/traverse/FDTraverse.java | 95 -- .../{iter => }/NetBreadthIterator.java | 2 +- .../{iter => }/NetClosestIterator.java | 2 +- .../traverse/{iter => }/NetIterator.java | 2 +- .../{iter => }/NetIteratorSupplier.java | 2 +- .../api/graphnet/traverse/RRTraverse.java | 75 -- .../ResilientNetClosestIterator.java | 2 +- .../api/graphnet/traverse/TweakedCSMCF.java | 828 ------------------ .../java/gregtech/api/util/GTUtility.java | 23 +- .../gregtech/common/covers/CoverConveyor.java | 376 +++++++- .../common/covers/CoverFluidRegulator.java | 19 - .../gregtech/common/covers/CoverPump.java | 530 +++++++---- .../common/covers/CoverRoboticArm.java | 28 - .../pipelike/net/energy/EnergyGroupData.java | 2 +- .../pipelike/net/energy/WorldEnergyNet.java | 2 +- .../net/fluid/FluidCapabilityObject.java | 68 +- .../pipelike/net/fluid/WorldFluidNet.java | 3 - .../net/item/ItemCapabilityObject.java | 218 +++-- .../pipelike/net/item/WorldItemNet.java | 3 - .../pipelike/net/laser/WorldLaserNet.java | 2 +- .../pipelike/net/optical/WorldOpticalNet.java | 2 +- .../resources/assets/gregtech/lang/en_us.lang | 2 +- .../java/gregtech/api/util/GTUtilityTest.java | 4 +- 39 files changed, 1123 insertions(+), 1859 deletions(-) create mode 100644 src/main/java/gregtech/api/capability/impl/FluidHandlerList.java delete mode 100644 src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java delete mode 100644 src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java rename src/main/java/gregtech/api/graphnet/traverse/{iter => }/EdgeDirection.java (94%) rename src/main/java/gregtech/api/graphnet/traverse/{iter => }/EdgeSelector.java (95%) delete mode 100644 src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java rename src/main/java/gregtech/api/graphnet/traverse/{iter => }/NetBreadthIterator.java (98%) rename src/main/java/gregtech/api/graphnet/traverse/{iter => }/NetClosestIterator.java (97%) rename src/main/java/gregtech/api/graphnet/traverse/{iter => }/NetIterator.java (93%) rename src/main/java/gregtech/api/graphnet/traverse/{iter => }/NetIteratorSupplier.java (84%) delete mode 100644 src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java rename src/main/java/gregtech/api/graphnet/traverse/{iter => }/ResilientNetClosestIterator.java (99%) delete mode 100644 src/main/java/gregtech/api/graphnet/traverse/TweakedCSMCF.java diff --git a/src/main/java/gregtech/api/capability/impl/FluidHandlerList.java b/src/main/java/gregtech/api/capability/impl/FluidHandlerList.java new file mode 100644 index 00000000000..ab6fad193b0 --- /dev/null +++ b/src/main/java/gregtech/api/capability/impl/FluidHandlerList.java @@ -0,0 +1,84 @@ +package gregtech.api.capability.impl; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.UnmodifiableView; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * Simple, standardized way to represent multiple fluid handlers as a single handler. + */ +public class FluidHandlerList implements IFluidHandler { + + private final Set list; + + public FluidHandlerList(Collection handlers) { + list = new ObjectOpenHashSet<>(handlers); + } + + @Override + public IFluidTankProperties[] getTankProperties() { + List list = new ObjectArrayList<>(); + for (IFluidHandler handler : this.list) { + Collections.addAll(list, handler.getTankProperties()); + } + return list.toArray(new IFluidTankProperties[0]); + } + + @Override + public int fill(FluidStack resource, boolean doFill) { + int filled = 0; + for (IFluidHandler handler : list) { + filled += handler.fill(resource, doFill); + } + return filled; + } + + @Override + public FluidStack drain(FluidStack resource, boolean doDrain) { + resource = resource.copy(); + int drain = 0; + for (IFluidHandler handler : list) { + FluidStack d = handler.drain(resource, doDrain); + if (d != null) { + drain += d.amount; + resource.amount -= d.amount; + } + } + if (drain == 0) return null; + resource.amount = drain; + return resource; + } + + @Override + public FluidStack drain(int maxDrain, boolean doDrain) { + FluidStack drain = null; + FluidStack helper = null; + for (IFluidHandler handler : list) { + if (drain == null) { + drain = handler.drain(maxDrain, doDrain); + helper = drain; + } else { + helper.amount = maxDrain - drain.amount; + FluidStack d = handler.drain(helper, doDrain); + if (d != null) drain.amount += d.amount; + } + } + return drain; + } + + @NotNull + @UnmodifiableView + public Collection getBackingHandlers() { + return list; + } +} diff --git a/src/main/java/gregtech/api/capability/impl/ItemHandlerList.java b/src/main/java/gregtech/api/capability/impl/ItemHandlerList.java index 78e52c7c72b..f38c15aeb42 100644 --- a/src/main/java/gregtech/api/capability/impl/ItemHandlerList.java +++ b/src/main/java/gregtech/api/capability/impl/ItemHandlerList.java @@ -6,7 +6,9 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.UnmodifiableView; import java.util.*; @@ -16,9 +18,9 @@ public class ItemHandlerList implements IItemHandlerModifiable { private final Int2ObjectMap handlerBySlotIndex = new Int2ObjectOpenHashMap<>(); - private final Map baseIndexOffset = new IdentityHashMap<>(); + private final Reference2IntOpenHashMap baseIndexOffset = new Reference2IntOpenHashMap<>(); - public ItemHandlerList(Iterable itemHandlerList) { + public ItemHandlerList(Collection itemHandlerList) { int currentSlotIndex = 0; for (IItemHandler itemHandler : itemHandlerList) { if (baseIndexOffset.containsKey(itemHandler)) { @@ -40,42 +42,50 @@ public int getSlots() { @Override public void setStackInSlot(int slot, @NotNull ItemStack stack) { - IItemHandler itemHandler = handlerBySlotIndex.get(slot); + IItemHandler itemHandler = getHandlerBySlot(slot); if (!(itemHandler instanceof IItemHandlerModifiable)) throw new UnsupportedOperationException("Handler " + itemHandler + " does not support this method"); - ((IItemHandlerModifiable) itemHandler).setStackInSlot(slot - baseIndexOffset.get(itemHandler), stack); + ((IItemHandlerModifiable) itemHandler).setStackInSlot(slot - getOffsetByHandler(itemHandler), stack); } @NotNull @Override public ItemStack getStackInSlot(int slot) { - IItemHandler itemHandler = handlerBySlotIndex.get(slot); - int realSlot = slot - baseIndexOffset.get(itemHandler); - return itemHandler.getStackInSlot(slot - baseIndexOffset.get(itemHandler)); + IItemHandler itemHandler = getHandlerBySlot(slot); + return itemHandler.getStackInSlot(slot - getOffsetByHandler(itemHandler)); } @Override public int getSlotLimit(int slot) { - IItemHandler itemHandler = handlerBySlotIndex.get(slot); - return itemHandler.getSlotLimit(slot - baseIndexOffset.get(itemHandler)); + IItemHandler itemHandler = getHandlerBySlot(slot); + return itemHandler.getSlotLimit(slot - getOffsetByHandler(itemHandler)); } @NotNull @Override public ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { - IItemHandler itemHandler = handlerBySlotIndex.get(slot); - return itemHandler.insertItem(slot - baseIndexOffset.get(itemHandler), stack, simulate); + IItemHandler itemHandler = getHandlerBySlot(slot); + return itemHandler.insertItem(slot - getOffsetByHandler(itemHandler), stack, simulate); } @NotNull @Override public ItemStack extractItem(int slot, int amount, boolean simulate) { - IItemHandler itemHandler = handlerBySlotIndex.get(slot); - return itemHandler.extractItem(slot - baseIndexOffset.get(itemHandler), amount, simulate); + IItemHandler itemHandler = getHandlerBySlot(slot); + return itemHandler.extractItem(slot - getOffsetByHandler(itemHandler), amount, simulate); } @NotNull + @UnmodifiableView public Collection getBackingHandlers() { - return Collections.unmodifiableCollection(handlerBySlotIndex.values()); + return handlerBySlotIndex.values(); + } + + public IItemHandler getHandlerBySlot(int slot) { + return handlerBySlotIndex.get(slot); + } + + public int getOffsetByHandler(IItemHandler handler) { + return baseIndexOffset.getInt(handler); } } diff --git a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java index a3215188dbf..6c67d8c4060 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetBacker.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetBacker.java @@ -3,12 +3,13 @@ import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.graph.INetGraph; +import gregtech.api.graphnet.group.GroupGraphView; import gregtech.api.graphnet.group.MergeDirection; import gregtech.api.graphnet.group.NetGroup; import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.traverse.iter.EdgeDirection; +import gregtech.api.graphnet.traverse.EdgeDirection; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -255,4 +256,38 @@ public void readFromNBT(@NotNull NBTTagCompound nbt) { return compound; } + + public static NBTTagCompound writeGroupToNBT(NetGroup group) { + NBTTagCompound compound = new NBTTagCompound(); + GroupGraphView graph = group.getGraphView(); + // map of net groups -> autogenerated ids; + // tag of autogenerated vertex ids -> node nbt & group id + // tag of autogenerated edge ids -> edge nbt & source/target ids + Object2IntOpenHashMap vertexMap = new Object2IntOpenHashMap<>(); + int i = 0; + NBTTagList vertices = new NBTTagList(); + for (GraphVertex graphVertex : graph.vertexSet()) { + if (graphVertex.wrapped == null) continue; + vertexMap.put(graphVertex, i); + NBTTagCompound tag = graphVertex.wrapped.serializeNBT(); + tag.setString("ClassType", graphVertex.wrapped.getType().getName()); + vertices.appendTag(tag); + i++; + } + compound.setTag("Vertices", vertices); + + NBTTagList edges = new NBTTagList(); + for (GraphEdge graphEdge : graph.edgeSet()) { + if (graphEdge.wrapped == null) continue; + NBTTagCompound tag = graphEdge.wrapped.serializeNBT(); + tag.setInteger("SourceID", vertexMap.getInt(graphEdge.getSource())); + tag.setInteger("TargetID", vertexMap.getInt(graphEdge.getTarget())); + tag.setDouble("Weight", graphEdge.getWeight()); + tag.setString("ClassType", graphEdge.wrapped.getType().getName()); + edges.appendTag(tag); + } + compound.setTag("Edges", edges); + + return compound; + } } diff --git a/src/main/java/gregtech/api/graphnet/GraphNetUtility.java b/src/main/java/gregtech/api/graphnet/GraphNetUtility.java index 73885bb8220..810204d6328 100644 --- a/src/main/java/gregtech/api/graphnet/GraphNetUtility.java +++ b/src/main/java/gregtech/api/graphnet/GraphNetUtility.java @@ -1,44 +1,97 @@ package gregtech.api.graphnet; import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.traverse.iter.EdgeDirection; -import gregtech.api.graphnet.traverse.iter.EdgeSelector; -import gregtech.api.graphnet.traverse.iter.NetClosestIterator; +import gregtech.api.graphnet.predicate.test.IPredicateTestObject; +import gregtech.api.graphnet.traverse.ResilientNetClosestIterator; +import gregtech.api.util.MapUtil; -import org.jetbrains.annotations.NotNull; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; + +import java.util.ArrayDeque; +import java.util.function.ObjIntConsumer; +import java.util.function.Predicate; +import java.util.function.ToIntFunction; public final class GraphNetUtility { private GraphNetUtility() {} - public static boolean isOnlyBridge(@NotNull NetEdge bridge) { - NetNode sourceNode = bridge.getSource(); - NetNode destNode = bridge.getTarget(); - if (sourceNode == null || destNode == null) return false; - EdgeSelector selector = bridgeFiltered(EdgeDirection.ALL, sourceNode, destNode); - NetClosestIterator sourceFrontier = new NetClosestIterator(sourceNode, selector); - NetClosestIterator destFrontier = new NetClosestIterator(destNode, selector); - // since we check all edges, if either frontier exhausts we know that they cannot coincide. - while (sourceFrontier.hasNext() && destFrontier.hasNext()) { - NetNode next = sourceFrontier.next(); - // the dest frontier has seen the next node in the source frontier, we are not the only bridge. - if (destFrontier.hasSeen(next)) return false; - next = destFrontier.next(); - // the source frontier has seen the next node in the dest frontier, we are not the only bridge. - if (sourceFrontier.hasSeen(next)) return false; + public static int p2pWalk(boolean simulate, int available, ToIntFunction limit, + ObjIntConsumer report, + ResilientNetClosestIterator forwardFrontier, + ResilientNetClosestIterator backwardFrontier) { + Object2IntOpenHashMap flowLimitCache = new Object2IntOpenHashMap<>(); + int actual = 0; + main: + while (forwardFrontier.hasNext() || backwardFrontier.hasNext()) { + if (available <= 0) break; + NetNode next = null; + if (forwardFrontier.hasNext()) { + next = forwardFrontier.next(); + if (MapUtil.computeIfAbsent(flowLimitCache, next, limit) <= 0) { + forwardFrontier.markInvalid(next); + next = null; + } + } + if (next == null || !backwardFrontier.hasSeen(next)) { + if (backwardFrontier.hasNext()) { + next = backwardFrontier.next(); + if (MapUtil.computeIfAbsent(flowLimitCache, next, limit) <= 0) { + backwardFrontier.markInvalid(next); + continue; + } + if (!forwardFrontier.hasSeen(next)) continue; + } else continue; + } + // next is not null and both frontiers have paths leading to next + int allowed = available; + NetEdge span; + NetNode trace = next; + ArrayDeque seen = new ArrayDeque<>(); + seen.add(next); + while ((span = forwardFrontier.getSpanningTreeEdge(trace)) != null) { + trace = span.getOppositeNode(trace); + if (trace == null) continue main; + int l = MapUtil.computeIfAbsent(flowLimitCache, trace, limit); + if (l == 0) { + // shouldn't happen + forwardFrontier.markInvalid(trace); + continue main; + } + allowed = Math.min(allowed, l); + seen.addFirst(trace); + } + trace = next; + while ((span = backwardFrontier.getSpanningTreeEdge(trace)) != null) { + trace = span.getOppositeNode(trace); + if (trace == null) continue main; + int l = MapUtil.computeIfAbsent(flowLimitCache, trace, limit); + if (l == 0) { + // shouldn't happen + backwardFrontier.markInvalid(trace); + continue main; + } + allowed = Math.min(allowed, l); + seen.addLast(trace); + } + available -= allowed; + actual += allowed; + for (NetNode n : seen) { + if (!simulate) report.accept(n, allowed); + int remaining = flowLimitCache.getInt(n) - allowed; + flowLimitCache.put(n, remaining); + if (remaining <= 0) { + forwardFrontier.markInvalid(n); + backwardFrontier.markInvalid(n); + } + } } - return true; + return actual; } - public static EdgeSelector bridgeFiltered(@NotNull EdgeSelector basis, - @NotNull NetNode sourceNode, @NotNull NetNode destNode) { - GraphEdge e1 = GraphEdge.unwrap(sourceNode.getNet().getEdge(sourceNode, destNode)); - GraphEdge e2 = GraphEdge.unwrap(sourceNode.getNet().getEdge(destNode, sourceNode)); - GraphVertex v1 = GraphVertex.unwrap(sourceNode); - GraphVertex v2 = GraphVertex.unwrap(destNode); - return null; + public static Predicate standardEdgeBlacklist(IPredicateTestObject testObject) { + return o -> o instanceof GraphEdge e && e.wrapped != null && !e.wrapped.test(testObject); } } diff --git a/src/main/java/gregtech/api/graphnet/group/NetGroup.java b/src/main/java/gregtech/api/graphnet/group/NetGroup.java index 118d73eaa37..2e53504c9ed 100644 --- a/src/main/java/gregtech/api/graphnet/group/NetGroup.java +++ b/src/main/java/gregtech/api/graphnet/group/NetGroup.java @@ -4,8 +4,8 @@ import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.traverse.iter.EdgeDirection; -import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; +import gregtech.api.graphnet.traverse.EdgeDirection; +import gregtech.api.graphnet.traverse.NetBreadthIterator; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; diff --git a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java index b02f7172217..40b4110a741 100644 --- a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java +++ b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java @@ -6,9 +6,9 @@ import gregtech.api.graphnet.path.PathBuilder; import gregtech.api.graphnet.path.SingletonNetPath; import gregtech.api.graphnet.path.StandardNetPath; -import gregtech.api.graphnet.traverse.iter.EdgeDirection; -import gregtech.api.graphnet.traverse.iter.NetIterator; -import gregtech.api.graphnet.traverse.iter.NetIteratorSupplier; +import gregtech.api.graphnet.traverse.EdgeDirection; +import gregtech.api.graphnet.traverse.NetIterator; +import gregtech.api.graphnet.traverse.NetIteratorSupplier; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.apache.commons.lang3.tuple.ImmutablePair; diff --git a/src/main/java/gregtech/api/graphnet/net/NetEdge.java b/src/main/java/gregtech/api/graphnet/net/NetEdge.java index ce20217a004..fd0632dad86 100644 --- a/src/main/java/gregtech/api/graphnet/net/NetEdge.java +++ b/src/main/java/gregtech/api/graphnet/net/NetEdge.java @@ -16,8 +16,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.function.Predicate; - public class NetEdge implements INBTSerializable { public static final GraphClassType TYPE = new GraphClassType<>(GTValues.MODID, "NetEdge", @@ -110,8 +108,4 @@ public void deserializeNBT(NBTTagCompound nbt) { public GraphClassType getType() { return TYPE; } - - public static Predicate standardBlacklist(IPredicateTestObject testObject) { - return o -> o instanceof NetEdge e && !e.test(testObject); - } } diff --git a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java index 884e8b138b9..3f49ea2e19f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/WorldPipeNet.java @@ -15,7 +15,7 @@ import gregtech.api.graphnet.pipenet.predicate.BlockedPredicate; import gregtech.api.graphnet.predicate.EdgePredicate; import gregtech.api.graphnet.predicate.NetPredicateType; -import gregtech.api.graphnet.traverse.iter.EdgeDirection; +import gregtech.api.graphnet.traverse.EdgeDirection; import gregtech.api.util.IDirtyNotifiable; import gregtech.api.util.reference.WeakHashSet; import gregtech.common.covers.CoverShutter; @@ -135,21 +135,21 @@ protected boolean predicateEdge(@NotNull NetEdge edge, @NotNull NetNode source, edge.getPredicateHandler().getPredicateSet()); edge.getPredicateHandler().clearPredicates(); coverPredication(edge, coverSource, coverTarget); - boolean edgeSame = !prevValue.equals(edge.getPredicateHandler().getPredicateSet()); + boolean edgeDifferent = !prevValue.equals(edge.getPredicateHandler().getPredicateSet()); if (getGraph().isDirected()) { edge = getEdge(target, source); - if (edge == null) return edgeSame; - if (edgeSame) { + if (edge == null) return edgeDifferent; + if (edgeDifferent) { prevValue.clear(); prevValue.putAll(edge.getPredicateHandler().getPredicateSet()); } edge.getPredicateHandler().clearPredicates(); coverPredication(edge, coverSource, coverTarget); - if (edgeSame) { - edgeSame = !prevValue.equals(edge.getPredicateHandler().getPredicateSet()); + if (!edgeDifferent) { + edgeDifferent = !prevValue.equals(edge.getPredicateHandler().getPredicateSet()); } } - return edgeSame; + return edgeDifferent; } /** diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java index 5e2f660e7e9..2c4ca57a15f 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeCapabilityWrapper.java @@ -9,7 +9,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public class PipeCapabilityWrapper implements ICapabilityProvider { @@ -65,16 +64,8 @@ public boolean isActive(@NotNull EnumFacing facing) { return (this.activeMask & 1 << facing.ordinal()) > 0; } - public T getCapabilityCoverQuery(@NotNull Capability capability, @Nullable EnumFacing facing) { - // covers have access to the capability objects no matter the connection status - IPipeCapabilityObject object = capabilities.get(capability); - if (object == null) return null; - return object.getCapability(capability, facing); - } - @Override public boolean hasCapability(@NotNull Capability capability, EnumFacing facing) { - if (facing != null && !isActive(facing)) return false; IPipeCapabilityObject obj = capabilities.get(capability); if (obj == null) return false; return obj.hasCapability(capability, facing); @@ -82,7 +73,6 @@ public boolean hasCapability(@NotNull Capability capability, EnumFacing facin @Override public T getCapability(@NotNull Capability capability, EnumFacing facing) { - if (facing != null && !isActive(facing)) return null; IPipeCapabilityObject obj = capabilities.get(capability); if (obj == null) return null; return obj.getCapability(capability, facing); diff --git a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java index a684f20d871..b30aaaec531 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/physical/tile/PipeTileEntity.java @@ -429,7 +429,7 @@ private void setAllIdle(EnumFacing facing) { public T getCapabilityCoverQuery(@NotNull Capability capability, @Nullable EnumFacing facing) { for (PipeCapabilityWrapper wrapper : netCapabilities.values()) { - T cap = wrapper.getCapabilityCoverQuery(capability, facing); + T cap = wrapper.getCapability(capability, facing); if (cap != null) return cap; } return null; diff --git a/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java b/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java deleted file mode 100644 index aa7f1e61c3a..00000000000 --- a/src/main/java/gregtech/api/graphnet/pipenet/traverse/RoundRobinCache.java +++ /dev/null @@ -1,103 +0,0 @@ -package gregtech.api.graphnet.pipenet.traverse; - -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.traverse.iter.NetIterator; - -import com.github.bsideup.jabel.Desugar; -import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; - -import java.util.ArrayDeque; -import java.util.Collection; -import java.util.function.Predicate; -import java.util.function.Supplier; - -@Desugar -public record RoundRobinCache(ObjectLinkedOpenHashSet sourceCache, - ObjectLinkedOpenHashSet destCache) { - - public static RoundRobinCache create() { - return new RoundRobinCache(new ObjectLinkedOpenHashSet<>(), new ObjectLinkedOpenHashSet<>()); - } - - public Supplier> buildSupplier(Collection sourceCandidates, - Collection destCandidates) { - return sourceCandidates.isEmpty() || destCandidates.isEmpty() ? () -> null : - new CacheSupplier(sourceCandidates, destCandidates); - } - - public RoundRobinCache refresh(NetIterator sources, NetIterator targets) { - sourceCache.removeIf(n -> !sources.hasSeen(n)); - destCache.removeIf(n -> !targets.hasSeen(n)); - return this; - } - - public void filter(Predicate sourceFilter, Predicate destFilter) { - sourceCache.removeIf(sourceFilter); - destCache.removeIf(destFilter); - } - - public void clear() { - sourceCache.clear(); - destCache.clear(); - } - - public RoundRobinCache copy() { - return new RoundRobinCache(sourceCache.clone(), destCache.clone()); - } - - private final class CacheSupplier implements Supplier> { - - private final ArrayDeque sources; - private ArrayDeque dests; - private ArrayDeque destBacklog; - - public CacheSupplier(Collection sourceCandidates, Collection destCandidates) { - this.sources = new ArrayDeque<>(sourceCandidates); - this.dests = new ArrayDeque<>(destCandidates); - this.destBacklog = new ArrayDeque<>(destCandidates.size()); - } - - @Override - public Predicate get() { - if (dests.isEmpty()) { - ArrayDeque queue = dests; - dests = destBacklog; - destBacklog = queue; - sources.removeFirst(); - if (sources.isEmpty()) return null; - int i = 0; - while (true) { - NetNode s = sources.peekFirst(); - // yeet the first if we've gone through the entire deque without a match - if (i >= sources.size()) { - sourceCache.removeFirst(); - i = 0; - } - if (!sourceCache.contains(s) || sourceCache.first() == s) break; - i++; - sources.addLast(sources.removeFirst()); - } - } - NetNode s = sources.peekFirst(); - NetNode d; - int i = 0; - while (true) { - d = dests.removeFirst(); - // yeet the first if we've gone through the entire deque without a match - if (i >= dests.size()) { - destCache.removeFirst(); - i = 0; - } - if (!destCache.contains(d) || destCache.first() == d) break; - i++; - dests.addLast(d); - - } - destBacklog.addLast(d); - sourceCache.addAndMoveToLast(s); - destCache.addAndMoveToLast(d); - NetNode finalD = d; - return n -> n == s || n == finalD; - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java index 990805dbc57..fa10f9c1fba 100644 --- a/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java +++ b/src/main/java/gregtech/api/graphnet/predicate/EdgePredicateHandler.java @@ -103,10 +103,7 @@ public void deserializeNBT(NBTTagList nbt) { for (int i = 0; i < nbt.tagCount(); i++) { NBTTagCompound tag = nbt.getCompoundTagAt(i); NetPredicateType type = NetPredicateRegistry.getType(tag.getString("Type")); - EdgePredicate entry = this.predicateSet.get(type); - if (entry == null) { - entry = type.getNew(); - } + EdgePredicate entry = this.predicateSet.computeIfAbsent(type, NetPredicateType::getNew); entry.deserializeNBTNaive(tag.getTag("Tag")); } } diff --git a/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java deleted file mode 100644 index e18414a065e..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverse/AbstractMinCostTraverse.java +++ /dev/null @@ -1,127 +0,0 @@ -package gregtech.api.graphnet.traverse; - -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.net.NetEdge; -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.util.GTUtility; - -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import org.jetbrains.annotations.NotNull; -import org.jgrapht.alg.flow.mincost.CapacityScalingMinimumCostFlow; -import org.jgrapht.alg.flow.mincost.MinimumCostFlowProblem; -import org.jgrapht.alg.interfaces.MinimumCostFlowAlgorithm; - -import java.util.function.Function; - -public abstract class AbstractMinCostTraverse implements MinimumCostFlowProblem { - - protected static final TweakedCSMCF MINCOST = new TweakedCSMCF(); - - protected static final GraphVertex CORRECTOR = new GraphVertex(); - - protected int correction = 0; - - public @NotNull EvaluationResult evaluate() { - try { - correction = 0; - getGraph().addVertex(CORRECTOR); - int count = 0; - for (GraphVertex v : getGraph().vertexSet()) { - if (v.getWrapped() != null) { - int supply = getSupply(v.getWrapped()); - if (supply != 0) { - correction -= supply; - GraphEdge e = new GraphEdge(); - if (supply < 0) { - if (!getGraph().addEdge(CORRECTOR, v, e)) { - getGraph().removeEdge(CORRECTOR, v); - getGraph().addEdge(CORRECTOR, v, e); - } - } else { - if (!getGraph().addEdge(v, CORRECTOR, e)) { - getGraph().removeEdge(v, CORRECTOR); - getGraph().addEdge(v, CORRECTOR, e); - } - } - getGraph().setEdgeWeight(e, CapacityScalingMinimumCostFlow.COST_INF - 1); - count++; - } - } - } - MinimumCostFlowAlgorithm.MinimumCostFlow flow = MINCOST.getMinimumCostFlow(this); - EvaluationResult result = new EvaluationResult(count, flow.getFlowMap().size()); - for (var entry : flow.getFlowMap().entrySet()) { - NetEdge e = entry.getKey().getWrapped(); - if (e == null) { - GraphVertex v = entry.getKey().getOppositeVertex(CORRECTOR); - if (v != null && v.getWrapped() != null) { - // flow through the corrector is always unsatisfied supply/demand - int sat = GTUtility.moveACloserTo0ByB(getSupply(v.getWrapped()), entry.getValue().intValue()); - result.reportSupply(v.getWrapped(), sat); - } - } else if (entry.getValue().intValue() != 0) { - result.reportFlow(e, entry.getValue().intValue()); - } - } - return result; - } catch (Exception ignored) { - return EvaluationResult.EMPTY; - } finally { - getGraph().removeVertex(CORRECTOR); - } - } - - @Override - public Function getArcCapacityLowerBounds() { - return e -> 0; - } - - @Override - public Function getArcCapacityUpperBounds() { - return e -> e.getWrapped() == null ? CapacityScalingMinimumCostFlow.CAP_INF : getCapacity(e.getWrapped()); - } - - @Override - public Function getNodeSupply() { - return v -> v.getWrapped() != null ? getSupply(v.getWrapped()) : v == CORRECTOR ? correction : 0; - } - - protected abstract int getSupply(NetNode node); - - protected abstract int getCapacity(NetEdge edge); - - public static class EvaluationResult { - - public static final EvaluationResult EMPTY = new EvaluationResult(0, 0); - - protected final Object2IntOpenHashMap flowMap; - protected final Object2IntOpenHashMap supplyMap; - - public EvaluationResult(int sizeSupply, int sizeFlow) { - supplyMap = new Object2IntOpenHashMap<>(sizeSupply); - flowMap = new Object2IntOpenHashMap<>(sizeFlow); - } - - public Object2IntOpenHashMap getFlowMap() { - return flowMap; - } - - public Object2IntOpenHashMap getSupplyMap() { - return supplyMap; - } - - public void reportFlow(NetEdge edge, int flow) { - flowMap.put(edge, flow); - } - - public void reportSupply(NetNode node, int supply) { - supplyMap.put(node, supply); - } - - public boolean isEmpty() { - // if there were no flows, there should be no supply - return flowMap.isEmpty(); - } - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java deleted file mode 100644 index 4d89679826b..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverse/EQTraverse.java +++ /dev/null @@ -1,143 +0,0 @@ -package gregtech.api.graphnet.traverse; - -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.group.NetGroup; -import gregtech.api.graphnet.net.NetEdge; -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.util.GTUtility; - -import com.github.bsideup.jabel.Desugar; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; - -import java.util.Comparator; -import java.util.Set; -import java.util.function.ObjIntConsumer; -import java.util.function.Predicate; -import java.util.function.ToIntFunction; - -public class EQTraverse extends AbstractMinCostTraverse { - - protected final Graph graph; - protected final ToIntFunction capacityFunction; - protected final ToIntFunction supplyFunction; - protected @Nullable Predicate lossyNodes; - - protected final Set suppliers; - protected final Set consumers; - protected TestCase testCase; - - /** - * Perform equal distribution traverse. Equal distribution traverse draws the same amount from all sources, - * and deposits a separately calculated amount to all sinks. Drawn and deposited amounts will be maximized, - * and loss will be ignored until the final stage of traverse and reporting. - * - * @param group the net group the traverse takes place in - * @param flowReporterNode flow reporter for nodes. Positive values mean draw, negative values mean sink. - * @param flowReporterEdge flow reporter for edges. Always positive. - * @param capacityFunction capacity function for edges. - * @param supplyFunction supply function for nodes. Positive values mean available draw, negative values mean - * available sink. - * @param lossyNodes optional function that marks nodes as lossy. Lossy nodes will eat up to - * {@link Short#MIN_VALUE} flow and their normal supply will be ignored. - * @param lossReporter optional reporter for loss. Always negative. Does nothing if lossy nodes is {@code null}. - * @return the total draw/sink after evaluation. - */ - public static int equalDistribution(@NotNull NetGroup group, - @NotNull ObjIntConsumer flowReporterNode, - @NotNull ObjIntConsumer flowReporterEdge, - @NotNull ToIntFunction capacityFunction, - @NotNull ToIntFunction supplyFunction, - @Nullable Predicate lossyNodes, - @Nullable ObjIntConsumer lossReporter) { - if (!group.getGraphView().getType().isDirected()) { - throw new IllegalArgumentException("Cannot perform equal distribution traverse logic on undirected graph!"); - } - int minSupplier = Integer.MAX_VALUE; - Set suppliers = new ObjectOpenHashSet<>(); - int minConsumer = Integer.MIN_VALUE; - Set consumers = new ObjectOpenHashSet<>(); - for (GraphVertex v : group.getGraphView().vertexSet()) { - if (v.getWrapped() != null) { - int supply = supplyFunction.applyAsInt(v.getWrapped()); - if (supply > 0) { - minSupplier = Math.min(minSupplier, supply); - suppliers.add(v.getWrapped()); - } else if (supply < 0) { - minConsumer = Math.max(minConsumer, supply); - consumers.add(v.getWrapped()); - } - } - } - if (suppliers.size() == 0 || consumers.size() == 0) return 0; - // do some math to determine the working multiples that need to be tested - // supplier count * test supply must equal consumer count * test consumption for all tests - // naive brute force search for now - ObjectArrayList cases = new ObjectArrayList<>(); - for (int s = 1; s <= minSupplier; s++) { - for (int c = -1; c >= minConsumer; c--) { - if (suppliers.size() * s == consumers.size() * -c) - cases.add(new TestCase(minSupplier, minConsumer)); - } - } - // sort the cases from max flow to min flow - TestCase[] arr = cases.stream().sorted(Comparator.comparingInt(c -> suppliers.size() * c.supply)) - .toArray(TestCase[]::new); - // execute binary searching on test cases - EQTraverse traverse = new EQTraverse(group.getGraphView(), capacityFunction, supplyFunction, suppliers, - consumers); - int solution = (int) GTUtility.binarySearch(0, arr.length - 1, l -> { - traverse.testCase = arr[(int) l]; - EvaluationResult result = traverse.evaluate(); - // a success requires flow to have happened, - // supply map to contain all suppliers and consumers and nothing else, - // and all supply values to match either the supply or consumption for the test case. - return !result.isEmpty() && - result.getSupplyMap().size() == traverse.suppliers.size() + traverse.consumers.size() && - result.getSupplyMap().object2IntEntrySet().stream().map(Object2IntMap.Entry::getIntValue) - .allMatch(i -> i == traverse.testCase.supply || i == traverse.testCase.consumption); - }, false); - // finally, evaluate with loss enabled - traverse.testCase = arr[solution]; - traverse.lossyNodes = lossyNodes; - EvaluationResult result = traverse.evaluate(); - if (result.isEmpty()) return 0; - result.getFlowMap().forEach(flowReporterEdge::accept); - return FDTraverse.reportSupply(flowReporterNode, lossyNodes, lossReporter, result); - } - - protected EQTraverse(Graph graph, ToIntFunction capacityFunction, - ToIntFunction supplyFunction, Set suppliers, Set consumers) { - this.graph = graph; - this.capacityFunction = capacityFunction; - this.supplyFunction = supplyFunction; - this.suppliers = suppliers; - this.consumers = consumers; - } - - @Override - protected int getSupply(NetNode node) { - if (lossyNodes != null && lossyNodes.test(node)) return Short.MIN_VALUE; - if (suppliers.contains(node)) return testCase.supply; - if (consumers.contains(node)) return testCase.consumption; - return 0; - } - - @Override - protected int getCapacity(NetEdge edge) { - return capacityFunction.applyAsInt(edge); - } - - @Override - public Graph getGraph() { - return graph; - } - - @Desugar - protected record TestCase(int supply, int consumption) {} -} diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java b/src/main/java/gregtech/api/graphnet/traverse/EdgeDirection.java similarity index 94% rename from src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java rename to src/main/java/gregtech/api/graphnet/traverse/EdgeDirection.java index c798fbc042e..6cce9fca6de 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeDirection.java +++ b/src/main/java/gregtech/api/graphnet/traverse/EdgeDirection.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.iter; +package gregtech.api.graphnet.traverse; import org.jgrapht.Graph; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java b/src/main/java/gregtech/api/graphnet/traverse/EdgeSelector.java similarity index 95% rename from src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java rename to src/main/java/gregtech/api/graphnet/traverse/EdgeSelector.java index 7cf07519d32..1082fd9b08e 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/EdgeSelector.java +++ b/src/main/java/gregtech/api/graphnet/traverse/EdgeSelector.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.iter; +package gregtech.api.graphnet.traverse; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jgrapht.Graph; diff --git a/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java deleted file mode 100644 index 81b66a355da..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverse/FDTraverse.java +++ /dev/null @@ -1,95 +0,0 @@ -package gregtech.api.graphnet.traverse; - -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.group.NetGroup; -import gregtech.api.graphnet.net.NetEdge; -import gregtech.api.graphnet.net.NetNode; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; - -import java.util.function.ObjIntConsumer; -import java.util.function.Predicate; -import java.util.function.ToIntFunction; - -public class FDTraverse extends AbstractMinCostTraverse { - - protected final Graph graph; - protected final ToIntFunction capacityFunction; - protected final ToIntFunction supplyFunction; - protected final Predicate lossyNodes; - - /** - * Perform flood traverse. Flood traverse takes the lowest cost (weight) paths while maximizing flow. - * - * @param group the net group the traverse takes place in - * @param flowReporterNode flow reporter for nodes. Positive values mean draw, negative values mean sink. - * @param flowReporterEdge flow reporter for edges. Always positive. - * @param capacityFunction capacity function for edges. - * @param supplyFunction supply function for nodes. Positive values mean available draw, negative values mean - * available sink. - * @param lossyNodes optional function that marks nodes as lossy. Lossy nodes will eat up to - * {@link Short#MIN_VALUE} flow and their normal supply will be ignored. - * @param lossReporter optional reporter for loss. Always negative. Does nothing if lossy nodes is {@code null}. - * @return the total draw/sink after evaluation. - */ - public static int flood(@NotNull NetGroup group, - @NotNull ObjIntConsumer flowReporterNode, - @NotNull ObjIntConsumer flowReporterEdge, - @NotNull ToIntFunction capacityFunction, - @NotNull ToIntFunction supplyFunction, - @Nullable Predicate lossyNodes, - @Nullable ObjIntConsumer lossReporter) { - if (!group.getGraphView().getType().isDirected()) { - throw new IllegalArgumentException("Cannot perform flood traverse logic on undirected graph!"); - } - EvaluationResult result = new FDTraverse(group.getGraphView(), capacityFunction, supplyFunction, lossyNodes) - .evaluate(); - if (result.isEmpty()) return 0; - result.getFlowMap().forEach(flowReporterEdge::accept); - return reportSupply(flowReporterNode, lossyNodes, lossReporter, result); - } - - protected FDTraverse(Graph graph, ToIntFunction capacityFunction, - ToIntFunction supplyFunction, @Nullable Predicate lossyNodes) { - this.graph = graph; - this.capacityFunction = capacityFunction; - this.supplyFunction = supplyFunction; - this.lossyNodes = lossyNodes != null ? lossyNodes : n -> false; - } - - static int reportSupply(@NotNull ObjIntConsumer flowReporterNode, - @Nullable Predicate lossyNodes, - @Nullable ObjIntConsumer lossReporter, @NotNull EvaluationResult result) { - int flow = 0; - for (var entry : result.getSupplyMap().object2IntEntrySet()) { - NetNode n = entry.getKey(); - int i = entry.getIntValue(); - if (lossyNodes != null && lossyNodes.test(n)) { - if (lossReporter != null) lossReporter.accept(n, i); - } else { - flowReporterNode.accept(n, i); - } - if (i > 0) flow += i; - } - return flow; - } - - @Override - protected int getSupply(NetNode node) { - if (lossyNodes.test(node)) return Short.MIN_VALUE; - else return supplyFunction.applyAsInt(node); - } - - @Override - protected int getCapacity(NetEdge edge) { - return capacityFunction.applyAsInt(edge); - } - - @Override - public Graph getGraph() { - return graph; - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java b/src/main/java/gregtech/api/graphnet/traverse/NetBreadthIterator.java similarity index 98% rename from src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java rename to src/main/java/gregtech/api/graphnet/traverse/NetBreadthIterator.java index dc61f0f085a..b72f3be9f3c 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetBreadthIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/NetBreadthIterator.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.iter; +package gregtech.api.graphnet.traverse; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java b/src/main/java/gregtech/api/graphnet/traverse/NetClosestIterator.java similarity index 97% rename from src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java rename to src/main/java/gregtech/api/graphnet/traverse/NetClosestIterator.java index c2cad5be484..6e8b39a23ea 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetClosestIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/NetClosestIterator.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.iter; +package gregtech.api.graphnet.traverse; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java b/src/main/java/gregtech/api/graphnet/traverse/NetIterator.java similarity index 93% rename from src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java rename to src/main/java/gregtech/api/graphnet/traverse/NetIterator.java index 758322731a9..260f17c49de 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/NetIterator.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.iter; +package gregtech.api.graphnet.traverse; import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java b/src/main/java/gregtech/api/graphnet/traverse/NetIteratorSupplier.java similarity index 84% rename from src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java rename to src/main/java/gregtech/api/graphnet/traverse/NetIteratorSupplier.java index dae29ec1cc1..0ebf5985e4d 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/NetIteratorSupplier.java +++ b/src/main/java/gregtech/api/graphnet/traverse/NetIteratorSupplier.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.iter; +package gregtech.api.graphnet.traverse; import gregtech.api.graphnet.net.NetNode; diff --git a/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java b/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java deleted file mode 100644 index 1fe6176af39..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverse/RRTraverse.java +++ /dev/null @@ -1,75 +0,0 @@ -package gregtech.api.graphnet.traverse; - -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; -import gregtech.api.graphnet.group.NetGroup; -import gregtech.api.graphnet.net.NetEdge; -import gregtech.api.graphnet.net.NetNode; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jgrapht.Graph; - -import java.util.function.ObjIntConsumer; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.function.ToIntFunction; - -public class RRTraverse extends FDTraverse { - - protected java.util.function.Predicate nextPredicate; - - /** - * Perform round robin traverse. Round robin traverse asks repeatedly for a node predicate; - * each predicate will be evaluated independently using flood traverse, where only nodes that match the predicate - * or have loss are allowed to have supply/demand. - * - * @param group the net group the traverse takes place in - * @param nextNodePredicateSupplier supplier for next predicate. Will be repeatedly queried until it returns null, - * at which point the traverse will exit. - * @param flowReporterNode flow reporter for nodes. Positive values mean draw, negative values mean sink. - * @param flowReporterEdge flow reporter for edges. Always positive. - * @param capacityFunction capacity function for edges. - * @param supplyFunction supply function for nodes. Positive values mean available draw, negative values - * mean available sink. - * @param lossyNodes optional function that marks nodes as lossy. Lossy nodes will eat up to - * {@link Short#MIN_VALUE} flow and their normal supply will be ignored. - * @param lossReporter optional reporter for loss. Always negative. Does nothing if lossy nodes is - * {@code null}. - * @return the total draw/sink after evaluation. - */ - public static int roundRobin(@NotNull NetGroup group, - Supplier<@Nullable Predicate> nextNodePredicateSupplier, - @NotNull ObjIntConsumer flowReporterNode, - @NotNull ObjIntConsumer flowReporterEdge, - @NotNull ToIntFunction capacityFunction, - @NotNull ToIntFunction supplyFunction, - @Nullable Predicate lossyNodes, - @Nullable ObjIntConsumer lossReporter) { - if (!group.getGraphView().getType().isDirected()) { - throw new IllegalArgumentException("Cannot perform RR traverse logic on undirected graph!"); - } - RRTraverse traverse = new RRTraverse(group.getGraphView(), capacityFunction, supplyFunction, lossyNodes); - - int flow = 0; - while ((traverse.nextPredicate = nextNodePredicateSupplier.get()) != null) { - EvaluationResult result = traverse.evaluate(); - if (result.isEmpty()) continue; - result.getFlowMap().forEach(flowReporterEdge::accept); - flow += reportSupply(flowReporterNode, lossyNodes, lossReporter, result); - } - return flow; - } - - protected RRTraverse(Graph graph, ToIntFunction capacityFunction, - ToIntFunction supplyFunction, @Nullable Predicate lossyNodes) { - super(graph, capacityFunction, supplyFunction, lossyNodes); - } - - @Override - protected int getSupply(NetNode node) { - if (lossyNodes.test(node)) return Short.MIN_VALUE; - if (nextPredicate == null || nextPredicate.test(node)) return 0; - return supplyFunction.applyAsInt(node); - } -} diff --git a/src/main/java/gregtech/api/graphnet/traverse/iter/ResilientNetClosestIterator.java b/src/main/java/gregtech/api/graphnet/traverse/ResilientNetClosestIterator.java similarity index 99% rename from src/main/java/gregtech/api/graphnet/traverse/iter/ResilientNetClosestIterator.java rename to src/main/java/gregtech/api/graphnet/traverse/ResilientNetClosestIterator.java index 900449d0862..b97dd1c137f 100644 --- a/src/main/java/gregtech/api/graphnet/traverse/iter/ResilientNetClosestIterator.java +++ b/src/main/java/gregtech/api/graphnet/traverse/ResilientNetClosestIterator.java @@ -1,4 +1,4 @@ -package gregtech.api.graphnet.traverse.iter; +package gregtech.api.graphnet.traverse; import gregtech.api.graphnet.graph.GraphEdge; import gregtech.api.graphnet.graph.GraphVertex; diff --git a/src/main/java/gregtech/api/graphnet/traverse/TweakedCSMCF.java b/src/main/java/gregtech/api/graphnet/traverse/TweakedCSMCF.java deleted file mode 100644 index acadfd5a276..00000000000 --- a/src/main/java/gregtech/api/graphnet/traverse/TweakedCSMCF.java +++ /dev/null @@ -1,828 +0,0 @@ -package gregtech.api.graphnet.traverse; - -import gregtech.api.graphnet.graph.GraphEdge; -import gregtech.api.graphnet.graph.GraphVertex; - -import org.jgrapht.Graph; -import org.jgrapht.alg.flow.mincost.CapacityScalingMinimumCostFlow; -import org.jgrapht.alg.flow.mincost.MinimumCostFlowProblem; -import org.jgrapht.alg.interfaces.MinimumCostFlowAlgorithm; -import org.jgrapht.alg.util.Pair; -import org.jgrapht.util.CollectionUtil; -import org.jheaps.AddressableHeap; -import org.jheaps.tree.PairingHeap; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -/** - * Copy of {@link CapacityScalingMinimumCostFlow} from JGraphT with edits made for optimization within GT's application. - */ -public class TweakedCSMCF implements MinimumCostFlowAlgorithm { - - /** - * A capacity which is considered to be infinite. Every arc, which has upper capacity greater - * that or equal to this value is considered to be an infinite capacity arc. - */ - public static final int CAP_INF = 1000 * 1000 * 1000; - /** - * A cost which is considered to be infinite. This value is used internally for flow network - * transformation. That is why arcs with cost magnitude greater than or equal to this value are - * not allowed. - */ - public static final double COST_INF = 1e9; - /** - * Default scaling factor - */ - public static final int DEFAULT_SCALING_FACTOR = 8; - /** - * Debug variable - */ - private static final boolean DEBUG = false; - /** - * Scaling factor of this algorithm - */ - private final int scalingFactor; - /** - * Number of vertices in the network - */ - private int n; - /** - * Number of edges in the network - */ - private int m; - /** - * Variable that is used to determine whether a vertex has been labeled temporarily or - * permanently during Dijkstra's algorithm - */ - private int counter = 1; - /** - * Specified minimum cost flow problem - */ - private MinimumCostFlowProblem problem; - /** - * Computed minimum cost flow - */ - private MinimumCostFlow minimumCostFlow; - /** - * Array of internal nodes used by the algorithm. Node: these nodes are stored in the same order - * as vertices of the specified flow network. This allows to determine quickly their - * counterparts in the network. - */ - private Node[] nodes; - /** - * Array of internal arcs. Note: these arcs are stored in the same order as edges of the - * specified flow network. This allows to determine quickly their counterparts in the network. - */ - private Arc[] arcs; - /** - * List of vertices of the flow network. - */ - private List graphVertices; - /** - * List of edges of the flow network. - */ - private List graphEdges; - - /** - * Constructs a new instance of the algorithm which uses default scaling factor. - */ - public TweakedCSMCF() { - this(DEFAULT_SCALING_FACTOR); - } - - /** - * Constructs a new instance of the algorithm with custom {@code scalingFactor}. If the - * {@code scalingFactor} is less than 2, the algorithm doesn't use scaling. - * - * @param scalingFactor custom scaling factor - */ - public TweakedCSMCF(int scalingFactor) { - this.scalingFactor = scalingFactor; - Node.ID = 0; // for debug - } - - /** - * Returns mapping from edge to flow value through this particular edge - * - * @return maximum flow mapping, or null if a MinimumCostFlowProblem has not yet been solved. - */ - @Override - public Map getFlowMap() { - return minimumCostFlow == null ? null : this.minimumCostFlow.getFlowMap(); - } - - /** - * {@inheritDoc} - */ - @Override - public GraphVertex getFlowDirection(GraphEdge edge) { - return problem.getGraph().getEdgeTarget(edge); - } - - /** - * {@inheritDoc} - */ - @Override - public MinimumCostFlow getMinimumCostFlow( - final MinimumCostFlowProblem minimumCostFlowProblem) { - this.problem = Objects.requireNonNull(minimumCostFlowProblem); - if (problem.getGraph().getType().isUndirected()) { - throw new IllegalArgumentException( - "The algorithm doesn't support undirected flow networks"); - } - n = problem.getGraph().vertexSet().size(); - m = problem.getGraph().edgeSet().size(); - calculateMinimumCostFlow(); - - return minimumCostFlow; - } - - /** - * Returns solution to the dual linear program formulated on the network. Serves as a - * certificate of optimality. - *

- * It is represented as a mapping from graph nodes to their potentials (dual variables). Reduced - * cost of a arc $(a, b)$ is defined as $cost((a, b)) + potential(b) - potential(b)$. According - * to the reduced cost optimality conditions, a feasible solution to the minimum cost flow - * problem is optimal if and only if reduced cost of every non-saturated arc is greater than or - * equal to $0$. - * - * @return solution to the dual linear program formulated on the network, or null if a - * MinimumCostFlowProblem has not yet been solved. - */ - public Map getDualSolution() { - if (minimumCostFlow == null) - return null; - - Map dualVariables = new HashMap<>(); - for (int i = 0; i < n; i++) { - dualVariables.put(graphVertices.get(i), nodes[i].potential); - } - return dualVariables; - } - - /** - * Calculated a solution to the specified minimum cost flow problem. If the scaling factor is - * greater than 1, performs scaling phases, otherwise uses simple capacity scaling algorithm. - */ - private void calculateMinimumCostFlow() { - init(); - if (scalingFactor > 1) { - // run with scaling - int U = getU(); - int delta = scalingFactor; - while (U >= delta) { - delta *= scalingFactor; - } - delta /= scalingFactor; - while (delta >= 1) { - Pair, Set> pair = scale(delta); - pushAllFlow(pair.getFirst(), pair.getSecond(), delta); - delta /= scalingFactor; - } - } else { - // run without scaling - Pair, Set> pair = scale(1); - pushAllFlow(pair.getFirst(), pair.getSecond(), 1); - } - minimumCostFlow = finish(); - } - - /** - * Converts the flow network in the form convenient for the algorithm. Validated the arc - * capacities and costs. - *

- * Also, adds a dummy node to the network and arcs from every node to this dummy node, and from - * this dummy node to every other node. These added arcs have infinite capacities - * {@link CapacityScalingMinimumCostFlow#CAP_INF} and infinite costs - * {@link CapacityScalingMinimumCostFlow#COST_INF}. This ensures, that every search for an - * augmenting path to send at least $\Delta$ units of flow succeeds. - *

- * If the flow network has a feasible solution, at the end there will be no flow on the added - * arcs. Otherwise, the specified problem has no feasible solution. - */ - private void init() { - int supplySum = 0; - - // initialize data structures - nodes = new Node[n + 1]; - nodes[n] = new Node(0); // dummy node - arcs = new Arc[m]; - graphEdges = new ArrayList<>(m); - graphVertices = new ArrayList<>(n); - - Map nodeMap = CollectionUtil.newHashMapWithExpectedSize(n); - Graph graph = problem.getGraph(); - - // convert vertices into internal nodes - int i = 0; - for (GraphVertex vertex : graph.vertexSet()) { - graphVertices.add(vertex); - int supply = problem.getNodeSupply().apply(vertex); - supplySum += supply; - nodes[i] = new Node(supply); - nodeMap.put(vertex, nodes[i]); - // reduction - nodes[i].addArcTo(nodes[n], CAP_INF, COST_INF); - nodes[n].addArcTo(nodes[i], CAP_INF, COST_INF); - ++i; - } - if (Math.abs(supplySum) > 0) { - throw new IllegalArgumentException("Total node supply isn't equal to 0"); - } - i = 0; - // convert edges into their internal counterparts - for (GraphEdge edge : graph.edgeSet()) { - graphEdges.add(edge); - Node node = nodeMap.get(graph.getEdgeSource(edge)); - Node opposite = nodeMap.get(graph.getEdgeTarget(edge)); - int upperCap = problem.getArcCapacityUpperBounds().apply(edge); - int lowerCap = problem.getArcCapacityLowerBounds().apply(edge); - double cost = graph.getEdgeWeight(edge); - - if (upperCap < 0) { - throw new IllegalArgumentException("Negative edge capacities are not allowed"); - } else if (lowerCap > upperCap) { - throw new IllegalArgumentException( - "Lower edge capacity must not exceed upper edge capacity"); - } else if (lowerCap >= CAP_INF) { - throw new IllegalArgumentException( - "The problem is unbounded due to the infinite lower capacity"); - } else if (upperCap >= CAP_INF && cost < 0) { - throw new IllegalArgumentException( - "The algorithm doesn't support infinite capacity arcs with negative cost"); - } else if (Math.abs(cost) >= COST_INF) { - throw new IllegalArgumentException( - "Specified flow network contains an edge of infinite cost"); - } else if (node == opposite) { - throw new IllegalArgumentException("Self-loops aren't allowed"); - } - // remove non-zero lower capacity - node.excess -= lowerCap; - opposite.excess += lowerCap; - if (cost < 0) { - // removing negative edge costs - node.excess -= upperCap - lowerCap; - opposite.excess += upperCap - lowerCap; - Node t = node; - node = opposite; - opposite = t; - cost *= -1; - } - arcs[i] = node.addArcTo(opposite, upperCap - lowerCap, cost); - if (DEBUG) { - System.out.println(arcs[i]); - } - ++i; - } - if (DEBUG) { - System.out.println("Printing mapping"); - for (Map.Entry entry : nodeMap.entrySet()) { - System.out.println(entry + " -> " + entry); - } - } - } - - /** - * Returns the largest magnitude of any supply/demand or finite arc capacity. - * - * @return the largest magnitude of any supply/demand or finite arc capacity. - */ - private int getU() { - int result = 0; - for (Node node : nodes) { - result = Math.max(result, Math.abs(node.excess)); - } - for (Arc arc : arcs) { - if (!arc.isInfiniteCapacityArc()) { - result = Math.max(result, arc.residualCapacity); - } - } - return result; - } - - /** - * Performs a scaling phase by saturating all negative reduced cost arcs with residual capacity - * greater than or equal to the {@code delta}, so that they don't belong to the - * $\Delta$-residual network and, hence, don't violate optimality conditions. After that this - * method computes and returns nodes with positive excess greater than or equal to the - * {@code delta} and nodes with negative excesses that are less than or equal to {@code delta} - * - * @param delta current value of $\Delta$ - * @return the nodes with excesses no less than {@code delta} and no greater than {@code -delta} - */ - private Pair, Set> scale(int delta) { - if (DEBUG) { - System.out.println(String.format("Current delta = %d", delta)); - } - - // saturate all non-saturated arcs with negative edge costs in the delta-residual network - for (Node node : nodes) { - Arc nextArc = node.firstNonSaturated; - for (Arc arc = nextArc; arc != null; arc = nextArc) { - nextArc = nextArc.next; - int residualCapacity = arc.residualCapacity; - if (arc.residualCapacity >= delta && arc.getReducedCost() < 0) { - if (DEBUG) { - System.out.println("Saturating arc " + arc); - } - arc.sendFlow(residualCapacity); - arc.head.excess += residualCapacity; - arc.revArc.head.excess -= residualCapacity; - } - } - } - - // finding all nodes with excess magnitude no less than delta - List positiveExcessNodes = new ArrayList<>(); - Set negativeExcessNodes = new HashSet<>(); - for (Node node : nodes) { - if (node.excess >= delta) { - positiveExcessNodes.add(node); - } else if (node.excess <= -delta) { - negativeExcessNodes.add(node); - } - } - return new Pair<>(positiveExcessNodes, negativeExcessNodes); - } - - /** - * For every node in the {@code positiveExcessNodes} pushes all flow away from it until its - * excess is less than {@code delta}. This is always possible due to the performed flow network - * reduction during the initialization phase. - * - * @param positiveExcessNodes nodes from the network with positive excesses no less than - * {@code delta} - * @param negativeExcessNodes nodes from the network with negative excesses no greater than - * {@code delta} - * @param delta the current value of $\Delta$ - */ - private void pushAllFlow( - List positiveExcessNodes, Set negativeExcessNodes, int delta) { - for (Node node : positiveExcessNodes) { - while (node.excess >= delta) { - if (negativeExcessNodes.isEmpty()) { - return; - } - pushDijkstra(node, negativeExcessNodes, delta); - } - } - } - - /** - * Runs the Dijkstra's algorithm in the residual network using {@link Arc#getReducedCost()} as - * arc distances. - *

- * After reaching a node with excess no greater than {@code -delta}, augments it. Since the - * search is performed in the $\Delta$-residual network, the augmentation carries at least - * {@code delta} units of flow. The search always succeeds due to the flow network reduction - * performed during the initialization phase. - *

- * Updates the potentials of the nodes so that they: - *

    - *
  • Satisfy optimality conditions in the $\Delta$-residual network
  • - *
  • The reduced cost of the augmented path is equal to $0$
  • - *
- *

- * Let us denote some permanently labeled vertex as $u$, and the first - * permanently labeled vertex with negative excess as $v$. Let $dist(x)$ be the - * distance function in the residual network. Then we use the following formula to update the - * node potentials: $v.potential = v.potential + dist(v) - dist(u)$. The potentials of the - * temporarily labeled and unvisited vertices stay unchanged. - * - * @param start the start node for Dijkstra's algorithm - * @param negativeExcessNodes nodes from the network with negative excesses no greater than - * {@code delta} - * @param delta the current value of $\Delta$ - */ - private void pushDijkstra(Node start, Set negativeExcessNodes, int delta) { - int TEMPORARILY_LABELED = counter++; - int PERMANENTLY_LABELED = counter++; - AddressableHeap.Handle currentFibNode; - AddressableHeap heap = new PairingHeap<>(); - List permanentlyLabeled = new LinkedList<>(); - start.parentArc = null; - start.handle = heap.insert(0d, start); - - while (!heap.isEmpty()) { - currentFibNode = heap.deleteMin(); - double distance = currentFibNode.getKey(); - Node currentNode = currentFibNode.getValue(); - if (negativeExcessNodes.contains(currentNode)) { - // the path to push at least delta units of flow is found - augmentPath(start, currentNode); - if (currentNode.excess > -delta) { - negativeExcessNodes.remove(currentNode); - } - // updating potentials - for (Node node : permanentlyLabeled) { - node.potential += distance; - } - if (DEBUG) { - System.out.println(String.format("Distance = %.1f", distance)); - for (Node node : nodes) { - System.out.println( - String.format("Id = %d, potential = %.1f", node.id, node.potential)); - } - } - return; - } - currentNode.labelType = PERMANENTLY_LABELED; // currentNode becomes permanently labeled - permanentlyLabeled.add(currentNode); - for (Arc currentArc = currentNode.firstNonSaturated; currentArc != null; currentArc = currentArc.next) { - // looking only for arcs with residual capacity greater than delta - if (currentArc.residualCapacity < delta) { - continue; - } - Node opposite = currentArc.head; - if (opposite.labelType != PERMANENTLY_LABELED) { - if (opposite.labelType == TEMPORARILY_LABELED) { - // opposite has been labeled already - if (distance + currentArc.getReducedCost() < opposite.handle.getKey()) { - opposite.handle.decreaseKey(distance + currentArc.getReducedCost()); - opposite.parentArc = currentArc; - } - } else { - // opposite is encountered for the first time - opposite.labelType = TEMPORARILY_LABELED; - opposite.handle = heap.insert(distance + currentArc.getReducedCost(), opposite); - opposite.parentArc = currentArc; - } - } - } - currentNode.potential -= distance; // allows not to store the distances of the nodes - } - } - - /** - * Augments the path from {@code start} to the {@code end} sending as much flow as possible. - * Uses {@link Node#parentArc} computed by the Dijkstra's algorithm. Updates the excesses of the - * {@code start} and the {@code end} nodes. - * - * @param start the start of the augmenting path - * @param end the end of the augmenting path - */ - private void augmentPath(Node start, Node end) { - // compute delta to augment - int valueToAugment = Math.min(start.excess, -end.excess); - for (Arc arc = end.parentArc; arc != null; arc = arc.revArc.head.parentArc) { - valueToAugment = Math.min(valueToAugment, arc.residualCapacity); - } - if (DEBUG) { - ArrayList stack = new ArrayList<>(); - for (Arc arc = end.parentArc; arc != null; arc = arc.revArc.head.parentArc) { - stack.add(arc.head); - } - stack.add(start); - System.out.println("Printing augmenting path"); - for (int i = stack.size() - 1; i > 0; i--) { - System.out.print(stack.get(i).id + " -> "); - } - System.out.println(stack.get(0).id + ", delta = " + valueToAugment); - } - // augmenting the flow - end.excess += valueToAugment; - for (Arc arc = end.parentArc; arc != null; arc = arc.revArc.head.parentArc) { - arc.sendFlow(valueToAugment); - } - start.excess -= valueToAugment; - } - - /** - * Finishes the computation by checking the flow feasibility, computing arc flows, and creating - * an instance of {@link MinimumCostFlow}. The resulting flow mapping contains all edges of the - * specified minimum cost flow problem. - * - * @return the solution to the minimum cost flow problem - */ - private MinimumCostFlow finish() { - Map flowMap = CollectionUtil.newHashMapWithExpectedSize(m); - double totalCost = 0; - // check feasibility - for (Arc arc = nodes[n].firstNonSaturated; arc != null; arc = arc.next) { - if (arc.revArc.residualCapacity > 0) { - throw new IllegalArgumentException( - "Specified flow network problem has no feasible solution"); - } - } - // create the solution object - for (int i = 0; i < m; i++) { - GraphEdge graphEdge = graphEdges.get(i); - Arc arc = arcs[i]; - double flowOnArc = arc.revArc.residualCapacity; // this value equals to the flow on the - // initial arc - if (problem.getGraph().getEdgeWeight(graphEdge) < 0) { - // the initial arc goes in the opposite direction - flowOnArc = problem.getArcCapacityUpperBounds().apply(graphEdge) - - problem.getArcCapacityLowerBounds().apply(graphEdge) - flowOnArc; - } - flowOnArc += problem.getArcCapacityLowerBounds().apply(graphEdge); - flowMap.put(graphEdge, flowOnArc); - totalCost += flowOnArc * problem.getGraph().getEdgeWeight(graphEdge); - } - return new MinimumCostFlowImpl<>(totalCost, flowMap); - } - - /** - * Tests the optimality conditions after a flow of minimum cost has been computed. - *

- * More precisely, tests, whether the reduced cost of every non-saturated arc in the residual - * network is non-negative. This validation is performed with precision of {@code eps}. If the - * solution doesn't meet this condition, returns, false. - *

- * In general, this method should always return true unless the algorithm implementation has a - * bug. - * - * @param eps the precision to use - * @return true, if the computed solution is optimal, false otherwise. - */ - public boolean testOptimality(double eps) { - if (minimumCostFlow == null) - throw new RuntimeException( - "Cannot return a dual solution before getMinimumCostFlow(MinimumCostFlowProblem minimumCostFlowProblem) is invoked!"); - - for (Node node : nodes) { - for (Arc arc = node.firstNonSaturated; arc != null; arc = arc.next) { - if (arc.getReducedCost() < -eps) { - return false; - } - } - } - return true; - } - - /** - * Supporting data structure for the {@link CapacityScalingMinimumCostFlow}. - *

- * Is used as an internal representation of the vertices of the flow network. Contains all - * information needed during the computation. - * - * @author Timofey Chudakov - * @since July 2018 - */ - private static class Node { - - /** - * Variable for debug purposes - */ - private static int ID = 0; - /** - * Reference to the {@link } this node is contained in - */ - AddressableHeap.Handle handle; - /** - * An arc on the augmenting path which head is this node. - */ - Arc parentArc; - /** - * The label of this node. Is used to distinguish temporarily and permanently labeled nodes - * during the Dijkstra's algorithm - */ - int labelType; - /** - * The excess of this node. If this value is positive, then this is a source node. If this - * value is 0, than this is a transhipment node. If this value if negative, this is a sink - * node. - */ - int excess; - /** - * The dual variable of this node. This is used to search for an augmenting path in the - * residual network using the reduced costs of the arcs as arc lengths. - */ - double potential; - /** - * Reference of the first outgoing saturated arc (with zero residual capacity) - * incident to this node - */ - Arc firstSaturated; - /** - * Reference of the first outgoing non-saturated arc (with positive residual - * capacity) incident to this node. - */ - Arc firstNonSaturated; - /** - * Variable for debug purposes - */ - private int id = ID++; - - /** - * Constructs a new node with {@code excess} - * - * @param excess the excess of this node - */ - public Node(int excess) { - this.excess = excess; - } - - /** - * Adds a new arc with {@code capacity}, {@code cost} to the {@code opposite}. This method - * also creates a reverse arc with zero capacity and {@code -cost}. - * - * @param opposite the head of the resulting arc. - * @param capacity the capacity of the resulting arc. - * @param cost the cost of the resulting arc - * @return the resulting arc to the {@code opposite} node - */ - Arc addArcTo(Node opposite, int capacity, double cost) { - Arc forwardArc = new Arc(opposite, capacity, cost); - if (capacity > 0) { - // forward arc becomes the first arc in the linked list of non-saturated arcs - if (firstNonSaturated != null) { - firstNonSaturated.prev = forwardArc; - } - forwardArc.next = firstNonSaturated; - firstNonSaturated = forwardArc; - } else { - // forward arc becomes the first arc in the linked list of saturated arcs - if (firstSaturated != null) { - firstSaturated.prev = forwardArc; - } - forwardArc.next = firstSaturated; - firstSaturated = forwardArc; - } - Arc reverseArc = new Arc(this, 0, -cost); - if (opposite.firstSaturated != null) { - opposite.firstSaturated.prev = reverseArc; - } - reverseArc.next = opposite.firstSaturated; - opposite.firstSaturated = reverseArc; - - forwardArc.revArc = reverseArc; - reverseArc.revArc = forwardArc; - - return forwardArc; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return String.format("Id = %d, excess = %d, potential = %.1f", id, excess, potential); - } - } - - /** - * Supporting data structure for the {@link CapacityScalingMinimumCostFlow}. - *

- * Represents a directed edge (arc) in the residual flow network. Contains all information - * needed during the computation. - * - * @author Timofey Chudakov - * @since July 2018 - */ - private static class Arc { - - /** - * The head (target) of this arc. - */ - final Node head; - /** - * The cost of sending one unit of flow across this arc. This value is positive for initial - * network arcs, negative - for the reverse residual arcs, and equals to the - * {@link CapacityScalingMinimumCostFlow#COST_INF} for the arcs used for the reduction. - */ - final double cost; - /** - * The reverse counterpart of this arc. - */ - Arc revArc; - /** - * The previous arc. This variable is used to maintain the presence of this arc in the - * linked list of arc which are either saturated or not. - */ - Arc prev; - /** - * The next arc. This variable is used to maintain the presence of this arc in the linked - * list of arc which are either saturated or not. - */ - Arc next; - /** - * The residual capacity of this arc. For forward arcs $(i, j)$ it equals $c_{i, j} - x_{i, - * j}$ where $x_{i, j}$ is the flow on this arc. For reverse arcs it equals $x_{i,j}$. - */ - int residualCapacity; - - /** - * Creates a new arc - * - * @param head the head (target) of this arc - * @param residualCapacity its residual capacity - * @param cost its cost - */ - Arc(Node head, int residualCapacity, double cost) { - this.head = head; - this.cost = cost; - this.residualCapacity = residualCapacity; - } - - /** - * Returns reduced cost of this arc. - * - * @return reduced cost of this arc. - */ - double getReducedCost() { - return cost + head.potential - revArc.head.potential; - } - - /** - * Sends {@code value units of flow across this arc}. - * - * @param value how many units of flow to send - */ - void sendFlow(int value) { - decreaseResidualCapacity(value); - revArc.increaseResidualCapacity(value); - } - - /** - * Decreases residual capacity of this arc by {@code value} units of flow. Moves this arc - * from list of non-saturated arc to the list of saturated arcs if necessary. - * - * @param value the value to subtract from the residual capacity of this arc - */ - private void decreaseResidualCapacity(int value) { - if (residualCapacity >= CAP_INF) { - return; - } - residualCapacity -= value; - if (residualCapacity == 0) { - // need to move this arc from list of non-saturated arcs to list of saturated arcs - Node tail = revArc.head; - if (next != null) { - next.prev = prev; - } - if (prev != null) { - prev.next = next; - } else { - tail.firstNonSaturated = next; - } - next = tail.firstSaturated; - if (tail.firstSaturated != null) { - tail.firstSaturated.prev = this; - } - tail.firstSaturated = this; - prev = null; - } - } - - /** - * Increases residual capacity of this arc by {@code value} units of flow. Moves this arc - * from list of saturated arc to the list of non-saturated arcs if necessary. - * - * @param value the value to add to the residual capacity of this arc - */ - private void increaseResidualCapacity(int value) { - if (residualCapacity >= CAP_INF) { - return; - } - if (residualCapacity == 0) { - // need to move this arc from list of saturated arcs to list of non-saturated arcs - Node tail = revArc.head; - if (next != null) { - next.prev = prev; - } - if (prev != null) { - prev.next = next; - } else { - tail.firstSaturated = next; - } - next = tail.firstNonSaturated; - if (tail.firstNonSaturated != null) { - tail.firstNonSaturated.prev = this; - } - tail.firstNonSaturated = this; - prev = null; - } - residualCapacity += value; - } - - /** - * Returns true if the arc has infinite capacity, false otherwise. - * - * @return true if the arc has infinite capacity, false otherwise. - */ - public boolean isInfiniteCapacityArc() { - return residualCapacity >= CAP_INF; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return String.format( - "(%d, %d), residual capacity = %s, reduced cost = %.1f, cost = %.1f", - revArc.head.id, head.id, - residualCapacity >= CAP_INF ? "INF" : String.valueOf(residualCapacity), - getReducedCost(), cost); - } - } -} diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 0c7a8721ff4..f3a31c22ca4 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -82,6 +82,7 @@ import java.util.function.BooleanSupplier; import java.util.function.DoubleSupplier; import java.util.function.Function; +import java.util.function.IntPredicate; import java.util.function.LongPredicate; import java.util.function.Predicate; @@ -940,7 +941,7 @@ public static EntityPlayer getSP() { * @param ascending determines the direction of search * @return the smallest succeeding value if ascending, or the largest succeeding value if descending. */ - public static long binarySearch(long minValue, long maxValue, LongPredicate test, boolean ascending) { + public static long binarySearchLong(long minValue, long maxValue, LongPredicate test, boolean ascending) { while (maxValue - minValue > 1) { long middle = (minValue + maxValue) / 2; // XOR @@ -953,6 +954,26 @@ public static long binarySearch(long minValue, long maxValue, LongPredicate test return test.test(ascending ? minValue : maxValue) ^ ascending ? maxValue : minValue; } + /** + * @param minValue the minimum possible succeeding value + * @param maxValue the maximum possible succeeding value + * @param test the predicate to query for success + * @param ascending determines the direction of search + * @return the smallest succeeding value if ascending, or the largest succeeding value if descending. + */ + public static int binarySearchInt(int minValue, int maxValue, IntPredicate test, boolean ascending) { + while (maxValue - minValue > 1) { + int middle = (minValue + maxValue) / 2; + // XOR + if (test.test(middle) ^ !ascending) { + maxValue = middle; + } else { + minValue = middle; + } + } + return test.test(ascending ? minValue : maxValue) ^ ascending ? maxValue : minValue; + } + public static int[] convertARGBtoArray(int argb) { int a = argb >> 24 & 255; int r = argb >> 16 & 255; diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 9431d684446..2235b2bf10a 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -4,16 +4,23 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; import gregtech.api.capability.impl.ItemHandlerDelegate; +import gregtech.api.capability.impl.ItemHandlerList; import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithItemFilter; +import gregtech.api.graphnet.GraphNetUtility; import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.pipenet.traverse.RoundRobinCache; +import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.predicate.test.ItemTestObject; +import gregtech.api.graphnet.traverse.EdgeDirection; +import gregtech.api.graphnet.traverse.EdgeSelector; +import gregtech.api.graphnet.traverse.NetClosestIterator; +import gregtech.api.graphnet.traverse.ResilientNetClosestIterator; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; +import gregtech.api.util.GTUtility; import gregtech.api.util.ItemStackHashStrategy; import gregtech.api.util.function.BiIntConsumer; import gregtech.client.renderer.pipe.cover.CoverRenderer; @@ -70,12 +77,19 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Iterator; import java.util.Map; +import java.util.Set; import java.util.function.IntUnaryOperator; +import java.util.function.Predicate; public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithItemFilter { @@ -91,7 +105,8 @@ public class CoverConveyor extends CoverBase implements CoverWithUI, ITickable, private CoverableItemHandlerWrapper itemHandlerWrapper; protected boolean isWorkingAllowed = true; - protected final RoundRobinCache roundRobinCache = RoundRobinCache.create(); + protected final ObjectLinkedOpenHashSet extractionRoundRobinCache = new ObjectLinkedOpenHashSet<>(); + protected final ObjectLinkedOpenHashSet insertionRoundRobinCache = new ObjectLinkedOpenHashSet<>(); protected @Nullable CoverRenderer rendererInverted; @@ -153,7 +168,10 @@ public DistributionMode getDistributionMode() { public void setDistributionMode(DistributionMode distributionMode) { this.distributionMode = distributionMode; - this.roundRobinCache.clear(); + this.extractionRoundRobinCache.clear(); + this.extractionRoundRobinCache.trim(16); + this.insertionRoundRobinCache.clear(); + this.insertionRoundRobinCache.trim(16); markDirty(); } @@ -255,9 +273,9 @@ protected int performTransfer(@NotNull IItemHandler sourceHandler, @NotNull IIte while (iter.hasNext()) { var next = iter.next(); int filterSlot = next.getIntKey(); - int min = minTransfer.applyAsInt(filterSlot); + int min = Math.max(minTransfer.applyAsInt(filterSlot), 1); int max = maxTransfer.applyAsInt(filterSlot); - if (max < min || max <= 0) continue; + if (max < min) continue; int slotTransfer = 0; if (next.getIntValue() >= min) { MergabilityInfo mergabilityInfo = filterSlotToMergability.get(filterSlot); @@ -268,25 +286,22 @@ protected int performTransfer(@NotNull IItemHandler sourceHandler, @NotNull IIte int transfer = Math.min(merge.getCount(), max); transfer = doInsert(destHandler, merge.getTestObject(), transfer, true); if (transfer < min) continue; - int toExtract = transfer; - for (int handlerSlot : merge.getHandlerSlots()) { - toExtract -= sourceHandler.extractItem(handlerSlot, toExtract, false).getCount(); - if (toExtract == 0) break; - } - doInsert(destHandler, merge.getTestObject(), transfer - toExtract, false); - int remaining = max - transfer + toExtract; + transfer = doExtract(sourceHandler, merge.getTestObject(), transfer, true); + if (transfer < min) continue; + doExtract(sourceHandler, merge.getTestObject(), transfer, false); + doInsert(destHandler, merge.getTestObject(), transfer, false); + int remaining = max - transfer; slotTransfer += transfer; if (remaining <= 0) continue; for (MergabilityInfo.Merge otherMerge : mergabilityInfo .getNonLargestMerges(merge)) { transfer = Math.min(otherMerge.getCount(), remaining); - transfer = doInsert(destHandler, merge.getTestObject(), transfer, true); - toExtract = transfer; - for (int handlerSlot : otherMerge.getHandlerSlots()) { - toExtract -= sourceHandler.extractItem(handlerSlot, toExtract, false).getCount(); - if (toExtract == 0) break; - } - doInsert(destHandler, otherMerge.getTestObject(), transfer - toExtract, false); + transfer = doInsert(destHandler, otherMerge.getTestObject(), transfer, true); + if (transfer < min) continue; + transfer = doExtract(sourceHandler, otherMerge.getTestObject(), transfer, true); + if (transfer < min) continue; + doExtract(sourceHandler, otherMerge.getTestObject(), transfer, false); + doInsert(destHandler, otherMerge.getTestObject(), transfer, false); remaining -= transfer; slotTransfer += transfer; if (remaining <= 0) break; @@ -299,20 +314,319 @@ protected int performTransfer(@NotNull IItemHandler sourceHandler, @NotNull IIte return totalTransfer; } - protected RoundRobinCache getRoundRobinCache(boolean simulate) { - return simulate ? roundRobinCache.copy() : roundRobinCache; - } - - protected int getSupplyOrDemand(NetNode node, ItemTestObject testObject, boolean supply) { - return ItemCapabilityObject.getSupplyOrDemand(node, testObject, supply); + protected ObjectLinkedOpenHashSet getRoundRobinCache(boolean extract, boolean simulate) { + ObjectLinkedOpenHashSet set = extract ? extractionRoundRobinCache : insertionRoundRobinCache; + return simulate ? set.clone() : set; + } + + protected int doExtract(@NotNull IItemHandler handler, ItemTestObject testObject, int count, boolean simulate) { + ItemCapabilityObject cap; + if (distributionMode == DistributionMode.FLOOD || (cap = ItemCapabilityObject.instanceOf(handler)) == null) + return simpleExtract(handler, testObject, count, simulate); + NetNode origin = cap.getNode(); + Predicate filter = GraphNetUtility.standardEdgeBlacklist(testObject); + // if you find yourself here because you added a new distribution mode and now it won't compile, + // good luck. + return switch (distributionMode) { + case ROUND_ROBIN -> { + ItemHandlerList view = cap.getNetworkView(); + Iterator iter = view.getBackingHandlers().iterator(); + ObjectLinkedOpenHashSet cache = getRoundRobinCache(true, simulate); + Set backlog = new ObjectOpenHashSet<>(); + Object2IntOpenHashMap flows = new Object2IntOpenHashMap<>(); + int available = count; + while (available > 0) { + if (!cache.isEmpty() && backlog.remove(cache.first())) { + IItemHandler candidate = cache.first(); + NetNode linked = cap.getHandlerToNodeMap().get(candidate); + if (linked == null) { + cache.removeFirst(); + continue; + } else { + cache.addAndMoveToLast(candidate); + } + available = rrExtract(testObject, simulate, origin, filter, flows, available, candidate, + linked); + continue; + } + if (iter.hasNext()) { + IItemHandler candidate = iter.next(); + boolean frontOfCache = !cache.isEmpty() && cache.first() == candidate; + if (frontOfCache || !cache.contains(candidate)) { + NetNode linked = cap.getHandlerToNodeMap().get(candidate); + if (linked == null) { + if (frontOfCache) cache.removeFirst(); + continue; + } else { + cache.addAndMoveToLast(candidate); + } + available = rrExtract(testObject, simulate, origin, filter, flows, available, candidate, + linked); + } else { + backlog.add(candidate); + } + } else if (backlog.isEmpty()) { + // we have finished the iterator and backlog + break; + } else { + if (!cache.isEmpty()) { + if (view.getBackingHandlers().contains(cache.first())) + break; // we've already visited the next node in the cache + else { + // the network view does not contain the node in the front of the cache, so yeet it. + cache.removeFirst(); + } + } else { + break; // cache is empty and iterator is empty, something is weird, just exit. + } + } + } + while (iter.hasNext()) { + cache.add(iter.next()); + } + if (!simulate) { + for (var entry : flows.object2IntEntrySet()) { + ItemCapabilityObject.reportFlow(entry.getKey(), entry.getIntValue(), testObject); + } + } + yield count - available; + } + case EQUALIZED -> { + NetClosestIterator gather = new NetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + Object2ObjectOpenHashMap candidates = new Object2ObjectOpenHashMap<>(); + while (gather.hasNext()) { + NetNode node = gather.next(); + if (node instanceof NodeExposingCapabilities exposer) { + IItemHandler h = exposer.getProvider().getCapability( + CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, + exposer.exposedFacing()); + if (h != null && ItemCapabilityObject.instanceOf(h) == null) { + candidates.put(node, h); + } + } + } + int largestMin = count / candidates.size(); + if (largestMin <= 0) yield 0; + for (IItemHandler value : candidates.values()) { + largestMin = Math.min(largestMin, simpleExtract(value, testObject, largestMin, true)); + if (largestMin <= 0) yield 0; + } + // binary search for largest scale that doesn't exceed flow limits + Int2ObjectArrayMap> flows = new Int2ObjectArrayMap<>(); + largestMin = GTUtility.binarySearchInt(0, largestMin, l -> { + if (flows.containsKey(l) && flows.get(l) == null) return false; + ResilientNetClosestIterator forwardFrontier = new ResilientNetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + Object2IntOpenHashMap localFlows = new Object2IntOpenHashMap<>(); + for (NetNode node : candidates.keySet()) { + ResilientNetClosestIterator backwardFrontier = new ResilientNetClosestIterator(node, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + if (GraphNetUtility.p2pWalk(simulate, l, + n -> ItemCapabilityObject.getFlowLimit(n, testObject) - localFlows.getInt(n), + (n, i) -> localFlows.put(n, localFlows.getInt(n) + i), + forwardFrontier, backwardFrontier) < l) + return false; + } + flows.put(l, localFlows); + return true; + }, false); + if (largestMin <= 0 || flows.get(largestMin) == null) yield 0; + if (!simulate) { + for (IItemHandler value : candidates.values()) { + simpleExtract(value, testObject, largestMin, false); + } + for (var e : flows.get(largestMin).object2IntEntrySet()) { + ItemCapabilityObject.reportFlow(e.getKey(), e.getIntValue(), testObject); + } + } + yield largestMin * candidates.size(); + } + case FLOOD -> 0; // how are you here? + }; + } + + protected int rrExtract(ItemTestObject testObject, boolean simulate, NetNode origin, Predicate filter, + Object2IntOpenHashMap flows, int available, IItemHandler candidate, + NetNode linked) { + int accepted = simpleExtract(candidate, testObject, available, true); + if (accepted > 0) { + ResilientNetClosestIterator forwardFrontier = new ResilientNetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + ResilientNetClosestIterator backwardFrontier = new ResilientNetClosestIterator(linked, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + accepted = GraphNetUtility.p2pWalk(simulate, accepted, + n -> ItemCapabilityObject.getFlowLimit(n, testObject) - flows.getInt(n), + (n, i) -> flows.put(n, flows.getInt(n) + i), + forwardFrontier, backwardFrontier); + if (accepted > 0) { + available -= accepted; + if (!simulate) simpleExtract(candidate, testObject, accepted, false); + } + } + return available; } - protected int doExtract(@NotNull IItemHandler handler, ItemTestObject testObject, int count, boolean simulate) {} - protected int simpleExtract(@NotNull IItemHandler handler, ItemTestObject testObject, int count, - boolean simulate) {} - - protected int doInsert(@NotNull IItemHandler handler, ItemTestObject testObject, int count, boolean simulate) {} + boolean simulate) { + int available = 0; + for (int i = 0; i < handler.getSlots(); i++) { + ItemStack slot = handler.getStackInSlot(i); + if (testObject.test(slot)) { + available += handler.extractItem(i, count - available, simulate).getCount(); + if (available == count) return count; + } + } + return available; + } + + protected int doInsert(@NotNull IItemHandler handler, ItemTestObject testObject, final int count, + boolean simulate) { + ItemCapabilityObject cap; + if (distributionMode == DistributionMode.FLOOD || (cap = ItemCapabilityObject.instanceOf(handler)) == null) + return simpleInsert(handler, testObject, count, simulate); + NetNode origin = cap.getNode(); + Predicate filter = GraphNetUtility.standardEdgeBlacklist(testObject); + // if you find yourself here because you added a new distribution mode and now it won't compile, + // good luck. + return switch (distributionMode) { + case ROUND_ROBIN -> { + ItemHandlerList view = cap.getNetworkView(); + Iterator iter = view.getBackingHandlers().iterator(); + ObjectLinkedOpenHashSet cache = getRoundRobinCache(false, simulate); + Set backlog = new ObjectOpenHashSet<>(); + Object2IntOpenHashMap flows = new Object2IntOpenHashMap<>(); + int available = count; + while (available > 0) { + if (!cache.isEmpty() && backlog.remove(cache.first())) { + IItemHandler candidate = cache.first(); + NetNode linked = cap.getHandlerToNodeMap().get(candidate); + if (linked == null) { + cache.removeFirst(); + continue; + } else { + cache.addAndMoveToLast(candidate); + } + available = rrInsert(testObject, simulate, origin, filter, flows, available, candidate, linked); + continue; + } + if (iter.hasNext()) { + IItemHandler candidate = iter.next(); + boolean frontOfCache = !cache.isEmpty() && cache.first() == candidate; + if (frontOfCache || !cache.contains(candidate)) { + NetNode linked = cap.getHandlerToNodeMap().get(candidate); + if (linked == null) { + if (frontOfCache) cache.removeFirst(); + continue; + } else { + cache.addAndMoveToLast(candidate); + } + available = rrInsert(testObject, simulate, origin, filter, flows, available, candidate, + linked); + } else { + backlog.add(candidate); + } + } else if (backlog.isEmpty()) { + // we have finished the iterator and backlog + break; + } else { + if (!cache.isEmpty()) { + if (view.getBackingHandlers().contains(cache.first())) + break; // we've already visited the next node in the cache + else { + // the network view does not contain the node in the front of the cache, so yeet it. + cache.removeFirst(); + } + } else { + break; // cache is empty and iterator is empty, something is weird, just exit. + } + } + } + while (iter.hasNext()) { + cache.add(iter.next()); + } + if (!simulate) { + for (var entry : flows.object2IntEntrySet()) { + ItemCapabilityObject.reportFlow(entry.getKey(), entry.getIntValue(), testObject); + } + } + yield count - available; + } + case EQUALIZED -> { + NetClosestIterator gather = new NetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + Object2ObjectOpenHashMap candidates = new Object2ObjectOpenHashMap<>(); + while (gather.hasNext()) { + NetNode node = gather.next(); + if (node instanceof NodeExposingCapabilities exposer) { + IItemHandler h = exposer.getProvider().getCapability( + CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, + exposer.exposedFacing()); + if (h != null && ItemCapabilityObject.instanceOf(h) == null) { + candidates.put(node, h); + } + } + } + int largestMin = count / candidates.size(); + if (largestMin <= 0) yield 0; + for (IItemHandler value : candidates.values()) { + largestMin = Math.min(largestMin, simpleInsert(value, testObject, largestMin, true)); + if (largestMin <= 0) yield 0; + } + // binary search for largest scale that doesn't exceed flow limits + Int2ObjectArrayMap> flows = new Int2ObjectArrayMap<>(); + largestMin = GTUtility.binarySearchInt(0, largestMin, l -> { + if (flows.containsKey(l) && flows.get(l) == null) return false; + ResilientNetClosestIterator forwardFrontier = new ResilientNetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + Object2IntOpenHashMap localFlows = new Object2IntOpenHashMap<>(); + for (NetNode node : candidates.keySet()) { + ResilientNetClosestIterator backwardFrontier = new ResilientNetClosestIterator(node, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + if (GraphNetUtility.p2pWalk(simulate, l, + n -> ItemCapabilityObject.getFlowLimit(n, testObject) - localFlows.getInt(n), + (n, i) -> localFlows.put(n, localFlows.getInt(n) + i), + forwardFrontier, backwardFrontier) < l) + return false; + } + flows.put(l, localFlows); + return true; + }, false); + if (largestMin <= 0 || flows.get(largestMin) == null) yield 0; + if (!simulate) { + for (IItemHandler value : candidates.values()) { + simpleInsert(value, testObject, largestMin, false); + } + for (var e : flows.get(largestMin).object2IntEntrySet()) { + ItemCapabilityObject.reportFlow(e.getKey(), e.getIntValue(), testObject); + } + } + yield largestMin * candidates.size(); + } + case FLOOD -> 0; // how are you here? + }; + } + + protected int rrInsert(ItemTestObject testObject, boolean simulate, NetNode origin, Predicate filter, + Object2IntOpenHashMap flows, int available, IItemHandler candidate, + NetNode linked) { + int accepted = simpleInsert(candidate, testObject, available, true); + if (accepted > 0) { + ResilientNetClosestIterator forwardFrontier = new ResilientNetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + ResilientNetClosestIterator backwardFrontier = new ResilientNetClosestIterator(linked, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + accepted = GraphNetUtility.p2pWalk(simulate, accepted, + n -> ItemCapabilityObject.getFlowLimit(n, testObject) - flows.getInt(n), + (n, i) -> flows.put(n, flows.getInt(n) + i), + forwardFrontier, backwardFrontier); + if (accepted > 0) { + available -= accepted; + if (!simulate) simpleInsert(candidate, testObject, accepted, false); + } + } + return available; + } protected int simpleInsert(@NotNull IItemHandler handler, ItemTestObject testObject, int count, boolean simulate) { @@ -320,7 +634,7 @@ protected int simpleInsert(@NotNull IItemHandler handler, ItemTestObject testObj for (int i = 0; i < handler.getSlots(); i++) { ItemStack toInsert = testObject.recombine(Math.min(available, handler.getSlotLimit(i))); available -= toInsert.getCount() - handler.insertItem(i, toInsert, simulate).getCount(); - if (available == 0) return count; + if (available <= 0) return count; } return count - available; } diff --git a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java index 385b0f3cf56..00db9af3384 100644 --- a/src/main/java/gregtech/common/covers/CoverFluidRegulator.java +++ b/src/main/java/gregtech/common/covers/CoverFluidRegulator.java @@ -3,8 +3,6 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.predicate.test.FluidTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.common.covers.filter.FluidFilterContainer; @@ -14,7 +12,6 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.util.EnumFacing; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidTankProperties; @@ -89,22 +86,6 @@ protected int simpleInsert(@NotNull IFluidHandler destHandler, FluidTestObject t return super.simpleInsert(destHandler, testObject, count, simulate); } - @Override - protected int getSupply(NetNode node, FluidTestObject testObject, boolean supply) { - if (transferMode != TransferMode.KEEP_EXACT || supply) return super.getSupply(node, testObject, supply); - if (node instanceof NodeExposingCapabilities exposer) { - IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - exposer.exposedFacing()); - if (handler != null) { - assert getFluidFilter() != null; - int kept = getFluidFilter().getTransferLimit(testObject.recombine()); - return -Math.min(handler.fill(testObject.recombine(Integer.MAX_VALUE), false), - kept - computeContained(handler, testObject)); - } - } - return 0; - } - public void setTransferMode(TransferMode transferMode) { if (this.transferMode != transferMode) { this.transferMode = transferMode; diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index f7a40246eea..b90bc55b5dc 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -4,25 +4,23 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; import gregtech.api.capability.impl.FluidHandlerDelegate; +import gregtech.api.capability.impl.FluidHandlerList; import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; import gregtech.api.cover.CoverableView; import gregtech.api.cover.filter.CoverWithFluidFilter; import gregtech.api.graphnet.GraphNetUtility; -import gregtech.api.graphnet.group.NetGroup; -import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; -import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; -import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; -import gregtech.api.graphnet.pipenet.traverse.RoundRobinCache; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverse.iter.EdgeDirection; -import gregtech.api.graphnet.traverse.iter.NetClosestIterator; -import gregtech.api.graphnet.traverse.iter.NetIterator; +import gregtech.api.graphnet.traverse.EdgeDirection; +import gregtech.api.graphnet.traverse.EdgeSelector; +import gregtech.api.graphnet.traverse.NetClosestIterator; +import gregtech.api.graphnet.traverse.ResilientNetClosestIterator; import gregtech.api.mui.GTGuiTextures; import gregtech.api.mui.GTGuis; +import gregtech.api.util.GTUtility; import gregtech.api.util.function.BiIntConsumer; import gregtech.client.renderer.pipe.cover.CoverRenderer; import gregtech.client.renderer.pipe.cover.CoverRendererBuilder; @@ -74,13 +72,18 @@ import com.cleanroommc.modularui.widgets.layout.Column; import com.cleanroommc.modularui.widgets.layout.Row; import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; +import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Map; +import java.util.Iterator; +import java.util.Set; import java.util.function.IntUnaryOperator; +import java.util.function.Predicate; public class CoverPump extends CoverBase implements CoverWithUI, ITickable, IControllable, CoverWithFluidFilter { @@ -96,7 +99,8 @@ public class CoverPump extends CoverBase implements CoverWithUI, ITickable, ICon protected FluidFilterContainer fluidFilterContainer; protected BucketMode bucketMode = BucketMode.MILLI_BUCKET; - protected final RoundRobinCache roundRobinCache = RoundRobinCache.create(); + protected final ObjectLinkedOpenHashSet extractionRoundRobinCache = new ObjectLinkedOpenHashSet<>(); + protected final ObjectLinkedOpenHashSet insertionRoundRobinCache = new ObjectLinkedOpenHashSet<>(); protected @Nullable CoverRenderer rendererInverted; @@ -169,7 +173,10 @@ public DistributionMode getDistributionMode() { public void setDistributionMode(DistributionMode distributionMode) { this.distributionMode = distributionMode; - this.roundRobinCache.clear(); + this.extractionRoundRobinCache.clear(); + this.extractionRoundRobinCache.trim(16); + this.insertionRoundRobinCache.clear(); + this.insertionRoundRobinCache.trim(16); markDirty(); } @@ -201,12 +208,12 @@ public FluidFilterContainer getFluidFilterContainer() { public void update() { long timer = getOffsetTimer(); if (isWorkingAllowed && getFluidsLeftToTransfer() > 0) { - TileEntity tileEntity = getNeighbor(getAttachedSide()); + EnumFacing side = getAttachedSide(); + TileEntity tileEntity = getNeighbor(side); IFluidHandler fluidHandler = tileEntity == null ? null : tileEntity - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, getAttachedSide().getOpposite()); + .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side.getOpposite()); IFluidHandler myFluidHandler = getCoverableView().getCapability( - CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - getAttachedSide()); + CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, side); if (myFluidHandler != null && fluidHandler != null) { if (pumpMode == PumpMode.EXPORT) { performTransferOnUpdate(myFluidHandler, fluidHandler); @@ -254,131 +261,38 @@ protected void performTransferOnUpdate(@NotNull IFluidHandler sourceHandler, @No protected int performTransfer(@NotNull IFluidHandler sourceHandler, @NotNull IFluidHandler destHandler, boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { - // if the source handler or the dest handler is a pipe, perform a pipenet transfer. Otherwise, do a simple one. - if (sourceHandler instanceof FluidCapabilityObject s) { - if (destHandler instanceof FluidCapabilityObject d) { - return transferWithinNet(s.getNode(), d.getNode(), byFilterSlot, minTransfer, maxTransfer, - transferReport); - } else { - PipeCapabilityWrapper wrapper = s.getNode().getTileEntity().getWrapperForNode(s.getNode()); - if (wrapper instanceof NodeManagingPCW managingPCW) { - // if export, we know we're on the pipe; otherwise, we're on the tile. - EnumFacing facing = pumpMode == PumpMode.EXPORT ? getAttachedSide() : - getAttachedSide().getOpposite(); - NetNode node = managingPCW.getNodeForFacing(facing); - if (node == null) return 0; - return transferWithinNet(s.getNode(), node, byFilterSlot, minTransfer, maxTransfer, transferReport); - } - return 0; - } - } else { - if (destHandler instanceof FluidCapabilityObject d) { - PipeCapabilityWrapper wrapper = d.getNode().getTileEntity().getWrapperForNode(d.getNode()); - if (wrapper instanceof NodeManagingPCW managingPCW) { - // if import, we know we're on the pipe; otherwise, we're on the tile. - EnumFacing facing = pumpMode == PumpMode.IMPORT ? getAttachedSide() : - getAttachedSide().getOpposite(); - NetNode node = managingPCW.getNodeForFacing(facing); - if (node == null) return 0; - return transferWithinNet(node, d.getNode(), byFilterSlot, minTransfer, maxTransfer, transferReport); - } - return 0; - } else { - return simpleTransfer(sourceHandler, destHandler, byFilterSlot, minTransfer, maxTransfer, - transferReport); - } - } - } - - protected RoundRobinCache getRoundRobinCache(boolean simulate) { - return simulate ? roundRobinCache.copy() : roundRobinCache; - } - - /** - * Performs transfer between two nodes of a pipenet. - * - * @param sourceNode the node to pull from - * @param destNode the node to push to - * @param byFilterSlot whether to perform the transfer by filter slot. - * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. - * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. - * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. - * Each filter slot will report its transfer before the next slot is calculated. - * @return how much was transferred in total. - */ - protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode destNode, - boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, - @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { - // first, evaluate whether we're the only bridge between two areas in a group - NetEdge bridge = sourceNode.getNet().getEdge(sourceNode, destNode); - if (bridge == null || !GraphNetUtility.isOnlyBridge(bridge)) return 0; - // second, build frontier information. If we have no candidates for either frontier, exit early. - NetClosestIterator sourceFrontier = new NetClosestIterator(sourceNode, - GraphNetUtility.bridgeFiltered(EdgeDirection.INCOMING, sourceNode, destNode)); - Map sourceCandidates = new Object2ObjectOpenHashMap<>(); - while (sourceFrontier.hasNext()) { - NetNode next = sourceFrontier.next(); - if (next instanceof NodeExposingCapabilities cap) { - IFluidHandler handler = cap.getProvider() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, cap.exposedFacing()); - if (handler != null && !(handler instanceof FluidCapabilityObject)) - sourceCandidates.put(next, handler); - } - } - if (sourceCandidates.isEmpty()) return 0; - NetClosestIterator destFrontier = new NetClosestIterator(destNode, - GraphNetUtility.bridgeFiltered(EdgeDirection.OUTGOING, sourceNode, destNode)); - Map destinationCandidates = new Object2ObjectOpenHashMap<>(); - while (destFrontier.hasNext()) { - NetNode next = destFrontier.next(); - if (next instanceof NodeExposingCapabilities cap) { - IFluidHandler handler = cap.getProvider() - .getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, cap.exposedFacing()); - if (handler != null && !(handler instanceof FluidCapabilityObject)) - destinationCandidates.put(next, handler); - } - } - if (destinationCandidates.isEmpty()) return 0; - // third, build merge information from source candidates FluidFilterContainer filter = this.getFluidFilter(); byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter Object2IntOpenHashMap contained = new Object2IntOpenHashMap<>(); - for (IFluidHandler handler : sourceCandidates.values()) { - var tanks = handler.getTankProperties(); - for (IFluidTankProperties tank : tanks) { - FluidStack contents = tank.getContents(); - if (contents != null) contained.merge(new FluidTestObject(contents), contents.amount, Integer::sum); - } + var tanks = sourceHandler.getTankProperties(); + for (IFluidTankProperties tank : tanks) { + FluidStack contents = tank.getContents(); + if (contents != null) contained.merge(new FluidTestObject(contents), contents.amount, Integer::sum); } var iter = contained.object2IntEntrySet().fastIterator(); int totalTransfer = 0; - // fourth, perform transfer based on merge information while (iter.hasNext()) { var content = iter.next(); - FluidStack contents = content.getKey().recombine(content.getIntValue()); MatchResult match = null; - if (filter == null || (match = filter.match(contents)).isMatched()) { + if (filter == null || + (match = filter.match(content.getKey().recombine(content.getIntValue()))).isMatched()) { int filterSlot = -1; if (byFilterSlot) { assert filter != null; // we know it is not null, because if it were byFilterSlot would be false. filterSlot = match.getFilterIndex(); } - int min = minTransfer.applyAsInt(filterSlot); + int min = Math.max(minTransfer.applyAsInt(filterSlot), 1); int max = maxTransfer.applyAsInt(filterSlot); - if (max < min || max <= 0) continue; - - if (contents.amount < min) continue; - int transfer = Math.min(contents.amount, max); - if (min > 0) { - transfer = attemptNetTransfer(sourceNode.getGroupSafe(), bridge, transfer, content.getKey(), - sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, - SimulatorKey.getNewSimulatorInstance()); - if (transfer < min) continue; - } - transfer = attemptNetTransfer(sourceNode.getGroupSafe(), bridge, transfer, content.getKey(), - sourceFrontier, sourceCandidates, destFrontier, destinationCandidates, null); + if (max < min) continue; + + if (content.getIntValue() < min) continue; + int transfer = Math.min(content.getIntValue(), max); + transfer = doInsert(destHandler, content.getKey(), transfer, true); + if (transfer < min) continue; + transfer = doExtract(sourceHandler, content.getKey(), transfer, true); + if (transfer < min) continue; + doExtract(sourceHandler, content.getKey(), transfer, false); + doInsert(destHandler, content.getKey(), transfer, false); if (transferReport != null) transferReport.accept(filterSlot, transfer); totalTransfer += transfer; } @@ -386,77 +300,317 @@ protected int transferWithinNet(@NotNull NetNode sourceNode, @NotNull NetNode de return totalTransfer; } - protected int attemptNetTransfer(NetGroup group, NetEdge bridge, int limit, FluidTestObject testObject, - NetIterator sources, Map sourceCandidates, - NetIterator targets, Map destCandidates, - @Nullable SimulatorKey key) { - return 0; - } - - protected int getSupply(NetNode node, FluidTestObject testObject, boolean supply) { - return FluidCapabilityObject.getSupplyOrDemand(node, testObject, supply); - } - - /** - * Performs transfer without involving the pipenet - * - * @param sourceHandler the handler to pull from - * @param destHandler the handler to push to - * @param byFilterSlot whether to perform the transfer by filter slot. - * @param minTransfer the minimum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. - * @param maxTransfer the maximum allowed transfer amount, when given a filter slot. If no filter exists or not - * transferring by slot, a filter slot of -1 will be passed in. - * @param transferReport where transfer is reported; a is the filter slot, b is the amount of transfer. - * Each filter slot will report its transfer before the next slot is calculated. - * @return how much was transferred in total. - */ - protected int simpleTransfer(@NotNull IFluidHandler sourceHandler, @NotNull IFluidHandler destHandler, - boolean byFilterSlot, @NotNull IntUnaryOperator minTransfer, - @NotNull IntUnaryOperator maxTransfer, @Nullable BiIntConsumer transferReport) { - FluidFilterContainer filter = this.getFluidFilter(); - byFilterSlot = byFilterSlot && filter != null; // can't be by filter slot if there is no filter - Object2IntOpenHashMap contained = new Object2IntOpenHashMap<>(); - var tanks = sourceHandler.getTankProperties(); - for (IFluidTankProperties tank : tanks) { - FluidStack contents = tank.getContents(); - if (contents != null) contained.merge(new FluidTestObject(contents), contents.amount, Integer::sum); + protected ObjectLinkedOpenHashSet getRoundRobinCache(boolean extract, boolean simulate) { + ObjectLinkedOpenHashSet set = extract ? extractionRoundRobinCache : insertionRoundRobinCache; + return simulate ? set.clone() : set; + } + + protected int doExtract(@NotNull IFluidHandler handler, FluidTestObject testObject, int count, + boolean simulate) { + FluidCapabilityObject cap; + if (distributionMode == DistributionMode.FLOOD || (cap = FluidCapabilityObject.instanceOf(handler)) == null) + return simpleExtract(handler, testObject, count, simulate); + NetNode origin = cap.getNode(); + Predicate filter = GraphNetUtility.standardEdgeBlacklist(testObject); + // if you find yourself here because you added a new distribution mode and now it won't compile, + // good luck. + return switch (distributionMode) { + case ROUND_ROBIN -> { + FluidHandlerList view = cap.getNetworkView(); + Iterator iter = view.getBackingHandlers().iterator(); + ObjectLinkedOpenHashSet cache = getRoundRobinCache(true, simulate); + Set backlog = new ObjectOpenHashSet<>(); + Object2IntOpenHashMap flows = new Object2IntOpenHashMap<>(); + int available = count; + while (available > 0) { + if (!cache.isEmpty() && backlog.remove(cache.first())) { + IFluidHandler candidate = cache.first(); + NetNode linked = cap.getHandlerToNodeMap().get(candidate); + if (linked == null) { + cache.removeFirst(); + continue; + } else { + cache.addAndMoveToLast(candidate); + } + available = rrExtract(testObject, simulate, origin, filter, flows, available, candidate, + linked); + continue; + } + if (iter.hasNext()) { + IFluidHandler candidate = iter.next(); + boolean frontOfCache = !cache.isEmpty() && cache.first() == candidate; + if (frontOfCache || !cache.contains(candidate)) { + NetNode linked = cap.getHandlerToNodeMap().get(candidate); + if (linked == null) { + if (frontOfCache) cache.removeFirst(); + continue; + } else { + cache.addAndMoveToLast(candidate); + } + available = rrExtract(testObject, simulate, origin, filter, flows, available, candidate, + linked); + } else { + backlog.add(candidate); + } + } else if (backlog.isEmpty()) { + // we have finished the iterator and backlog + break; + } else { + if (!cache.isEmpty()) { + if (view.getBackingHandlers().contains(cache.first())) + break; // we've already visited the next node in the cache + else { + // the network view does not contain the node in the front of the cache, so yeet it. + cache.removeFirst(); + } + } else { + break; // cache is empty and iterator is empty, something is weird, just exit. + } + } + } + while (iter.hasNext()) { + cache.add(iter.next()); + } + if (!simulate) { + for (var entry : flows.object2IntEntrySet()) { + FluidCapabilityObject.reportFlow(entry.getKey(), entry.getIntValue(), testObject); + } + } + yield count - available; + } + case EQUALIZED -> { + NetClosestIterator gather = new NetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + Object2ObjectOpenHashMap candidates = new Object2ObjectOpenHashMap<>(); + while (gather.hasNext()) { + NetNode node = gather.next(); + if (node instanceof NodeExposingCapabilities exposer) { + IFluidHandler h = exposer.getProvider().getCapability( + CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + exposer.exposedFacing()); + if (h != null && FluidCapabilityObject.instanceOf(h) == null) { + candidates.put(node, h); + } + } + } + int largestMin = count / candidates.size(); + if (largestMin <= 0) yield 0; + for (IFluidHandler value : candidates.values()) { + largestMin = Math.min(largestMin, simpleExtract(value, testObject, largestMin, true)); + if (largestMin <= 0) yield 0; + } + // binary search for largest scale that doesn't exceed flow limits + Int2ObjectArrayMap> flows = new Int2ObjectArrayMap<>(); + largestMin = GTUtility.binarySearchInt(0, largestMin, l -> { + if (flows.containsKey(l) && flows.get(l) == null) return false; + ResilientNetClosestIterator forwardFrontier = new ResilientNetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + Object2IntOpenHashMap localFlows = new Object2IntOpenHashMap<>(); + for (NetNode node : candidates.keySet()) { + ResilientNetClosestIterator backwardFrontier = new ResilientNetClosestIterator(node, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + if (GraphNetUtility.p2pWalk(simulate, l, + n -> FluidCapabilityObject.getFlowLimit(n, testObject) - localFlows.getInt(n), + (n, i) -> localFlows.put(n, localFlows.getInt(n) + i), + forwardFrontier, backwardFrontier) < l) + return false; + } + flows.put(l, localFlows); + return true; + }, false); + if (largestMin <= 0 || flows.get(largestMin) == null) yield 0; + if (!simulate) { + for (IFluidHandler value : candidates.values()) { + simpleExtract(value, testObject, largestMin, false); + } + for (var e : flows.get(largestMin).object2IntEntrySet()) { + FluidCapabilityObject.reportFlow(e.getKey(), e.getIntValue(), testObject); + } + } + yield largestMin * candidates.size(); + } + case FLOOD -> 0; // how are you here? + }; + } + + protected int rrExtract(FluidTestObject testObject, boolean simulate, NetNode origin, Predicate filter, + Object2IntOpenHashMap flows, int available, IFluidHandler candidate, + NetNode linked) { + int accepted = simpleExtract(candidate, testObject, available, true); + if (accepted > 0) { + ResilientNetClosestIterator forwardFrontier = new ResilientNetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + ResilientNetClosestIterator backwardFrontier = new ResilientNetClosestIterator(linked, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + accepted = GraphNetUtility.p2pWalk(simulate, accepted, + n -> FluidCapabilityObject.getFlowLimit(n, testObject) - flows.getInt(n), + (n, i) -> flows.put(n, flows.getInt(n) + i), + forwardFrontier, backwardFrontier); + if (accepted > 0) { + available -= accepted; + if (!simulate) simpleExtract(candidate, testObject, accepted, false); + } } - var iter = contained.object2IntEntrySet().fastIterator(); - int totalTransfer = 0; - while (iter.hasNext()) { - var content = iter.next(); - FluidStack contents = content.getKey().recombine(content.getIntValue()); - MatchResult match = null; - if (filter == null || (match = filter.match(contents)).isMatched()) { - int filterSlot = -1; - if (byFilterSlot) { - assert filter != null; // we know it is not null, because if it were byFilterSlot would be false. - filterSlot = match.getFilterIndex(); + return available; + } + + protected int simpleExtract(@NotNull IFluidHandler destHandler, FluidTestObject testObject, int count, + boolean simulate) { + FluidStack ext = destHandler.drain(testObject.recombine(count), !simulate); + return ext == null ? 0 : ext.amount; + } + + protected int doInsert(@NotNull IFluidHandler handler, FluidTestObject testObject, int count, + boolean simulate) { + FluidCapabilityObject cap; + if (distributionMode == DistributionMode.FLOOD || (cap = FluidCapabilityObject.instanceOf(handler)) == null) + return simpleInsert(handler, testObject, count, simulate); + NetNode origin = cap.getNode(); + Predicate filter = GraphNetUtility.standardEdgeBlacklist(testObject); + // if you find yourself here because you added a new distribution mode and now it won't compile, + // good luck. + return switch (distributionMode) { + case ROUND_ROBIN -> { + FluidHandlerList view = cap.getNetworkView(); + Iterator iter = view.getBackingHandlers().iterator(); + ObjectLinkedOpenHashSet cache = getRoundRobinCache(false, simulate); + Set backlog = new ObjectOpenHashSet<>(); + Object2IntOpenHashMap flows = new Object2IntOpenHashMap<>(); + int available = count; + while (available > 0) { + if (!cache.isEmpty() && backlog.remove(cache.first())) { + IFluidHandler candidate = cache.first(); + NetNode linked = cap.getHandlerToNodeMap().get(candidate); + if (linked == null) { + cache.removeFirst(); + continue; + } else { + cache.addAndMoveToLast(candidate); + } + available = rrInsert(testObject, simulate, origin, filter, flows, available, candidate, linked); + continue; + } + if (iter.hasNext()) { + IFluidHandler candidate = iter.next(); + boolean frontOfCache = !cache.isEmpty() && cache.first() == candidate; + if (frontOfCache || !cache.contains(candidate)) { + NetNode linked = cap.getHandlerToNodeMap().get(candidate); + if (linked == null) { + if (frontOfCache) cache.removeFirst(); + continue; + } else { + cache.addAndMoveToLast(candidate); + } + available = rrInsert(testObject, simulate, origin, filter, flows, available, candidate, + linked); + } else { + backlog.add(candidate); + } + } else if (backlog.isEmpty()) { + // we have finished the iterator and backlog + break; + } else { + if (!cache.isEmpty()) { + if (view.getBackingHandlers().contains(cache.first())) + break; // we've already visited the next node in the cache + else { + // the network view does not contain the node in the front of the cache, so yeet it. + cache.removeFirst(); + } + } else { + break; // cache is empty and iterator is empty, something is weird, just exit. + } + } } - int min = minTransfer.applyAsInt(filterSlot); - int max = maxTransfer.applyAsInt(filterSlot); - if (max < min || max <= 0) continue; - - if (contents.amount < min) continue; - int transfer = Math.min(contents.amount, max); - FluidStack extracted = sourceHandler.drain(content.getKey().recombine(transfer), false); - if (extracted == null || extracted.amount < min) continue; - transfer = simpleInsert(destHandler, content.getKey(), extracted.amount, true); - if (transfer <= 0 || transfer < min) continue; - extracted = sourceHandler.drain(content.getKey().recombine(transfer), true); - if (extracted == null) continue; - transfer = simpleInsert(destHandler, content.getKey(), extracted.amount, false); - if (transferReport != null) transferReport.accept(filterSlot, transfer); - totalTransfer += transfer; + while (iter.hasNext()) { + cache.add(iter.next()); + } + if (!simulate) { + for (var entry : flows.object2IntEntrySet()) { + FluidCapabilityObject.reportFlow(entry.getKey(), entry.getIntValue(), testObject); + } + } + yield count - available; + } + case EQUALIZED -> { + NetClosestIterator gather = new NetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + Object2ObjectOpenHashMap candidates = new Object2ObjectOpenHashMap<>(); + while (gather.hasNext()) { + NetNode node = gather.next(); + if (node instanceof NodeExposingCapabilities exposer) { + IFluidHandler h = exposer.getProvider().getCapability( + CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + exposer.exposedFacing()); + if (h != null && FluidCapabilityObject.instanceOf(h) == null) { + candidates.put(node, h); + } + } + } + int largestMin = count / candidates.size(); + if (largestMin <= 0) yield 0; + for (IFluidHandler value : candidates.values()) { + largestMin = Math.min(largestMin, simpleInsert(value, testObject, largestMin, true)); + if (largestMin <= 0) yield 0; + } + // binary search for largest scale that doesn't exceed flow limits + Int2ObjectArrayMap> flows = new Int2ObjectArrayMap<>(); + largestMin = GTUtility.binarySearchInt(0, largestMin, l -> { + if (flows.containsKey(l) && flows.get(l) == null) return false; + ResilientNetClosestIterator forwardFrontier = new ResilientNetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + Object2IntOpenHashMap localFlows = new Object2IntOpenHashMap<>(); + for (NetNode node : candidates.keySet()) { + ResilientNetClosestIterator backwardFrontier = new ResilientNetClosestIterator(node, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + if (GraphNetUtility.p2pWalk(simulate, l, + n -> FluidCapabilityObject.getFlowLimit(n, testObject) - localFlows.getInt(n), + (n, i) -> localFlows.put(n, localFlows.getInt(n) + i), + forwardFrontier, backwardFrontier) < l) + return false; + } + flows.put(l, localFlows); + return true; + }, false); + if (largestMin <= 0 || flows.get(largestMin) == null) yield 0; + if (!simulate) { + for (IFluidHandler value : candidates.values()) { + simpleInsert(value, testObject, largestMin, false); + } + for (var e : flows.get(largestMin).object2IntEntrySet()) { + FluidCapabilityObject.reportFlow(e.getKey(), e.getIntValue(), testObject); + } + } + yield largestMin * candidates.size(); + } + case FLOOD -> 0; // how are you here? + }; + } + + protected int rrInsert(FluidTestObject testObject, boolean simulate, NetNode origin, Predicate filter, + Object2IntOpenHashMap flows, int available, IFluidHandler candidate, + NetNode linked) { + int accepted = simpleInsert(candidate, testObject, available, true); + if (accepted > 0) { + ResilientNetClosestIterator forwardFrontier = new ResilientNetClosestIterator(origin, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + ResilientNetClosestIterator backwardFrontier = new ResilientNetClosestIterator(linked, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + accepted = GraphNetUtility.p2pWalk(simulate, accepted, + n -> FluidCapabilityObject.getFlowLimit(n, testObject) - flows.getInt(n), + (n, i) -> flows.put(n, flows.getInt(n) + i), + forwardFrontier, backwardFrontier); + if (accepted > 0) { + available -= accepted; + if (!simulate) simpleInsert(candidate, testObject, accepted, false); } } - return totalTransfer; + return available; } protected int simpleInsert(@NotNull IFluidHandler destHandler, FluidTestObject testObject, int count, boolean simulate) { - return count - destHandler.fill(testObject.recombine(count), !simulate); + return destHandler.fill(testObject.recombine(count), !simulate); } protected boolean checkInputFluid(FluidStack fluidStack) { diff --git a/src/main/java/gregtech/common/covers/CoverRoboticArm.java b/src/main/java/gregtech/common/covers/CoverRoboticArm.java index 61abdaa240c..8f02ef02946 100644 --- a/src/main/java/gregtech/common/covers/CoverRoboticArm.java +++ b/src/main/java/gregtech/common/covers/CoverRoboticArm.java @@ -3,8 +3,6 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverableView; -import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.predicate.test.ItemTestObject; import gregtech.api.mui.GTGuiTextures; import gregtech.client.renderer.pipe.cover.CoverRenderer; @@ -17,7 +15,6 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; -import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import codechicken.lib.render.CCRenderState; @@ -116,31 +113,6 @@ protected int simpleInsert(@NotNull IItemHandler handler, ItemTestObject testObj return super.simpleInsert(handler, testObject, count, simulate); } - @Override - protected int getSupplyOrDemand(NetNode node, ItemTestObject testObject, boolean supply) { - if (transferMode != TransferMode.KEEP_EXACT || supply) return super.getSupplyOrDemand(node, testObject, supply); - if (node instanceof NodeExposingCapabilities exposer) { - IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, - exposer.exposedFacing()); - if (handler != null) { - int sum = 0; - assert getItemFilter() != null; - int kept = getItemFilter().getTransferLimit(testObject.recombine()); - ItemStack stack = testObject.recombineSafe(Integer.MAX_VALUE); - for (int i = 0; i < handler.getSlots(); i++) { - sum += stack.getCount() - handler.insertItem(i, stack, true).getCount(); - ItemStack contained = handler.getStackInSlot(i); - if (testObject.test(contained)) { - kept -= contained.getCount(); - if (kept <= 0) return 0; - } - } - return -Math.min(kept, sum); - } - } - return 0; - } - public void setTransferMode(TransferMode transferMode) { if (this.transferMode != transferMode) { this.transferMode = transferMode; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java index ff22ea1ffe7..a8d22b5c75c 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/EnergyGroupData.java @@ -4,7 +4,7 @@ import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.path.NetPath; import gregtech.api.graphnet.path.PathBuilder; -import gregtech.api.graphnet.traverse.iter.NetIteratorSupplier; +import gregtech.api.graphnet.traverse.NetIteratorSupplier; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java index 55413b0cfa9..5674600fbdd 100644 --- a/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java +++ b/src/main/java/gregtech/common/pipelike/net/energy/WorldEnergyNet.java @@ -7,7 +7,7 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.traverse.iter.NetClosestIterator; +import gregtech.api.graphnet.traverse.NetClosestIterator; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index 98978f39c06..8127a16ac01 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -1,7 +1,9 @@ package gregtech.common.pipelike.net.fluid; +import gregtech.api.capability.impl.FluidHandlerList; import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; +import gregtech.api.graphnet.GraphNetUtility; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.net.NetEdge; @@ -15,9 +17,9 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.FluidTestObject; -import gregtech.api.graphnet.traverse.iter.EdgeDirection; -import gregtech.api.graphnet.traverse.iter.EdgeSelector; -import gregtech.api.graphnet.traverse.iter.ResilientNetClosestIterator; +import gregtech.api.graphnet.traverse.EdgeDirection; +import gregtech.api.graphnet.traverse.EdgeSelector; +import gregtech.api.graphnet.traverse.ResilientNetClosestIterator; import gregtech.api.util.GTUtility; import gregtech.api.util.MapUtil; @@ -31,6 +33,7 @@ import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2LongMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,6 +54,10 @@ public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandl private boolean transferring = false; + private @Nullable FluidHandlerList networkView; + private long networkViewGatherTick; + private final Object2ObjectOpenHashMap handlerToNodeMap = new Object2ObjectOpenHashMap<>(); + public FluidCapabilityObject(WorldPipeNode node) { this.node = node; properties = new IFluidTankProperties[node.getData().getLogicEntryDefaultable(ChannelCountLogic.TYPE) @@ -79,7 +86,7 @@ private boolean inputDisallowed(EnumFacing side) { } @Override - public T getCapability(Capability capability, @Nullable EnumFacing facing) { + public T getCapability(@NotNull Capability capability, @Nullable EnumFacing facing) { // can't expose the sided capability if there is no node to interact with if (facing != null && capabilityWrapper.getNodeForFacing(facing) == null) return null; if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { @@ -95,13 +102,13 @@ public T getCapability(Capability capability, @Nullable EnumFacing facing protected int fill(FluidStack resource, boolean doFill, EnumFacing side) { if (this.transferring || inputDisallowed(side)) return 0; NetNode node = getRelevantNode(side); - if (node == null) return 0; + if (node == null) node = this.node; this.transferring = true; int flow = resource.amount; FluidTestObject testObject = new FluidTestObject(resource); ResilientNetClosestIterator iter = new ResilientNetClosestIterator(node, - EdgeSelector.filtered(EdgeDirection.OUTGOING, e -> e instanceof NetEdge n && !n.test(testObject))); + EdgeSelector.filtered(EdgeDirection.OUTGOING, GraphNetUtility.standardEdgeBlacklist(testObject))); Object2IntOpenHashMap availableDemandCache = new Object2IntOpenHashMap<>(); Object2IntOpenHashMap flowLimitCache = new Object2IntOpenHashMap<>(); Object2BooleanOpenHashMap lossyCache = new Object2BooleanOpenHashMap<>(); @@ -162,20 +169,21 @@ protected int fill(FluidStack resource, boolean doFill, EnumFacing side) { } protected FluidStack drain(int maxDrain, boolean doDrain, EnumFacing side) { - // TODO expose connected fluidnet through capability & allow untyped draining - return null; + FluidStack stack = getNetworkView().drain(maxDrain, false); + if (stack == null) return null; + return drain(stack, doDrain, side); } protected FluidStack drain(FluidStack resource, boolean doDrain, EnumFacing side) { if (this.transferring) return null; NetNode node = getRelevantNode(side); - if (node == null) return null; + if (node == null) node = this.node; this.transferring = true; int flow = resource.amount; FluidTestObject testObject = new FluidTestObject(resource); ResilientNetClosestIterator iter = new ResilientNetClosestIterator(node, - EdgeSelector.filtered(EdgeDirection.INCOMING, e -> e instanceof NetEdge n && !n.test(testObject))); + EdgeSelector.filtered(EdgeDirection.INCOMING, GraphNetUtility.standardEdgeBlacklist(testObject))); Object2IntOpenHashMap availableSupplyCache = new Object2IntOpenHashMap<>(); Object2IntOpenHashMap flowLimitCache = new Object2IntOpenHashMap<>(); Object2BooleanOpenHashMap lossyCache = new Object2BooleanOpenHashMap<>(); @@ -235,7 +243,7 @@ protected FluidStack drain(FluidStack resource, boolean doDrain, EnumFacing side return testObject.recombine(total); } - protected int getFlowLimit(NetNode node, FluidTestObject testObject) { + public static int getFlowLimit(NetNode node, FluidTestObject testObject) { ThroughputLogic throughput = node.getData().getLogicEntryNullable(ThroughputLogic.TYPE); if (throughput == null) return Integer.MAX_VALUE; FluidFlowLogic history = node.getData().getLogicEntryNullable(FluidFlowLogic.TYPE); @@ -311,7 +319,7 @@ public static int getSupplyOrDemand(NetNode node, FluidTestObject testObject, bo if (node instanceof NodeExposingCapabilities exposer) { IFluidHandler handler = exposer.getProvider().getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, exposer.exposedFacing()); - if (handler != null && !(handler instanceof FluidCapabilityObject)) { + if (handler != null && instanceOf(handler) == null) { if (supply) { FluidStack s = handler.drain(testObject.recombine(Integer.MAX_VALUE), false); return s == null ? 0 : s.amount; @@ -323,6 +331,31 @@ public static int getSupplyOrDemand(NetNode node, FluidTestObject testObject, bo return 0; } + public @NotNull FluidHandlerList getNetworkView() { + long tick = GTUtility.getTick(); + if (networkView == null || tick > networkViewGatherTick) { + handlerToNodeMap.clear(); + for (NetNode node : this.node.getGroupSafe().getNodes()) { + if (node instanceof NodeExposingCapabilities exposer) { + IFluidHandler handler = exposer.getProvider().getCapability( + CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + exposer.exposedFacing()); + if (handler != null && instanceOf(handler) == null) { + handlerToNodeMap.put(handler, node); + } + } + } + networkView = new FluidHandlerList(handlerToNodeMap.keySet()); + networkViewGatherTick = tick; + } + return networkView; + } + + public Object2ObjectOpenHashMap getHandlerToNodeMap() { + getNetworkView(); + return handlerToNodeMap; + } + @Override public int fill(FluidStack resource, boolean doFill) { return fill(resource, doFill, null); @@ -373,6 +406,13 @@ public boolean canDrainFluidType(FluidStack fluidStack) { return true; } + @Nullable + public static FluidCapabilityObject instanceOf(IFluidHandler handler) { + if (handler instanceof FluidCapabilityObject f) return f; + if (handler instanceof Wrapper w) return w.getParent(); + return null; + } + protected class Wrapper implements IFluidHandler, IFluidTankProperties { private final EnumFacing facing; @@ -433,5 +473,9 @@ public boolean canFillFluidType(FluidStack fluidStack) { public boolean canDrainFluidType(FluidStack fluidStack) { return true; } + + public FluidCapabilityObject getParent() { + return FluidCapabilityObject.this; + } } } diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 9dfb478d613..7bb59b36dc7 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -26,9 +26,6 @@ public class WorldFluidNet extends WorldPipeNet { - public static final Capability[] CAPABILITIES = new Capability[] { - CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY }; - private static final String DATA_ID_BASE = "gregtech.world_fluid_net"; public static @NotNull WorldFluidNet getWorldNet(World world) { diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index 3563ddb49fe..ae6e872e445 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -1,8 +1,9 @@ package gregtech.common.pipelike.net.item; +import gregtech.api.capability.impl.ItemHandlerList; +import gregtech.api.graphnet.GraphNetUtility; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.ThroughputLogic; -import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.net.NetNode; import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.pipenet.WorldPipeNode; @@ -11,11 +12,10 @@ import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; import gregtech.api.graphnet.predicate.test.ItemTestObject; -import gregtech.api.graphnet.traverse.iter.EdgeDirection; -import gregtech.api.graphnet.traverse.iter.EdgeSelector; -import gregtech.api.graphnet.traverse.iter.ResilientNetClosestIterator; +import gregtech.api.graphnet.traverse.EdgeDirection; +import gregtech.api.graphnet.traverse.EdgeSelector; +import gregtech.api.graphnet.traverse.ResilientNetClosestIterator; import gregtech.api.util.GTUtility; -import gregtech.api.util.MapUtil; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; @@ -23,13 +23,13 @@ import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2LongMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayDeque; import java.util.EnumMap; +import java.util.function.Predicate; public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler { @@ -41,6 +41,10 @@ public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler private boolean transferring = false; + private @Nullable ItemHandlerList networkView; + private long networkViewGatherTick; + private Object2ObjectOpenHashMap handlerToNodeMap = new Object2ObjectOpenHashMap<>(); + public ItemCapabilityObject(WorldPipeNode node) { this.node = node; for (EnumFacing facing : EnumFacing.VALUES) { @@ -77,68 +81,72 @@ public T getCapability(Capability capability, @Nullable EnumFacing facing return facing == null ? node : capabilityWrapper.getNodeForFacing(facing); } - protected @NotNull ItemStack insertItem(@NotNull ItemStack stack, boolean simulate, EnumFacing side) { - if (this.transferring || inputDisallowed(side)) return stack; - NetNode node = getRelevantNode(side); - if (node == null) return stack; - this.transferring = true; - - int flow = stack.getCount(); - ItemTestObject testObject = new ItemTestObject(stack); - ResilientNetClosestIterator iter = new ResilientNetClosestIterator(node, - EdgeSelector.filtered(EdgeDirection.OUTGOING, NetEdge.standardBlacklist(testObject))); - Object2IntOpenHashMap availableDemandCache = new Object2IntOpenHashMap<>(); - Object2IntOpenHashMap flowLimitCache = new Object2IntOpenHashMap<>(); - main: - while (iter.hasNext()) { - if (flow <= 0) break; - final NetNode next = iter.next(); - int limit = Math.min(MapUtil.computeIfAbsent(flowLimitCache, next, n -> getFlowLimit(n, testObject)), flow); - if (limit <= 0) { - iter.markInvalid(next); - continue; - } - int demand = MapUtil.computeIfAbsent(availableDemandCache, next, - n -> getSupplyOrDemand(n, testObject, false)); - if (demand <= 0) continue; - demand = Math.min(demand, limit); - NetEdge span; - NetNode trace = next; - ArrayDeque seen = new ArrayDeque<>(); - seen.add(next); - while ((span = iter.getSpanningTreeEdge(trace)) != null) { - trace = span.getOppositeNode(trace); - if (trace == null) continue main; - int l = MapUtil.computeIfAbsent(flowLimitCache, trace, n -> getFlowLimit(n, testObject)); - if (l == 0) { - iter.markInvalid(node); - continue main; - } - demand = Math.min(demand, l); - seen.addFirst(trace); - } - flow -= demand; - for (NetNode n : seen) { - if (!simulate) reportFlow(n, demand, testObject); - int remaining = flowLimitCache.getInt(n) - demand; - flowLimitCache.put(n, remaining); - if (remaining <= 0) { - iter.markInvalid(n); + protected @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate, EnumFacing side) { + @NotNull + ItemStack result = stack; + if (!this.transferring && !inputDisallowed(side)) { + NetNode node = getRelevantNode(side); + if (node == null) node = this.node; + this.transferring = true; + ItemHandlerList networkView = getNetworkView(); + IItemHandler targetHandler = networkView.getHandlerBySlot(slot); + NetNode targetNode = handlerToNodeMap.get(targetHandler); + if (targetNode != null) { + int handlerSlot = slot - networkView.getOffsetByHandler(targetHandler); + int insertable = stack.getCount() - targetHandler.insertItem(handlerSlot, stack, true).getCount(); + if (insertable > 0) { + final ItemTestObject testObject = new ItemTestObject(stack); + Predicate filter = GraphNetUtility.standardEdgeBlacklist(testObject); + ResilientNetClosestIterator forwardFrontier = new ResilientNetClosestIterator(node, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + ResilientNetClosestIterator backwardFrontier = new ResilientNetClosestIterator(targetNode, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + insertable = GraphNetUtility.p2pWalk(simulate, insertable, n -> getFlowLimit(n, testObject), + (n, i) -> reportFlow(n, i, testObject), forwardFrontier, backwardFrontier); + if (!simulate) targetHandler.insertItem(handlerSlot, testObject.recombine(insertable), false); + result = testObject.recombine(stack.getCount() - insertable); } } - if (!simulate) reportExtractedInserted(next, demand, testObject, false); - availableDemandCache.put(next, availableDemandCache.getInt(next) - demand); + this.transferring = false; } - this.transferring = false; - return testObject.recombine(flow); + + return result; } protected @NotNull ItemStack extractItem(int slot, int amount, boolean simulate, EnumFacing side) { - // TODO expose connected itemnet through capability & allow extraction - return ItemStack.EMPTY; + @NotNull + ItemStack result = ItemStack.EMPTY; + if (!this.transferring && !inputDisallowed(side)) { + NetNode node = getRelevantNode(side); + if (node == null) node = this.node; + this.transferring = true; + ItemHandlerList networkView = getNetworkView(); + IItemHandler targetHandler = networkView.getHandlerBySlot(slot); + NetNode targetNode = handlerToNodeMap.get(targetHandler); + if (targetNode != null) { + int handlerSlot = slot - networkView.getOffsetByHandler(targetHandler); + ItemStack stack = targetHandler.extractItem(handlerSlot, amount, true); + int extractable = stack.getCount(); + if (extractable > 0) { + final ItemTestObject testObject = new ItemTestObject(stack); + Predicate filter = GraphNetUtility.standardEdgeBlacklist(testObject); + ResilientNetClosestIterator forwardFrontier = new ResilientNetClosestIterator(node, + EdgeSelector.filtered(EdgeDirection.INCOMING, filter)); + ResilientNetClosestIterator backwardFrontier = new ResilientNetClosestIterator(targetNode, + EdgeSelector.filtered(EdgeDirection.OUTGOING, filter)); + extractable = GraphNetUtility.p2pWalk(simulate, extractable, n -> getFlowLimit(n, testObject), + (n, i) -> reportFlow(n, i, testObject), forwardFrontier, backwardFrontier); + if (!simulate) targetHandler.extractItem(handlerSlot, extractable, false); + result = testObject.recombine(extractable); + } + } + this.transferring = false; + } + + return result; } - protected int getFlowLimit(NetNode node, ItemTestObject testObject) { + public static int getFlowLimit(NetNode node, ItemTestObject testObject) { ThroughputLogic throughput = node.getData().getLogicEntryNullable(ThroughputLogic.TYPE); if (throughput == null) return Integer.MAX_VALUE; ItemFlowLogic history = node.getData().getLogicEntryNullable(ItemFlowLogic.TYPE); @@ -162,71 +170,44 @@ public static void reportFlow(NetNode node, int flow, ItemTestObject testObject) logic.recordFlow(GTUtility.getTick(), testObject.recombine(flow)); } - public static void reportExtractedInserted(NetNode node, int flow, ItemTestObject testObject, boolean extracted) { - if (flow == 0) return; - if (node instanceof NodeExposingCapabilities exposer) { - IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, - exposer.exposedFacing()); - if (handler != null) { - // positive flow is supply, aka we pulled flow from this node - if (extracted) { - for (int i = 0; i < handler.getSlots(); i++) { - ItemStack stack = handler.extractItem(i, flow, true); - if (testObject.test(stack)) { - stack = handler.extractItem(i, flow, false); - flow -= stack.getCount(); - } - if (flow == 0) return; - } - } else { - for (int i = 0; i < handler.getSlots(); i++) { - ItemStack stack = testObject.recombineSafe(flow); - flow -= stack.getCount() - handler.insertItem(i, stack, false).getCount(); - if (flow <= 0) return; + public @NotNull ItemHandlerList getNetworkView() { + long tick = GTUtility.getTick(); + if (networkView == null || tick > networkViewGatherTick) { + handlerToNodeMap.clear(); + for (NetNode node : this.node.getGroupSafe().getNodes()) { + if (node instanceof NodeExposingCapabilities exposer) { + IItemHandler handler = exposer.getProvider().getCapability( + CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, + exposer.exposedFacing()); + if (handler != null && instanceOf(handler) == null) { + handlerToNodeMap.put(handler, node); } } } + networkView = new ItemHandlerList(handlerToNodeMap.keySet()); + networkViewGatherTick = tick; } + return networkView; } - public static int getSupplyOrDemand(NetNode node, ItemTestObject testObject, boolean supply) { - if (node instanceof NodeExposingCapabilities exposer) { - IItemHandler handler = exposer.getProvider().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, - exposer.exposedFacing()); - if (handler != null && !(handler instanceof ItemCapabilityObject)) { - if (supply) { - int sum = 0; - for (int i = 0; i < handler.getSlots(); i++) { - ItemStack stack = handler.extractItem(i, Integer.MAX_VALUE, true); - if (testObject.test(stack)) sum += stack.getCount(); - } - return sum; - } else { - int sum = 0; - ItemStack stack = testObject.recombineSafe(Integer.MAX_VALUE); - for (int i = 0; i < handler.getSlots(); i++) { - sum += stack.getCount() - handler.insertItem(i, stack, true).getCount(); - } - return sum; - } - } - } - return 0; + public Object2ObjectOpenHashMap getHandlerToNodeMap() { + getNetworkView(); + return handlerToNodeMap; } @Override public int getSlots() { - return 1; + return getNetworkView().getSlots(); } @Override public @NotNull ItemStack getStackInSlot(int slot) { - return ItemStack.EMPTY; + return getNetworkView().getStackInSlot(slot); } @Override public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { - return insertItem(stack, simulate, null); + return insertItem(slot, stack, simulate, null); } @Override @@ -236,7 +217,14 @@ public int getSlots() { @Override public int getSlotLimit(int slot) { - return 64; + return getNetworkView().getSlotLimit(slot); + } + + @Nullable + public static ItemCapabilityObject instanceOf(IItemHandler handler) { + if (handler instanceof ItemCapabilityObject i) return i; + if (handler instanceof Wrapper w) return w.getParent(); + return null; } protected class Wrapper implements IItemHandler { @@ -249,17 +237,17 @@ public Wrapper(EnumFacing facing) { @Override public int getSlots() { - return 1; + return ItemCapabilityObject.this.getSlots(); } @Override public @NotNull ItemStack getStackInSlot(int slot) { - return ItemStack.EMPTY; + return ItemCapabilityObject.this.getStackInSlot(slot); } @Override public @NotNull ItemStack insertItem(int slot, @NotNull ItemStack stack, boolean simulate) { - return ItemCapabilityObject.this.insertItem(stack, simulate, facing); + return ItemCapabilityObject.this.insertItem(slot, stack, simulate, facing); } @Override @@ -269,7 +257,11 @@ public int getSlots() { @Override public int getSlotLimit(int slot) { - return 64; + return ItemCapabilityObject.this.getSlotLimit(slot); + } + + public ItemCapabilityObject getParent() { + return ItemCapabilityObject.this; } } } diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index 6f8212abc47..b1f8ac63dd7 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -26,9 +26,6 @@ public class WorldItemNet extends WorldPipeNet { - public static final Capability[] CAPABILITIES = new Capability[] { - CapabilityItemHandler.ITEM_HANDLER_CAPABILITY }; - private static final String DATA_ID_BASE = "gregtech.world_item_net"; public static @NotNull WorldItemNet getWorldNet(World world) { diff --git a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java index 614b9d1c9f0..17ffcf1abe7 100644 --- a/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java +++ b/src/main/java/gregtech/common/pipelike/net/laser/WorldLaserNet.java @@ -8,7 +8,7 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; +import gregtech.api.graphnet.traverse.NetBreadthIterator; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; diff --git a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java index 85b7cc9202f..7bf74060ded 100644 --- a/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java +++ b/src/main/java/gregtech/common/pipelike/net/optical/WorldOpticalNet.java @@ -8,7 +8,7 @@ import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.PipeCapabilityWrapper; import gregtech.api.graphnet.pipenet.physical.tile.PipeTileEntity; -import gregtech.api.graphnet.traverse.iter.NetBreadthIterator; +import gregtech.api.graphnet.traverse.NetBreadthIterator; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 8224c92412c..43662c42aa3 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -1305,7 +1305,7 @@ cover.generic.transfer_mode=Transfer Mode cover.generic.manual_io=Manual IO Mode cover.generic.io=IO Mode cover.generic.distribution.name=Distribution Mode -cover.generic.distribution.equalized=§bEqual Distribution§r\n§7Fills all destinations by the same amount per operation. +cover.generic.distribution.equalized=§bEqual Distribution§r\n§7Fills all destinations by the same amount per operation.\n§cMay be computationally expensive. Use sparingly. cover.generic.distribution.round_robin=§bRound Robin§r\n§7Fills destinations in a fixed order, but does not equalize. cover.generic.distribution.flood=§bFlood Insert§r\n§7Fills destinations based on their priorities and does not equalize. cover.pump.mode=Pump Mode diff --git a/src/test/java/gregtech/api/util/GTUtilityTest.java b/src/test/java/gregtech/api/util/GTUtilityTest.java index b2bc0520559..30d9d50fc6d 100644 --- a/src/test/java/gregtech/api/util/GTUtilityTest.java +++ b/src/test/java/gregtech/api/util/GTUtilityTest.java @@ -9,7 +9,7 @@ public void binarySearchTest() { for (int i = 0; i < 1000; i++) { int finalI = i; - long result = GTUtility.binarySearch(0, 10000, l -> l >= finalI, true); + long result = GTUtility.binarySearchLong(0, 10000, l -> l >= finalI, true); if (result != finalI) { throw new AssertionError("Got " + result + " when desiring " + finalI); @@ -18,7 +18,7 @@ public void binarySearchTest() { for (int i = 0; i < 1000; i++) { int finalI = i; - long result = GTUtility.binarySearch(0, 10000, l -> l <= finalI, false); + long result = GTUtility.binarySearchLong(0, 10000, l -> l <= finalI, false); if (result != finalI) { throw new AssertionError("Got " + result + " when desiring " + finalI); From 7d43f8cbd2bfcdc441599ab595187b6c6621b499 Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Tue, 24 Dec 2024 20:01:42 -0700 Subject: [PATCH 156/157] Improved caching --- .../api/capability/impl/FluidHandlerList.java | 5 +- .../graphnet/group/NodeCacheGroupData.java | 43 ++++++ .../graphnet/group/PathCacheGroupData.java | 132 ++++++++---------- .../gregtech/common/covers/CoverConveyor.java | 22 +-- .../gregtech/common/covers/CoverPump.java | 22 +-- .../net/fluid/FluidCapabilityObject.java | 34 +---- .../pipelike/net/fluid/FluidNetworkView.java | 20 +++ .../net/fluid/FluidNetworkViewGroupData.java | 78 +++++++++++ .../pipelike/net/fluid/WorldFluidNet.java | 6 + .../net/item/ItemCapabilityObject.java | 55 ++------ .../pipelike/net/item/ItemNetworkView.java | 20 +++ .../net/item/ItemNetworkViewGroupData.java | 78 +++++++++++ .../pipelike/net/item/WorldItemNet.java | 6 + 13 files changed, 358 insertions(+), 163 deletions(-) create mode 100644 src/main/java/gregtech/api/graphnet/group/NodeCacheGroupData.java create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/FluidNetworkView.java create mode 100644 src/main/java/gregtech/common/pipelike/net/fluid/FluidNetworkViewGroupData.java create mode 100644 src/main/java/gregtech/common/pipelike/net/item/ItemNetworkView.java create mode 100644 src/main/java/gregtech/common/pipelike/net/item/ItemNetworkViewGroupData.java diff --git a/src/main/java/gregtech/api/capability/impl/FluidHandlerList.java b/src/main/java/gregtech/api/capability/impl/FluidHandlerList.java index ab6fad193b0..3e0ead683dd 100644 --- a/src/main/java/gregtech/api/capability/impl/FluidHandlerList.java +++ b/src/main/java/gregtech/api/capability/impl/FluidHandlerList.java @@ -5,7 +5,7 @@ import net.minecraftforge.fluids.capability.IFluidTankProperties; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.UnmodifiableView; @@ -22,7 +22,8 @@ public class FluidHandlerList implements IFluidHandler { private final Set list; public FluidHandlerList(Collection handlers) { - list = new ObjectOpenHashSet<>(handlers); + // use a linked set to preserve iteration order + list = new ObjectLinkedOpenHashSet<>(handlers); } @Override diff --git a/src/main/java/gregtech/api/graphnet/group/NodeCacheGroupData.java b/src/main/java/gregtech/api/graphnet/group/NodeCacheGroupData.java new file mode 100644 index 00000000000..d0d1e283a83 --- /dev/null +++ b/src/main/java/gregtech/api/graphnet/group/NodeCacheGroupData.java @@ -0,0 +1,43 @@ +package gregtech.api.graphnet.group; + +import gregtech.api.graphnet.net.NetNode; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +public abstract class NodeCacheGroupData extends GroupData { + + protected final @NotNull Object2ObjectOpenHashMap cache; + + public NodeCacheGroupData() { + this(new Object2ObjectOpenHashMap<>()); + } + + public NodeCacheGroupData(@NotNull Object2ObjectOpenHashMap cache) { + this.cache = cache; + } + + @NotNull + public T getOrCreate(@NotNull NetNode node) { + return cache.computeIfAbsent(node, this::getNew); + } + + protected abstract T getNew(@NotNull NetNode node); + + public void invalidateAll() { + cache.clear(); + cache.trim(16); + } + + @Override + public @NotNull Pair splitAcross(@NotNull Set sourceNodes, + @NotNull Set targetNodes) { + return ImmutablePair.of(buildFilteredCache(sourceNodes), buildFilteredCache(targetNodes)); + } + + protected abstract @NotNull NodeCacheGroupData buildFilteredCache(@NotNull Set filterNodes); +} diff --git a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java index 40b4110a741..dfdf1a4231f 100644 --- a/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java +++ b/src/main/java/gregtech/api/graphnet/group/PathCacheGroupData.java @@ -11,99 +11,35 @@ import gregtech.api.graphnet.traverse.NetIteratorSupplier; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Set; -public class PathCacheGroupData extends GroupData { +public class PathCacheGroupData extends NodeCacheGroupData { protected final NetIteratorSupplier iteratorSupplier; - protected final @NotNull Object2ObjectOpenHashMap cache; - public PathCacheGroupData(NetIteratorSupplier iteratorSupplier) { this(iteratorSupplier, new Object2ObjectOpenHashMap<>()); } public PathCacheGroupData(NetIteratorSupplier iteratorSupplier, @NotNull Object2ObjectOpenHashMap cache) { - this.cache = cache; + super(cache); this.iteratorSupplier = iteratorSupplier; } - @NotNull - public SecondaryCache getOrCreate(@NotNull NetNode source) { - return cache.computeIfAbsent(source, SecondaryCache::new); - } - - public void invalidateAll() { - cache.clear(); - cache.trim(16); + @Override + protected SecondaryCache getNew(@NotNull NetNode node) { + return new SecondaryCache(node); } public void notifyTopologicalChange() { cache.forEach((key, value) -> value.notifyTopologicalChange()); } - public class SecondaryCache extends Object2ObjectOpenHashMap { - - protected final @NotNull NetNode source; - protected @Nullable NetIterator searchFrontier; - - protected NetPath singleton; - - protected int frontierPosition; - - public SecondaryCache(@NotNull NetNode source) { - this.source = source; - } - - @Nullable - public NetPath getOrCompute(@NotNull NetNode target) { - if (target == source) { - if (singleton == null) singleton = buildSingleton(source); - return singleton; - } - - if (searchFrontier == null) searchFrontier = iteratorSupplier.create(source, EdgeDirection.OUTGOING); - - NetPath existing = this.get(target); - if (existing != null) return existing; - NetIterator targetFrontier = iteratorSupplier.create(target, EdgeDirection.INCOMING); - int frontierPosition = 0; - // first, attempt to bring the target frontier up to date with the search frontier. - while (frontierPosition < this.frontierPosition && targetFrontier.hasNext()) { - NetNode node = targetFrontier.next(); - frontierPosition++; - if (searchFrontier.hasSeen(node)) { - NetPath built = buildPath(node, targetFrontier, searchFrontier); - this.put(target, built); - return built; - } - } - // second, move both frontiers forward until intersect or exhaustion of iterators. - while (searchFrontier.hasNext() && targetFrontier.hasNext()) { - searchFrontier.next(); - NetNode node = targetFrontier.next(); - this.frontierPosition++; - if (searchFrontier.hasSeen(node)) { - NetPath built = buildPath(node, targetFrontier, searchFrontier); - this.put(target, built); - return built; - } - } - return null; - } - - public void notifyTopologicalChange() { - this.searchFrontier = null; - this.frontierPosition = 0; - } - } - protected PathBuilder createBuilder(@NotNull NetNode origin) { return new StandardNetPath.Builder(origin); } @@ -164,7 +100,7 @@ public void notifyOfRemovedEdge(@NotNull NetEdge edge) { public @NotNull Pair splitAcross(@NotNull Set sourceNodes, @NotNull Set targetNodes) { notifyTopologicalChange(); - return ImmutablePair.of(buildFilteredCache(sourceNodes), buildFilteredCache(targetNodes)); + return super.splitAcross(sourceNodes, targetNodes); } protected @NotNull PathCacheGroupData buildFilteredCache(@NotNull Set filterNodes) { @@ -177,4 +113,60 @@ public void notifyOfRemovedEdge(@NotNull NetEdge edge) { }); return new PathCacheGroupData(iteratorSupplier, child); } + + public class SecondaryCache extends Object2ObjectOpenHashMap { + + protected final @NotNull NetNode source; + protected @Nullable NetIterator searchFrontier; + + protected NetPath singleton; + + protected int frontierPosition; + + public SecondaryCache(@NotNull NetNode source) { + this.source = source; + } + + @Nullable + public NetPath getOrCompute(@NotNull NetNode target) { + if (target == source) { + if (singleton == null) singleton = buildSingleton(source); + return singleton; + } + + if (searchFrontier == null) searchFrontier = iteratorSupplier.create(source, EdgeDirection.OUTGOING); + + NetPath existing = this.get(target); + if (existing != null) return existing; + NetIterator targetFrontier = iteratorSupplier.create(target, EdgeDirection.INCOMING); + int frontierPosition = 0; + // first, attempt to bring the target frontier up to date with the search frontier. + while (frontierPosition < this.frontierPosition && targetFrontier.hasNext()) { + NetNode node = targetFrontier.next(); + frontierPosition++; + if (searchFrontier.hasSeen(node)) { + NetPath built = buildPath(node, targetFrontier, searchFrontier); + this.put(target, built); + return built; + } + } + // second, move both frontiers forward until intersect or exhaustion of iterators. + while (searchFrontier.hasNext() && targetFrontier.hasNext()) { + searchFrontier.next(); + NetNode node = targetFrontier.next(); + this.frontierPosition++; + if (searchFrontier.hasSeen(node)) { + NetPath built = buildPath(node, targetFrontier, searchFrontier); + this.put(target, built); + return built; + } + } + return null; + } + + public void notifyTopologicalChange() { + this.searchFrontier = null; + this.frontierPosition = 0; + } + } } diff --git a/src/main/java/gregtech/common/covers/CoverConveyor.java b/src/main/java/gregtech/common/covers/CoverConveyor.java index 2235b2bf10a..4d88a09dd03 100644 --- a/src/main/java/gregtech/common/covers/CoverConveyor.java +++ b/src/main/java/gregtech/common/covers/CoverConveyor.java @@ -4,7 +4,6 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; import gregtech.api.capability.impl.ItemHandlerDelegate; -import gregtech.api.capability.impl.ItemHandlerList; import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; @@ -31,6 +30,7 @@ import gregtech.common.covers.filter.MatchResult; import gregtech.common.covers.filter.MergabilityInfo; import gregtech.common.pipelike.net.item.ItemCapabilityObject; +import gregtech.common.pipelike.net.item.ItemNetworkView; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; @@ -329,8 +329,8 @@ protected int doExtract(@NotNull IItemHandler handler, ItemTestObject testObject // good luck. return switch (distributionMode) { case ROUND_ROBIN -> { - ItemHandlerList view = cap.getNetworkView(); - Iterator iter = view.getBackingHandlers().iterator(); + ItemNetworkView view = cap.getNetworkView(); + Iterator iter = view.handler().getBackingHandlers().iterator(); ObjectLinkedOpenHashSet cache = getRoundRobinCache(true, simulate); Set backlog = new ObjectOpenHashSet<>(); Object2IntOpenHashMap flows = new Object2IntOpenHashMap<>(); @@ -338,7 +338,7 @@ protected int doExtract(@NotNull IItemHandler handler, ItemTestObject testObject while (available > 0) { if (!cache.isEmpty() && backlog.remove(cache.first())) { IItemHandler candidate = cache.first(); - NetNode linked = cap.getHandlerToNodeMap().get(candidate); + NetNode linked = view.handlerNetNodeBiMap().get(candidate); if (linked == null) { cache.removeFirst(); continue; @@ -353,7 +353,7 @@ protected int doExtract(@NotNull IItemHandler handler, ItemTestObject testObject IItemHandler candidate = iter.next(); boolean frontOfCache = !cache.isEmpty() && cache.first() == candidate; if (frontOfCache || !cache.contains(candidate)) { - NetNode linked = cap.getHandlerToNodeMap().get(candidate); + NetNode linked = view.handlerNetNodeBiMap().get(candidate); if (linked == null) { if (frontOfCache) cache.removeFirst(); continue; @@ -370,7 +370,7 @@ protected int doExtract(@NotNull IItemHandler handler, ItemTestObject testObject break; } else { if (!cache.isEmpty()) { - if (view.getBackingHandlers().contains(cache.first())) + if (view.handler().getBackingHandlers().contains(cache.first())) break; // we've already visited the next node in the cache else { // the network view does not contain the node in the front of the cache, so yeet it. @@ -491,8 +491,8 @@ protected int doInsert(@NotNull IItemHandler handler, ItemTestObject testObject, // good luck. return switch (distributionMode) { case ROUND_ROBIN -> { - ItemHandlerList view = cap.getNetworkView(); - Iterator iter = view.getBackingHandlers().iterator(); + ItemNetworkView view = cap.getNetworkView(); + Iterator iter = view.handler().getBackingHandlers().iterator(); ObjectLinkedOpenHashSet cache = getRoundRobinCache(false, simulate); Set backlog = new ObjectOpenHashSet<>(); Object2IntOpenHashMap flows = new Object2IntOpenHashMap<>(); @@ -500,7 +500,7 @@ protected int doInsert(@NotNull IItemHandler handler, ItemTestObject testObject, while (available > 0) { if (!cache.isEmpty() && backlog.remove(cache.first())) { IItemHandler candidate = cache.first(); - NetNode linked = cap.getHandlerToNodeMap().get(candidate); + NetNode linked = view.handlerNetNodeBiMap().get(candidate); if (linked == null) { cache.removeFirst(); continue; @@ -514,7 +514,7 @@ protected int doInsert(@NotNull IItemHandler handler, ItemTestObject testObject, IItemHandler candidate = iter.next(); boolean frontOfCache = !cache.isEmpty() && cache.first() == candidate; if (frontOfCache || !cache.contains(candidate)) { - NetNode linked = cap.getHandlerToNodeMap().get(candidate); + NetNode linked = view.handlerNetNodeBiMap().get(candidate); if (linked == null) { if (frontOfCache) cache.removeFirst(); continue; @@ -531,7 +531,7 @@ protected int doInsert(@NotNull IItemHandler handler, ItemTestObject testObject, break; } else { if (!cache.isEmpty()) { - if (view.getBackingHandlers().contains(cache.first())) + if (view.handler().getBackingHandlers().contains(cache.first())) break; // we've already visited the next node in the cache else { // the network view does not contain the node in the front of the cache, so yeet it. diff --git a/src/main/java/gregtech/common/covers/CoverPump.java b/src/main/java/gregtech/common/covers/CoverPump.java index b90bc55b5dc..e46f63387f5 100644 --- a/src/main/java/gregtech/common/covers/CoverPump.java +++ b/src/main/java/gregtech/common/covers/CoverPump.java @@ -4,7 +4,6 @@ import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IControllable; import gregtech.api.capability.impl.FluidHandlerDelegate; -import gregtech.api.capability.impl.FluidHandlerList; import gregtech.api.cover.CoverBase; import gregtech.api.cover.CoverDefinition; import gregtech.api.cover.CoverWithUI; @@ -29,6 +28,7 @@ import gregtech.common.covers.filter.FluidFilterContainer; import gregtech.common.covers.filter.MatchResult; import gregtech.common.pipelike.net.fluid.FluidCapabilityObject; +import gregtech.common.pipelike.net.fluid.FluidNetworkView; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.player.EntityPlayer; @@ -316,8 +316,8 @@ protected int doExtract(@NotNull IFluidHandler handler, FluidTestObject testObje // good luck. return switch (distributionMode) { case ROUND_ROBIN -> { - FluidHandlerList view = cap.getNetworkView(); - Iterator iter = view.getBackingHandlers().iterator(); + FluidNetworkView view = cap.getNetworkView(); + Iterator iter = view.handler().getBackingHandlers().iterator(); ObjectLinkedOpenHashSet cache = getRoundRobinCache(true, simulate); Set backlog = new ObjectOpenHashSet<>(); Object2IntOpenHashMap flows = new Object2IntOpenHashMap<>(); @@ -325,7 +325,7 @@ protected int doExtract(@NotNull IFluidHandler handler, FluidTestObject testObje while (available > 0) { if (!cache.isEmpty() && backlog.remove(cache.first())) { IFluidHandler candidate = cache.first(); - NetNode linked = cap.getHandlerToNodeMap().get(candidate); + NetNode linked = view.handlerNetNodeBiMap().get(candidate); if (linked == null) { cache.removeFirst(); continue; @@ -340,7 +340,7 @@ protected int doExtract(@NotNull IFluidHandler handler, FluidTestObject testObje IFluidHandler candidate = iter.next(); boolean frontOfCache = !cache.isEmpty() && cache.first() == candidate; if (frontOfCache || !cache.contains(candidate)) { - NetNode linked = cap.getHandlerToNodeMap().get(candidate); + NetNode linked = view.handlerNetNodeBiMap().get(candidate); if (linked == null) { if (frontOfCache) cache.removeFirst(); continue; @@ -357,7 +357,7 @@ protected int doExtract(@NotNull IFluidHandler handler, FluidTestObject testObje break; } else { if (!cache.isEmpty()) { - if (view.getBackingHandlers().contains(cache.first())) + if (view.handler().getBackingHandlers().contains(cache.first())) break; // we've already visited the next node in the cache else { // the network view does not contain the node in the front of the cache, so yeet it. @@ -471,8 +471,8 @@ protected int doInsert(@NotNull IFluidHandler handler, FluidTestObject testObjec // good luck. return switch (distributionMode) { case ROUND_ROBIN -> { - FluidHandlerList view = cap.getNetworkView(); - Iterator iter = view.getBackingHandlers().iterator(); + FluidNetworkView view = cap.getNetworkView(); + Iterator iter = view.handler().getBackingHandlers().iterator(); ObjectLinkedOpenHashSet cache = getRoundRobinCache(false, simulate); Set backlog = new ObjectOpenHashSet<>(); Object2IntOpenHashMap flows = new Object2IntOpenHashMap<>(); @@ -480,7 +480,7 @@ protected int doInsert(@NotNull IFluidHandler handler, FluidTestObject testObjec while (available > 0) { if (!cache.isEmpty() && backlog.remove(cache.first())) { IFluidHandler candidate = cache.first(); - NetNode linked = cap.getHandlerToNodeMap().get(candidate); + NetNode linked = view.handlerNetNodeBiMap().get(candidate); if (linked == null) { cache.removeFirst(); continue; @@ -494,7 +494,7 @@ protected int doInsert(@NotNull IFluidHandler handler, FluidTestObject testObjec IFluidHandler candidate = iter.next(); boolean frontOfCache = !cache.isEmpty() && cache.first() == candidate; if (frontOfCache || !cache.contains(candidate)) { - NetNode linked = cap.getHandlerToNodeMap().get(candidate); + NetNode linked = view.handlerNetNodeBiMap().get(candidate); if (linked == null) { if (frontOfCache) cache.removeFirst(); continue; @@ -511,7 +511,7 @@ protected int doInsert(@NotNull IFluidHandler handler, FluidTestObject testObjec break; } else { if (!cache.isEmpty()) { - if (view.getBackingHandlers().contains(cache.first())) + if (view.handler().getBackingHandlers().contains(cache.first())) break; // we've already visited the next node in the cache else { // the network view does not contain the node in the front of the cache, so yeet it. diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java index 8127a16ac01..59aaff5c331 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidCapabilityObject.java @@ -1,6 +1,5 @@ package gregtech.common.pipelike.net.fluid; -import gregtech.api.capability.impl.FluidHandlerList; import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttribute; import gregtech.api.graphnet.GraphNetUtility; @@ -33,7 +32,6 @@ import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2LongMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,10 +52,6 @@ public class FluidCapabilityObject implements IPipeCapabilityObject, IFluidHandl private boolean transferring = false; - private @Nullable FluidHandlerList networkView; - private long networkViewGatherTick; - private final Object2ObjectOpenHashMap handlerToNodeMap = new Object2ObjectOpenHashMap<>(); - public FluidCapabilityObject(WorldPipeNode node) { this.node = node; properties = new IFluidTankProperties[node.getData().getLogicEntryDefaultable(ChannelCountLogic.TYPE) @@ -169,7 +163,7 @@ protected int fill(FluidStack resource, boolean doFill, EnumFacing side) { } protected FluidStack drain(int maxDrain, boolean doDrain, EnumFacing side) { - FluidStack stack = getNetworkView().drain(maxDrain, false); + FluidStack stack = getNetworkView().handler().drain(maxDrain, false); if (stack == null) return null; return drain(stack, doDrain, side); } @@ -331,29 +325,11 @@ public static int getSupplyOrDemand(NetNode node, FluidTestObject testObject, bo return 0; } - public @NotNull FluidHandlerList getNetworkView() { - long tick = GTUtility.getTick(); - if (networkView == null || tick > networkViewGatherTick) { - handlerToNodeMap.clear(); - for (NetNode node : this.node.getGroupSafe().getNodes()) { - if (node instanceof NodeExposingCapabilities exposer) { - IFluidHandler handler = exposer.getProvider().getCapability( - CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, - exposer.exposedFacing()); - if (handler != null && instanceOf(handler) == null) { - handlerToNodeMap.put(handler, node); - } - } - } - networkView = new FluidHandlerList(handlerToNodeMap.keySet()); - networkViewGatherTick = tick; + public @NotNull FluidNetworkView getNetworkView() { + if (node.getGroupSafe().getData() instanceof FluidNetworkViewGroupData data) { + return data.getOrCreate(node); } - return networkView; - } - - public Object2ObjectOpenHashMap getHandlerToNodeMap() { - getNetworkView(); - return handlerToNodeMap; + return FluidNetworkView.EMPTY; } @Override diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidNetworkView.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidNetworkView.java new file mode 100644 index 00000000000..d42ff25e9e0 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidNetworkView.java @@ -0,0 +1,20 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.capability.impl.FluidHandlerList; +import gregtech.api.graphnet.net.NetNode; + +import net.minecraftforge.fluids.capability.IFluidHandler; + +import com.github.bsideup.jabel.Desugar; +import com.google.common.collect.BiMap; +import com.google.common.collect.ImmutableBiMap; + +@Desugar +public record FluidNetworkView(FluidHandlerList handler, BiMap handlerNetNodeBiMap) { + + public static final FluidNetworkView EMPTY = FluidNetworkView.of(ImmutableBiMap.of()); + + public static FluidNetworkView of(BiMap handlerNetNodeBiMap) { + return new FluidNetworkView(new FluidHandlerList(handlerNetNodeBiMap.keySet()), handlerNetNodeBiMap); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/FluidNetworkViewGroupData.java b/src/main/java/gregtech/common/pipelike/net/fluid/FluidNetworkViewGroupData.java new file mode 100644 index 00000000000..4fc1c596f6b --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/fluid/FluidNetworkViewGroupData.java @@ -0,0 +1,78 @@ +package gregtech.common.pipelike.net.fluid; + +import gregtech.api.capability.impl.FluidHandlerList; +import gregtech.api.graphnet.group.GroupData; +import gregtech.api.graphnet.group.NodeCacheGroupData; +import gregtech.api.graphnet.net.NetEdge; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; +import gregtech.api.graphnet.traverse.EdgeDirection; +import gregtech.api.graphnet.traverse.NetClosestIterator; +import gregtech.api.graphnet.traverse.NetIterator; + +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Set; + +public class FluidNetworkViewGroupData extends NodeCacheGroupData { + + @Override + protected FluidNetworkView getNew(@NotNull NetNode node) { + // use a list to preserve 'found order' from the iterator, + // so closer handlers are earlier in our handler list's extraction/insertion preference + List handlerList = new ObjectArrayList<>(); + BiMap map = HashBiMap.create(); + NetIterator iter = new NetClosestIterator(node, EdgeDirection.ALL); + while (iter.hasNext()) { + NetNode next = iter.next(); + if (next instanceof NodeExposingCapabilities exposer) { + IFluidHandler handler = exposer.getProvider().getCapability( + CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + exposer.exposedFacing()); + if (handler != null && FluidCapabilityObject.instanceOf(handler) == null) { + map.put(handler, next); + handlerList.add(handler); + } + } + } + return new FluidNetworkView(new FluidHandlerList(handlerList), map); + } + + @Override + public void notifyOfBridgingEdge(@NotNull NetEdge edge) { + invalidateAll(); + } + + @Override + public void notifyOfRemovedEdge(@NotNull NetEdge edge) { + invalidateAll(); + } + + @Override + protected @Nullable GroupData mergeAcross(@Nullable GroupData other, @NotNull NetEdge edge) { + invalidateAll(); + return this; + } + + @Override + public @NotNull Pair splitAcross(@NotNull Set sourceNodes, + @NotNull Set targetNodes) { + invalidateAll(); + return Pair.of(this, new FluidNetworkViewGroupData()); + } + + // unused since we override splitAcross + @Override + protected @NotNull NodeCacheGroupData buildFilteredCache(@NotNull Set filterNodes) { + return this; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java index 7bb59b36dc7..5670eadfee8 100644 --- a/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java +++ b/src/main/java/gregtech/common/pipelike/net/fluid/WorldFluidNet.java @@ -2,6 +2,7 @@ import gregtech.api.cover.Cover; import gregtech.api.cover.filter.CoverWithFluidFilter; +import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.pipenet.WorldPipeNet; @@ -93,4 +94,9 @@ public static int getBufferTicks() { public int getNetworkID() { return 1; } + + @Override + public @Nullable GroupData getBlankGroupData() { + return new FluidNetworkViewGroupData(); + } } diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java index ae6e872e445..6ef01bd646a 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemCapabilityObject.java @@ -1,11 +1,9 @@ package gregtech.common.pipelike.net.item; -import gregtech.api.capability.impl.ItemHandlerList; import gregtech.api.graphnet.GraphNetUtility; import gregtech.api.graphnet.logic.ChannelCountLogic; import gregtech.api.graphnet.logic.ThroughputLogic; import gregtech.api.graphnet.net.NetNode; -import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; import gregtech.api.graphnet.pipenet.WorldPipeNode; import gregtech.api.graphnet.pipenet.physical.IPipeCapabilityObject; import gregtech.api.graphnet.pipenet.physical.tile.NodeManagingPCW; @@ -24,7 +22,6 @@ import net.minecraftforge.items.IItemHandler; import it.unimi.dsi.fastutil.objects.Object2LongMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,10 +38,6 @@ public class ItemCapabilityObject implements IPipeCapabilityObject, IItemHandler private boolean transferring = false; - private @Nullable ItemHandlerList networkView; - private long networkViewGatherTick; - private Object2ObjectOpenHashMap handlerToNodeMap = new Object2ObjectOpenHashMap<>(); - public ItemCapabilityObject(WorldPipeNode node) { this.node = node; for (EnumFacing facing : EnumFacing.VALUES) { @@ -88,11 +81,11 @@ public T getCapability(Capability capability, @Nullable EnumFacing facing NetNode node = getRelevantNode(side); if (node == null) node = this.node; this.transferring = true; - ItemHandlerList networkView = getNetworkView(); - IItemHandler targetHandler = networkView.getHandlerBySlot(slot); - NetNode targetNode = handlerToNodeMap.get(targetHandler); + ItemNetworkView networkView = getNetworkView(); + IItemHandler targetHandler = networkView.handler().getHandlerBySlot(slot); + NetNode targetNode = networkView.handlerNetNodeBiMap().get(targetHandler); if (targetNode != null) { - int handlerSlot = slot - networkView.getOffsetByHandler(targetHandler); + int handlerSlot = slot - networkView.handler().getOffsetByHandler(targetHandler); int insertable = stack.getCount() - targetHandler.insertItem(handlerSlot, stack, true).getCount(); if (insertable > 0) { final ItemTestObject testObject = new ItemTestObject(stack); @@ -120,11 +113,11 @@ public T getCapability(Capability capability, @Nullable EnumFacing facing NetNode node = getRelevantNode(side); if (node == null) node = this.node; this.transferring = true; - ItemHandlerList networkView = getNetworkView(); - IItemHandler targetHandler = networkView.getHandlerBySlot(slot); - NetNode targetNode = handlerToNodeMap.get(targetHandler); + ItemNetworkView networkView = getNetworkView(); + IItemHandler targetHandler = networkView.handler().getHandlerBySlot(slot); + NetNode targetNode = networkView.handlerNetNodeBiMap().get(targetHandler); if (targetNode != null) { - int handlerSlot = slot - networkView.getOffsetByHandler(targetHandler); + int handlerSlot = slot - networkView.handler().getOffsetByHandler(targetHandler); ItemStack stack = targetHandler.extractItem(handlerSlot, amount, true); int extractable = stack.getCount(); if (extractable > 0) { @@ -170,39 +163,21 @@ public static void reportFlow(NetNode node, int flow, ItemTestObject testObject) logic.recordFlow(GTUtility.getTick(), testObject.recombine(flow)); } - public @NotNull ItemHandlerList getNetworkView() { - long tick = GTUtility.getTick(); - if (networkView == null || tick > networkViewGatherTick) { - handlerToNodeMap.clear(); - for (NetNode node : this.node.getGroupSafe().getNodes()) { - if (node instanceof NodeExposingCapabilities exposer) { - IItemHandler handler = exposer.getProvider().getCapability( - CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, - exposer.exposedFacing()); - if (handler != null && instanceOf(handler) == null) { - handlerToNodeMap.put(handler, node); - } - } - } - networkView = new ItemHandlerList(handlerToNodeMap.keySet()); - networkViewGatherTick = tick; + public @NotNull ItemNetworkView getNetworkView() { + if (node.getGroupSafe().getData() instanceof ItemNetworkViewGroupData data) { + return data.getOrCreate(node); } - return networkView; - } - - public Object2ObjectOpenHashMap getHandlerToNodeMap() { - getNetworkView(); - return handlerToNodeMap; + return ItemNetworkView.EMPTY; } @Override public int getSlots() { - return getNetworkView().getSlots(); + return getNetworkView().handler().getSlots(); } @Override public @NotNull ItemStack getStackInSlot(int slot) { - return getNetworkView().getStackInSlot(slot); + return getNetworkView().handler().getStackInSlot(slot); } @Override @@ -217,7 +192,7 @@ public int getSlots() { @Override public int getSlotLimit(int slot) { - return getNetworkView().getSlotLimit(slot); + return getNetworkView().handler().getSlotLimit(slot); } @Nullable diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemNetworkView.java b/src/main/java/gregtech/common/pipelike/net/item/ItemNetworkView.java new file mode 100644 index 00000000000..420ea81a2be --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemNetworkView.java @@ -0,0 +1,20 @@ +package gregtech.common.pipelike.net.item; + +import gregtech.api.capability.impl.ItemHandlerList; +import gregtech.api.graphnet.net.NetNode; + +import net.minecraftforge.items.IItemHandler; + +import com.github.bsideup.jabel.Desugar; +import com.google.common.collect.BiMap; +import com.google.common.collect.ImmutableBiMap; + +@Desugar +public record ItemNetworkView(ItemHandlerList handler, BiMap handlerNetNodeBiMap) { + + public static final ItemNetworkView EMPTY = ItemNetworkView.of(ImmutableBiMap.of()); + + public static ItemNetworkView of(BiMap handlerNetNodeBiMap) { + return new ItemNetworkView(new ItemHandlerList(handlerNetNodeBiMap.keySet()), handlerNetNodeBiMap); + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/ItemNetworkViewGroupData.java b/src/main/java/gregtech/common/pipelike/net/item/ItemNetworkViewGroupData.java new file mode 100644 index 00000000000..7a7d5e9b972 --- /dev/null +++ b/src/main/java/gregtech/common/pipelike/net/item/ItemNetworkViewGroupData.java @@ -0,0 +1,78 @@ +package gregtech.common.pipelike.net.item; + +import gregtech.api.capability.impl.ItemHandlerList; +import gregtech.api.graphnet.group.GroupData; +import gregtech.api.graphnet.group.NodeCacheGroupData; +import gregtech.api.graphnet.net.NetEdge; +import gregtech.api.graphnet.net.NetNode; +import gregtech.api.graphnet.pipenet.NodeExposingCapabilities; +import gregtech.api.graphnet.traverse.EdgeDirection; +import gregtech.api.graphnet.traverse.NetClosestIterator; +import gregtech.api.graphnet.traverse.NetIterator; + +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.apache.commons.lang3.tuple.Pair; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Set; + +public class ItemNetworkViewGroupData extends NodeCacheGroupData { + + @Override + protected ItemNetworkView getNew(@NotNull NetNode node) { + // use a list to preserve 'found order' from the iterator, + // so closer handlers are lower in our handler list's slot order. + List handlerList = new ObjectArrayList<>(); + BiMap map = HashBiMap.create(); + NetIterator iter = new NetClosestIterator(node, EdgeDirection.ALL); + while (iter.hasNext()) { + NetNode next = iter.next(); + if (next instanceof NodeExposingCapabilities exposer) { + IItemHandler handler = exposer.getProvider().getCapability( + CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, + exposer.exposedFacing()); + if (handler != null && ItemCapabilityObject.instanceOf(handler) == null) { + handlerList.add(handler); + map.put(handler, next); + } + } + } + return new ItemNetworkView(new ItemHandlerList(handlerList), map); + } + + @Override + public void notifyOfBridgingEdge(@NotNull NetEdge edge) { + invalidateAll(); + } + + @Override + public void notifyOfRemovedEdge(@NotNull NetEdge edge) { + invalidateAll(); + } + + @Override + protected @Nullable GroupData mergeAcross(@Nullable GroupData other, @NotNull NetEdge edge) { + invalidateAll(); + return this; + } + + @Override + public @NotNull Pair splitAcross(@NotNull Set sourceNodes, + @NotNull Set targetNodes) { + invalidateAll(); + return Pair.of(this, new ItemNetworkViewGroupData()); + } + + // unused since we override splitAcross + @Override + protected @NotNull NodeCacheGroupData buildFilteredCache(@NotNull Set filterNodes) { + return this; + } +} diff --git a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java index b1f8ac63dd7..0cdd5f5afd8 100644 --- a/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java +++ b/src/main/java/gregtech/common/pipelike/net/item/WorldItemNet.java @@ -2,6 +2,7 @@ import gregtech.api.cover.Cover; import gregtech.api.cover.filter.CoverWithItemFilter; +import gregtech.api.graphnet.group.GroupData; import gregtech.api.graphnet.net.IGraphNet; import gregtech.api.graphnet.net.NetEdge; import gregtech.api.graphnet.pipenet.WorldPipeNet; @@ -97,4 +98,9 @@ public static int getBufferRegenerationFactor() { public int getNetworkID() { return 2; } + + @Override + public @Nullable GroupData getBlankGroupData() { + return new ItemNetworkViewGroupData(); + } } From 6b71cb6885f67e529bfd15be871e9ce3de005ef2 Mon Sep 17 00:00:00 2001 From: M-W-K <31022105+M-W-K@users.noreply.github.com> Date: Mon, 30 Dec 2024 21:16:56 -0700 Subject: [PATCH 157/157] Fix temperature logic and allow iridium to carry l. helium --- .../gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java | 3 ++- .../api/unification/material/materials/ElementMaterials.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java index f87784653ca..7a483b13ddc 100644 --- a/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java +++ b/src/main/java/gregtech/api/graphnet/pipenet/logic/TemperatureLogic.java @@ -125,7 +125,8 @@ public void applyThermalEnergy(float energy, long tick) { public void moveTowardsTemperature(int temperature, long tick, float mult, boolean noParticle) { int temp = getTemperature(tick); - float thermalEnergy = mult * (temperature - temp); + float thermalEnergy = (float) (this.thermalMass * (temperature - temp) * + (1 - Math.pow(0.5, mult / this.thermalMass))); if (noParticle) { float thermalMax = this.thermalMass * (GTOverheatParticle.TEMPERATURE_CUTOFF - DEFAULT_TEMPERATURE); if (thermalEnergy + this.energy > thermalMax) { diff --git a/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java b/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java index 5a28aa3e4ef..cbfa1e8ffa2 100644 --- a/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/ElementMaterials.java @@ -369,7 +369,7 @@ public static void register() { .flags(EXT2_METAL, GENERATE_DOUBLE_PLATE, GENERATE_FINE_WIRE, GENERATE_GEAR, GENERATE_FRAME) .element(Elements.Ir) .rotorStats(7.0f, 3.0f, 2560) - .fluidPipeProperties(3398, 5, 250, true, false, false) + .fluidPipeProperties(3398, 4, 250, true, false, false) .blast(b -> b .temp(4500, GasTier.HIGH) .blastStats(VA[IV], 1100)