Merge pull request #2385 from rwtema/master

Add IItemHandler capability
This commit is contained in:
LexManos 2016-01-23 22:06:29 -08:00
commit e9a86f27fb
20 changed files with 1299 additions and 1 deletions

View file

@ -0,0 +1,11 @@
--- ../src-base/minecraft/net/minecraft/block/BlockDropper.java
+++ ../src-work/minecraft/net/minecraft/block/BlockDropper.java
@@ -43,7 +43,7 @@
{
ItemStack itemstack = tileentitydispenser.func_70301_a(i);
- if (itemstack != null)
+ if (itemstack != null && net.minecraftforge.items.VanillaInventoryCodeHooks.dropperInsertHook(p_176439_1_, p_176439_2_, tileentitydispenser, i, itemstack))
{
EnumFacing enumfacing = (EnumFacing)p_176439_1_.func_180495_p(p_176439_2_).func_177229_b(field_176441_a);
BlockPos blockpos = p_176439_2_.func_177972_a(enumfacing);

View file

@ -8,3 +8,26 @@
if (!this.field_70170_p.field_72995_K)
{
p_130002_1_.func_71007_a(this);
@@ -232,4 +233,22 @@
this.field_94113_a[i] = null;
}
}
+
+ public net.minecraftforge.items.IItemHandler itemHandler = new net.minecraftforge.items.wrapper.InvWrapper(this);
+
+ @Override
+ public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, net.minecraft.util.EnumFacing facing)
+ {
+ if (capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
+ {
+ return (T) itemHandler;
+ }
+ return super.getCapability(capability, facing);
+ }
+
+ @Override
+ public boolean hasCapability(net.minecraftforge.common.capabilities.Capability<?> capability, net.minecraft.util.EnumFacing facing)
+ {
+ return capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing);
+ }
}

View file

@ -76,3 +76,22 @@
}
public boolean[] func_174902_m()
@@ -386,4 +393,18 @@
this.field_145945_j[i] = null;
}
}
+
+ net.minecraftforge.items.IItemHandler handlerInput = new net.minecraftforge.items.wrapper.SidedInvWrapper(this, net.minecraft.util.EnumFacing.UP);
+ net.minecraftforge.items.IItemHandler handlerOutput = new net.minecraftforge.items.wrapper.SidedInvWrapper(this, net.minecraft.util.EnumFacing.DOWN);
+
+ @Override
+ public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, net.minecraft.util.EnumFacing facing)
+ {
+ if (facing != null && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
+ if (facing == EnumFacing.UP)
+ return (T) handlerInput;
+ else
+ return (T) handlerOutput;
+ return super.getCapability(capability, facing);
+ }
}

View file

@ -0,0 +1,35 @@
--- ../src-base/minecraft/net/minecraft/tileentity/TileEntityChest.java
+++ ../src-work/minecraft/net/minecraft/tileentity/TileEntityChest.java
@@ -186,6 +186,7 @@
{
super.func_145836_u();
this.field_145984_a = false;
+ doubleChestHandler = null;
}
@SuppressWarnings("incomplete-switch")
@@ -468,4 +469,24 @@
this.field_145985_p[i] = null;
}
}
+
+ public net.minecraftforge.items.VanillaDoubleChestItemHandler doubleChestHandler;
+
+ @Override
+ public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, net.minecraft.util.EnumFacing facing)
+ {
+ if (capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
+ {
+ if(doubleChestHandler == null || doubleChestHandler.needsRefresh())
+ doubleChestHandler = net.minecraftforge.items.VanillaDoubleChestItemHandler.get(this);
+ if (doubleChestHandler != null && doubleChestHandler != net.minecraftforge.items.VanillaDoubleChestItemHandler.NO_ADJACENT_CHESTS_INSTANCE)
+ return (T) doubleChestHandler;
+ }
+ return super.getCapability(capability, facing);
+ }
+
+ public net.minecraftforge.items.IItemHandler getSingleChestHandler()
+ {
+ return super.getCapability(net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
+ }
}

View file

@ -49,3 +49,25 @@
}
}
@@ -451,4 +462,21 @@
this.field_145957_n[i] = null;
}
}
+
+ net.minecraftforge.items.IItemHandler handlerTop = new net.minecraftforge.items.wrapper.SidedInvWrapper(this, net.minecraft.util.EnumFacing.UP);
+ net.minecraftforge.items.IItemHandler handlerBottom = new net.minecraftforge.items.wrapper.SidedInvWrapper(this, net.minecraft.util.EnumFacing.DOWN);
+ net.minecraftforge.items.IItemHandler handlerSide = new net.minecraftforge.items.wrapper.SidedInvWrapper(this, net.minecraft.util.EnumFacing.WEST);
+
+ @Override
+ public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, net.minecraft.util.EnumFacing facing)
+ {
+ if (facing != null && capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
+ if (facing == EnumFacing.DOWN)
+ return (T) handlerBottom;
+ else if (facing == EnumFacing.UP)
+ return (T) handlerTop;
+ else
+ return (T) handlerSide;
+ return super.getCapability(capability, facing);
+ }
}

View file

@ -1,6 +1,22 @@
--- ../src-base/minecraft/net/minecraft/tileentity/TileEntityHopper.java
+++ ../src-work/minecraft/net/minecraft/tileentity/TileEntityHopper.java
@@ -515,17 +515,31 @@
@@ -260,6 +260,7 @@
private boolean func_145883_k()
{
+ if (net.minecraftforge.items.VanillaInventoryCodeHooks.insertHook(this)) { return true; }
IInventory iinventory = this.func_145895_l();
if (iinventory == null)
@@ -366,6 +367,7 @@
public static boolean func_145891_a(IHopper p_145891_0_)
{
+ if (net.minecraftforge.items.VanillaInventoryCodeHooks.extractHook(p_145891_0_)) { return true; }
IInventory iinventory = func_145884_b(p_145891_0_);
if (iinventory != null)
@@ -515,17 +517,31 @@
if (itemstack == null)
{
@ -33,3 +49,14 @@
}
if (flag)
@@ -668,4 +684,10 @@
this.field_145900_a[i] = null;
}
}
+
+
+ protected net.minecraftforge.items.IItemHandler createUnSidedHandler()
+ {
+ return new net.minecraftforge.items.VanillaHopperItemHandler(this);
+ }
}

View file

@ -0,0 +1,28 @@
--- ../src-base/minecraft/net/minecraft/tileentity/TileEntityLockable.java
+++ ../src-work/minecraft/net/minecraft/tileentity/TileEntityLockable.java
@@ -47,4 +47,25 @@
{
return (IChatComponent)(this.func_145818_k_() ? new ChatComponentText(this.func_70005_c_()) : new ChatComponentTranslation(this.func_70005_c_(), new Object[0]));
}
+
+ private net.minecraftforge.items.IItemHandler itemHandler;
+
+ protected net.minecraftforge.items.IItemHandler createUnSidedHandler()
+ {
+ return new net.minecraftforge.items.wrapper.InvWrapper(this);
+ }
+
+ @Override
+ public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, net.minecraft.util.EnumFacing facing)
+ {
+ if (capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
+ return (T) (itemHandler == null ? (itemHandler = createUnSidedHandler()) : itemHandler);
+ return super.getCapability(capability, facing);
+ }
+
+ @Override
+ public boolean hasCapability(net.minecraftforge.common.capabilities.Capability<?> capability, net.minecraft.util.EnumFacing facing)
+ {
+ return capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing);
+ }
}

View file

@ -26,6 +26,7 @@ import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.common.network.ForgeNetworkHandler;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.oredict.OreDictionary;
import net.minecraftforge.oredict.RecipeSorter;
import net.minecraftforge.server.command.ForgeCommand;
@ -310,6 +311,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
@Subscribe
public void preInit(FMLPreInitializationEvent evt)
{
CapabilityItemHandler.register();
MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER);
ForgeChunkManager.captureConfig(evt.getModConfigurationDirectory());
MinecraftForge.EVENT_BUS.register(this);

View file

@ -0,0 +1,70 @@
package net.minecraftforge.items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityManager;
import java.util.concurrent.Callable;
public class CapabilityItemHandler
{
@CapabilityInject(IItemHandler.class)
public static Capability<IItemHandler> ITEM_HANDLER_CAPABILITY = null;
public static void register()
{
CapabilityManager.INSTANCE.register(IItemHandler.class, new Capability.IStorage<IItemHandler>()
{
@Override
public NBTBase writeNBT(Capability<IItemHandler> capability, IItemHandler instance, EnumFacing side)
{
NBTTagList nbtTagList = new NBTTagList();
int size = instance.getSlots();
for (int i = 0; i < size; i++)
{
ItemStack stack = instance.getStackInSlot(i);
if (stack != null)
{
NBTTagCompound itemTag = new NBTTagCompound();
itemTag.setInteger("Slot", i);
stack.writeToNBT(itemTag);
nbtTagList.appendTag(itemTag);
}
}
return nbtTagList;
}
@Override
public void readNBT(Capability<IItemHandler> capability, IItemHandler instance, EnumFacing side, NBTBase base)
{
if (!(instance instanceof IItemHandlerModifiable))
throw new RuntimeException("IItemHandler instance does not implement IItemHandlerModifiable");
IItemHandlerModifiable itemHandlerModifiable = (IItemHandlerModifiable) instance;
NBTTagList tagList = (NBTTagList) base;
for (int i = 0; i < tagList.tagCount(); i++)
{
NBTTagCompound itemTags = tagList.getCompoundTagAt(i);
int j = itemTags.getInteger("Slot");
if (j > 0 && j < instance.getSlots())
{
itemHandlerModifiable.setStackInSlot(j, ItemStack.loadItemStackFromNBT(itemTags));
}
}
}
}, new Callable<ItemStackHandler>()
{
@Override
public ItemStackHandler call() throws Exception
{
return new ItemStackHandler();
}
});
}
}

View file

@ -0,0 +1,57 @@
package net.minecraftforge.items;
import net.minecraft.item.ItemStack;
public interface IItemHandler
{
/**
* Returns the number of slots available
*
* @return The number of slots available
**/
int getSlots();
/**
* Returns the ItemStack in a given slot.
*
* The result's stack size may be greater than the itemstacks max size.
*
* If the result is null, then the slot is empty.
* If the result is not null but the stack size is zero, then it represents
* an empty slot that will only accept* a specific itemstack.
*
* <p/>
* IMPORTANT: This ItemStack MUST NOT be modified. This method is not for
* altering an inventories contents. Any implementers who are able to detect
* modification through this method should throw an exception.
* <p/>
* SERIOUSLY: DO NOT MODIFY THE RETURNED ITEMSTACK
*
* @param slot Slot to query
* @return ItemStack in given slot. May be null.
**/
ItemStack getStackInSlot(int slot);
/**
* Inserts an ItemStack into the given slot and return the remainder.
* Note: This behaviour is subtly different from IFluidHandlers.fill()
*
* @param slot Slot to insert into.
* @param stack ItemStack to insert
* @param simulate If true, the insertion is only simulated
* @return The remaining ItemStack that was not inserted (if the entire stack is accepted, then return null)
**/
ItemStack insertItem(int slot, ItemStack stack, boolean simulate);
/**
* Extracts an ItemStack from the given slot. The returned value must be null
* if nothing is extracted, otherwise it's stack size must not be greater than amount or the
* itemstacks getMaxStackSize().
*
* @param slot Slot to extract from.
* @param amount Amount to extract (may be greater than the current stacks max limit)
* @param simulate If true, the extraction is only simulated
* @return ItemStack extracted from the slot, must be null, if nothing can be extracted
**/
ItemStack extractItem(int slot, int amount, boolean simulate);
}

View file

@ -0,0 +1,19 @@
package net.minecraftforge.items;
import net.minecraft.item.ItemStack;
public interface IItemHandlerModifiable extends IItemHandler
{
/**
* Overrides the stack in the given slot. This method is used by the
* standard Forge helper methods and classes. It is not intended for
* general use by other mods, and the handler may throw an error if it
* is called unexpectedly.
*
* @param slot Slot to modify
* @param stack ItemStack to set slot to (may be null)
* @throws RuntimeException if the handler is called in a way that the handler
* was not expecting.
**/
void setStackInSlot(int slot, ItemStack stack);
}

View file

@ -0,0 +1,43 @@
package net.minecraftforge.items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
public class ItemHandlerHelper
{
public static ItemStack insertItem(IItemHandler dest, ItemStack stack, boolean simulate)
{
if (dest == null || stack == null)
return stack;
for (int i = 0; i < dest.getSlots(); i++)
{
stack = dest.insertItem(i, stack, simulate);
if (stack == null || stack.stackSize <= 0)
{
return null;
}
}
return stack;
}
public static boolean canItemStacksStack(ItemStack a, ItemStack b)
{
if (a == null || !a.isItemEqual(b))
return false;
final NBTTagCompound aTag = a.getTagCompound();
final NBTTagCompound bTag = b.getTagCompound();
return (aTag != null || bTag == null) && (aTag == null || aTag.equals(bTag));
}
public static ItemStack copyStackWithSize(ItemStack itemStack, int size)
{
if (size == 0)
return null;
ItemStack copy = ItemStack.copyItemStack(itemStack);
copy.stackSize = size;
return copy;
}
}

View file

@ -0,0 +1,185 @@
package net.minecraftforge.items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.INBTSerializable;
public class ItemStackHandler implements IItemHandler, IItemHandlerModifiable, INBTSerializable<NBTTagCompound>
{
protected ItemStack[] stacks;
public ItemStackHandler()
{
this(1);
}
public ItemStackHandler(int size)
{
stacks = new ItemStack[size];
}
public void setSize(int size)
{
stacks = new ItemStack[size];
}
@Override
public void setStackInSlot(int slot, ItemStack stack)
{
validateSlotIndex(slot);
if (ItemStack.areItemStacksEqual(this.stacks[slot], stack))
return;
this.stacks[slot] = stack;
onContentsChanged(slot);
}
@Override
public int getSlots()
{
return stacks.length;
}
@Override
public ItemStack getStackInSlot(int slot)
{
validateSlotIndex(slot);
return this.stacks[slot];
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate)
{
if (stack == null || stack.stackSize == 0)
return null;
validateSlotIndex(slot);
ItemStack existing = this.stacks[slot];
int limit = getStackLimit(slot, stack);
if (existing != null)
{
if (!ItemHandlerHelper.canItemStacksStack(stack, existing))
return stack;
limit -= existing.stackSize;
}
if (limit <= 0)
return stack;
boolean reachedLimit = stack.stackSize > limit;
if (!simulate)
{
if (existing == null)
{
this.stacks[slot] = reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, limit) : stack;
}
else
{
existing.stackSize += reachedLimit ? limit : stack.stackSize;
}
onContentsChanged(slot);
}
return reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, stack.stackSize - limit) : null;
}
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
if (amount == 0)
return null;
validateSlotIndex(slot);
ItemStack existing = this.stacks[slot];
if (existing == null)
return null;
int toExtract = Math.min(amount, existing.getMaxStackSize());
if (existing.stackSize <= toExtract)
{
if (!simulate)
{
this.stacks[slot] = null;
onContentsChanged(slot);
}
return existing;
}
else
{
if (!simulate)
{
this.stacks[slot] = ItemHandlerHelper.copyStackWithSize(existing, existing.stackSize - toExtract);
onContentsChanged(slot);
}
return ItemHandlerHelper.copyStackWithSize(existing, toExtract);
}
}
protected int getStackLimit(int slot, ItemStack stack)
{
return stack.getMaxStackSize();
}
@Override
public NBTTagCompound serializeNBT()
{
NBTTagList nbtTagList = new NBTTagList();
for (int i = 0; i < stacks.length; i++)
{
if (stacks[i] != null)
{
NBTTagCompound itemTag = new NBTTagCompound();
itemTag.setInteger("Slot", i);
stacks[i].writeToNBT(itemTag);
nbtTagList.appendTag(itemTag);
}
}
NBTTagCompound nbt = new NBTTagCompound();
nbt.setTag("Items", nbtTagList);
nbt.setInteger("Size", stacks.length);
return nbt;
}
@Override
public void deserializeNBT(NBTTagCompound nbt)
{
setSize(nbt.hasKey("Size", Constants.NBT.TAG_INT) ? nbt.getInteger("Size") : stacks.length);
NBTTagList tagList = nbt.getTagList("Items", Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < tagList.tagCount(); i++)
{
NBTTagCompound itemTags = tagList.getCompoundTagAt(i);
int slot = itemTags.getInteger("Slot");
if (slot >= 0 && slot < stacks.length)
{
stacks[slot] = ItemStack.loadItemStackFromNBT(itemTags);
}
}
onLoad();
}
protected void validateSlotIndex(int slot)
{
if (slot < 0 || slot >= stacks.length)
throw new RuntimeException("Slot " + slot + " not in valid range - [0," + stacks.length + ")");
}
protected void onLoad()
{
}
protected void onContentsChanged(int slot)
{
}
}

View file

@ -0,0 +1,75 @@
package net.minecraftforge.items;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryBasic;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
public class SlotItemHandler extends Slot
{
private static IInventory emptyInventory = new InventoryBasic("[Null]", true, 0);
public final IItemHandler itemHandler;
private final int index;
public SlotItemHandler(IItemHandler itemHandler, int index, int xPosition, int yPosition)
{
super(emptyInventory, index, xPosition, yPosition);
this.itemHandler = itemHandler;
this.index = index;
}
@Override
public boolean isItemValid(ItemStack stack)
{
if (stack == null)
return false;
ItemStack remainder = this.itemHandler.insertItem(index, stack, true);
return remainder == null || remainder.stackSize < stack.stackSize;
}
@Override
public ItemStack getStack()
{
return this.itemHandler.getStackInSlot(index);
}
// Override if your IItemHandler does not implement IItemHandlerModifiable
@Override
public void putStack(ItemStack stack)
{
((IItemHandlerModifiable) this.itemHandler).setStackInSlot(index, stack);
this.onSlotChanged();
}
@Override
public void onSlotChange(ItemStack p_75220_1_, ItemStack p_75220_2_)
{
}
@Override
public int getItemStackLimit(ItemStack stack)
{
ItemStack maxAdd = stack.copy();
maxAdd.stackSize = maxAdd.getMaxStackSize();
ItemStack currentStack = this.itemHandler.getStackInSlot(index);
ItemStack remainder = this.itemHandler.insertItem(index, maxAdd, true);
int current = currentStack == null ? 0 : currentStack.stackSize;
int added = maxAdd.stackSize - (remainder != null ? remainder.stackSize : 0);
return current + added;
}
@Override
public boolean canTakeStack(EntityPlayer playerIn)
{
return this.itemHandler.extractItem(index, 1, true) != null;
}
@Override
public ItemStack decrStackSize(int amount)
{
return this.itemHandler.extractItem(index, amount, false);
}
}

View file

@ -0,0 +1,144 @@
package net.minecraftforge.items;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityChest;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
import java.lang.ref.WeakReference;
import java.util.Objects;
public class VanillaDoubleChestItemHandler extends WeakReference<TileEntityChest> implements IItemHandler
{
// Dummy cache value to signify that we have checked and definitely found no adjacent chests
public static final VanillaDoubleChestItemHandler NO_ADJACENT_CHESTS_INSTANCE = new VanillaDoubleChestItemHandler(null, null, false);
private final boolean mainChestIsUpper;
private final TileEntityChest mainChest;
private final int hashCode;
public VanillaDoubleChestItemHandler(TileEntityChest mainChest, TileEntityChest other, boolean mainChestIsUpper)
{
super(other);
this.mainChest = mainChest;
this.mainChestIsUpper = mainChestIsUpper;
hashCode = Objects.hashCode(mainChestIsUpper ? mainChest : other) * 31 + Objects.hashCode(!mainChestIsUpper ? mainChest : other);
}
public static VanillaDoubleChestItemHandler get(TileEntityChest chest)
{
World world = chest.getWorld();
BlockPos pos = chest.getPos();
if (world == null || pos == null || !world.isBlockLoaded(pos))
return null; // Still loading
Block blockType = chest.getBlockType();
EnumFacing[] horizontals = EnumFacing.HORIZONTALS;
for (int i = horizontals.length - 1; i >= 0; i--) // Use reverse order so we can return early
{
EnumFacing enumfacing = horizontals[i];
BlockPos blockpos = pos.offset(enumfacing);
Block block = world.getBlockState(blockpos).getBlock();
if (block == blockType)
{
TileEntity otherTE = world.getTileEntity(blockpos);
if (otherTE instanceof TileEntityChest)
{
TileEntityChest otherChest = (TileEntityChest) otherTE;
return new VanillaDoubleChestItemHandler(chest, otherChest,
enumfacing != net.minecraft.util.EnumFacing.WEST && enumfacing != net.minecraft.util.EnumFacing.NORTH);
}
}
}
return NO_ADJACENT_CHESTS_INSTANCE; //All alone
}
public TileEntityChest getChest(boolean accessingUpper)
{
if (accessingUpper == mainChestIsUpper)
return mainChest;
else
{
return getOtherChest();
}
}
private TileEntityChest getOtherChest()
{
TileEntityChest tileEntityChest = get();
return tileEntityChest != null && !tileEntityChest.isInvalid() ? tileEntityChest : null;
}
@Override
public int getSlots()
{
return 27 * 2;
}
@Override
public ItemStack getStackInSlot(int slot)
{
boolean accessingUpperChest = slot < 27;
int targetSlot = accessingUpperChest ? slot : slot - 27;
TileEntityChest chest = getChest(accessingUpperChest);
return chest != null ? chest.getStackInSlot(targetSlot) : null;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate)
{
boolean accessingUpperChest = slot < 27;
int targetSlot = accessingUpperChest ? slot : slot - 27;
TileEntityChest chest = getChest(accessingUpperChest);
return chest != null ? chest.getSingleChestHandler().insertItem(targetSlot, stack, simulate) : stack;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
boolean accessingUpperChest = slot < 27;
int targetSlot = accessingUpperChest ? slot : slot - 27;
TileEntityChest chest = getChest(accessingUpperChest);
return chest != null ? chest.getSingleChestHandler().extractItem(targetSlot, amount, simulate) : null;
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
VanillaDoubleChestItemHandler that = (VanillaDoubleChestItemHandler) o;
if (hashCode != that.hashCode)
return false;
final TileEntityChest otherChest = getOtherChest();
if (mainChestIsUpper == that.mainChestIsUpper)
return Objects.equals(mainChest, that.mainChest) && Objects.equals(otherChest, that.getOtherChest());
else
return Objects.equals(mainChest, that.getOtherChest()) && Objects.equals(otherChest, that.mainChest);
}
@Override
public int hashCode()
{
return hashCode;
}
public boolean needsRefresh()
{
if (this == NO_ADJACENT_CHESTS_INSTANCE)
return false;
TileEntityChest tileEntityChest = get();
return tileEntityChest == null || tileEntityChest.isInvalid();
}
}

View file

@ -0,0 +1,33 @@
package net.minecraftforge.items;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntityHopper;
import net.minecraftforge.items.wrapper.InvWrapper;
public class VanillaHopperItemHandler extends InvWrapper
{
private final TileEntityHopper hopper;
public VanillaHopperItemHandler(TileEntityHopper hopper)
{
super(hopper);
this.hopper = hopper;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate)
{
if (stack == null)
return null;
if (simulate || !hopper.mayTransfer())
return super.insertItem(slot, stack, simulate);
int curStackSize = stack.stackSize;
ItemStack itemStack = super.insertItem(slot, stack, false);
if (itemStack == null || curStackSize != itemStack.stackSize)
{
hopper.setTransferCooldown(8);
}
return itemStack;
}
}

View file

@ -0,0 +1,122 @@
package net.minecraftforge.items;
import net.minecraft.block.BlockDropper;
import net.minecraft.block.BlockHopper;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.IHopper;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.tileentity.TileEntityHopper;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
public class VanillaInventoryCodeHooks
{
public static boolean extractHook(IHopper dest)
{
TileEntity tileEntity = dest.getWorld().getTileEntity(new BlockPos(dest.getXPos(), dest.getYPos() + 1, dest.getZPos()));
if (tileEntity == null || !tileEntity.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.DOWN))
return false;
IItemHandler handler = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.DOWN);
for (int i = 0; i < handler.getSlots(); i++)
{
ItemStack extractItem = handler.extractItem(i, 1, true);
if (extractItem != null)
{
for (int j = 0; j < dest.getSizeInventory(); j++)
{
ItemStack destStack = dest.getStackInSlot(j);
if (destStack == null || destStack.stackSize < destStack.getMaxStackSize() || ItemHandlerHelper.canItemStacksStack(extractItem, destStack))
{
extractItem = handler.extractItem(i, 1, false);
if (destStack == null)
dest.setInventorySlotContents(j, extractItem);
else
{
destStack.stackSize++;
dest.setInventorySlotContents(j, destStack);
}
dest.markDirty();
return true;
}
}
}
}
return true;
}
public static boolean dropperInsertHook(World world, BlockPos pos, TileEntityDispenser dropper, int slot, ItemStack stack)
{
EnumFacing enumfacing = world.getBlockState(pos).getValue(BlockDropper.FACING);
BlockPos offsetPos = pos.offset(enumfacing);
TileEntity tileEntity = world.getTileEntity(offsetPos);
if (tileEntity == null)
return false;
if (!tileEntity.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, enumfacing.getOpposite()))
return true;
IItemHandler capability = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, enumfacing.getOpposite());
ItemStack result = ItemHandlerHelper.insertItem(capability, ItemHandlerHelper.copyStackWithSize(stack, 1), false);
if (result == null)
{
result = stack.copy();
if (--result.stackSize == 0)
{
result = null;
}
}
else
{
result = stack.copy();
}
dropper.setInventorySlotContents(slot, result);
dropper.markDirty();
return false;
}
public static boolean insertHook(TileEntityHopper hopper)
{
return insertHook(hopper, BlockHopper.getFacing(hopper.getBlockMetadata()));
}
public static boolean insertHook(IHopper hopper, EnumFacing facing)
{
TileEntity tileEntity = hopper.getWorld().getTileEntity(
new BlockPos(hopper.getXPos(), hopper.getYPos(), hopper.getZPos()).offset(facing));
if (tileEntity == null)
return false;
if (!tileEntity.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite()))
return false;
IItemHandler handler = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite());
for (int i = 0; i < hopper.getSizeInventory(); i++)
{
ItemStack stackInSlot = hopper.getStackInSlot(i);
if (stackInSlot != null)
{
ItemStack insert = stackInSlot.copy();
insert.stackSize = 1;
ItemStack newStack = ItemHandlerHelper.insertItem(handler, insert, true);
if (newStack == null || newStack.stackSize == 0)
{
ItemHandlerHelper.insertItem(handler, hopper.decrStackSize(i, 1), false);
hopper.markDirty();
return true;
}
}
}
return true;
}
}

View file

@ -0,0 +1,33 @@
package net.minecraftforge.items.wrapper;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
public class EmptyHandler implements IItemHandler
{
public static IItemHandler INSTANCE = new EmptyHandler();
@Override
public int getSlots()
{
return 0;
}
@Override
public ItemStack getStackInSlot(int slot)
{
return null;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate)
{
return stack;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
return null;
}
}

View file

@ -0,0 +1,166 @@
package net.minecraftforge.items.wrapper;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper;
public class InvWrapper implements IItemHandlerModifiable
{
public final IInventory inv;
public InvWrapper(IInventory inv)
{
this.inv = inv;
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
InvWrapper that = (InvWrapper) o;
return inv.equals(that.inv);
}
@Override
public int hashCode()
{
return inv.hashCode();
}
@Override
public int getSlots()
{
return inv.getSizeInventory();
}
@Override
public ItemStack getStackInSlot(int slot)
{
return inv.getStackInSlot(slot);
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate)
{
if (stack == null)
return null;
if (!inv.isItemValidForSlot(slot, stack))
return stack;
ItemStack stackInSlot = inv.getStackInSlot(slot);
int m;
if (stackInSlot != null)
{
if (!ItemHandlerHelper.canItemStacksStack(stack, stackInSlot))
return stack;
m = Math.min(stack.getMaxStackSize(), inv.getInventoryStackLimit()) - stackInSlot.stackSize;
if (stack.stackSize <= m)
{
if (!simulate)
{
ItemStack copy = stack.copy();
copy.stackSize += stackInSlot.stackSize;
inv.setInventorySlotContents(slot, copy);
inv.markDirty();
}
return null;
}
else
{
if (!simulate)
{
ItemStack copy = stack.splitStack(m);
copy.stackSize += stackInSlot.stackSize;
inv.setInventorySlotContents(slot, copy);
inv.markDirty();
return stack;
}
else
{
stack.stackSize -= m;
return stack;
}
}
}
else
{
m = Math.min(stack.getMaxStackSize(), inv.getInventoryStackLimit());
if (m < stack.stackSize)
{
if (!simulate)
{
inv.setInventorySlotContents(slot, stack.splitStack(m));
inv.markDirty();
return stack;
}
else
{
stack.stackSize -= m;
return stack;
}
}
else
{
if (!simulate)
{
inv.setInventorySlotContents(slot, stack);
inv.markDirty();
}
return null;
}
}
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
if (amount == 0)
return null;
ItemStack stackInSlot = inv.getStackInSlot(slot);
if (stackInSlot == null)
return null;
if (simulate)
{
if (stackInSlot.stackSize < amount)
{
return stackInSlot.copy();
}
else
{
ItemStack copy = stackInSlot.copy();
copy.stackSize = amount;
return copy;
}
}
else
{
int m = Math.min(stackInSlot.stackSize, amount);
ItemStack decrStackSize = inv.decrStackSize(slot, m);
inv.markDirty();
return decrStackSize;
}
}
@Override
public void setStackInSlot(int slot, ItemStack stack)
{
inv.setInventorySlotContents(slot, stack);
}
}

View file

@ -0,0 +1,184 @@
package net.minecraftforge.items.wrapper;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper;
public class SidedInvWrapper implements IItemHandlerModifiable
{
protected final ISidedInventory inv;
protected final EnumFacing side;
public SidedInvWrapper(ISidedInventory inv, EnumFacing side)
{
this.inv = inv;
this.side = side;
}
public static int getSlot(ISidedInventory inv, int slot, EnumFacing side)
{
int[] slots = inv.getSlotsForFace(side);
if (slot < slots.length)
return slots[slot];
return -1;
}
@Override
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
SidedInvWrapper that = (SidedInvWrapper) o;
return inv.equals(that.inv) && side == that.side;
}
@Override
public int hashCode()
{
int result = inv.hashCode();
result = 31 * result + side.hashCode();
return result;
}
@Override
public int getSlots()
{
return inv.getSlotsForFace(side).length;
}
@Override
public ItemStack getStackInSlot(int slot)
{
int i = getSlot(inv, slot, side);
return i == -1 ? null : inv.getStackInSlot(i);
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate)
{
if (stack == null)
return null;
int slot1 = getSlot(inv, slot, side);
if (slot1 == -1)
return stack;
if (!inv.isItemValidForSlot(slot1, stack) || !inv.canInsertItem(slot1, stack, side))
return stack;
ItemStack stackInSlot = inv.getStackInSlot(slot1);
int m;
if (stackInSlot != null)
{
if (!ItemHandlerHelper.canItemStacksStack(stack, stackInSlot))
return stack;
m = Math.min(stack.getMaxStackSize(), inv.getInventoryStackLimit()) - stackInSlot.stackSize;
if (stack.stackSize <= m)
{
if (!simulate)
{
ItemStack copy = stack.copy();
copy.stackSize += stackInSlot.stackSize;
inv.setInventorySlotContents(slot1, copy);
}
return null;
}
else
{
if (!simulate)
{
ItemStack copy = stack.splitStack(m);
copy.stackSize += stackInSlot.stackSize;
inv.setInventorySlotContents(slot1, copy);
return stack;
}
else
{
stack.stackSize -= m;
return stack;
}
}
}
else
{
m = Math.min(stack.getMaxStackSize(), inv.getInventoryStackLimit());
if (m < stack.stackSize)
{
if (!simulate)
{
inv.setInventorySlotContents(slot1, stack.splitStack(m));
return stack;
}
else
{
stack.stackSize -= m;
return stack;
}
}
else
{
if (!simulate)
inv.setInventorySlotContents(slot1, stack);
return null;
}
}
}
@Override
public void setStackInSlot(int slot, ItemStack stack)
{
inv.setInventorySlotContents(slot, stack);
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
if (amount == 0)
return null;
int slot1 = getSlot(inv, slot, side);
if (slot1 == -1)
return null;
ItemStack stackInSlot = inv.getStackInSlot(slot1);
if (stackInSlot == null)
return null;
if (!inv.canExtractItem(slot1, stackInSlot, side))
return null;
if (simulate)
{
if (stackInSlot.stackSize < amount)
{
return stackInSlot.copy();
}
else
{
ItemStack copy = stackInSlot.copy();
copy.stackSize = amount;
return copy;
}
}
else
{
int m = Math.min(stackInSlot.stackSize, amount);
return inv.decrStackSize(slot1, m);
}
}
}