diff --git a/CHANGELOG.md b/CHANGELOG.md index 434d152de..96ed1e354 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ - Added Crafting Upgrade support for fluids on the Exporter, Constructor and Fluid Interface (raoulvdberge) - Added support for JEI ghost slot dragging (raoulvdberge) - Added config option to hide covers in the creative mode tabs and JEI (raoulvdberge) +- Added the ability to connect the External Storage to (Fluid) Interfaces of other networks, allowing subnetting (raoulvdberge) +- The External Storage no longer lets a network connection through through its front face, to allow for subnetting (raoulvdberge) +- An empty Interface now exposes the entire item storage again (raoulvdberge) +- An empty Fluid Interface now exposes the entire fluid storage (raoulvdberge) - Removed "emit signal when item is being autocrafted" option in the Detector (raoulvdberge) - The Crafting Card no longer schedules requests when there are items or fluids missing (raoulvdberge) - You can now keep fluids in stock by attaching a External Storage in fluid mode to a Fluid Interface with a Crafting Upgrade (raoulvdberge) diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/storage/IStorageCache.java b/src/main/java/com/raoulvdberge/refinedstorage/api/storage/IStorageCache.java index c9d568f94..394973a16 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/storage/IStorageCache.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/storage/IStorageCache.java @@ -25,7 +25,7 @@ public interface IStorageCache { * Adds a stack to the cache. *

* Note that this doesn't modify any of the connected storages, but just modifies the cache. - * Use {@link IStorage#insert(T, int, boolean)} to add a stack to an actual storage. + * Use {@link IStorage#insert(T, int, com.raoulvdberge.refinedstorage.api.util.Action)} to add a stack to an actual storage. *

* Will merge it with another stack if it already exists. * @@ -40,7 +40,7 @@ public interface IStorageCache { * Removes a stack from the cache. *

* Note that this doesn't modify any of the connected storages, but just modifies the cache. - * Use {@link IStorage#extract(T, int, int, boolean)} to remove a stack from an actual storage. + * Use {@link IStorage#extract(T, int, int, com.raoulvdberge.refinedstorage.api.util.Action)} to remove a stack from an actual storage. * * @param stack the stack to remove, do NOT modify * @param size the size to remove diff --git a/src/main/java/com/raoulvdberge/refinedstorage/api/util/IStackList.java b/src/main/java/com/raoulvdberge/refinedstorage/api/util/IStackList.java index 15071d0a9..7fe8f25ef 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/api/util/IStackList.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/api/util/IStackList.java @@ -2,7 +2,7 @@ package com.raoulvdberge.refinedstorage.api.util; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Collection; +import java.util.List; /** * A stack list. @@ -21,9 +21,7 @@ public interface IStackList { * * @param stack the stack */ - default void add(@Nonnull T stack) { - add(stack, getSizeFromStack(stack)); - } + void add(@Nonnull T stack); /** * Decrements the count of that stack in the list. @@ -40,9 +38,7 @@ public interface IStackList { * @param stack the stack * @return true if the remove was successful for the full amount, false otherwise */ - default boolean remove(@Nonnull T stack) { - return remove(stack, getSizeFromStack(stack)); - } + boolean remove(@Nonnull T stack); /** * Returns a stack. @@ -85,16 +81,10 @@ public interface IStackList { boolean isEmpty(); /** - * @param stack the stack - * @return the size of the stack - */ - int getSizeFromStack(T stack); - - /** - * @return a collection of stacks in this list + * @return a list of stacks in this list */ @Nonnull - Collection getStacks(); + List getStacks(); /** * @return a new copy of this list, with the stacks in it copied as well diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNode.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNode.java index b8ae342b0..694562a2c 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNode.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNode.java @@ -214,7 +214,20 @@ public abstract class NetworkNode implements INetworkNode, INetworkNodeVisitor { return world; } + public boolean canConductThroughFace() { + return true; + } + public boolean canConduct(@Nullable EnumFacing direction) { + if (direction == getDirection() && !canConductThroughFace()) { + return false; + } + + INetworkNode faceNode = API.instance().getNetworkNodeManager(world).getNode(pos.offset(direction)); + if (faceNode instanceof NetworkNode && !((NetworkNode) faceNode).canConductThroughFace() && direction == ((NetworkNode) faceNode).getDirection().getOpposite()) { + return false; + } + return true; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCable.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCable.java index 5ed76f2a0..703614064 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCable.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeCable.java @@ -39,7 +39,7 @@ public class NetworkNodeCable extends NetworkNode implements ICoverable { @Override public boolean canConduct(@Nullable EnumFacing direction) { - return coverManager.canConduct(direction); + return coverManager.canConduct(direction) && super.canConduct(direction); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java index 95b1ff00d..0d1359da4 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeConstructor.java @@ -354,7 +354,7 @@ public class NetworkNodeConstructor extends NetworkNode implements IComparable, @Override public boolean canConduct(@Nullable EnumFacing direction) { - return coverManager.canConduct(direction); + return coverManager.canConduct(direction) && super.canConduct(direction); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java index 0b1a27fe7..e5501f36f 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeDestructor.java @@ -330,7 +330,7 @@ public class NetworkNodeDestructor extends NetworkNode implements IComparable, I @Override public boolean canConduct(@Nullable EnumFacing direction) { - return coverManager.canConduct(direction); + return coverManager.canConduct(direction) && super.canConduct(direction); } public boolean isPickupItem() { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java index 1836b1acc..35ba6a4ed 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExporter.java @@ -258,7 +258,7 @@ public class NetworkNodeExporter extends NetworkNode implements IComparable, ITy @Override public boolean canConduct(@Nullable EnumFacing direction) { - return coverManager.canConduct(direction); + return coverManager.canConduct(direction) && super.canConduct(direction); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExternalStorage.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExternalStorage.java index 91b3252c0..6d1461ad4 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExternalStorage.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeExternalStorage.java @@ -366,7 +366,12 @@ public class NetworkNodeExternalStorage extends NetworkNode implements IStorageP @Override public boolean canConduct(@Nullable EnumFacing direction) { - return coverManager.canConduct(direction); + return coverManager.canConduct(direction) && super.canConduct(direction); + } + + @Override + public boolean canConductThroughFace() { + return false; } @Nullable diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeFluidInterface.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeFluidInterface.java index f37f9582d..e4a6a14d7 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeFluidInterface.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeFluidInterface.java @@ -7,6 +7,7 @@ import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.storage.externalstorage.StorageExternalFluid; import com.raoulvdberge.refinedstorage.inventory.fluid.FluidHandlerFluidInterface; +import com.raoulvdberge.refinedstorage.inventory.fluid.FluidHandlerProxy; import com.raoulvdberge.refinedstorage.inventory.fluid.FluidInventory; import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerBase; import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerUpgrade; @@ -23,6 +24,7 @@ import net.minecraft.world.World; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.wrapper.CombinedInvWrapper; import org.apache.commons.lang3.tuple.Pair; @@ -50,7 +52,8 @@ public class NetworkNodeFluidInterface extends NetworkNode { }; private FluidTank tankOut = new FluidTank(TANK_CAPACITY); - private FluidHandlerFluidInterface tank = new FluidHandlerFluidInterface(tankIn, tankOut); + private FluidHandlerProxy tank = new FluidHandlerProxy(tankIn, tankOut); + private FluidHandlerFluidInterface fluids = new FluidHandlerFluidInterface(this); private ItemHandlerBase in = new ItemHandlerBase(1, new ListenerNetworkNode(this), stack -> StackUtils.getFluid(stack, true).getRight() != null); private FluidInventory out = new FluidInventory(1, TANK_CAPACITY, new ListenerNetworkNode(this)); @@ -245,8 +248,8 @@ public class NetworkNodeFluidInterface extends NetworkNode { return out; } - public FluidHandlerFluidInterface getTank() { - return tank; + public IFluidHandler getTank() { + return out.getFluid(0) == null ? fluids : tank; } public FluidTank getTankIn() { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java index 8ce19d8e6..19149de7f 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeImporter.java @@ -231,7 +231,7 @@ public class NetworkNodeImporter extends NetworkNode implements IComparable, IFi @Override public boolean canConduct(@Nullable EnumFacing direction) { - return coverManager.canConduct(direction); + return coverManager.canConduct(direction) && super.canConduct(direction); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeInterface.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeInterface.java index 1472d162b..f4088486d 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeInterface.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeInterface.java @@ -7,6 +7,7 @@ import com.raoulvdberge.refinedstorage.api.util.IComparer; import com.raoulvdberge.refinedstorage.apiimpl.API; import com.raoulvdberge.refinedstorage.apiimpl.storage.externalstorage.StorageExternalItem; import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerBase; +import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerInterface; import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerProxy; import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerUpgrade; import com.raoulvdberge.refinedstorage.inventory.listener.ListenerNetworkNode; @@ -34,6 +35,8 @@ public class NetworkNodeInterface extends NetworkNode implements IComparable { private IItemHandler items = new ItemHandlerProxy(importItems, exportItems); + private ItemHandlerInterface networkItems = new ItemHandlerInterface(this); + private ItemHandlerUpgrade upgrades = new ItemHandlerUpgrade(4, new ListenerNetworkNode(this), ItemUpgrade.TYPE_SPEED, ItemUpgrade.TYPE_STACK, ItemUpgrade.TYPE_CRAFTING); private int compare = IComparer.COMPARE_NBT | IComparer.COMPARE_DAMAGE; @@ -221,7 +224,7 @@ public class NetworkNodeInterface extends NetworkNode implements IComparable { } public IItemHandler getItems() { - return items; + return exportFilterItems.isEmpty() ? networkItems : items; } public IItemHandler getUpgrades() { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeReader.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeReader.java index 83cd3928a..2a142f891 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeReader.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeReader.java @@ -98,7 +98,7 @@ public class NetworkNodeReader extends NetworkNode implements IReader, IGuiReade @Override public boolean canConduct(@Nullable EnumFacing direction) { - return coverManager.canConduct(direction); + return coverManager.canConduct(direction) && super.canConduct(direction); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeRelay.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeRelay.java index 0d1fe302b..fcd82aba8 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeRelay.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeRelay.java @@ -39,7 +39,7 @@ public class NetworkNodeRelay extends NetworkNode { @Override public boolean canConduct(@Nullable EnumFacing direction) { - return canUpdate(); + return canUpdate() && super.canConduct(direction); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeWriter.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeWriter.java index 691dc5372..8d3ce652c 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeWriter.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/NetworkNodeWriter.java @@ -130,7 +130,7 @@ public class NetworkNodeWriter extends NetworkNode implements IWriter, IGuiReade @Override public boolean canConduct(@Nullable EnumFacing direction) { - return coverManager.canConduct(direction); + return coverManager.canConduct(direction) && super.canConduct(direction); } @Override diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/diskmanipulator/NetworkNodeDiskManipulator.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/diskmanipulator/NetworkNodeDiskManipulator.java index e889d1761..327670f4d 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/diskmanipulator/NetworkNodeDiskManipulator.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/network/node/diskmanipulator/NetworkNodeDiskManipulator.java @@ -232,7 +232,7 @@ public class NetworkNodeDiskManipulator extends NetworkNode implements IComparab ItemStack extracted = null; int i = 0; - if (IFilterable.isEmpty(itemFilters)) { + if (itemFilters.isEmpty()) { ItemStack toExtract = null; ArrayList networkItems = new ArrayList<>(network.getItemStorageCache().getList().getStacks()); @@ -331,7 +331,7 @@ public class NetworkNodeDiskManipulator extends NetworkNode implements IComparab FluidStack extracted = null; int i = 0; - if (IFilterable.isEmpty(itemFilters)) { + if (fluidFilters.isEmpty()) { FluidStack toExtract = null; ArrayList networkFluids = new ArrayList<>(network.getFluidStorageCache().getList().getStacks()); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/OneSixMigrationHelper.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/OneSixMigrationHelper.java index 6e736151b..a4bda085c 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/OneSixMigrationHelper.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/OneSixMigrationHelper.java @@ -10,6 +10,7 @@ import com.raoulvdberge.refinedstorage.apiimpl.network.node.storage.NetworkNodeF import com.raoulvdberge.refinedstorage.apiimpl.network.node.storage.NetworkNodeStorage; import com.raoulvdberge.refinedstorage.block.enums.FluidStorageType; import com.raoulvdberge.refinedstorage.block.enums.ItemStorageType; +import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerBase; import com.raoulvdberge.refinedstorage.item.ItemPattern; import com.raoulvdberge.refinedstorage.tile.config.IFilterable; import net.minecraft.item.Item; @@ -205,10 +206,10 @@ public class OneSixMigrationHelper implements IOneSixMigrationHelper { public static void removalHook() { } - public static void migrateEmptyWhitelistToEmptyBlacklist(String version, IFilterable filterable, @Nullable IItemHandler itemFilterInv) { + public static void migrateEmptyWhitelistToEmptyBlacklist(String version, IFilterable filterable, @Nullable ItemHandlerBase itemFilterInv) { // Only migrate if we come from a version where the RS version tag stuff in NetworkNode wasn't added yet. // Otherwise, we would constantly migrate empty whitelists to empty blacklists... - if (version == null && filterable.getMode() == IFilterable.WHITELIST && IFilterable.isEmpty(itemFilterInv)) { + if (version == null && filterable.getMode() == IFilterable.WHITELIST && (itemFilterInv == null || itemFilterInv.isEmpty())) { filterable.setMode(IFilter.MODE_BLACKLIST); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListFluid.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListFluid.java index ddd5bc9a9..94e1b529e 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListFluid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListFluid.java @@ -1,24 +1,24 @@ package com.raoulvdberge.refinedstorage.apiimpl.util; -import com.google.common.collect.ArrayListMultimap; import com.raoulvdberge.refinedstorage.api.util.IStackList; import com.raoulvdberge.refinedstorage.apiimpl.API; +import com.raoulvdberge.refinedstorage.util.MultiMap; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Collection; +import java.util.List; public class StackListFluid implements IStackList { - private ArrayListMultimap stacks = ArrayListMultimap.create(); + private MultiMap stacks = new MultiMap<>(); @Override public void add(@Nonnull FluidStack stack, int size) { if (stack == null || size < 0) { throw new IllegalArgumentException("Cannot accept empty stack"); } - + for (FluidStack otherStack : stacks.get(stack.getFluid())) { if (stack.isFluidEqual(otherStack)) { if ((long) otherStack.amount + (long) size > Integer.MAX_VALUE) { @@ -36,6 +36,11 @@ public class StackListFluid implements IStackList { stacks.put(stack.getFluid(), newStack); } + @Override + public void add(@Nonnull FluidStack stack) { + add(stack, stack.amount); + } + @Override public boolean remove(@Nonnull FluidStack stack, int size) { for (FluidStack otherStack : stacks.get(stack.getFluid())) { @@ -55,6 +60,11 @@ public class StackListFluid implements IStackList { return false; } + @Override + public boolean remove(@Nonnull FluidStack stack) { + return remove(stack, stack.amount); + } + @Override @Nullable public FluidStack get(@Nonnull FluidStack stack, int flags) { @@ -89,14 +99,9 @@ public class StackListFluid implements IStackList { return stacks.isEmpty(); } - @Override - public int getSizeFromStack(FluidStack stack) { - return stack.amount; - } - @Nonnull @Override - public Collection getStacks() { + public List getStacks() { return stacks.values(); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListItem.java b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListItem.java index f5733004b..d7a075298 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListItem.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/apiimpl/util/StackListItem.java @@ -1,18 +1,18 @@ package com.raoulvdberge.refinedstorage.apiimpl.util; -import com.google.common.collect.ArrayListMultimap; import com.raoulvdberge.refinedstorage.api.util.IStackList; import com.raoulvdberge.refinedstorage.apiimpl.API; +import com.raoulvdberge.refinedstorage.util.MultiMap; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraftforge.items.ItemHandlerHelper; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Collection; +import java.util.List; public class StackListItem implements IStackList { - private ArrayListMultimap stacks = ArrayListMultimap.create(); + private MultiMap stacks = new MultiMap<>(); @Override public void add(@Nonnull ItemStack stack, int size) { @@ -35,6 +35,11 @@ public class StackListItem implements IStackList { stacks.put(stack.getItem(), ItemHandlerHelper.copyStackWithSize(stack, size)); } + @Override + public void add(@Nonnull ItemStack stack) { + add(stack, stack.getCount()); + } + @Override public boolean remove(@Nonnull ItemStack stack, int size) { for (ItemStack otherStack : stacks.get(stack.getItem())) { @@ -54,6 +59,11 @@ public class StackListItem implements IStackList { return false; } + @Override + public boolean remove(@Nonnull ItemStack stack) { + return remove(stack, stack.getCount()); + } + @Override @Nullable public ItemStack get(@Nonnull ItemStack stack, int flags) { @@ -88,14 +98,9 @@ public class StackListItem implements IStackList { return stacks.isEmpty(); } - @Override - public int getSizeFromStack(ItemStack stack) { - return stack.getCount(); - } - @Nonnull @Override - public Collection getStacks() { + public List getStacks() { return stacks.values(); } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/inventory/fluid/FluidHandlerFluidInterface.java b/src/main/java/com/raoulvdberge/refinedstorage/inventory/fluid/FluidHandlerFluidInterface.java index 4b9451c81..e22126be7 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/inventory/fluid/FluidHandlerFluidInterface.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/inventory/fluid/FluidHandlerFluidInterface.java @@ -1,46 +1,131 @@ package com.raoulvdberge.refinedstorage.inventory.fluid; +import com.raoulvdberge.refinedstorage.api.network.INetwork; +import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode; +import com.raoulvdberge.refinedstorage.api.util.Action; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; -import net.minecraftforge.fluids.capability.FluidTankPropertiesWrapper; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidTankProperties; import javax.annotation.Nullable; +import java.util.List; public class FluidHandlerFluidInterface implements IFluidHandler { - private FluidTank input; - private FluidTank output; - private IFluidTankProperties[] properties; + private static final IFluidTankProperties[] NO_PROPS = new IFluidTankProperties[0]; - public FluidHandlerFluidInterface(FluidTank input, FluidTank output) { - this.input = input; - this.output = output; - this.properties = new IFluidTankProperties[]{ - new FluidTankPropertiesWrapper(input), - new FluidTankPropertiesWrapper(output) - }; + private INetworkNode node; + + public FluidHandlerFluidInterface(INetworkNode node) { + this.node = node; + } + + @Nullable + private INetwork getNetwork() { + if (node.getNetwork() != null && node.canUpdate()) { + return node.getNetwork(); + } + + return null; } @Override public IFluidTankProperties[] getTankProperties() { - return properties; + INetwork network = getNetwork(); + + if (network == null) { + return NO_PROPS; + } + + List stacks = network.getFluidStorageCache().getList().getStacks(); + + if (stacks.isEmpty()) { + return NO_PROPS; + } + + IFluidTankProperties[] props = new IFluidTankProperties[stacks.size()]; + + for (int i = 0; i < stacks.size(); ++i) { + FluidStack stack = stacks.get(i); + + props[i] = new IFluidTankProperties() { + @Nullable + @Override + public FluidStack getContents() { + return stack; + } + + @Override + public int getCapacity() { + return -1; + } + + @Override + public boolean canFill() { + return false; + } + + @Override + public boolean canDrain() { + return false; + } + + @Override + public boolean canFillFluidType(FluidStack fluidStack) { + return false; + } + + @Override + public boolean canDrainFluidType(FluidStack fluidStack) { + return false; + } + }; + } + + return props; } @Override public int fill(FluidStack resource, boolean doFill) { - return input.fill(resource, doFill); + INetwork network = getNetwork(); + + if (network != null) { + FluidStack remainder = network.insertFluid(resource, resource.amount, doFill ? Action.PERFORM : Action.SIMULATE); + + return remainder == null ? resource.amount : resource.amount - remainder.amount; + } + + return 0; } @Nullable @Override public FluidStack drain(FluidStack resource, boolean doDrain) { - return output.drain(resource, doDrain); + INetwork network = getNetwork(); + + if (network != null) { + return network.extractFluid(resource, resource.amount, doDrain ? Action.PERFORM : Action.SIMULATE); + } + + return null; } @Nullable @Override public FluidStack drain(int maxDrain, boolean doDrain) { - return output.drain(maxDrain, doDrain); + INetwork network = getNetwork(); + + if (network != null) { + List fluids = network.getFluidStorageCache().getList().getStacks(); + + if (fluids.isEmpty()) { + return null; + } + + FluidStack firstFluid = fluids.get(0); + + return network.extractFluid(firstFluid, Math.min(firstFluid.amount, maxDrain), doDrain ? Action.PERFORM : Action.SIMULATE); + } + + return null; } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/inventory/fluid/FluidHandlerProxy.java b/src/main/java/com/raoulvdberge/refinedstorage/inventory/fluid/FluidHandlerProxy.java new file mode 100644 index 000000000..ece085c74 --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/inventory/fluid/FluidHandlerProxy.java @@ -0,0 +1,46 @@ +package com.raoulvdberge.refinedstorage.inventory.fluid; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fluids.capability.FluidTankPropertiesWrapper; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; + +import javax.annotation.Nullable; + +public class FluidHandlerProxy implements IFluidHandler { + private FluidTank insertHandler; + private FluidTank extractHandler; + private IFluidTankProperties[] properties; + + public FluidHandlerProxy(FluidTank insertHandler, FluidTank extractHandler) { + this.insertHandler = insertHandler; + this.extractHandler = extractHandler; + this.properties = new IFluidTankProperties[]{ + new FluidTankPropertiesWrapper(insertHandler), + new FluidTankPropertiesWrapper(extractHandler) + }; + } + + @Override + public IFluidTankProperties[] getTankProperties() { + return properties; + } + + @Override + public int fill(FluidStack resource, boolean doFill) { + return insertHandler.fill(resource, doFill); + } + + @Nullable + @Override + public FluidStack drain(FluidStack resource, boolean doDrain) { + return extractHandler.drain(resource, doDrain); + } + + @Nullable + @Override + public FluidStack drain(int maxDrain, boolean doDrain) { + return extractHandler.drain(maxDrain, doDrain); + } +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/inventory/fluid/FluidInventory.java b/src/main/java/com/raoulvdberge/refinedstorage/inventory/fluid/FluidInventory.java index 3e0133071..a70314c25 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/inventory/fluid/FluidInventory.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/inventory/fluid/FluidInventory.java @@ -11,6 +11,7 @@ public class FluidInventory { private FluidStack[] fluids; private int maxAmount; + private boolean empty = true; @Nullable private Consumer listener; @@ -56,6 +57,24 @@ public class FluidInventory { if (listener != null) { listener.accept(slot); } + + updateEmptyState(); + } + + private void updateEmptyState() { + this.empty = true; + + for (FluidStack fluid : fluids) { + if (fluid != null) { + this.empty = false; + + return; + } + } + } + + public boolean isEmpty() { + return empty; } public NBTTagCompound writeToNbt() { @@ -80,5 +99,7 @@ public class FluidInventory { fluids[i] = FluidStack.loadFluidStackFromNBT(tag.getCompoundTag(key)); } } + + updateEmptyState(); } } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/inventory/item/ItemHandlerBase.java b/src/main/java/com/raoulvdberge/refinedstorage/inventory/item/ItemHandlerBase.java index 8c9c193ba..1d69bf8d9 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/inventory/item/ItemHandlerBase.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/inventory/item/ItemHandlerBase.java @@ -1,6 +1,7 @@ package com.raoulvdberge.refinedstorage.inventory.item; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.items.ItemStackHandler; import javax.annotation.Nonnull; @@ -27,15 +28,6 @@ public class ItemHandlerBase extends ItemStackHandler { this(size, null, validators); } - @Override - public void setStackInSlot(int slot, @Nonnull ItemStack stack) { - validateSlotIndex(slot); - - stacks.set(slot, stack); - - onContentsChanged(slot); - } - @Override @Nonnull public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { @@ -63,6 +55,13 @@ public class ItemHandlerBase extends ItemStackHandler { this.empty = stacks.stream().allMatch(ItemStack::isEmpty); } + @Override + public void deserializeNBT(NBTTagCompound tag) { + super.deserializeNBT(tag); + + this.empty = stacks.stream().allMatch(ItemStack::isEmpty); + } + public boolean isEmpty() { return empty; } diff --git a/src/main/java/com/raoulvdberge/refinedstorage/inventory/item/ItemHandlerInterface.java b/src/main/java/com/raoulvdberge/refinedstorage/inventory/item/ItemHandlerInterface.java new file mode 100644 index 000000000..620f7a881 --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/inventory/item/ItemHandlerInterface.java @@ -0,0 +1,88 @@ +package com.raoulvdberge.refinedstorage.inventory.item; + +import com.raoulvdberge.refinedstorage.api.network.INetwork; +import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode; +import com.raoulvdberge.refinedstorage.api.util.Action; +import com.raoulvdberge.refinedstorage.util.StackUtils; +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.IItemHandler; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ItemHandlerInterface implements IItemHandler { + private INetworkNode node; + + public ItemHandlerInterface(INetworkNode node) { + this.node = node; + } + + @Nullable + private INetwork getNetwork() { + if (node.getNetwork() != null && node.canUpdate()) { + return node.getNetwork(); + } + + return null; + } + + @Override + public int getSlots() { + INetwork network = getNetwork(); + + if (network != null) { + // One additional slot for possible input. + return network.getItemStorageCache().getList().getStacks().size() + 1; + } + + return 0; + } + + @Nonnull + @Override + public ItemStack getStackInSlot(int slot) { + INetwork network = getNetwork(); + + if (network != null) { + List stacks = network.getItemStorageCache().getList().getStacks(); + + if (slot < stacks.size()) { + return stacks.get(slot); + } + } + + return ItemStack.EMPTY; + } + + @Nonnull + @Override + public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { + INetwork network = getNetwork(); + + if (network != null) { + return StackUtils.nullToEmpty(network.insertItem(stack, stack.getCount(), simulate ? Action.SIMULATE : Action.PERFORM)); + } + + return stack; + } + + @Nonnull + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + INetwork network = getNetwork(); + + if (network != null) { + ItemStack stack = getStackInSlot(slot); + + return StackUtils.nullToEmpty(network.extractItem(stack, Math.min(amount, 64), simulate ? Action.SIMULATE : Action.PERFORM)); + } + + return ItemStack.EMPTY; + } + + @Override + public int getSlotLimit(int slot) { + return Integer.MAX_VALUE; + } +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/inventory/item/ItemHandlerPortableGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/inventory/item/ItemHandlerPortableGrid.java new file mode 100644 index 000000000..96bb519a9 --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/inventory/item/ItemHandlerPortableGrid.java @@ -0,0 +1,70 @@ +package com.raoulvdberge.refinedstorage.inventory.item; + +import com.raoulvdberge.refinedstorage.api.util.Action; +import com.raoulvdberge.refinedstorage.api.util.IComparer; +import com.raoulvdberge.refinedstorage.tile.grid.portable.TilePortableGrid; +import com.raoulvdberge.refinedstorage.util.StackUtils; +import net.minecraft.item.ItemStack; +import net.minecraftforge.items.IItemHandler; + +import javax.annotation.Nonnull; +import java.util.List; + +public class ItemHandlerPortableGrid implements IItemHandler { + private TilePortableGrid portableGrid; + + public ItemHandlerPortableGrid(TilePortableGrid portableGrid) { + this.portableGrid = portableGrid; + } + + @Override + public int getSlots() { + if (portableGrid.getStorageCache() != null) { + // One additional slot for possible input. + return portableGrid.getStorageCache().getList().getStacks().size() + 1; + } + + return 0; + } + + @Nonnull + @Override + public ItemStack getStackInSlot(int slot) { + if (portableGrid.getStorageCache() != null) { + List stacks = portableGrid.getStorageCache().getList().getStacks(); + + if (slot < stacks.size()) { + return stacks.get(slot); + } + } + + return ItemStack.EMPTY; + } + + @Nonnull + @Override + public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { + if (portableGrid.getStorage() != null) { + return StackUtils.nullToEmpty(portableGrid.getStorage().insert(stack, stack.getCount(), simulate ? Action.SIMULATE : Action.PERFORM)); + } + + return stack; + } + + @Nonnull + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + if (portableGrid.getStorage() != null) { + ItemStack stack = getStackInSlot(slot); + + return StackUtils.nullToEmpty(portableGrid.getStorage().extract(stack, stack.getCount(), IComparer.COMPARE_NBT | IComparer.COMPARE_DAMAGE, simulate ? Action.SIMULATE : Action.PERFORM)); + } + + return ItemStack.EMPTY; + } + + @Override + public int getSlotLimit(int slot) { + return Integer.MAX_VALUE; + } +} diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/config/IFilterable.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/config/IFilterable.java index d3789cd30..6beb6aae8 100755 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/config/IFilterable.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/config/IFilterable.java @@ -10,8 +10,6 @@ import net.minecraft.tileentity.TileEntity; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.items.IItemHandler; -import javax.annotation.Nullable; - public interface IFilterable { int WHITELIST = 0; int BLACKLIST = 1; @@ -76,20 +74,6 @@ public interface IFilterable { return false; } - static boolean isEmpty(@Nullable IItemHandler filter) { - if (filter == null) { - return true; - } - - for (int i = 0; i < filter.getSlots(); i++) { - if (!filter.getStackInSlot(i).isEmpty()) { - return false; - } - } - - return true; - } - void setMode(int mode); int getMode(); diff --git a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java index 69d53c69d..af2c6c20c 100644 --- a/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java +++ b/src/main/java/com/raoulvdberge/refinedstorage/tile/grid/portable/TilePortableGrid.java @@ -30,6 +30,7 @@ import com.raoulvdberge.refinedstorage.gui.GuiBase; import com.raoulvdberge.refinedstorage.gui.grid.GuiGrid; import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerBase; import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerFilter; +import com.raoulvdberge.refinedstorage.inventory.item.ItemHandlerPortableGrid; import com.raoulvdberge.refinedstorage.inventory.listener.ListenerTile; import com.raoulvdberge.refinedstorage.item.ItemWirelessGrid; import com.raoulvdberge.refinedstorage.item.itemblock.ItemBlockPortableGrid; @@ -55,6 +56,7 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.Constants; import net.minecraftforge.energy.CapabilityEnergy; import net.minecraftforge.energy.EnergyStorage; +import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import javax.annotation.Nonnull; @@ -142,6 +144,7 @@ public class TilePortableGrid extends TileBase implements IGrid, IPortableGrid, private ItemGridHandlerPortable handler = new ItemGridHandlerPortable(this, this); private PortableGridDiskState diskState = PortableGridDiskState.NONE; private boolean connected; + private ItemHandlerPortableGrid items = new ItemHandlerPortableGrid(this); private StorageTrackerItem storageTracker = new StorageTrackerItem(this::markDirty); @@ -626,13 +629,19 @@ public class TilePortableGrid extends TileBase implements IGrid, IPortableGrid, @Override public boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) { - return capability == CapabilityEnergy.ENERGY || super.hasCapability(capability, facing); + return capability == CapabilityEnergy.ENERGY || capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing); } @Nullable @Override public T getCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) { - return capability == CapabilityEnergy.ENERGY ? CapabilityEnergy.ENERGY.cast(energyStorage) : super.getCapability(capability, facing); + if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { + return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.cast(items); + } else if (capability == CapabilityEnergy.ENERGY) { + return CapabilityEnergy.ENERGY.cast(energyStorage); + } + + return super.getCapability(capability, facing); } public void onOpened() { diff --git a/src/main/java/com/raoulvdberge/refinedstorage/util/MultiMap.java b/src/main/java/com/raoulvdberge/refinedstorage/util/MultiMap.java new file mode 100644 index 000000000..749f46538 --- /dev/null +++ b/src/main/java/com/raoulvdberge/refinedstorage/util/MultiMap.java @@ -0,0 +1,54 @@ +package com.raoulvdberge.refinedstorage.util; + +import java.util.*; + +public class MultiMap { + private Map> map = new HashMap<>(); + private List allValues = new ArrayList<>(); + + public List get(K key) { + List values = map.get(key); + + if (values == null) { + return Collections.emptyList(); + } + + return values; + } + + public void put(K key, V value) { + List values = map.computeIfAbsent(key, k -> new ArrayList<>()); + + allValues.add(value); + + values.add(value); + } + + public void remove(K key, V value) { + List values = map.get(key); + + if (values != null) { + values.remove(value); + + if (values.isEmpty()) { + map.remove(key); + } + + allValues.remove(value); + } + } + + public void clear() { + map.clear(); + + allValues.clear(); + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + public List values() { + return allValues; + } +}