[1.11] INetworkNode needs to be a capability (#687)

* Remove INetworkNode.getPosition(), add INetworkNode.getItemStack()

* Remove INetworkNode.getNodeWorld(), add IWirelessTransmitter.getDimension()

* Add INetworkNode Capability, Remove INetworkNode.canConduct(...), use tile.hasCapability(...) to test conductivity. WirelessTransmitter conduct on DOWN side.

* Remove isConnected() from INetworkNode
Use "active" instead of "connected" for client(remote) state
Replace isConnected by isActive in IGrid, ICraftingMonitor, IReaderWriter

* Refactor getConnectableConditions to use side and capability

* INetworkNode capability
Refactor rebuild network graph

* Clean code and fix rebuild for other mods

* Make TileController a INetworkNode, and some cleaning

* Fix dropping controller

* Use EnumFacing.VALUES

* Make getItemStack return @Notnull, return ItemStack.EMPTY by default
This commit is contained in:
Jeremy Judeaux
2016-11-30 23:51:09 +08:00
committed by Raoul
parent 8576ba3675
commit d04ac11bde
34 changed files with 407 additions and 245 deletions

View File

@@ -12,11 +12,12 @@ import com.raoulvdberge.refinedstorage.api.util.IComparer;
import com.raoulvdberge.refinedstorage.api.util.IStackList;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.fluids.FluidStack;
import javax.annotation.Nonnull;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.BiPredicate;
/**
* Represents a Refined Storage API implementation.
@@ -95,5 +96,5 @@ public interface IRSAPI {
/**
* @return a set with the predicates to check if a block is connectable
*/
Set<Predicate<TileEntity>> getConnectableConditions();
Set<BiPredicate<TileEntity, EnumFacing>> getConnectableConditions();
}

View File

@@ -0,0 +1,17 @@
package com.raoulvdberge.refinedstorage.api.network;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
/**
* Allow the network nodes to implement more optimal or non-regular discovery of neighbor nodes
*/
public interface INetworkNeighborhoodAware {
void walkNeighborhood(Operator operator);
@FunctionalInterface
interface Operator {
void apply(World world, BlockPos pos, EnumFacing side);
}
}

View File

@@ -1,8 +1,8 @@
package com.raoulvdberge.refinedstorage.api.network;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull;
/**
* Represents a node in the network.
@@ -14,9 +14,10 @@ public interface INetworkNode {
int getEnergyUsage();
/**
* @return the position of this node in the world
* @return the item of the node
*/
BlockPos getPosition();
@Nonnull
ItemStack getItemStack();
/**
* Called when this node is connected to a network.
@@ -32,29 +33,13 @@ public interface INetworkNode {
*/
void onDisconnected(INetworkMaster network);
/**
* @return true if this is node is connected to a network, or false otherwise
*/
boolean isConnected();
/**
* @return true if this node can be treated as active, typically checks the redstone configuration
*/
boolean canUpdate();
/**
* @param direction the direction to do a conduction check
* @return true if this node can conduct a connection to the given direction, false otherwise
*/
boolean canConduct(EnumFacing direction);
/**
* @return the network
*/
INetworkMaster getNetwork();
/**
* @return the world where this node is in
*/
World getNodeWorld();
}

View File

@@ -1,8 +1,5 @@
package com.raoulvdberge.refinedstorage.api.network;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nullable;
import java.util.List;
/**
@@ -10,19 +7,10 @@ import java.util.List;
*/
public interface INetworkNodeGraph {
/**
* Rebuilds the node graph.
*
* @param start the starting position to start looking for nodes, or null to start at network begin position
* @param notify true to notify the nodes of a connection change, false to not notify
*/
void rebuild(@Nullable BlockPos start, boolean notify);
/**
* Rebuilds the network graph.
*/
default void rebuild() {
rebuild(null, true);
}
void rebuild();
/**
* @return a list of all connected nodes

View File

@@ -15,4 +15,9 @@ public interface IWirelessTransmitter {
* @return the position where the wireless signal starts
*/
BlockPos getOrigin();
/**
* @return the dimension in which the transmitter is
*/
int getDimension();
}

View File

@@ -24,6 +24,7 @@ import com.raoulvdberge.refinedstorage.apiimpl.util.StackListFluid;
import com.raoulvdberge.refinedstorage.apiimpl.util.StackListItem;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
@@ -31,7 +32,7 @@ import javax.annotation.Nonnull;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.BiPredicate;
public class API implements IRSAPI {
private static final IRSAPI INSTANCE = new API();
@@ -42,7 +43,30 @@ public class API implements IRSAPI {
private ICraftingMonitorElementRegistry craftingMonitorElementRegistry = new CraftingMonitorElementRegistry();
private ICraftingPreviewElementRegistry craftingPreviewElementRegistry = new CraftingPreviewElementRegistry();
private IReaderWriterHandlerRegistry readerWriterHandlerRegistry = new ReaderWriterHandlerRegistry();
private Set<Predicate<TileEntity>> connectableConditions = new HashSet<>();
private Set<BiPredicate<TileEntity, EnumFacing>> connectableConditions = new HashSet<>();
public static IRSAPI instance() {
return INSTANCE;
}
public static void deliver(ASMDataTable asmDataTable) {
String annotationClassName = RSAPIInject.class.getCanonicalName();
Set<ASMDataTable.ASMData> asmDataSet = asmDataTable.getAll(annotationClassName);
for (ASMDataTable.ASMData asmData : asmDataSet) {
try {
Class clazz = Class.forName(asmData.getClassName());
Field field = clazz.getField(asmData.getObjectName());
if (field.getType() == IRSAPI.class) {
field.set(null, INSTANCE);
}
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException("Failed to set: {}" + asmData.getClassName() + "." + asmData.getObjectName(), e);
}
}
}
@Nonnull
@Override
@@ -115,30 +139,7 @@ public class API implements IRSAPI {
}
@Override
public Set<Predicate<TileEntity>> getConnectableConditions() {
public Set<BiPredicate<TileEntity, EnumFacing>> getConnectableConditions() {
return connectableConditions;
}
public static IRSAPI instance() {
return INSTANCE;
}
public static void deliver(ASMDataTable asmDataTable) {
String annotationClassName = RSAPIInject.class.getCanonicalName();
Set<ASMDataTable.ASMData> asmDataSet = asmDataTable.getAll(annotationClassName);
for (ASMDataTable.ASMData asmData : asmDataSet) {
try {
Class clazz = Class.forName(asmData.getClassName());
Field field = clazz.getField(asmData.getObjectName());
if (field.getType() == IRSAPI.class) {
field.set(null, INSTANCE);
}
} catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException("Failed to set: {}" + asmData.getClassName() + "." + asmData.getObjectName(), e);
}
}
}
}

View File

@@ -2,12 +2,12 @@ package com.raoulvdberge.refinedstorage.apiimpl.network;
import com.raoulvdberge.refinedstorage.RSBlocks;
import com.raoulvdberge.refinedstorage.api.autocrafting.ICraftingPatternContainer;
import com.raoulvdberge.refinedstorage.api.network.INetworkNeighborhoodAware;
import com.raoulvdberge.refinedstorage.api.network.INetworkNode;
import com.raoulvdberge.refinedstorage.api.network.INetworkNodeGraph;
import com.raoulvdberge.refinedstorage.api.storage.IStorageProvider;
import com.raoulvdberge.refinedstorage.item.ItemBlockController;
import com.raoulvdberge.refinedstorage.tile.TileController;
import com.raoulvdberge.refinedstorage.tile.TileNetworkTransmitter;
import net.minecraft.block.state.IBlockState;
import net.minecraft.inventory.InventoryHelper;
import net.minecraft.item.ItemStack;
@@ -15,10 +15,11 @@ 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 java.util.*;
import static com.raoulvdberge.refinedstorage.proxy.CapabilityNetworkNode.NETWORK_NODE_CAPABILITY;
public class NetworkNodeGraph implements INetworkNodeGraph {
private TileController controller;
@@ -29,11 +30,7 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
}
@Override
public void rebuild(BlockPos start, boolean notify) {
if (start == null) {
start = controller.getPosition();
}
public void rebuild() {
if (!controller.canRun()) {
if (!nodes.isEmpty()) {
disconnectAll();
@@ -42,112 +39,53 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
return;
}
World world = getWorld();
Set<INetworkNode> newNodes = new HashSet<>();
Queue<NodeToCheck> toCheck = new ArrayDeque<>();
List<INetworkNode> newNodes = new ArrayList<>();
Set<BlockPos> checked = new HashSet<>();
Queue<BlockPos> toCheck = new ArrayDeque<>();
checked.add(start);
toCheck.add(start);
INetworkNeighborhoodAware.Operator operator = (world, pos, side) -> {
TileEntity tile = world.getTileEntity(pos);
if (tile != null) {
if (tile instanceof TileController) {
removeOtherControler(world, pos);
} else {
INetworkNode otherNode = NETWORK_NODE_CAPABILITY.cast(tile.getCapability(NETWORK_NODE_CAPABILITY, side));
if (otherNode != null && newNodes.add(otherNode)) {
toCheck.add(new NodeToCheck(otherNode, world, pos, side, tile));
}
}
}
};
BlockPos controllerPos = controller.getPos();
World controlerWorld = controller.getWorld();
for (EnumFacing facing : EnumFacing.VALUES) {
BlockPos pos = start.offset(facing);
checked.add(pos);
toCheck.add(pos);
BlockPos pos = controllerPos.offset(facing);
operator.apply(controlerWorld, pos, facing.getOpposite());
}
BlockPos currentPos;
while ((currentPos = toCheck.poll()) != null) {
TileEntity tile = world.getTileEntity(currentPos);
if (tile instanceof TileController && !controller.getPos().equals(currentPos)) {
world.setBlockToAir(currentPos);
IBlockState state = world.getBlockState(currentPos);
InventoryHelper.spawnItemStack(
world,
currentPos.getX(),
currentPos.getY(),
currentPos.getZ(),
ItemBlockController.createStackWithNBT(new ItemStack(RSBlocks.CONTROLLER, 1, state.getBlock().getMetaFromState(state)))
);
continue;
}
if (!(tile instanceof INetworkNode)) {
continue;
}
INetworkNode node = (INetworkNode) tile;
newNodes.add(node);
if (tile instanceof TileNetworkTransmitter) {
final TileNetworkTransmitter transmitter = (TileNetworkTransmitter) tile;
if (transmitter.canTransmit()) {
if (!transmitter.isSameDimension()) {
final World dimensionWorld = DimensionManager.getWorld(transmitter.getReceiverDimension());
if (dimensionWorld != null) {
NetworkNodeGraph dimensionGraph = new NetworkNodeGraph(controller) {
@Override
public World getWorld() {
return dimensionWorld;
}
};
dimensionGraph.rebuild(transmitter.getReceiver(), false);
newNodes.addAll(dimensionGraph.all());
}
} else {
BlockPos receiver = transmitter.getReceiver();
if (checked.add(receiver)) {
toCheck.add(receiver);
}
}
}
}
for (EnumFacing facing : EnumFacing.VALUES) {
if (node.canConduct(facing)) {
BlockPos pos = currentPos.offset(facing);
if (checked.add(pos)) {
toCheck.add(pos);
}
}
}
NodeToCheck currentNodeToCheck;
while ((currentNodeToCheck = toCheck.poll()) != null) {
currentNodeToCheck.walkNeighborhood(operator);
}
List<INetworkNode> oldNodes = new ArrayList<>(nodes);
this.nodes = newNodes;
List<INetworkNode> oldNodes = nodes;
nodes = new ArrayList<>(newNodes);
boolean changed = false;
if (notify) {
for (INetworkNode node : nodes) {
if (!oldNodes.contains(node)) {
node.onConnected(controller);
for (INetworkNode node : nodes) {
if (!oldNodes.contains(node)) {
node.onConnected(controller);
changed = true;
}
changed = true;
}
}
for (INetworkNode oldNode : oldNodes) {
if (!nodes.contains(oldNode)) {
oldNode.onDisconnected(controller);
for (INetworkNode oldNode : oldNodes) {
if (!nodes.contains(oldNode)) {
oldNode.onDisconnected(controller);
changed = true;
}
changed = true;
}
}
@@ -185,7 +123,7 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
nodes.clear();
for (INetworkNode node : oldNodes) {
if (node.isConnected()) {
if (node.getNetwork() == controller) {
node.onDisconnected(controller);
}
}
@@ -196,4 +134,54 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
protected World getWorld() {
return controller.getWorld();
}
private void removeOtherControler(World world, BlockPos otherControllerPos) {
if (!controller.getPos().equals(otherControllerPos)) {
IBlockState state = world.getBlockState(otherControllerPos);
ItemStack itemStackToSpawn = ItemBlockController.createStackWithNBT(new ItemStack(RSBlocks.CONTROLLER, 1, state.getBlock().getMetaFromState(state)));
world.setBlockToAir(otherControllerPos);
InventoryHelper.spawnItemStack(
world,
otherControllerPos.getX(),
otherControllerPos.getY(),
otherControllerPos.getZ(),
itemStackToSpawn
);
}
}
private class NodeToCheck implements INetworkNeighborhoodAware {
private final INetworkNode node;
private final World world;
private final BlockPos pos;
private final EnumFacing side;
private final TileEntity tile;
NodeToCheck(INetworkNode node, World world, BlockPos pos, EnumFacing side, TileEntity tile) {
this.node = node;
this.world = world;
this.pos = pos;
this.side = side;
this.tile = tile;
}
@Override
public void walkNeighborhood(Operator operator) {
if (node instanceof INetworkNeighborhoodAware) {
((INetworkNeighborhoodAware) node).walkNeighborhood(operator);
} else {
for (EnumFacing checkSide : EnumFacing.VALUES) {
if (checkSide != side) { // Avoid going backward
INetworkNode nodeOnSide = NETWORK_NODE_CAPABILITY.cast(tile.getCapability(NETWORK_NODE_CAPABILITY, checkSide));
if (nodeOnSide == node) {
operator.apply(world, pos.offset(checkSide), checkSide.getOpposite());
}
}
}
}
}
}
}

View File

@@ -36,7 +36,7 @@ public class NetworkItemHandler implements INetworkItemHandler {
boolean inRange = false;
for (INetworkNode node : network.getNodeGraph().all()) {
if (node instanceof IWirelessTransmitter && node.getNodeWorld().provider.getDimension() == player.dimension) {
if (node instanceof IWirelessTransmitter && ((IWirelessTransmitter) node).getDimension() == player.dimension) {
IWirelessTransmitter transmitter = (IWirelessTransmitter) node;
double distance = Math.sqrt(Math.pow(transmitter.getOrigin().getX() - player.posX, 2) + Math.pow(transmitter.getOrigin().getY() - player.posY, 2) + Math.pow(transmitter.getOrigin().getZ() - player.posZ, 2));

View File

@@ -90,9 +90,10 @@ public class BlockCable extends BlockNode {
}
private boolean hasConnectionWith(IBlockAccess world, BlockPos pos, EnumFacing direction) {
TileEntity facing = world.getTileEntity(pos.offset(direction));
TileEntity otherTile = world.getTileEntity(pos.offset(direction));
EnumFacing otherTileSide = direction.getOpposite();
return API.instance().getConnectableConditions().stream().anyMatch(p -> p.test(facing));
return API.instance().getConnectableConditions().stream().anyMatch(p -> p.test(otherTile, otherTileSide));
}
private boolean isInAABB(AxisAlignedBB aabb, float hitX, float hitY, float hitZ) {

View File

@@ -87,7 +87,7 @@ public class BlockExternalStorage extends BlockCable {
if (!world.isRemote) {
TileExternalStorage externalStorage = (TileExternalStorage) world.getTileEntity(pos);
if (externalStorage.getNetwork() != null) {
if (externalStorage.hasNetwork()) {
externalStorage.updateStorage(externalStorage.getNetwork());
}
}

View File

@@ -44,7 +44,7 @@ public abstract class BlockNode extends BlockBase {
@Override
public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos) {
if (hasConnectivityState()) {
return super.getActualState(state, world, pos).withProperty(CONNECTED, ((TileNode) world.getTileEntity(pos)).isConnected());
return super.getActualState(state, world, pos).withProperty(CONNECTED, ((TileNode) world.getTileEntity(pos)).isActive());
}
return super.getActualState(state, world, pos);
@@ -58,7 +58,7 @@ public abstract class BlockNode extends BlockBase {
for (EnumFacing facing : EnumFacing.VALUES) {
TileEntity tile = world.getTileEntity(pos.offset(facing));
if (tile instanceof TileNode && ((TileNode) tile).isConnected()) {
if (tile instanceof TileNode && ((TileNode) tile).hasNetwork()) {
((TileNode) tile).getNetwork().getNodeGraph().rebuild();
break;

View File

@@ -58,7 +58,7 @@ public class GuiCraftingMonitor extends GuiBase {
}
private List<ICraftingMonitorElement> getElements() {
return craftingMonitor.isConnected() ? ELEMENTS : Collections.emptyList();
return craftingMonitor.isActive() ? ELEMENTS : Collections.emptyList();
}
@Override

View File

@@ -193,6 +193,6 @@ public class GuiReaderWriter extends GuiBase {
}
private List<String> getChannels() {
return readerWriter.isConnected() ? CHANNELS : Collections.emptyList();
return readerWriter.isActive() ? CHANNELS : Collections.emptyList();
}
}

View File

@@ -88,7 +88,7 @@ public class GuiGrid extends GuiBase {
this.container = container;
this.grid = grid;
this.wasConnected = grid.isConnected();
this.wasConnected = this.grid.isActive();
this.scrollbar = new Scrollbar(174, 20, 12, (grid.getType() == EnumGridType.CRAFTING || grid.getType() == EnumGridType.PATTERN || grid.getType() == EnumGridType.FLUID) ? 70 : 88);
@@ -139,7 +139,7 @@ public class GuiGrid extends GuiBase {
private void sortItems() {
List<IClientStack> stacks = new ArrayList<>();
if (grid.isConnected()) {
if (grid.isActive()) {
stacks.addAll(grid.getType() == EnumGridType.FLUID ? FLUIDS.values() : ITEMS.values());
List<IGridFilter> filters = GridFilterParser.getFilters(grid, searchField.getText());
@@ -183,8 +183,8 @@ public class GuiGrid extends GuiBase {
}
}
if (wasConnected != grid.isConnected()) {
wasConnected = grid.isConnected();
if (wasConnected != grid.isActive()) {
wasConnected = grid.isActive();
markForSorting();
}
@@ -201,7 +201,7 @@ public class GuiGrid extends GuiBase {
}
private boolean isOverSlotWithItem() {
return grid.isConnected() && isOverSlot() && slotNumber < STACKS.size();
return grid.isActive() && isOverSlot() && slotNumber < STACKS.size();
}
private boolean isOverSlot() {
@@ -278,7 +278,7 @@ public class GuiGrid extends GuiBase {
int xx = x + (konami.isEmpty() ? konamiOffsetsX[i] : 0);
int yy = y + (konami.isEmpty() ? konamiOffsetsY[i] : 0);
if (inBounds(xx, yy, 16, 16, mouseX, mouseY) || !grid.isConnected()) {
if (inBounds(xx, yy, 16, 16, mouseX, mouseY) || !grid.isActive()) {
this.slotNumber = slot;
}
@@ -286,8 +286,8 @@ public class GuiGrid extends GuiBase {
STACKS.get(slot).draw(this, xx, yy, GuiScreen.isShiftKeyDown() && slotNumber == slot);
}
if (inBounds(xx, yy, 16, 16, mouseX, mouseY) || !grid.isConnected()) {
int color = grid.isConnected() ? -2130706433 : 0xFF5B5B5B;
if (inBounds(xx, yy, 16, 16, mouseX, mouseY) || !grid.isActive()) {
int color = grid.isActive() ? -2130706433 : 0xFF5B5B5B;
GlStateManager.disableLighting();
GlStateManager.disableDepth();
@@ -354,7 +354,7 @@ public class GuiGrid extends GuiBase {
BlockPos gridPos = ((TileGrid) grid).getPos();
RS.INSTANCE.network.sendToServer(new MessageGridPatternCreate(gridPos.getX(), gridPos.getY(), gridPos.getZ()));
} else if (grid.isConnected()) {
} else if (grid.isActive()) {
if (clickedClear) {
RS.INSTANCE.network.sendToServer(new MessageGridCraftingClear((TileGrid) grid));
}

View File

@@ -45,7 +45,7 @@ public class MessageGridCraftingClear extends MessageHandlerPlayerToServer<Messa
if (tile instanceof TileGrid) {
TileGrid grid = (TileGrid) tile;
if (grid.isConnected()) {
if (grid.hasNetwork()) {
if (grid.getType() == EnumGridType.CRAFTING) {
for (int i = 0; i < grid.getMatrix().getSizeInventory(); ++i) {
ItemStack slot = grid.getMatrix().getStackInSlot(i);

View File

@@ -0,0 +1,65 @@
package com.raoulvdberge.refinedstorage.proxy;
import com.google.common.base.Preconditions;
import com.raoulvdberge.refinedstorage.api.network.INetworkMaster;
import com.raoulvdberge.refinedstorage.api.network.INetworkNode;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityManager;
import javax.annotation.Nonnull;
public class CapabilityNetworkNode {
@CapabilityInject(INetworkNode.class)
public static Capability<INetworkNode> NETWORK_NODE_CAPABILITY = null;
public static void register() {
CapabilityManager.INSTANCE.register(INetworkNode.class, new Capability.IStorage<INetworkNode>() {
public NBTBase writeNBT(Capability<INetworkNode> capability, INetworkNode instance, EnumFacing side) {
return new NBTTagCompound();
}
public void readNBT(Capability<INetworkNode> capability, INetworkNode instance, EnumFacing side, NBTBase base) {
// no-op
}
}, () -> new INetworkNode() {
private INetworkMaster network;
@Override
public int getEnergyUsage() {
return 0;
}
@Nonnull
@Override
public ItemStack getItemStack() {
return ItemStack.EMPTY;
}
@Override
public void onConnected(INetworkMaster network) {
this.network = network;
}
@Override
public void onDisconnected(INetworkMaster network) {
}
@Override
public boolean canUpdate() {
return false;
}
@Override
public INetworkMaster getNetwork() {
return network;
}
});
Preconditions.checkNotNull(NETWORK_NODE_CAPABILITY, "Capability not registered");
}
}

View File

@@ -5,7 +5,6 @@ import com.raoulvdberge.refinedstorage.RSBlocks;
import com.raoulvdberge.refinedstorage.RSItems;
import com.raoulvdberge.refinedstorage.RSUtils;
import com.raoulvdberge.refinedstorage.api.network.INetworkMaster;
import com.raoulvdberge.refinedstorage.api.network.INetworkNode;
import com.raoulvdberge.refinedstorage.apiimpl.API;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.craftingmonitor.*;
import com.raoulvdberge.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementFluidStack;
@@ -60,6 +59,8 @@ public class ProxyCommon {
IntegrationCraftingTweaks.register();
}
CapabilityNetworkNode.register();
API.deliver(e.getAsmData());
API.instance().getCraftingTaskRegistry().addFactory(CraftingTaskFactory.ID, new CraftingTaskFactory());
@@ -88,7 +89,8 @@ public class ProxyCommon {
API.instance().getReaderWriterHandlerRegistry().add(ReaderWriterHandlerRedstone.ID, tag -> new ReaderWriterHandlerRedstone());
API.instance().getReaderWriterHandlerRegistry().add(ReaderWriterHandlerForgeEnergy.ID, ReaderWriterHandlerForgeEnergy::new);
API.instance().getConnectableConditions().add(tile -> tile instanceof INetworkMaster || tile instanceof INetworkNode);
API.instance().getConnectableConditions().add((tile, side) -> tile != null &&
(tile instanceof INetworkMaster || tile.hasCapability(CapabilityNetworkNode.NETWORK_NODE_CAPABILITY, side)));
if (IntegrationTesla.isLoaded()) {
API.instance().getReaderWriterHandlerRegistry().add(ReaderWriterHandlerTesla.ID, ReaderWriterHandlerTesla::new);

View File

@@ -13,6 +13,8 @@ public interface IReaderWriter extends INetworkNode {
TileDataParameter<String> getChannelParameter();
boolean isActive();
default void onAdd(String name) {
INetworkMaster network = getNetwork();

View File

@@ -1,5 +1,6 @@
package com.raoulvdberge.refinedstorage.tile;
import com.google.common.base.Preconditions;
import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.RSBlocks;
import com.raoulvdberge.refinedstorage.RSUtils;
@@ -40,6 +41,7 @@ import com.raoulvdberge.refinedstorage.integration.forgeenergy.ControllerEnergyF
import com.raoulvdberge.refinedstorage.integration.tesla.ControllerEnergyTesla;
import com.raoulvdberge.refinedstorage.integration.tesla.IntegrationTesla;
import com.raoulvdberge.refinedstorage.network.*;
import com.raoulvdberge.refinedstorage.proxy.CapabilityNetworkNode;
import com.raoulvdberge.refinedstorage.tile.config.IRedstoneConfigurable;
import com.raoulvdberge.refinedstorage.tile.config.RedstoneMode;
import com.raoulvdberge.refinedstorage.tile.data.ITileDataProducer;
@@ -52,6 +54,7 @@ import net.darkhax.tesla.capability.TeslaCapabilities;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
@@ -71,7 +74,7 @@ import javax.annotation.Nullable;
import java.util.*;
import java.util.stream.Collectors;
public class TileController extends TileBase implements INetworkMaster, IRedstoneConfigurable {
public class TileController extends TileBase implements INetworkMaster, IRedstoneConfigurable, INetworkNode {
public static final TileDataParameter<Integer> REDSTONE_MODE = RedstoneMode.createParameter();
public static final TileDataParameter<Integer> ENERGY_USAGE = new TileDataParameter<>(DataSerializers.VARINT, 0, new ITileDataProducer<Integer, TileController>() {
@@ -102,18 +105,17 @@ public class TileController extends TileBase implements INetworkMaster, IRedston
for (INetworkNode node : tile.nodeGraph.all()) {
if (node.canUpdate()) {
IBlockState state = tile.getWorld().getBlockState(node.getPosition());
ClientNode clientNode = new ClientNode(
new ItemStack(state.getBlock(), 1, state.getBlock().getMetaFromState(state)),
1,
node.getEnergyUsage()
);
if (clientNode.getStack().getItem() == null) {
ItemStack itemStack = node.getItemStack();
if (itemStack.isEmpty()) {
continue;
}
ClientNode clientNode = new ClientNode(
itemStack,
1,
node.getEnergyUsage()
);
if (nodes.contains(clientNode)) {
ClientNode other = nodes.get(nodes.indexOf(clientNode));
@@ -558,7 +560,7 @@ public class TileController extends TileBase implements INetworkMaster, IRedston
public void sendReaderWriterChannelUpdate() {
getWorld().getMinecraftServer().getPlayerList().getPlayers().stream()
.filter(player -> player.openContainer instanceof ContainerReaderWriter &&
((ContainerReaderWriter) player.openContainer).getReaderWriter().isConnected() &&
((ContainerReaderWriter) player.openContainer).getReaderWriter().getNetwork() != null &&
pos.equals(((ContainerReaderWriter) player.openContainer).getReaderWriter().getNetwork().getPosition()))
.forEach(this::sendReaderWriterChannelUpdate);
}
@@ -900,6 +902,34 @@ public class TileController extends TileBase implements INetworkMaster, IRedston
return usage;
}
@Nonnull
@Override
public ItemStack getItemStack() {
IBlockState state = getWorld().getBlockState(pos);
Item item = Item.getItemFromBlock(state.getBlock());
return new ItemStack(item, 1, state.getBlock().getMetaFromState(state));
}
@Override
public void onConnected(INetworkMaster network) {
Preconditions.checkArgument(this == network, "Should not be connected to another controller");
}
@Override
public void onDisconnected(INetworkMaster network) {
Preconditions.checkArgument(this == network, "Should not be connected to another controller");
}
@Override
public boolean canUpdate() {
return false;
}
@Override
public INetworkMaster getNetwork() {
return this;
}
public EnumControllerType getType() {
if (type == null && getWorld().getBlockState(pos).getBlock() == RSBlocks.CONTROLLER) {
this.type = (EnumControllerType) getWorld().getBlockState(pos).getValue(BlockController.TYPE);
@@ -911,11 +941,20 @@ public class TileController extends TileBase implements INetworkMaster, IRedston
@Override
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
if (capability == CapabilityEnergy.ENERGY) {
return (T) energy;
return CapabilityEnergy.ENERGY.cast(energy);
}
if (energyTesla != null && (capability == TeslaCapabilities.CAPABILITY_HOLDER || capability == TeslaCapabilities.CAPABILITY_CONSUMER)) {
return (T) energyTesla;
if (energyTesla != null) {
if (capability == TeslaCapabilities.CAPABILITY_HOLDER) {
return TeslaCapabilities.CAPABILITY_HOLDER.cast(energyTesla);
}
if (capability == TeslaCapabilities.CAPABILITY_CONSUMER) {
return TeslaCapabilities.CAPABILITY_CONSUMER.cast(energyTesla);
}
}
if (capability == CapabilityNetworkNode.NETWORK_NODE_CAPABILITY) {
return CapabilityNetworkNode.NETWORK_NODE_CAPABILITY.cast(this);
}
return super.getCapability(capability, facing);
@@ -925,6 +964,7 @@ public class TileController extends TileBase implements INetworkMaster, IRedston
public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {
return capability == CapabilityEnergy.ENERGY
|| (energyTesla != null && (capability == TeslaCapabilities.CAPABILITY_HOLDER || capability == TeslaCapabilities.CAPABILITY_CONSUMER))
|| capability == CapabilityNetworkNode.NETWORK_NODE_CAPABILITY
|| super.hasCapability(capability, facing);
}
}

View File

@@ -17,6 +17,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
@@ -187,6 +188,11 @@ public class TileCrafter extends TileNode implements ICraftingPatternContainer {
return actualPatterns;
}
@Override
public BlockPos getPosition() {
return pos;
}
public IItemHandler getPatternItems() {
return patterns;
}

View File

@@ -341,7 +341,7 @@ public class TileDiskDrive extends TileNode implements IStorageProvider, IStorag
public NBTTagCompound writeUpdate(NBTTagCompound tag) {
super.writeUpdate(tag);
writeDiskState(tag, 8, connected, itemStorages, fluidStorages);
writeDiskState(tag, 8, hasNetwork(), itemStorages, fluidStorages);
return tag;
}

View File

@@ -578,7 +578,7 @@ public class TileDiskManipulator extends TileNode implements IComparable, IFilte
public NBTTagCompound writeUpdate(NBTTagCompound tag) {
super.writeUpdate(tag);
TileDiskDrive.writeDiskState(tag, 6, connected, itemStorages, fluidStorages);
TileDiskDrive.writeDiskState(tag, 6, hasNetwork(), itemStorages, fluidStorages);
return tag;
}

View File

@@ -14,6 +14,8 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
@@ -156,4 +158,17 @@ public class TileNetworkTransmitter extends TileNode {
public boolean hasConnectivityState() {
return true;
}
@Override
public void walkNeighborhood(Operator operator) {
super.walkNeighborhood(operator);
if (canTransmit()) {
if (!isSameDimension()) {
final World dimensionWorld = DimensionManager.getWorld(receiverDimension);
operator.apply(dimensionWorld, receiver, null);
} else {
operator.apply(getWorld(), receiver, null);
}
}
}
}

View File

@@ -1,21 +1,29 @@
package com.raoulvdberge.refinedstorage.tile;
import com.raoulvdberge.refinedstorage.api.network.INetworkMaster;
import com.raoulvdberge.refinedstorage.api.network.INetworkNeighborhoodAware;
import com.raoulvdberge.refinedstorage.api.network.INetworkNode;
import com.raoulvdberge.refinedstorage.api.util.IWrenchable;
import com.raoulvdberge.refinedstorage.proxy.CapabilityNetworkNode;
import com.raoulvdberge.refinedstorage.tile.config.IRedstoneConfigurable;
import com.raoulvdberge.refinedstorage.tile.config.RedstoneMode;
import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
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.minecraftforge.common.capabilities.Capability;
public abstract class TileNode extends TileBase implements INetworkNode, IRedstoneConfigurable, IWrenchable {
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public abstract class TileNode extends TileBase implements INetworkNode, IRedstoneConfigurable, IWrenchable, INetworkNeighborhoodAware {
public static final TileDataParameter<Integer> REDSTONE_MODE = RedstoneMode.createParameter();
private static final String NBT_CONNECTED = "Connected";
private static final String NBT_ACTIVE = "Connected";
private static final String NBT_NETWORK = "Network";
private RedstoneMode redstoneMode = RedstoneMode.IGNORE;
@@ -24,7 +32,6 @@ public abstract class TileNode extends TileBase implements INetworkNode, IRedsto
private BlockPos networkPos;
protected boolean connected;
protected INetworkMaster network;
protected boolean rebuildOnUpdateChange;
@@ -39,7 +46,7 @@ public abstract class TileNode extends TileBase implements INetworkNode, IRedsto
}
public boolean isActive() {
return isConnected() && canUpdate();
return active;
}
public abstract void updateNode();
@@ -69,13 +76,13 @@ public abstract class TileNode extends TileBase implements INetworkNode, IRedsto
}
}
if (active != isActive() && hasConnectivityState()) {
boolean wasActive = active;
active = hasNetwork() && canUpdate();
if (active != wasActive && hasConnectivityState()) {
updateBlock();
active = isActive();
}
if (isActive()) {
if (active) {
updateNode();
}
}
@@ -85,7 +92,6 @@ public abstract class TileNode extends TileBase implements INetworkNode, IRedsto
@Override
public void onConnected(INetworkMaster network) {
this.connected = true;
this.network = network;
onConnectionChange(network, true);
@@ -97,7 +103,6 @@ public abstract class TileNode extends TileBase implements INetworkNode, IRedsto
public void onDisconnected(INetworkMaster network) {
onConnectionChange(network, false);
this.connected = false;
this.network = null;
markDirty();
@@ -107,29 +112,41 @@ public abstract class TileNode extends TileBase implements INetworkNode, IRedsto
// NO OP
}
@Override
public boolean canConduct(EnumFacing direction) {
public boolean canConduct(@Nullable EnumFacing direction) {
return true;
}
@Override
public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing side) {
if (capability == CapabilityNetworkNode.NETWORK_NODE_CAPABILITY && canConduct(side)) {
return true;
}
return super.hasCapability(capability, side);
}
@Override
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing side) {
if (capability == CapabilityNetworkNode.NETWORK_NODE_CAPABILITY && canConduct(side)) {
return CapabilityNetworkNode.NETWORK_NODE_CAPABILITY.cast(this);
}
return super.getCapability(capability, side);
}
@Override
public INetworkMaster getNetwork() {
return network;
}
@Override
public World getNodeWorld() {
return getWorld();
public boolean hasNetwork() {
return network != null;
}
@Nonnull
@Override
public BlockPos getPosition() {
return pos;
}
@Override
public boolean isConnected() {
return connected;
public ItemStack getItemStack() {
IBlockState state = getWorld().getBlockState(pos);
Item item = Item.getItemFromBlock(state.getBlock());
return new ItemStack(item, 1, state.getBlock().getMetaFromState(state));
}
@Override
@@ -184,7 +201,7 @@ public abstract class TileNode extends TileBase implements INetworkNode, IRedsto
super.writeUpdate(tag);
if (hasConnectivityState()) {
tag.setBoolean(NBT_CONNECTED, isActive());
tag.setBoolean(NBT_ACTIVE, active);
}
return tag;
@@ -192,7 +209,7 @@ public abstract class TileNode extends TileBase implements INetworkNode, IRedsto
public void readUpdate(NBTTagCompound tag) {
if (hasConnectivityState()) {
connected = tag.getBoolean(NBT_CONNECTED);
active = tag.getBoolean(NBT_ACTIVE);
}
super.readUpdate(tag);
@@ -201,4 +218,11 @@ public abstract class TileNode extends TileBase implements INetworkNode, IRedsto
public boolean hasConnectivityState() {
return false;
}
@Override
public void walkNeighborhood(Operator operator) {
for (EnumFacing facing : EnumFacing.VALUES) {
operator.apply(getWorld(), pos.offset(facing), facing.getOpposite());
}
}
}

View File

@@ -161,7 +161,7 @@ public class TileReader extends TileNode implements IReader {
}
public void onOpened(EntityPlayer entity) {
if (isConnected()) {
if (hasNetwork()) {
network.sendReaderWriterChannelUpdate((EntityPlayerMP) entity);
}
}

View File

@@ -4,6 +4,8 @@ import com.raoulvdberge.refinedstorage.RS;
import com.raoulvdberge.refinedstorage.tile.config.RedstoneMode;
import net.minecraft.util.EnumFacing;
import javax.annotation.Nullable;
public class TileRelay extends TileNode {
public TileRelay() {
setRedstoneMode(RedstoneMode.LOW);
@@ -21,7 +23,7 @@ public class TileRelay extends TileNode {
}
@Override
public boolean canConduct(EnumFacing direction) {
public boolean canConduct(@Nullable EnumFacing direction) {
return canUpdate();
}

View File

@@ -67,6 +67,11 @@ public class TileWirelessTransmitter extends TileNode implements IWirelessTransm
return pos;
}
@Override
public int getDimension() {
return getWorld().provider.getDimension();
}
public ItemHandlerBasic getUpgrades() {
return upgrades;
}
@@ -77,8 +82,8 @@ public class TileWirelessTransmitter extends TileNode implements IWirelessTransm
}
@Override
public boolean canConduct(EnumFacing direction) {
return false;
public boolean canConduct(@Nullable EnumFacing direction) {
return direction != null && EnumFacing.DOWN.equals(direction);
}
@Override
@@ -99,4 +104,9 @@ public class TileWirelessTransmitter extends TileNode implements IWirelessTransm
public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing facing) {
return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing);
}
@Override
public void walkNeighborhood(Operator operator) {
operator.apply(getWorld(), pos.offset(EnumFacing.DOWN), EnumFacing.UP);
}
}

View File

@@ -51,7 +51,7 @@ public class TileWriter extends TileNode implements IWriter {
@Override
public int getRedstoneStrength() {
return connected ? redstoneStrength : 0;
return network != null ? redstoneStrength : 0;
}
@Override
@@ -172,7 +172,7 @@ public class TileWriter extends TileNode implements IWriter {
}
public void onOpened(EntityPlayer entity) {
if (isConnected()) {
if (hasNetwork()) {
network.sendReaderWriterChannelUpdate((EntityPlayerMP) entity);
}
}

View File

@@ -4,12 +4,15 @@ import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nullable;
public interface ICraftingMonitor {
void onCancelled(EntityPlayerMP player, int id);
TileDataParameter<Integer> getRedstoneModeParameter();
@Nullable
BlockPos getNetworkPosition();
boolean isConnected();
boolean isActive();
}

View File

@@ -7,6 +7,8 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nullable;
public class TileCraftingMonitor extends TileNode implements ICraftingMonitor {
@Override
public int getEnergyUsage() {
@@ -24,7 +26,7 @@ public class TileCraftingMonitor extends TileNode implements ICraftingMonitor {
@Override
public void onCancelled(EntityPlayerMP player, int id) {
if (isConnected()) {
if (hasNetwork()) {
network.getItemGridHandler().onCraftingCancelRequested(player, id);
}
}
@@ -34,13 +36,14 @@ public class TileCraftingMonitor extends TileNode implements ICraftingMonitor {
return REDSTONE_MODE;
}
@Nullable
@Override
public BlockPos getNetworkPosition() {
return network != null ? network.getPosition() : null;
}
public void onOpened(EntityPlayer player) {
if (isConnected()) {
if (hasNetwork()) {
network.sendCraftingMonitorUpdate((EntityPlayerMP) player);
}
}

View File

@@ -38,11 +38,6 @@ public class WirelessCraftingMonitor implements ICraftingMonitor {
return controller;
}
@Override
public boolean isConnected() {
return true;
}
private TileController getController() {
World world = DimensionManager.getWorld(controllerDimension);
@@ -54,4 +49,9 @@ public class WirelessCraftingMonitor implements ICraftingMonitor {
return null;
}
@Override
public boolean isActive() {
return true;
}
}

View File

@@ -8,11 +8,13 @@ import com.raoulvdberge.refinedstorage.inventory.ItemHandlerBasic;
import com.raoulvdberge.refinedstorage.tile.data.TileDataParameter;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nullable;
import java.util.List;
public interface IGrid {
EnumGridType getType();
@Nullable
BlockPos getNetworkPosition();
IItemGridHandler getItemHandler();
@@ -43,5 +45,5 @@ public interface IGrid {
TileDataParameter<Integer> getRedstoneModeConfig();
boolean isConnected();
boolean isActive();
}

View File

@@ -36,6 +36,7 @@ import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import net.minecraftforge.items.wrapper.InvWrapper;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -210,13 +211,14 @@ public class TileGrid extends TileNode implements IGrid {
return type == null ? EnumGridType.NORMAL : type;
}
@Nullable
@Override
public BlockPos getNetworkPosition() {
return network != null ? network.getPosition() : null;
}
public void onOpened(EntityPlayer player) {
if (isConnected()) {
if (hasNetwork()) {
if (getType() == EnumGridType.FLUID) {
network.sendFluidStorageToClient((EntityPlayerMP) player);
} else {
@@ -227,12 +229,12 @@ public class TileGrid extends TileNode implements IGrid {
@Override
public IItemGridHandler getItemHandler() {
return connected ? network.getItemGridHandler() : null;
return hasNetwork() ? network.getItemGridHandler() : null;
}
@Override
public IFluidGridHandler getFluidHandler() {
return connected ? network.getFluidGridHandler() : null;
return hasNetwork() ? network.getFluidGridHandler() : null;
}
@Override
@@ -290,7 +292,7 @@ public class TileGrid extends TileNode implements IGrid {
matrix.setInventorySlotContents(i, remainder.get(i).copy());
}
} else if (!slot.isEmpty()) {
if (slot.getCount() == 1 && isConnected()) {
if (slot.getCount() == 1 && hasNetwork()) {
matrix.setInventorySlotContents(i, RSUtils.getStack(network.extractItem(slot, 1, false)));
} else {
matrix.decrStackSize(i, 1);
@@ -364,7 +366,7 @@ public class TileGrid extends TileNode implements IGrid {
// Only if we are a crafting grid. Pattern grids can just be emptied.
if (getType() == EnumGridType.CRAFTING) {
// If we are connected, try to insert into network. If it fails, stop.
if (isConnected()) {
if (hasNetwork()) {
if (network.insertItem(slot, slot.getCount(), true) != null) {
return;
} else {
@@ -392,7 +394,7 @@ public class TileGrid extends TileNode implements IGrid {
boolean found = false;
// If we are connected, first try to get the possibilities from the network
if (isConnected()) {
if (hasNetwork()) {
for (ItemStack possibility : possibilities) {
ItemStack took = network.extractItem(possibility, 1, false);

View File

@@ -172,7 +172,7 @@ public class WirelessGrid implements IGrid {
}
@Override
public boolean isConnected() {
public boolean isActive() {
return true;
}