diff --git a/src/com/jaquadro/minecraft/storagedrawers/api/capabilities/IItemRepository.java b/src/com/jaquadro/minecraft/storagedrawers/api/capabilities/IItemRepository.java index 38d5cfaa4..750e63cfe 100644 --- a/src/com/jaquadro/minecraft/storagedrawers/api/capabilities/IItemRepository.java +++ b/src/com/jaquadro/minecraft/storagedrawers/api/capabilities/IItemRepository.java @@ -4,12 +4,23 @@ import net.minecraft.util.NonNullList; import javax.annotation.Nonnull; +import java.util.function.Predicate; +/** + * An interface for treating an inventory as a slotless, central repository of items. + * + * For all operations that accept a predicate, if a predicate is supplied, a stored ItemStack must pass the predicate + * in order to be considered for the given operation. + * + * An IItemRepository implementation MAY relax or eliminate its own internal tests when a predicate is supplied. If + * the predicate is derived from DefaultPredicate, then the implementation MUST apply any tests it would have applied + * had no predicate been provided at all, in addition to testing the predicate itself. + */ public interface IItemRepository { /** * Gets a list of all items in the inventory. The same item may appear multiple times with varying counts. - * + * @return A list of zero or more items in the inventory. */ @Nonnull @@ -20,24 +31,90 @@ public interface IItemRepository * * @param stack ItemStack to insert. * @param simulate If true, the insertion is only simulated + * @param predicate See interface notes about predicates. Passing null specifies default matching. * @return The remaining ItemStack that was not inserted. If the entire stack was accepted, returns * ItemStack.EMPTY instead. */ @Nonnull - ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate); + ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate, Predicate predicate); + + @Nonnull + default ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate) { + return insertItem(stack, simulate, null); + } /** * Tries to extract the given ItemStack from the inventory. The returned value will be a matching ItemStack * with a stack size equal to or less than amount, or the empty ItemStack if the item could not be found at all. - * The returned stack size may exceed the itemstack's getMaxStackSize() value. - * + * The returned stack size may exceed the ItemStack's getMaxStackSize() value. + * @param stack The item to extract. The stack size is ignored. * @param amount Amount to extract (may be greater than the stacks max limit) * @param simulate If true, the extraction is only simulated + * @param predicate See interface notes about predicates. Passing null specifies default matching. * @return ItemStack extracted from the inventory, or ItemStack.EMPTY if nothing could be extracted. */ @Nonnull - ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate); + ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate, Predicate predicate); + + @Nonnull + default ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate) { + return extractItem(stack, amount, simulate, null); + } + + /** + * Gets the number of items matching the given ItemStack stored by the inventory. + + * @param stack ItemStack to query. + * @param predicate See interface notes about predicates. Passing null specifies default matching. + * @return The number of stored matching items. A value of Integer.MAX_VALUE may indicate an infinite item source. + */ + default int getStoredItemCount (@Nonnull ItemStack stack, Predicate predicate) { + ItemStack amount = extractItem(stack, Integer.MAX_VALUE, true, predicate); + return amount.getCount(); + } + + default int getStoredItemCount (@Nonnull ItemStack stack) { + return getStoredItemCount(stack, null); + } + + /** + * Gets the number items matching the given ItemStack that additionally still be stored by the inventory. + * Remaining capacity may include space that is internally empty or unassigned to any given item. + * + * @param stack ItemStack to query. + * @param predicate See interface notes about predicates. Passing null specifies default matching. + * @return The available remaining space for matching items. + */ + default int getRemainingItemCapacity (@Nonnull ItemStack stack, Predicate predicate) { + stack = stack.copy(); + stack.setCount(Integer.MAX_VALUE); + ItemStack remainder = insertItem(stack, true, predicate); + return Integer.MAX_VALUE - remainder.getCount(); + } + + default int getRemainingItemCapacity (@Nonnull ItemStack stack) { + return getRemainingItemCapacity(stack, null); + } + + /** + * Gets the total inventory capacity for items matching the given ItemStack. + * Total capacity may include space that is internally empty or unassigned to any given item. + * + * @param stack ItemStack to query. + * @param predicate See interface notes about predicates. Passing null specifies default matching. + * @return The total capacity for matching items. + */ + default int getItemCapacity (@Nonnull ItemStack stack, Predicate predicate) { + long capacity = getStoredItemCount(stack, predicate) + getRemainingItemCapacity(stack, predicate); + if (capacity > Integer.MAX_VALUE) + return Integer.MAX_VALUE; + return (int)capacity; + } + + default int getItemCapacity (@Nonnull ItemStack stack) { + return getItemCapacity(stack, null); + } /** * An item record representing an item and the amount stored. @@ -56,4 +133,11 @@ public ItemRecord (@Nonnull ItemStack itemPrototype, int count) { this.count = count; } } + + /** + * A variant of the standard Predicate interface that when passed to IItemRepository functions, will ask the + * internal default predicate to be tested in addition to the custom predicate. An IItemRepository function + * may choose to enforce its own predicate regardless. + */ + interface DefaultPredicate extends Predicate { } } diff --git a/src/com/jaquadro/minecraft/storagedrawers/api/storage/Drawers.java b/src/com/jaquadro/minecraft/storagedrawers/api/storage/Drawers.java index b9237ad8e..cf888af0f 100644 --- a/src/com/jaquadro/minecraft/storagedrawers/api/storage/Drawers.java +++ b/src/com/jaquadro/minecraft/storagedrawers/api/storage/Drawers.java @@ -3,6 +3,7 @@ import net.minecraft.item.ItemStack; import javax.annotation.Nonnull; +import java.util.function.Predicate; public class Drawers { @@ -44,12 +45,12 @@ public int getRemainingCapacity () { } @Override - public boolean canItemBeStored (@Nonnull ItemStack itemPrototype) { + public boolean canItemBeStored (@Nonnull ItemStack itemPrototype, Predicate matchPredicate) { return false; } @Override - public boolean canItemBeExtracted (@Nonnull ItemStack itemPrototype) { + public boolean canItemBeExtracted (@Nonnull ItemStack itemPrototype, Predicate matchPredicate) { return false; } diff --git a/src/com/jaquadro/minecraft/storagedrawers/api/storage/IDrawer.java b/src/com/jaquadro/minecraft/storagedrawers/api/storage/IDrawer.java index 05cb454b3..dc8b86b6d 100644 --- a/src/com/jaquadro/minecraft/storagedrawers/api/storage/IDrawer.java +++ b/src/com/jaquadro/minecraft/storagedrawers/api/storage/IDrawer.java @@ -3,6 +3,7 @@ import net.minecraft.item.ItemStack; import javax.annotation.Nonnull; +import java.util.function.Predicate; public interface IDrawer { @@ -113,26 +114,36 @@ default int getStoredItemStackSize () { } /** - * Gets whether or not an item of the given type and data can be stored in this drawer. + * Gets whether or not an item of the given type and data can be stored in this drawer using a custom matching + * predicate. If matchPredicate is null, the drawer's default item matching rules are applied instead. * - * Stack size and available capacity are not considered. For drawers that are not empty, this - * method can allow ore-dictionary compatible items to be accepted into the drawer, as defined by what - * the drawer considers to be an equivalent item. - * For drawers that are empty, locking status is considered. + * Some attributes, like locking status, are considered regardless of the predicate. * - * @param itemPrototype An ItemStack representing the type, metadata, and tags of an item. + * @param itemPrototype An ItemStack representing the type, metadata, and tags of an item. + * @param matchPredicate A custom predicate for testing the stored ItemStack for equivalence. + * @return */ - boolean canItemBeStored (@Nonnull ItemStack itemPrototype); + boolean canItemBeStored (@Nonnull ItemStack itemPrototype, Predicate matchPredicate); + + default boolean canItemBeStored (@Nonnull ItemStack itemPrototype) { + return canItemBeStored(itemPrototype, null); + } /** - * Gets whether or not an item of the given type and data can be extracted from this drawer. + * Gets whether or not an item of the given type and data can be extracted from this drawer using a custom matching + * predicate. If matchPredicate is null, the drawer's default item matching rules are applied instead. * - * This is intended to allow outbound ore-dictionary conversions of compatible items, as defined by what - * the drawer considers to be an equivalent item. + * This is intended to allow outbound conversions of compatible items, as defined by what the drawer or predicate + * considers to be an equivalent item. * - * @param itemPrototype An ItemStack representing the type, metadata, and tags of an item. + * @param itemPrototype An ItemStack representing the type, metadata, and tags of an item. + * @param matchPredicate A custom predicate for testing the stored ItemStack for equivalence. */ - boolean canItemBeExtracted (@Nonnull ItemStack itemPrototype); + boolean canItemBeExtracted (@Nonnull ItemStack itemPrototype, Predicate matchPredicate); + + default boolean canItemBeExtracted (@Nonnull ItemStack itemPrototype) { + return canItemBeExtracted(itemPrototype, null); + } /** * Gets whether or not the drawer has items. diff --git a/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntityController.java b/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntityController.java index d38403f6d..369388b2c 100644 --- a/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntityController.java +++ b/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntityController.java @@ -8,6 +8,7 @@ import com.jaquadro.minecraft.storagedrawers.api.storage.attribute.IProtectable; import com.jaquadro.minecraft.storagedrawers.api.storage.attribute.LockAttribute; import com.jaquadro.minecraft.storagedrawers.block.BlockSlave; +import com.jaquadro.minecraft.storagedrawers.capabilities.DrawerGroupItemRepository; import com.jaquadro.minecraft.storagedrawers.core.ModBlocks; import com.jaquadro.minecraft.storagedrawers.inventory.DrawerItemHandler; import com.jaquadro.minecraft.storagedrawers.security.SecurityManager; @@ -34,6 +35,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; +import java.util.function.Predicate; public class TileEntityController extends TileEntity implements IDrawerGroup { @@ -214,7 +216,7 @@ public int interactPutItemsIntoInventory (EntityPlayer player) { } protected int insertItems (@Nonnull ItemStack stack, GameProfile profile) { - int remainder = new ProtectedItemRepository(profile).insertItem(stack, false).getCount(); + int remainder = new ProtectedItemRepository(this, profile).insertItem(stack, false).getCount(); int added = stack.getCount() - remainder; stack.setCount(remainder); @@ -652,7 +654,7 @@ public IItemRepository getItemRepository () { static Capability DRAWER_GROUP_CAPABILITY = null; private DrawerItemHandler itemHandler = new DrawerItemHandler(this); - private ItemRepository itemRepository = new ItemRepository(); + private ItemRepository itemRepository = new ItemRepository(this); @Override public boolean hasCapability (@Nonnull Capability capability, @Nullable EnumFacing facing) { @@ -675,28 +677,15 @@ public T getCapability (@Nonnull Capability capability, @Nullable EnumFac return super.getCapability(capability, facing); } - private class ItemRepository implements IItemRepository + private class ItemRepository extends DrawerGroupItemRepository { - @Nonnull - @Override - public NonNullList getAllItems () { - NonNullList records = NonNullList.create(); - - for (int slot : drawerSlots) { - IDrawer drawer = getDrawer(slot); - if (drawer.isEmpty()) - continue; - - ItemStack stack = drawer.getStoredItemPrototype(); - records.add(new ItemRecord(stack, drawer.getStoredItemCount())); - } - - return records; + public ItemRepository (IDrawerGroup group) { + super(group); } @Nonnull @Override - public ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate) { + public ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate, Predicate predicate) { Collection primaryRecords = drawerPrimaryLookup.getEntries(stack.getItem(), stack.getMetadata()); Set checkedSlots = (simulate) ? new HashSet<>() : null; @@ -708,7 +697,11 @@ public ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate) { continue; IDrawer drawer = candidateGroup.getDrawer(record.slot); - if (drawer.isEmpty() || !drawer.canItemBeStored(stack) || !hasAccess(candidateGroup, drawer)) + if (drawer.isEmpty()) + continue; + if (!testPredicateInsert(drawer, stack, predicate)) + continue; + if (!hasAccess(candidateGroup, drawer)) continue; amount = (simulate) @@ -725,7 +718,11 @@ public ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate) { for (int slot : drawerSlots) { IDrawer drawer = getDrawer(slot); - if (!drawer.isEnabled() || !drawer.canItemBeStored(stack) || !hasAccess(getGroupForDrawerSlot(slot), drawer)) + if (!drawer.isEnabled()) + continue; + if (!testPredicateInsert(drawer, stack, predicate)) + continue; + if (!hasAccess(getGroupForDrawerSlot(slot), drawer)) continue; if (simulate && checkedSlots.contains(slot)) continue; @@ -746,7 +743,7 @@ public ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate) { @Nonnull @Override - public ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate) { + public ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate, Predicate predicate) { Collection primaryRecords = drawerPrimaryLookup.getEntries(stack.getItem(), stack.getMetadata()); Set checkedSlots = (simulate) ? new HashSet<>() : null; @@ -757,7 +754,11 @@ public ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simu continue; IDrawer drawer = candidateGroup.getDrawer(record.slot); - if (!drawer.canItemBeExtracted(stack) || !hasAccess(candidateGroup, drawer)) + if (!drawer.isEnabled()) + continue; + if (!testPredicateExtract(drawer, stack, predicate)) + continue; + if (!hasAccess(candidateGroup, drawer)) continue; remaining = (simulate) @@ -773,11 +774,17 @@ public ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simu for (int slot : drawerSlots) { IDrawer drawer = getDrawer(slot); - if (!drawer.canItemBeExtracted(stack) || !hasAccess(getGroupForDrawerSlot(slot), drawer)) + if (!drawer.isEnabled()) + continue; + if (!testPredicateExtract(drawer, stack, predicate)) continue; if (simulate && checkedSlots.contains(slot)) continue; + remaining = (simulate) + ? Math.max(remaining - drawer.getStoredItemCount(), 0) + : drawer.adjustStoredItemCount(-remaining); + if (remaining == 0) return stackResult(stack, amount); } @@ -790,19 +797,14 @@ public ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simu protected boolean hasAccess (IDrawerGroup group, IDrawer drawer) { return true; } - - private ItemStack stackResult (@Nonnull ItemStack stack, int amount) { - ItemStack result = stack.copy(); - result.setCount(amount); - return result; - } } private class ProtectedItemRepository extends ItemRepository { private GameProfile profile; - public ProtectedItemRepository (GameProfile profile) { + public ProtectedItemRepository (IDrawerGroup group, GameProfile profile) { + super(group); this.profile = profile; } diff --git a/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntityDrawers.java b/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntityDrawers.java index 4ff8f84ec..0a7b83838 100644 --- a/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntityDrawers.java +++ b/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntityDrawers.java @@ -11,6 +11,7 @@ import com.jaquadro.minecraft.storagedrawers.block.tile.tiledata.ControllerData; import com.jaquadro.minecraft.storagedrawers.block.tile.tiledata.MaterialData; import com.jaquadro.minecraft.storagedrawers.block.tile.tiledata.UpgradeData; +import com.jaquadro.minecraft.storagedrawers.capabilities.DrawerGroupItemRepository; import com.jaquadro.minecraft.storagedrawers.core.ModItems; import com.jaquadro.minecraft.storagedrawers.capabilities.BasicDrawerAttributes; import com.jaquadro.minecraft.storagedrawers.inventory.DrawerItemHandler; @@ -623,18 +624,17 @@ public int[] getAccessibleDrawerSlots () { @CapabilityInject(IItemHandler.class) static Capability ITEM_HANDLER_CAPABILITY = null; - private net.minecraftforge.items.IItemHandler itemHandler; - - protected IItemHandler createUnSidedHandler () { - return new DrawerItemHandler(getGroup()); - } + private IItemHandler itemHandler = new DrawerItemHandler(this); + private IItemRepository itemRepository = new DrawerGroupItemRepository(this); @SuppressWarnings("unchecked") @Override public T getCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) { if (capability == ITEM_HANDLER_CAPABILITY) - return (T) (itemHandler == null ? (itemHandler = createUnSidedHandler()) : itemHandler); + return (T) itemHandler; + if (capability == ITEM_REPOSITORY_CAPABILITY) + return (T) itemRepository; if (capability == DRAWER_ATTRIBUTES_CAPABILITY) return (T) drawerAttributes; if (capability == DRAWER_GROUP_CAPABILITY) @@ -647,6 +647,7 @@ public T getCapability(@Nonnull Capability capability, @Nullable EnumFaci public boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) { return capability == ITEM_HANDLER_CAPABILITY + || capability == ITEM_REPOSITORY_CAPABILITY || capability == DRAWER_ATTRIBUTES_CAPABILITY || capability == DRAWER_GROUP_CAPABILITY || super.hasCapability(capability, facing); diff --git a/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntitySlave.java b/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntitySlave.java index 224b8e6b7..ae0749c3d 100644 --- a/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntitySlave.java +++ b/src/com/jaquadro/minecraft/storagedrawers/block/tile/TileEntitySlave.java @@ -20,6 +20,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.function.Predicate; public class TileEntitySlave extends ChamTileEntity implements IDrawerGroup { @@ -132,22 +133,49 @@ public NonNullList getAllItems () { @Nonnull @Override - public ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate) { + public ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate, Predicate predicate) { TileEntityController controller = getController(); if (controller == null || !controller.isValidSlave(getPos())) return stack; - return controller.getItemRepository().insertItem(stack, simulate); + return controller.getItemRepository().insertItem(stack, simulate, predicate); } @Nonnull @Override - public ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate) { + public ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate, Predicate predicate) { TileEntityController controller = getController(); if (controller == null || !controller.isValidSlave(getPos())) return ItemStack.EMPTY; - return controller.getItemRepository().extractItem(stack, amount, simulate); + return controller.getItemRepository().extractItem(stack, amount, simulate, predicate); + } + + @Override + public int getStoredItemCount (@Nonnull ItemStack stack, Predicate predicate) { + TileEntityController controller = getController(); + if (controller == null || !controller.isValidSlave(getPos())) + return 0; + + return controller.getItemRepository().getStoredItemCount(stack, predicate); + } + + @Override + public int getRemainingItemCapacity (@Nonnull ItemStack stack, Predicate predicate) { + TileEntityController controller = getController(); + if (controller == null || !controller.isValidSlave(getPos())) + return 0; + + return controller.getItemRepository().getRemainingItemCapacity(stack, predicate); + } + + @Override + public int getItemCapacity (@Nonnull ItemStack stack, Predicate predicate) { + TileEntityController controller = getController(); + if (controller == null || !controller.isValidSlave(getPos())) + return 0; + + return controller.getItemRepository().getItemCapacity(stack, predicate); } } } diff --git a/src/com/jaquadro/minecraft/storagedrawers/block/tile/tiledata/FractionalDrawerGroup.java b/src/com/jaquadro/minecraft/storagedrawers/block/tile/tiledata/FractionalDrawerGroup.java index 0972ee305..68940e088 100644 --- a/src/com/jaquadro/minecraft/storagedrawers/block/tile/tiledata/FractionalDrawerGroup.java +++ b/src/com/jaquadro/minecraft/storagedrawers/block/tile/tiledata/FractionalDrawerGroup.java @@ -20,6 +20,7 @@ import javax.annotation.Nonnull; import java.util.Stack; +import java.util.function.Predicate; public class FractionalDrawerGroup extends TileDataShim implements IDrawerGroup { @@ -329,15 +330,22 @@ public boolean isEnabled (int slot) { return !protoStack[slot].isEmpty(); } - public boolean canItemBeStored (int slot, @Nonnull ItemStack itemPrototype) { + public boolean canItemBeStored (int slot, @Nonnull ItemStack itemPrototype, Predicate predicate) { if (protoStack[slot].isEmpty() && !attrs.isItemLocked(LockAttribute.LOCK_EMPTY)) return true; - return matchers[slot].matches(itemPrototype); + if (predicate == null) + return matchers[slot].matches(itemPrototype); + return predicate.test(protoStack[slot]); } - public boolean canItemBeExtracted (int slot, @Nonnull ItemStack itemPrototype) { - return matchers[slot].matches(itemPrototype); + public boolean canItemBeExtracted (int slot, @Nonnull ItemStack itemPrototype, Predicate predicate) { + if (protoStack[slot].isEmpty()) + return false; + + if (predicate == null) + return matchers[slot].matches(itemPrototype); + return predicate.test(protoStack[slot]); } public int getConversionRate (int slot) { @@ -595,13 +603,13 @@ public int getAcceptingRemainingCapacity () { } @Override - public boolean canItemBeStored (@Nonnull ItemStack itemPrototype) { - return storage.canItemBeStored(slot, itemPrototype); + public boolean canItemBeStored (@Nonnull ItemStack itemPrototype, Predicate matchPredicate) { + return storage.canItemBeStored(slot, itemPrototype, matchPredicate); } @Override - public boolean canItemBeExtracted (@Nonnull ItemStack itemPrototype) { - return storage.canItemBeExtracted(slot, itemPrototype); + public boolean canItemBeExtracted (@Nonnull ItemStack itemPrototype, Predicate matchPredicate) { + return storage.canItemBeExtracted(slot, itemPrototype, matchPredicate); } @Override diff --git a/src/com/jaquadro/minecraft/storagedrawers/block/tile/tiledata/StandardDrawerGroup.java b/src/com/jaquadro/minecraft/storagedrawers/block/tile/tiledata/StandardDrawerGroup.java index c44c6c6a0..3306d04fc 100644 --- a/src/com/jaquadro/minecraft/storagedrawers/block/tile/tiledata/StandardDrawerGroup.java +++ b/src/com/jaquadro/minecraft/storagedrawers/block/tile/tiledata/StandardDrawerGroup.java @@ -17,6 +17,7 @@ import net.minecraftforge.common.util.INBTSerializable; import javax.annotation.Nonnull; +import java.util.function.Predicate; public abstract class StandardDrawerGroup extends TileDataShim implements IDrawerGroup { @@ -316,19 +317,23 @@ public int getAcceptingRemainingCapacity () { } @Override - public boolean canItemBeStored (@Nonnull ItemStack itemPrototype) { + public boolean canItemBeStored (@Nonnull ItemStack itemPrototype, Predicate matchPredicate) { if (protoStack.isEmpty() && !attrs.isItemLocked(LockAttribute.LOCK_EMPTY)) return true; - return matcher.matches(itemPrototype); + if (matchPredicate == null) + return matcher.matches(itemPrototype); + return matchPredicate.test(protoStack); } @Override - public boolean canItemBeExtracted (@Nonnull ItemStack itemPrototype) { + public boolean canItemBeExtracted (@Nonnull ItemStack itemPrototype, Predicate matchPredicate) { if (protoStack.isEmpty()) return false; - return matcher.matches(itemPrototype); + if (matchPredicate == null) + return matcher.matches(itemPrototype); + return matchPredicate.test(protoStack); } @Override diff --git a/src/com/jaquadro/minecraft/storagedrawers/capabilities/CapabilityItemRepository.java b/src/com/jaquadro/minecraft/storagedrawers/capabilities/CapabilityItemRepository.java index 905f6cd60..c8195cf65 100644 --- a/src/com/jaquadro/minecraft/storagedrawers/capabilities/CapabilityItemRepository.java +++ b/src/com/jaquadro/minecraft/storagedrawers/capabilities/CapabilityItemRepository.java @@ -13,6 +13,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.function.Predicate; public class CapabilityItemRepository { @@ -55,13 +56,13 @@ public NonNullList getAllItems () { @Nonnull @Override - public ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate) { + public ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate, Predicate predicate) { return stack; } @Nonnull @Override - public ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate) { + public ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate, Predicate predicate) { return ItemStack.EMPTY; } } diff --git a/src/com/jaquadro/minecraft/storagedrawers/capabilities/DrawerGroupItemRepository.java b/src/com/jaquadro/minecraft/storagedrawers/capabilities/DrawerGroupItemRepository.java new file mode 100644 index 000000000..cad67373d --- /dev/null +++ b/src/com/jaquadro/minecraft/storagedrawers/capabilities/DrawerGroupItemRepository.java @@ -0,0 +1,165 @@ +package com.jaquadro.minecraft.storagedrawers.capabilities; + +import com.jaquadro.minecraft.storagedrawers.api.capabilities.IItemRepository; +import com.jaquadro.minecraft.storagedrawers.api.storage.IDrawer; +import com.jaquadro.minecraft.storagedrawers.api.storage.IDrawerGroup; +import net.minecraft.item.ItemStack; +import net.minecraft.util.NonNullList; + +import javax.annotation.Nonnull; +import java.util.function.Predicate; + +public class DrawerGroupItemRepository implements IItemRepository +{ + protected IDrawerGroup group; + + public DrawerGroupItemRepository (IDrawerGroup group) { + this.group = group; + } + + @Nonnull + @Override + public NonNullList getAllItems () { + NonNullList records = NonNullList.create(); + if (group == null) + return records; + + for (int slot : group.getAccessibleDrawerSlots()) { + IDrawer drawer = group.getDrawer(slot); + if (drawer.isEmpty()) + continue; + + ItemStack stack = drawer.getStoredItemPrototype(); + records.add(new ItemRecord(stack, drawer.getStoredItemCount())); + } + + return records; + } + + @Nonnull + @Override + public ItemStack insertItem (@Nonnull ItemStack stack, boolean simulate, Predicate predicate) { + int amount = stack.getCount(); + + for (int slot : group.getAccessibleDrawerSlots()) { + IDrawer drawer = group.getDrawer(slot); + if (!drawer.isEnabled()) + continue; + if (!testPredicateInsert(drawer, stack, predicate)) + continue; + + if (drawer.isEmpty()) + drawer = drawer.setStoredItem(stack); + + amount = (simulate) + ? Math.max(amount - drawer.getAcceptingRemainingCapacity(), 0) + : drawer.adjustStoredItemCount(amount); + + if (amount == 0) + return ItemStack.EMPTY; + } + + return stackResult(stack, amount); + } + + @Nonnull + @Override + public ItemStack extractItem (@Nonnull ItemStack stack, int amount, boolean simulate, Predicate predicate) { + int remaining = amount; + + for (int slot : group.getAccessibleDrawerSlots()) { + IDrawer drawer = group.getDrawer(slot); + if (!drawer.isEnabled()) + continue; + if (!testPredicateExtract(drawer, stack, predicate)) + continue; + + remaining = (simulate) + ? Math.max(remaining - drawer.getStoredItemCount(), 0) + : drawer.adjustStoredItemCount(-remaining); + + if (remaining == 0) + return stackResult(stack, amount); + } + + return (amount == remaining) + ? ItemStack.EMPTY + : stackResult(stack, amount - remaining); + } + + @Override + public int getStoredItemCount (@Nonnull ItemStack stack, Predicate predicate) { + long count = 0; + for (int slot : group.getAccessibleDrawerSlots()) { + IDrawer drawer = group.getDrawer(slot); + if (!testPredicateInsert(drawer, stack, predicate)) + continue; + + count += drawer.getStoredItemCount(); + if (count >= Integer.MAX_VALUE) + return Integer.MAX_VALUE; + } + + return (int)count; + } + + @Override + public int getRemainingItemCapacity (@Nonnull ItemStack stack, Predicate predicate) { + long remainder = 0; + for (int slot : group.getAccessibleDrawerSlots()) { + IDrawer drawer = group.getDrawer(slot); + if (!testPredicateInsert(drawer, stack, predicate)) + continue; + + remainder += drawer.getRemainingCapacity(); + if (remainder >= Integer.MAX_VALUE) + return Integer.MAX_VALUE; + } + + return (int)remainder; + } + + @Override + public int getItemCapacity (@Nonnull ItemStack stack, Predicate predicate) { + long capacity = 0; + for (int slot : group.getAccessibleDrawerSlots()) { + IDrawer drawer = group.getDrawer(slot); + if (!testPredicateInsert(drawer, stack, predicate)) + continue; + + capacity += drawer.getMaxCapacity(); + if (capacity >= Integer.MAX_VALUE) + return Integer.MAX_VALUE; + } + + return (int)capacity; + } + + protected boolean testPredicateInsert (IDrawer drawer, @Nonnull ItemStack stack, Predicate predicate) { + if (predicate instanceof DefaultPredicate) { + if (!drawer.canItemBeStored(stack) && !predicate.test(drawer.getStoredItemPrototype())) + return false; + } + else if (!drawer.canItemBeStored(stack, predicate)) + return false; + + return true; + } + + protected boolean testPredicateExtract (IDrawer drawer, @Nonnull ItemStack stack, Predicate predicate) { + if (predicate instanceof DefaultPredicate) { + if (!drawer.canItemBeExtracted(stack) && !predicate.test(drawer.getStoredItemPrototype())) + return false; + } + else if (!drawer.canItemBeStored(stack, predicate)) + return false; + + return true; + } + + protected ItemStack stackResult (@Nonnull ItemStack stack, int amount) { + ItemStack result = stack.copy(); + result.setCount(amount); + return result; + } +}