Add the ability to simulate in the node graph.

This commit is contained in:
raoulvdberge
2018-11-05 17:13:45 +01:00
parent 29285b1092
commit 643ae63c87
13 changed files with 107 additions and 47 deletions

View File

@@ -1,6 +1,8 @@
package com.raoulvdberge.refinedstorage.api.network; package com.raoulvdberge.refinedstorage.api.network;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode; import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
import com.raoulvdberge.refinedstorage.api.util.Action;
import net.minecraft.util.math.BlockPos;
import java.util.Collection; import java.util.Collection;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -11,15 +13,48 @@ import java.util.function.Consumer;
public interface INetworkNodeGraph { public interface INetworkNodeGraph {
/** /**
* Rebuilds the network graph. * Rebuilds the network graph.
*
* @deprecated Use {@link #invalidate(Action, BlockPos)} - needed to support simulating the calculation of network connections
*/ */
void rebuild(); @Deprecated
default void rebuild() {
invalidate(Action.PERFORM, getNetworkForBCReasons().getPosition());
}
/** /**
* Adds a runnable that is run after the graph is rebuilt. * DON'T USE THIS!
* This method exists to support a default {@link #rebuild()} method to maintain backward compatibility.
*/
@Deprecated
INetwork getNetworkForBCReasons();
/**
* Rebuilds the network graph.
*
* @param action whether to perform or simulate
* @param origin the origin, usually the network position
*/
void invalidate(Action action, BlockPos origin);
/**
* Runs an action on the network.
* If the network is rebuilding it's graph, the action will be executed after the graph was built.
*
* @param handler the action to run
* @deprecated Use {@link #runActionWhenPossible(Consumer)} - just a method rename
*/
@Deprecated
default void addPostRebuildHandler(Consumer<INetwork> handler) {
runActionWhenPossible(handler);
}
/**
* Runs an action on the network.
* If the network is rebuilding it's graph, the action will be executed after the graph was built.
* *
* @param handler the action to run * @param handler the action to run
*/ */
void addPostRebuildHandler(Consumer<INetwork> handler); void runActionWhenPossible(Consumer<INetwork> handler);
/** /**
* @return a collection of all connected nodes * @return a collection of all connected nodes

View File

@@ -4,6 +4,8 @@ import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import javax.annotation.Nullable;
/** /**
* Allows the network nodes to implement more optimal or non-regular discovery of neighbor nodes. * Allows the network nodes to implement more optimal or non-regular discovery of neighbor nodes.
*/ */
@@ -12,6 +14,6 @@ public interface INetworkNodeVisitor {
@FunctionalInterface @FunctionalInterface
interface Operator { interface Operator {
void apply(World world, BlockPos pos, EnumFacing side); void apply(World world, BlockPos pos, @Nullable EnumFacing side);
} }
} }

View File

@@ -25,10 +25,7 @@ import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskManager;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskRegistry; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskRegistry;
import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskSync; import com.raoulvdberge.refinedstorage.api.storage.disk.IStorageDiskSync;
import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageProvider; import com.raoulvdberge.refinedstorage.api.storage.externalstorage.IExternalStorageProvider;
import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.api.util.*;
import com.raoulvdberge.refinedstorage.api.util.IOneSixMigrationHelper;
import com.raoulvdberge.refinedstorage.api.util.IQuantityFormatter;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.CraftingRequestInfo; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.CraftingRequestInfo;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementList; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementList;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementRegistry; import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementRegistry;
@@ -295,7 +292,7 @@ public class API implements IRSAPI {
INetworkNode node = nodeProxy.getNode(); INetworkNode node = nodeProxy.getNode();
if (node.getNetwork() != null) { if (node.getNetwork() != null) {
node.getNetwork().getNodeGraph().rebuild(); node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getPosition());
return; return;
} }

View File

@@ -6,7 +6,9 @@ import com.raoulvdberge.refinedstorage.api.network.INetworkNodeGraph;
import com.raoulvdberge.refinedstorage.api.network.INetworkNodeVisitor; import com.raoulvdberge.refinedstorage.api.network.INetworkNodeVisitor;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode; import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeProxy; import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeProxy;
import com.raoulvdberge.refinedstorage.api.util.Action;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.ICoverable; import com.raoulvdberge.refinedstorage.apiimpl.network.node.ICoverable;
import com.raoulvdberge.refinedstorage.apiimpl.util.OneSixMigrationHelper;
import com.raoulvdberge.refinedstorage.tile.TileController; import com.raoulvdberge.refinedstorage.tile.TileController;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.inventory.InventoryHelper; import net.minecraft.inventory.InventoryHelper;
@@ -17,6 +19,7 @@ import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import javax.annotation.Nullable;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -25,24 +28,25 @@ import static com.raoulvdberge.refinedstorage.capability.CapabilityNetworkNodePr
public class NetworkNodeGraph implements INetworkNodeGraph { public class NetworkNodeGraph implements INetworkNodeGraph {
private TileController controller; private TileController controller;
private Set<INetworkNode> nodes = Sets.newConcurrentHashSet(); private Set<INetworkNode> nodes = Sets.newConcurrentHashSet();
private Set<Consumer<INetwork>> postRebuildHandlers = new HashSet<>();
private boolean rebuilding = false; private Set<Consumer<INetwork>> actions = new HashSet<>();
private boolean invalidating = false;
public NetworkNodeGraph(TileController controller) { public NetworkNodeGraph(TileController controller) {
this.controller = controller; this.controller = controller;
} }
@Override @Override
public void rebuild() { public void invalidate(Action action, BlockPos origin) {
rebuilding = true; this.invalidating = true;
Operator operator = new Operator(); Operator operator = new Operator(action);
BlockPos controllerPos = controller.getPos();
World controllerWorld = controller.getWorld(); World controllerWorld = controller.getWorld();
for (EnumFacing facing : EnumFacing.VALUES) { for (EnumFacing facing : EnumFacing.VALUES) {
BlockPos pos = controllerPos.offset(facing); BlockPos pos = origin.offset(facing);
// Little hack to support not conducting through covers (if the cover is right next to the controller). // Little hack to support not conducting through covers (if the cover is right next to the controller).
TileEntity tile = controllerWorld.getTileEntity(pos); TileEntity tile = controllerWorld.getTileEntity(pos);
@@ -67,6 +71,7 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
this.nodes = operator.foundNodes; this.nodes = operator.foundNodes;
if (action == Action.PERFORM) {
for (INetworkNode node : operator.newNodes) { for (INetworkNode node : operator.newNodes) {
node.onConnected(controller); node.onConnected(controller);
} }
@@ -75,20 +80,28 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
node.onDisconnected(controller); node.onDisconnected(controller);
} }
postRebuildHandlers.forEach(h -> h.accept(controller)); actions.forEach(h -> h.accept(controller));
postRebuildHandlers.clear(); actions.clear();
if (!operator.newNodes.isEmpty() || !operator.previousNodes.isEmpty()) { if (!operator.newNodes.isEmpty() || !operator.previousNodes.isEmpty()) {
controller.getDataManager().sendParameterToWatchers(TileController.NODES); controller.getDataManager().sendParameterToWatchers(TileController.NODES);
} }
}
rebuilding = false; invalidating = false;
} }
@Override @Override
public void addPostRebuildHandler(Consumer<INetwork> handler) { public INetwork getNetworkForBCReasons() {
if (rebuilding) { OneSixMigrationHelper.removalHook();
postRebuildHandlers.add(handler);
return controller;
}
@Override
public void runActionWhenPossible(Consumer<INetwork> handler) {
if (invalidating) {
actions.add(handler);
} else { } else {
handler.accept(controller); handler.accept(controller);
} }
@@ -134,8 +147,14 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
private Queue<Visitor> toCheck = new ArrayDeque<>(); private Queue<Visitor> toCheck = new ArrayDeque<>();
private Action action;
public Operator(Action action) {
this.action = action;
}
@Override @Override
public void apply(World world, BlockPos pos, EnumFacing side) { public void apply(World world, BlockPos pos, @Nullable EnumFacing side) {
TileEntity tile = world.getTileEntity(pos); TileEntity tile = world.getTileEntity(pos);
if (tile != null && tile.hasCapability(NETWORK_NODE_PROXY_CAPABILITY, side)) { if (tile != null && tile.hasCapability(NETWORK_NODE_PROXY_CAPABILITY, side)) {
@@ -144,7 +163,10 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
// This will work for regular nodes and for controllers too since controllers are internally a INetworkNode (and return themselves in INetworkNode#getNetwork). // This will work for regular nodes and for controllers too since controllers are internally a INetworkNode (and return themselves in INetworkNode#getNetwork).
if (otherNode.getNetwork() != null && otherNode.getNetwork() != controller) { if (otherNode.getNetwork() != null && otherNode.getNetwork() != controller) {
if (action == Action.PERFORM) {
dropConflictingBlock(world, tile.getPos()); dropConflictingBlock(world, tile.getPos());
}
return; return;
} }

View File

@@ -4,6 +4,7 @@ import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.api.network.INetwork; import com.raoulvdberge.refinedstorage.api.network.INetwork;
import com.raoulvdberge.refinedstorage.api.network.INetworkNodeVisitor; import com.raoulvdberge.refinedstorage.api.network.INetworkNodeVisitor;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode; import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
import com.raoulvdberge.refinedstorage.api.util.Action;
import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.util.OneSixMigrationHelper; import com.raoulvdberge.refinedstorage.apiimpl.util.OneSixMigrationHelper;
import com.raoulvdberge.refinedstorage.tile.config.RedstoneMode; import com.raoulvdberge.refinedstorage.tile.config.RedstoneMode;
@@ -142,7 +143,7 @@ public abstract class NetworkNode implements INetworkNode, INetworkNodeVisitor {
onConnectedStateChange(network, canUpdate); onConnectedStateChange(network, canUpdate);
if (shouldRebuildGraphOnChange()) { if (shouldRebuildGraphOnChange()) {
network.getNodeGraph().rebuild(); network.getNodeGraph().invalidate(Action.PERFORM, network.getPosition());
} }
} }
} }

View File

@@ -248,8 +248,8 @@ public class NetworkNodeExternalStorage extends NetworkNode implements IStorageP
} }
} }
network.getNodeGraph().addPostRebuildHandler(StorageCacheItem.INVALIDATE); network.getNodeGraph().runActionWhenPossible(StorageCacheItem.INVALIDATE);
network.getNodeGraph().addPostRebuildHandler(StorageCacheFluid.INVALIDATE); network.getNodeGraph().runActionWhenPossible(StorageCacheFluid.INVALIDATE);
} }
@Override @Override

View File

@@ -2,6 +2,7 @@ package com.raoulvdberge.refinedstorage.apiimpl.network.node;
import com.raoulvdberge.refinedstorage.RS; import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.RSItems; import com.raoulvdberge.refinedstorage.RSItems;
import com.raoulvdberge.refinedstorage.api.util.Action;
import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerBase; import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerBase;
import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerUpgrade; import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerUpgrade;
import com.raoulvdberge.refinedstorage.inventory.item.validator.ItemValidatorBasic; import com.raoulvdberge.refinedstorage.inventory.item.validator.ItemValidatorBasic;
@@ -28,7 +29,7 @@ public class NetworkNodeNetworkTransmitter extends NetworkNode {
super.onContentsChanged(slot); super.onContentsChanged(slot);
if (network != null) { if (network != null) {
network.getNodeGraph().rebuild(); network.getNodeGraph().invalidate(Action.PERFORM, network.getPosition());
} }
} }
}; };
@@ -48,7 +49,7 @@ public class NetworkNodeNetworkTransmitter extends NetworkNode {
} }
if (network != null) { if (network != null) {
network.getNodeGraph().rebuild(); network.getNodeGraph().invalidate(Action.PERFORM, network.getPosition());
} }
} }
}; };

View File

@@ -1,6 +1,7 @@
package com.raoulvdberge.refinedstorage.apiimpl.network.node.cover; package com.raoulvdberge.refinedstorage.apiimpl.network.node.cover;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode; import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
import com.raoulvdberge.refinedstorage.api.util.Action;
import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.ICoverable; import com.raoulvdberge.refinedstorage.apiimpl.network.node.ICoverable;
import com.raoulvdberge.refinedstorage.apiimpl.network.node.NetworkNode; import com.raoulvdberge.refinedstorage.apiimpl.network.node.NetworkNode;
@@ -80,7 +81,7 @@ public class CoverManager {
node.markDirty(); node.markDirty();
if (node.getNetwork() != null) { if (node.getNetwork() != null) {
node.getNetwork().getNodeGraph().rebuild(); node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getPosition());
} }
return true; return true;

View File

@@ -147,8 +147,8 @@ public class NetworkNodeDiskDrive extends NetworkNode implements IGuiStorage, IS
public void onConnectedStateChange(INetwork network, boolean state) { public void onConnectedStateChange(INetwork network, boolean state) {
super.onConnectedStateChange(network, state); super.onConnectedStateChange(network, state);
network.getNodeGraph().addPostRebuildHandler(StorageCacheItem.INVALIDATE); network.getNodeGraph().runActionWhenPossible(StorageCacheItem.INVALIDATE);
network.getNodeGraph().addPostRebuildHandler(StorageCacheFluid.INVALIDATE); network.getNodeGraph().runActionWhenPossible(StorageCacheFluid.INVALIDATE);
WorldUtils.updateBlock(world, pos); WorldUtils.updateBlock(world, pos);
} }

View File

@@ -69,7 +69,7 @@ public class NetworkNodeFluidStorage extends NetworkNode implements IGuiStorage,
public void onConnectedStateChange(INetwork network, boolean state) { public void onConnectedStateChange(INetwork network, boolean state) {
super.onConnectedStateChange(network, state); super.onConnectedStateChange(network, state);
network.getNodeGraph().addPostRebuildHandler(StorageCacheFluid.INVALIDATE); network.getNodeGraph().runActionWhenPossible(StorageCacheFluid.INVALIDATE);
} }
@Override @Override

View File

@@ -69,7 +69,7 @@ public class NetworkNodeStorage extends NetworkNode implements IGuiStorage, ISto
public void onConnectedStateChange(INetwork network, boolean state) { public void onConnectedStateChange(INetwork network, boolean state) {
super.onConnectedStateChange(network, state); super.onConnectedStateChange(network, state);
network.getNodeGraph().addPostRebuildHandler(StorageCacheItem.INVALIDATE); network.getNodeGraph().runActionWhenPossible(StorageCacheItem.INVALIDATE);
} }
@Override @Override

View File

@@ -2,6 +2,7 @@ package com.raoulvdberge.refinedstorage.block;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode; import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeManager; import com.raoulvdberge.refinedstorage.api.network.node.INetworkNodeManager;
import com.raoulvdberge.refinedstorage.api.util.Action;
import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.block.info.IBlockInfo; import com.raoulvdberge.refinedstorage.block.info.IBlockInfo;
import com.raoulvdberge.refinedstorage.tile.TileNode; import com.raoulvdberge.refinedstorage.tile.TileNode;
@@ -52,7 +53,7 @@ public abstract class BlockNode extends BlockNodeProxy {
manager.markForSaving(); manager.markForSaving();
if (node != null && node.getNetwork() != null) { if (node != null && node.getNetwork() != null) {
node.getNetwork().getNodeGraph().rebuild(); node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getPosition());
} }
} }

View File

@@ -231,7 +231,7 @@ public class TileController extends TileBase implements ITickable, INetwork, IRe
couldRun = canRun; couldRun = canRun;
throttlingDisabled = false; throttlingDisabled = false;
nodeGraph.rebuild(); nodeGraph.invalidate(Action.PERFORM, pos);
securityManager.invalidate(); securityManager.invalidate();
} }
} else { } else {