Add IItemHandler capability
Add the actual patches that I forgot. Add simple implementations of IStorage and the factory methods. Add ItemStackHandler. A simple IItemHandler implementaton. return nulls, not throw nulls. Move the vanilla wrappers to a separate class for now. Minor clean ups of VanillaWrapper code. Inline static methods. Add comments. Minor cleanup of code. Remove redundant size field and add a validate slot index method. Minor formatting issues. Break early If stacksize to insert is 0. Remove setByte() methods. Throw exception if IItemHandler can't be modifyed in NBT loading. Replace event handler with patches Add capability to mine cart inventory entities. Change formatting and registration of capability. Make InventoryPlayer implements IItemHandler because why not. Also added a field to allow mods that add additional player inventory space to publicly expose them. Reduce patch sizes Lazy initialization of the item handler for vanilla tiles. Minor formatting changes. Create a single vanilla chest item handler that will merge with adjacent chests when detected. Added hooks to reset the cached adjacent value when a block update is detected and when a chunk loads. Revert "Make InventoryPlayer implements IItemHandler because why not. Also added a field to allow mods that add additional player inventory space to publicly expose them." This reverts commit 306d4a37fd0e8c8a0754411c013b750dfe8e2c87. Fix furnace derp Replace double chest code with a simpler method. Vanilla wrappers implement IItemHandlerModifiable (since they are modifiable) Minor code cleanups Add an onContentsChanged() and onLoad() callback methods.to the default implementation. Add slot as a parameter in the callback method. Change IItemHandlerModifiable.setStackInSlot() to void, and added a note about not being intended for cross-mod use. Improve ItemStackHandler handling of errored NBT. Make the stacks array protected. Fix a lot of derps in SlotItemHandler. Fix derp in ItemStackHandler Clarify comments on IItemHandler ItemStackHandler no longer caches the stack array in local variable. Clean up the Chests code to make intentions clearer Vanilla hoppers have their cooldown activated when an item is inserted. Made this behavior part of an item handler (rather than the insertion code) Fix mistake in ItemStackHandler More documentation of potential edge cases in getStackInSlot() Make limit checking more resiliant.
This commit is contained in:
parent
b8238e7f22
commit
a1e41f5464
20 changed files with 1299 additions and 1 deletions
|
@ -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);
|
|
@ -8,3 +8,26 @@
|
||||||
if (!this.field_70170_p.field_72995_K)
|
if (!this.field_70170_p.field_72995_K)
|
||||||
{
|
{
|
||||||
p_130002_1_.func_71007_a(this);
|
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);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
|
@ -76,3 +76,22 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean[] func_174902_m()
|
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);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
+ }
|
||||||
|
}
|
|
@ -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);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
--- ../src-base/minecraft/net/minecraft/tileentity/TileEntityHopper.java
|
--- ../src-base/minecraft/net/minecraft/tileentity/TileEntityHopper.java
|
||||||
+++ ../src-work/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)
|
if (itemstack == null)
|
||||||
{
|
{
|
||||||
|
@ -33,3 +49,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag)
|
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);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
+ }
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ import net.minecraftforge.common.config.Configuration;
|
||||||
import net.minecraftforge.common.config.Property;
|
import net.minecraftforge.common.config.Property;
|
||||||
import net.minecraftforge.common.network.ForgeNetworkHandler;
|
import net.minecraftforge.common.network.ForgeNetworkHandler;
|
||||||
import net.minecraftforge.fluids.FluidRegistry;
|
import net.minecraftforge.fluids.FluidRegistry;
|
||||||
|
import net.minecraftforge.items.CapabilityItemHandler;
|
||||||
import net.minecraftforge.oredict.OreDictionary;
|
import net.minecraftforge.oredict.OreDictionary;
|
||||||
import net.minecraftforge.oredict.RecipeSorter;
|
import net.minecraftforge.oredict.RecipeSorter;
|
||||||
import net.minecraftforge.server.command.ForgeCommand;
|
import net.minecraftforge.server.command.ForgeCommand;
|
||||||
|
@ -310,6 +311,7 @@ public class ForgeModContainer extends DummyModContainer implements WorldAccessC
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void preInit(FMLPreInitializationEvent evt)
|
public void preInit(FMLPreInitializationEvent evt)
|
||||||
{
|
{
|
||||||
|
CapabilityItemHandler.register();
|
||||||
MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER);
|
MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER);
|
||||||
ForgeChunkManager.captureConfig(evt.getModConfigurationDirectory());
|
ForgeChunkManager.captureConfig(evt.getModConfigurationDirectory());
|
||||||
MinecraftForge.EVENT_BUS.register(this);
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
57
src/main/java/net/minecraftforge/items/IItemHandler.java
Normal file
57
src/main/java/net/minecraftforge/items/IItemHandler.java
Normal 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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
185
src/main/java/net/minecraftforge/items/ItemStackHandler.java
Normal file
185
src/main/java/net/minecraftforge/items/ItemStackHandler.java
Normal 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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
75
src/main/java/net/minecraftforge/items/SlotItemHandler.java
Normal file
75
src/main/java/net/minecraftforge/items/SlotItemHandler.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
166
src/main/java/net/minecraftforge/items/wrapper/InvWrapper.java
Normal file
166
src/main/java/net/minecraftforge/items/wrapper/InvWrapper.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue