(Fluid) interfaces now expose entire storage again + add subnetting.

This commit is contained in:
raoulvdberge
2018-07-27 19:47:32 +02:00
parent c38bb10553
commit e1fcee90a7
28 changed files with 481 additions and 96 deletions

View File

@@ -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)

View File

@@ -25,7 +25,7 @@ public interface IStorageCache<T> {
* Adds a stack to the cache.
* <p>
* 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.
* <p>
* Will merge it with another stack if it already exists.
*
@@ -40,7 +40,7 @@ public interface IStorageCache<T> {
* Removes a stack from the cache.
* <p>
* 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

View File

@@ -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<T> {
*
* @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<T> {
* @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<T> {
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<T> getStacks();
List<T> getStacks();
/**
* @return a new copy of this list, with the stacks in it copied as well

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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() {

View File

@@ -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

View File

@@ -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

View File

@@ -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() {

View File

@@ -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

View File

@@ -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() {

View File

@@ -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

View File

@@ -39,7 +39,7 @@ public class NetworkNodeRelay extends NetworkNode {
@Override
public boolean canConduct(@Nullable EnumFacing direction) {
return canUpdate();
return canUpdate() && super.canConduct(direction);
}
@Override

View File

@@ -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

View File

@@ -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<ItemStack> 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<FluidStack> networkFluids = new ArrayList<>(network.getFluidStorageCache().getList().getStacks());

View File

@@ -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);
}
}

View File

@@ -1,17 +1,17 @@
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<FluidStack> {
private ArrayListMultimap<Fluid, FluidStack> stacks = ArrayListMultimap.create();
private MultiMap<Fluid, FluidStack> stacks = new MultiMap<>();
@Override
public void add(@Nonnull FluidStack stack, int size) {
@@ -36,6 +36,11 @@ public class StackListFluid implements IStackList<FluidStack> {
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<FluidStack> {
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<FluidStack> {
return stacks.isEmpty();
}
@Override
public int getSizeFromStack(FluidStack stack) {
return stack.amount;
}
@Nonnull
@Override
public Collection<FluidStack> getStacks() {
public List<FluidStack> getStacks() {
return stacks.values();
}

View File

@@ -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<ItemStack> {
private ArrayListMultimap<Item, ItemStack> stacks = ArrayListMultimap.create();
private MultiMap<Item, ItemStack> stacks = new MultiMap<>();
@Override
public void add(@Nonnull ItemStack stack, int size) {
@@ -35,6 +35,11 @@ public class StackListItem implements IStackList<ItemStack> {
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<ItemStack> {
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<ItemStack> {
return stacks.isEmpty();
}
@Override
public int getSizeFromStack(ItemStack stack) {
return stack.getCount();
}
@Nonnull
@Override
public Collection<ItemStack> getStacks() {
public List<ItemStack> getStacks() {
return stacks.values();
}

View File

@@ -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<FluidStack> 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<FluidStack> 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;
}
}

View File

@@ -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);
}
}

View File

@@ -11,6 +11,7 @@ public class FluidInventory {
private FluidStack[] fluids;
private int maxAmount;
private boolean empty = true;
@Nullable
private Consumer<Integer> 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();
}
}

View File

@@ -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;
}

View File

@@ -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<ItemStack> 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;
}
}

View File

@@ -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<ItemStack> 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;
}
}

View File

@@ -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();

View File

@@ -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> T getCapability(@Nonnull Capability<T> 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() {

View File

@@ -0,0 +1,54 @@
package com.raoulvdberge.refinedstorage.util;
import java.util.*;
public class MultiMap<K, V> {
private Map<K, List<V>> map = new HashMap<>();
private List<V> allValues = new ArrayList<>();
public List<V> get(K key) {
List<V> values = map.get(key);
if (values == null) {
return Collections.emptyList();
}
return values;
}
public void put(K key, V value) {
List<V> values = map.computeIfAbsent(key, k -> new ArrayList<>());
allValues.add(value);
values.add(value);
}
public void remove(K key, V value) {
List<V> 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<V> values() {
return allValues;
}
}