Add functionality in IItemHandler to test if a slot can accept an item (#5033)

This commit is contained in:
Cody Brittain 2018-07-28 20:38:18 -04:00 committed by LexManos
parent eb870bc84c
commit 4acfca27f8
10 changed files with 105 additions and 28 deletions

View file

@ -19,7 +19,10 @@
package net.minecraftforge.items; package net.minecraftforge.items;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -35,16 +38,18 @@ public interface IItemHandler
/** /**
* Returns the ItemStack in a given slot. * Returns the ItemStack in a given slot.
* *
* The result's stack size may be greater than the itemstacks max size. * The result's stack size may be greater than the itemstack's max size.
* *
* If the result is empty, then the slot is empty. * If the result is empty, then the slot is empty.
* *
* <p/> * <p>
* IMPORTANT: This ItemStack MUST NOT be modified. This method is not for * <strong>IMPORTANT:</strong> This ItemStack <em>MUST NOT</em> be modified. This method is not for
* altering an inventories contents. Any implementers who are able to detect * altering an inventory's contents. Any implementers who are able to detect
* modification through this method should throw an exception. * modification through this method should throw an exception.
* <p/> * </p>
* SERIOUSLY: DO NOT MODIFY THE RETURNED ITEMSTACK * <p>
* <strong><em>SERIOUSLY: DO NOT MODIFY THE RETURNED ITEMSTACK</em></strong>
* </p>
* *
* @param slot Slot to query * @param slot Slot to query
* @return ItemStack in given slot. Empty Itemstack if the slot is empty. * @return ItemStack in given slot. Empty Itemstack if the slot is empty.
@ -53,9 +58,11 @@ public interface IItemHandler
ItemStack getStackInSlot(int slot); ItemStack getStackInSlot(int slot);
/** /**
* <p>
* Inserts an ItemStack into the given slot and return the remainder. * Inserts an ItemStack into the given slot and return the remainder.
* The ItemStack should not be modified in this function! * The ItemStack <em>should not</em> be modified in this function!
* Note: This behaviour is subtly different from IFluidHandlers.fill() * </p>
* Note: This behaviour is subtly different from {@link IFluidHandler#fill(FluidStack, boolean)}
* *
* @param slot Slot to insert into. * @param slot Slot to insert into.
* @param stack ItemStack to insert. This must not be modified by the item handler. * @param stack ItemStack to insert. This must not be modified by the item handler.
@ -69,11 +76,13 @@ public interface IItemHandler
/** /**
* Extracts an ItemStack from the given slot. * Extracts an ItemStack from the given slot.
* <p>
* The returned value must be empty if nothing is extracted, * The returned value must be empty if nothing is extracted,
* otherwise it's stack size must less than than amount and {@link ItemStack#getMaxStackSize()}. * otherwise its stack size must be less than or equal to {@code amount} and {@link ItemStack#getMaxStackSize()}.
* </p>
* *
* @param slot Slot to extract from. * @param slot Slot to extract from.
* @param amount Amount to extract (may be greater than the current stacks max limit) * @param amount Amount to extract (may be greater than the current stack's max limit)
* @param simulate If true, the extraction is only simulated * @param simulate If true, the extraction is only simulated
* @return ItemStack extracted from the slot, must be empty if nothing can be extracted. * @return ItemStack extracted from the slot, must be empty if nothing can be extracted.
* The returned ItemStack can be safely modified after, so item handlers should return a new or copied stack. * The returned ItemStack can be safely modified after, so item handlers should return a new or copied stack.
@ -88,4 +97,26 @@ public interface IItemHandler
* @return The maximum stack size allowed in the slot. * @return The maximum stack size allowed in the slot.
*/ */
int getSlotLimit(int slot); int getSlotLimit(int slot);
/**
* <p>
* This function re-implements the vanilla function {@link IInventory#isItemValidForSlot(int, ItemStack)}.
* It should be used instead of simulated insertions in cases where the contents and state of the inventory are
* irrelevant, mainly for the purpose of automation and logic (for instance, testing if a minecart can wait
* to deposit its items into a full inventory, or if the items in the minecart can never be placed into the
* inventory and should move on).
* </p>
* <ul>
* <li>isItemValid is false when insertion of the item is never valid.</li>
* <li>When isItemValid is true, no assumptions can be made and insertion must be simulated case-by-case.</li>
* <li>The actual items in the inventory, its fullness, or any other state are <strong>not</strong> considered by isItemValid.</li>
* </ul>
* @param slot Slot to query for validity
* @param stack Stack to test with for validity
*
* @return true if the slot can insert the ItemStack, not considering the current state of the inventory.
* false if the slot can never insert the ItemStack in any situation.
*/
//todo Make non-default and/or replace in 1.13
default boolean isItemValid(int slot, @Nonnull ItemStack stack) { return true; }
} }

View file

@ -164,6 +164,12 @@ public class ItemStackHandler implements IItemHandler, IItemHandlerModifiable, I
return Math.min(getSlotLimit(slot), stack.getMaxStackSize()); return Math.min(getSlotLimit(slot), stack.getMaxStackSize());
} }
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
return true;
}
@Override @Override
public NBTTagCompound serializeNBT() public NBTTagCompound serializeNBT()
{ {

View file

@ -46,24 +46,7 @@ public class SlotItemHandler extends Slot
if (stack.isEmpty()) if (stack.isEmpty())
return false; return false;
IItemHandler handler = this.getItemHandler(); return itemHandler.isItemValid(index, stack);
ItemStack remainder;
if (handler instanceof IItemHandlerModifiable)
{
IItemHandlerModifiable handlerModifiable = (IItemHandlerModifiable) handler;
ItemStack currentStack = handlerModifiable.getStackInSlot(index);
handlerModifiable.setStackInSlot(index, ItemStack.EMPTY);
remainder = handlerModifiable.insertItem(index, stack, true);
handlerModifiable.setStackInSlot(index, currentStack);
}
else
{
remainder = handler.insertItem(index, stack, true);
}
return remainder.isEmpty() || remainder.getCount() < stack.getCount();
} }
@Override @Override

View file

@ -187,6 +187,19 @@ public class VanillaDoubleChestItemHandler extends WeakReference<TileEntityChest
return getChest(accessingUpperChest).getInventoryStackLimit(); return getChest(accessingUpperChest).getInventoryStackLimit();
} }
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
boolean accessingUpperChest = slot < 27;
int targetSlot = accessingUpperChest ? slot : slot - 27;
TileEntityChest chest = getChest(accessingUpperChest);
if (chest != null)
{
return chest.getSingleChestHandler().isItemValid(targetSlot, stack);
}
return true;
}
@Override @Override
public boolean equals(Object o) public boolean equals(Object o)
{ {

View file

@ -132,4 +132,13 @@ public class CombinedInvWrapper implements IItemHandlerModifiable
int localSlot = getSlotFromIndex(slot, index); int localSlot = getSlotFromIndex(slot, index);
return handler.getSlotLimit(localSlot); return handler.getSlotLimit(localSlot);
} }
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
int index = getIndexForSlot(slot);
IItemHandlerModifiable handler = getHandlerFromIndex(index);
int localSlot = getSlotFromIndex(slot, index);
return handler.isItemValid(localSlot, stack);
}
} }

View file

@ -67,4 +67,10 @@ public class EmptyHandler implements IItemHandlerModifiable
{ {
return 0; return 0;
} }
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
return false;
}
} }

View file

@ -179,6 +179,12 @@ public abstract class EntityEquipmentInvWrapper implements IItemHandlerModifiabl
entity.setItemStackToSlot(equipmentSlot, stack); entity.setItemStackToSlot(equipmentSlot, stack);
} }
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
return IItemHandlerModifiable.super.isItemValid(slot, stack);
}
protected EntityEquipmentSlot validateSlotIndex(final int slot) protected EntityEquipmentSlot validateSlotIndex(final int slot)
{ {
if (slot < 0 || slot >= slots.size()) if (slot < 0 || slot >= slots.size())

View file

@ -204,6 +204,12 @@ public class InvWrapper implements IItemHandlerModifiable
return getInv().getInventoryStackLimit(); return getInv().getInventoryStackLimit();
} }
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
return getInv().isItemValidForSlot(slot, stack);
}
public IInventory getInv() public IInventory getInv()
{ {
return inv; return inv;

View file

@ -105,6 +105,17 @@ public class RangedWrapper implements IItemHandlerModifiable {
return 0; return 0;
} }
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
if (checkSlot(slot))
{
return compose.isItemValid(slot + minSlot, stack);
}
return false;
}
private boolean checkSlot(int localSlot) private boolean checkSlot(int localSlot)
{ {
return localSlot + minSlot < maxSlot; return localSlot + minSlot < maxSlot;

View file

@ -230,4 +230,10 @@ public class SidedInvWrapper implements IItemHandlerModifiable
{ {
return inv.getInventoryStackLimit(); return inv.getInventoryStackLimit();
} }
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
return inv.isItemValidForSlot(slot, stack);
}
} }