base mod created

This commit is contained in:
Mohammad-Ali Minaie
2018-10-08 09:07:47 -04:00
parent 0a7700c356
commit b86dedad2f
7848 changed files with 584664 additions and 1 deletions

View File

@@ -0,0 +1,82 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
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.isEmpty())
{
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, new ItemStack(itemTags));
}
}
}
}, ItemStackHandler::new);
}
}

View File

@@ -0,0 +1,122 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.capability.IFluidHandler;
import javax.annotation.Nonnull;
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 itemstack's max size.
*
* If the result is empty, then the slot is empty.
*
* <p>
* <strong>IMPORTANT:</strong> This ItemStack <em>MUST NOT</em> be modified. This method is not for
* altering an inventory's contents. Any implementers who are able to detect
* modification through this method should throw an exception.
* </p>
* <p>
* <strong><em>SERIOUSLY: DO NOT MODIFY THE RETURNED ITEMSTACK</em></strong>
* </p>
*
* @param slot Slot to query
* @return ItemStack in given slot. Empty Itemstack if the slot is empty.
**/
@Nonnull
ItemStack getStackInSlot(int slot);
/**
* <p>
* Inserts an ItemStack into the given slot and return the remainder.
* The ItemStack <em>should not</em> be modified in this function!
* </p>
* Note: This behaviour is subtly different from {@link IFluidHandler#fill(FluidStack, boolean)}
*
* @param slot Slot to insert into.
* @param stack ItemStack to insert. This must not be modified by the item handler.
* @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 an empty ItemStack).
* May be the same as the input ItemStack if unchanged, otherwise a new ItemStack.
* The returned ItemStack can be safely modified after.
**/
@Nonnull
ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate);
/**
* Extracts an ItemStack from the given slot.
* <p>
* The returned value must be empty if nothing is extracted,
* 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 amount Amount to extract (may be greater than the current stack's max limit)
* @param simulate If true, the extraction is only simulated
* @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.
**/
@Nonnull
ItemStack extractItem(int slot, int amount, boolean simulate);
/**
* Retrieves the maximum stack size allowed to exist in the given slot.
*
* @param slot Slot to query.
* @return The maximum stack size allowed in the 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

@@ -0,0 +1,40 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items;
import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull;
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 empty).
* @throws RuntimeException if the handler is called in a way that the handler
* was not expecting.
**/
void setStackInSlot(int slot, @Nonnull ItemStack stack);
}

View File

@@ -0,0 +1,234 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.items.wrapper.PlayerMainInvWrapper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class ItemHandlerHelper
{
@Nonnull
public static ItemStack insertItem(IItemHandler dest, @Nonnull ItemStack stack, boolean simulate)
{
if (dest == null || stack.isEmpty())
return stack;
for (int i = 0; i < dest.getSlots(); i++)
{
stack = dest.insertItem(i, stack, simulate);
if (stack.isEmpty())
{
return ItemStack.EMPTY;
}
}
return stack;
}
public static boolean canItemStacksStack(@Nonnull ItemStack a, @Nonnull ItemStack b)
{
if (a.isEmpty() || !a.isItemEqual(b) || a.hasTagCompound() != b.hasTagCompound())
return false;
return (!a.hasTagCompound() || a.getTagCompound().equals(b.getTagCompound())) && a.areCapsCompatible(b);
}
/**
* A relaxed version of canItemStacksStack that stacks itemstacks with different metadata if they don't have subtypes.
* This usually only applies when players pick up items.
*/
public static boolean canItemStacksStackRelaxed(@Nonnull ItemStack a, @Nonnull ItemStack b)
{
if (a.isEmpty() || b.isEmpty() || a.getItem() != b.getItem())
return false;
if (!a.isStackable())
return false;
// Metadata value only matters when the item has subtypes
// Vanilla stacks non-subtype items with different metadata together
// e.g. a stick with metadata 0 and a stick with metadata 1 stack
if (a.getHasSubtypes() && a.getMetadata() != b.getMetadata())
return false;
if (a.hasTagCompound() != b.hasTagCompound())
return false;
return (!a.hasTagCompound() || a.getTagCompound().equals(b.getTagCompound())) && a.areCapsCompatible(b);
}
@Nonnull
public static ItemStack copyStackWithSize(@Nonnull ItemStack itemStack, int size)
{
if (size == 0)
return ItemStack.EMPTY;
ItemStack copy = itemStack.copy();
copy.setCount(size);
return copy;
}
/**
* Inserts the ItemStack into the inventory, filling up already present stacks first.
* This is equivalent to the behaviour of a player picking up an item.
* Note: This function stacks items without subtypes with different metadata together.
*/
@Nonnull
public static ItemStack insertItemStacked(IItemHandler inventory, @Nonnull ItemStack stack, boolean simulate)
{
if (inventory == null || stack.isEmpty())
return stack;
// not stackable -> just insert into a new slot
if (!stack.isStackable())
{
return insertItem(inventory, stack, simulate);
}
int sizeInventory = inventory.getSlots();
// go through the inventory and try to fill up already existing items
for (int i = 0; i < sizeInventory; i++)
{
ItemStack slot = inventory.getStackInSlot(i);
if (canItemStacksStackRelaxed(slot, stack))
{
stack = inventory.insertItem(i, stack, simulate);
if (stack.isEmpty())
{
break;
}
}
}
// insert remainder into empty slots
if (!stack.isEmpty())
{
// find empty slot
for (int i = 0; i < sizeInventory; i++)
{
if (inventory.getStackInSlot(i).isEmpty())
{
stack = inventory.insertItem(i, stack, simulate);
if (stack.isEmpty())
{
break;
}
}
}
}
return stack;
}
/** giveItemToPlayer without preferred slot */
public static void giveItemToPlayer(EntityPlayer player, @Nonnull ItemStack stack) {
giveItemToPlayer(player, stack, -1);
}
/**
* Inserts the given itemstack into the players inventory.
* If the inventory can't hold it, the item will be dropped in the world at the players position.
*
* @param player The player to give the item to
* @param stack The itemstack to insert
*/
public static void giveItemToPlayer(EntityPlayer player, @Nonnull ItemStack stack, int preferredSlot)
{
if (stack.isEmpty()) return;
IItemHandler inventory = new PlayerMainInvWrapper(player.inventory);
World world = player.world;
// try adding it into the inventory
ItemStack remainder = stack;
// insert into preferred slot first
if (preferredSlot >= 0 && preferredSlot < inventory.getSlots())
{
remainder = inventory.insertItem(preferredSlot, stack, false);
}
// then into the inventory in general
if (!remainder.isEmpty())
{
remainder = insertItemStacked(inventory, remainder, false);
}
// play sound if something got picked up
if (remainder.isEmpty() || remainder.getCount() != stack.getCount())
{
world.playSound(null, player.posX, player.posY + 0.5, player.posZ,
SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, 0.2F, ((world.rand.nextFloat() - world.rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
}
// drop remaining itemstack into the world
if (!remainder.isEmpty() && !world.isRemote)
{
EntityItem entityitem = new EntityItem(world, player.posX, player.posY + 0.5, player.posZ, remainder);
entityitem.setPickupDelay(40);
entityitem.motionX = 0;
entityitem.motionZ = 0;
world.spawnEntity(entityitem);
}
}
/**
* This method uses the standard vanilla algorithm to calculate a comparator output for how "full" the inventory is.
* This method is an adaptation of Container#calcRedstoneFromInventory(IInventory).
* @param inv The inventory handler to test.
* @return A redstone value in the range [0,15] representing how "full" this inventory is.
*/
public static int calcRedstoneFromInventory(@Nullable IItemHandler inv)
{
if (inv == null)
{
return 0;
}
else
{
int itemsFound = 0;
float proportion = 0.0F;
for (int j = 0; j < inv.getSlots(); ++j)
{
ItemStack itemstack = inv.getStackInSlot(j);
if (!itemstack.isEmpty())
{
proportion += (float)itemstack.getCount() / (float)Math.min(inv.getSlotLimit(j), itemstack.getMaxStackSize());
++itemsFound;
}
}
proportion = proportion / (float)inv.getSlots();
return MathHelper.floor(proportion * 14.0F) + (itemsFound > 0 ? 1 : 0);
}
}
}

View File

@@ -0,0 +1,226 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.NonNullList;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.INBTSerializable;
import javax.annotation.Nonnull;
public class ItemStackHandler implements IItemHandler, IItemHandlerModifiable, INBTSerializable<NBTTagCompound>
{
protected NonNullList<ItemStack> stacks;
public ItemStackHandler()
{
this(1);
}
public ItemStackHandler(int size)
{
stacks = NonNullList.withSize(size, ItemStack.EMPTY);
}
public ItemStackHandler(NonNullList<ItemStack> stacks)
{
this.stacks = stacks;
}
public void setSize(int size)
{
stacks = NonNullList.withSize(size, ItemStack.EMPTY);
}
@Override
public void setStackInSlot(int slot, @Nonnull ItemStack stack)
{
validateSlotIndex(slot);
this.stacks.set(slot, stack);
onContentsChanged(slot);
}
@Override
public int getSlots()
{
return stacks.size();
}
@Override
@Nonnull
public ItemStack getStackInSlot(int slot)
{
validateSlotIndex(slot);
return this.stacks.get(slot);
}
@Override
@Nonnull
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate)
{
if (stack.isEmpty())
return ItemStack.EMPTY;
validateSlotIndex(slot);
ItemStack existing = this.stacks.get(slot);
int limit = getStackLimit(slot, stack);
if (!existing.isEmpty())
{
if (!ItemHandlerHelper.canItemStacksStack(stack, existing))
return stack;
limit -= existing.getCount();
}
if (limit <= 0)
return stack;
boolean reachedLimit = stack.getCount() > limit;
if (!simulate)
{
if (existing.isEmpty())
{
this.stacks.set(slot, reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, limit) : stack);
}
else
{
existing.grow(reachedLimit ? limit : stack.getCount());
}
onContentsChanged(slot);
}
return reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, stack.getCount()- limit) : ItemStack.EMPTY;
}
@Override
@Nonnull
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
if (amount == 0)
return ItemStack.EMPTY;
validateSlotIndex(slot);
ItemStack existing = this.stacks.get(slot);
if (existing.isEmpty())
return ItemStack.EMPTY;
int toExtract = Math.min(amount, existing.getMaxStackSize());
if (existing.getCount() <= toExtract)
{
if (!simulate)
{
this.stacks.set(slot, ItemStack.EMPTY);
onContentsChanged(slot);
}
return existing;
}
else
{
if (!simulate)
{
this.stacks.set(slot, ItemHandlerHelper.copyStackWithSize(existing, existing.getCount() - toExtract));
onContentsChanged(slot);
}
return ItemHandlerHelper.copyStackWithSize(existing, toExtract);
}
}
@Override
public int getSlotLimit(int slot)
{
return 64;
}
protected int getStackLimit(int slot, @Nonnull ItemStack stack)
{
return Math.min(getSlotLimit(slot), stack.getMaxStackSize());
}
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
return true;
}
@Override
public NBTTagCompound serializeNBT()
{
NBTTagList nbtTagList = new NBTTagList();
for (int i = 0; i < stacks.size(); i++)
{
if (!stacks.get(i).isEmpty())
{
NBTTagCompound itemTag = new NBTTagCompound();
itemTag.setInteger("Slot", i);
stacks.get(i).writeToNBT(itemTag);
nbtTagList.appendTag(itemTag);
}
}
NBTTagCompound nbt = new NBTTagCompound();
nbt.setTag("Items", nbtTagList);
nbt.setInteger("Size", stacks.size());
return nbt;
}
@Override
public void deserializeNBT(NBTTagCompound nbt)
{
setSize(nbt.hasKey("Size", Constants.NBT.TAG_INT) ? nbt.getInteger("Size") : stacks.size());
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.size())
{
stacks.set(slot, new ItemStack(itemTags));
}
}
onLoad();
}
protected void validateSlotIndex(int slot)
{
if (slot < 0 || slot >= stacks.size())
throw new RuntimeException("Slot " + slot + " not in valid range - [0," + stacks.size() + ")");
}
protected void onLoad()
{
}
protected void onContentsChanged(int slot)
{
}
}

View File

@@ -0,0 +1,155 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
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;
import javax.annotation.Nonnull;
public class SlotItemHandler extends Slot
{
private static IInventory emptyInventory = new InventoryBasic("[Null]", true, 0);
private 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;
}
/**
* Check if the stack is allowed to be placed in this slot, used for armor slots as well as furnace fuel.
*/
@Override
public boolean isItemValid(@Nonnull ItemStack stack)
{
if (stack.isEmpty())
return false;
return itemHandler.isItemValid(index, stack);
}
/**
* Helper fnct to get the stack in the slot.
*/
@Override
@Nonnull
public ItemStack getStack()
{
return this.getItemHandler().getStackInSlot(index);
}
// Override if your IItemHandler does not implement IItemHandlerModifiable
/**
* Helper method to put a stack in the slot.
*/
@Override
public void putStack(@Nonnull ItemStack stack)
{
((IItemHandlerModifiable) this.getItemHandler()).setStackInSlot(index, stack);
this.onSlotChanged();
}
/**
* if par2 has more items than par1, onCrafting(item,countIncrease) is called
*/
@Override
public void onSlotChange(@Nonnull ItemStack p_75220_1_, @Nonnull ItemStack p_75220_2_)
{
}
/**
* Returns the maximum stack size for a given slot (usually the same as getInventoryStackLimit(), but 1 in the case
* of armor slots)
*/
@Override
public int getSlotStackLimit()
{
return this.itemHandler.getSlotLimit(this.index);
}
@Override
public int getItemStackLimit(@Nonnull ItemStack stack)
{
ItemStack maxAdd = stack.copy();
int maxInput = stack.getMaxStackSize();
maxAdd.setCount(maxInput);
IItemHandler handler = this.getItemHandler();
ItemStack currentStack = handler.getStackInSlot(index);
if (handler instanceof IItemHandlerModifiable) {
IItemHandlerModifiable handlerModifiable = (IItemHandlerModifiable) handler;
handlerModifiable.setStackInSlot(index, ItemStack.EMPTY);
ItemStack remainder = handlerModifiable.insertItem(index, maxAdd, true);
handlerModifiable.setStackInSlot(index, currentStack);
return maxInput - remainder.getCount();
}
else
{
ItemStack remainder = handler.insertItem(index, maxAdd, true);
int current = currentStack.getCount();
int added = maxInput - remainder.getCount();
return current + added;
}
}
/**
* Return whether this slot's stack can be taken from this slot.
*/
@Override
public boolean canTakeStack(EntityPlayer playerIn)
{
return !this.getItemHandler().extractItem(index, 1, true).isEmpty();
}
/**
* Decrease the size of the stack in slot (first int arg) by the amount of the second int arg. Returns the new
* stack.
*/
@Override
@Nonnull
public ItemStack decrStackSize(int amount)
{
return this.getItemHandler().extractItem(index, amount, false);
}
public IItemHandler getItemHandler()
{
return itemHandler;
}
@Override
public boolean isSameInventory(Slot other)
{
return other instanceof SlotItemHandler && ((SlotItemHandler) other).getItemHandler() == this.itemHandler;
}
}

View File

@@ -0,0 +1,236 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
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.math.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
import java.lang.ref.WeakReference;
import com.google.common.base.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class VanillaDoubleChestItemHandler extends WeakReference<TileEntityChest> implements IItemHandlerModifiable
{
// 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(@Nullable TileEntityChest mainChest, @Nullable TileEntityChest other, boolean mainChestIsUpper)
{
super(other);
this.mainChest = mainChest;
this.mainChestIsUpper = mainChestIsUpper;
hashCode = Objects.hashCode(mainChestIsUpper ? mainChest : other) * 31 + Objects.hashCode(!mainChestIsUpper ? mainChest : other);
}
@Nullable
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
}
@Nullable
public TileEntityChest getChest(boolean accessingUpper)
{
if (accessingUpper == mainChestIsUpper)
return mainChest;
else
{
return getOtherChest();
}
}
@Nullable
private TileEntityChest getOtherChest()
{
TileEntityChest tileEntityChest = get();
return tileEntityChest != null && !tileEntityChest.isInvalid() ? tileEntityChest : null;
}
@Override
public int getSlots()
{
return 27 * 2;
}
@Override
@Nonnull
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) : ItemStack.EMPTY;
}
@Override
public void setStackInSlot(int slot, @Nonnull ItemStack stack)
{
boolean accessingUpperChest = slot < 27;
int targetSlot = accessingUpperChest ? slot : slot - 27;
TileEntityChest chest = getChest(accessingUpperChest);
if (chest != null)
{
IItemHandler singleHandler = chest.getSingleChestHandler();
if (singleHandler instanceof IItemHandlerModifiable)
{
((IItemHandlerModifiable) singleHandler).setStackInSlot(targetSlot, stack);
}
}
chest = getChest(!accessingUpperChest);
if (chest != null)
chest.markDirty();
}
@Override
@Nonnull
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate)
{
boolean accessingUpperChest = slot < 27;
int targetSlot = accessingUpperChest ? slot : slot - 27;
TileEntityChest chest = getChest(accessingUpperChest);
if (chest == null)
return stack;
int starting = stack.getCount();
ItemStack ret = chest.getSingleChestHandler().insertItem(targetSlot, stack, simulate);
if (ret.getCount() != starting && !simulate)
{
chest = getChest(!accessingUpperChest);
if (chest != null)
chest.markDirty();
}
return ret;
}
@Override
@Nonnull
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
boolean accessingUpperChest = slot < 27;
int targetSlot = accessingUpperChest ? slot : slot - 27;
TileEntityChest chest = getChest(accessingUpperChest);
if (chest == null)
return ItemStack.EMPTY;
ItemStack ret = chest.getSingleChestHandler().extractItem(targetSlot, amount, simulate);
if (!ret.isEmpty() && !simulate)
{
chest = getChest(!accessingUpperChest);
if (chest != null)
chest.markDirty();
}
return ret;
}
@Override
public int getSlotLimit(int slot)
{
boolean accessingUpperChest = slot < 27;
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
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.equal(mainChest, that.mainChest) && Objects.equal(otherChest, that.getOtherChest());
else
return Objects.equal(mainChest, that.getOtherChest()) && Objects.equal(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,69 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntityHopper;
import net.minecraftforge.items.wrapper.InvWrapper;
import javax.annotation.Nonnull;
public class VanillaHopperItemHandler extends InvWrapper
{
private final TileEntityHopper hopper;
public VanillaHopperItemHandler(TileEntityHopper hopper)
{
super(hopper);
this.hopper = hopper;
}
@Override
@Nonnull
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate)
{
if (simulate)
{
return super.insertItem(slot, stack, simulate);
}
else
{
boolean wasEmpty = getInv().isEmpty();
int originalStackSize = stack.getCount();
stack = super.insertItem(slot, stack, simulate);
if (wasEmpty && originalStackSize > stack.getCount())
{
if (!hopper.mayTransfer())
{
// This cooldown is always set to 8 in vanilla with one exception:
// Hopper -> Hopper transfer sets this cooldown to 7 when this hopper
// has not been updated as recently as the one pushing items into it.
// This vanilla behavior is preserved by VanillaInventoryCodeHooks#insertStack,
// the cooldown is set properly by the hopper that is pushing items into this one.
hopper.setTransferCooldown(8);
}
}
return stack;
}
}
}

View File

@@ -0,0 +1,282 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items;
import net.minecraft.block.Block;
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.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class VanillaInventoryCodeHooks
{
/**
* Copied from TileEntityHopper#captureDroppedItems and added capability support
* @return Null if we did nothing {no IItemHandler}, True if we moved an item, False if we moved no items
*/
@Nullable
public static Boolean extractHook(IHopper dest)
{
Pair<IItemHandler, Object> itemHandlerResult = getItemHandler(dest, EnumFacing.UP);
if (itemHandlerResult == null)
return null;
IItemHandler handler = itemHandlerResult.getKey();
for (int i = 0; i < handler.getSlots(); i++)
{
ItemStack extractItem = handler.extractItem(i, 1, true);
if (!extractItem.isEmpty())
{
for (int j = 0; j < dest.getSizeInventory(); j++)
{
ItemStack destStack = dest.getStackInSlot(j);
if (dest.isItemValidForSlot(j, extractItem) && (destStack.isEmpty() || destStack.getCount() < destStack.getMaxStackSize() && destStack.getCount() < dest.getInventoryStackLimit() && ItemHandlerHelper.canItemStacksStack(extractItem, destStack)))
{
extractItem = handler.extractItem(i, 1, false);
if (destStack.isEmpty())
dest.setInventorySlotContents(j, extractItem);
else
{
destStack.grow(1);
dest.setInventorySlotContents(j, destStack);
}
dest.markDirty();
return true;
}
}
}
}
return false;
}
/**
* Copied from BlockDropper#dispense and added capability support
*/
public static boolean dropperInsertHook(World world, BlockPos pos, TileEntityDispenser dropper, int slot, @Nonnull ItemStack stack)
{
EnumFacing enumfacing = world.getBlockState(pos).getValue(BlockDropper.FACING);
BlockPos blockpos = pos.offset(enumfacing);
Pair<IItemHandler, Object> destinationResult = getItemHandler(world, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), enumfacing.getOpposite());
if (destinationResult == null)
{
return true;
}
else
{
IItemHandler itemHandler = destinationResult.getKey();
Object destination = destinationResult.getValue();
ItemStack dispensedStack = stack.copy().splitStack(1);
ItemStack remainder = putStackInInventoryAllSlots(dropper, destination, itemHandler, dispensedStack);
if (remainder.isEmpty())
{
remainder = stack.copy();
remainder.shrink(1);
}
else
{
remainder = stack.copy();
}
dropper.setInventorySlotContents(slot, remainder);
return false;
}
}
/**
* Copied from TileEntityHopper#transferItemsOut and added capability support
*/
public static boolean insertHook(TileEntityHopper hopper)
{
EnumFacing hopperFacing = BlockHopper.getFacing(hopper.getBlockMetadata());
Pair<IItemHandler, Object> destinationResult = getItemHandler(hopper, hopperFacing);
if (destinationResult == null)
{
return false;
}
else
{
IItemHandler itemHandler = destinationResult.getKey();
Object destination = destinationResult.getValue();
if (isFull(itemHandler))
{
return false;
}
else
{
for (int i = 0; i < hopper.getSizeInventory(); ++i)
{
if (!hopper.getStackInSlot(i).isEmpty())
{
ItemStack originalSlotContents = hopper.getStackInSlot(i).copy();
ItemStack insertStack = hopper.decrStackSize(i, 1);
ItemStack remainder = putStackInInventoryAllSlots(hopper, destination, itemHandler, insertStack);
if (remainder.isEmpty())
{
return true;
}
hopper.setInventorySlotContents(i, originalSlotContents);
}
}
return false;
}
}
}
private static ItemStack putStackInInventoryAllSlots(TileEntity source, Object destination, IItemHandler destInventory, ItemStack stack)
{
for (int slot = 0; slot < destInventory.getSlots() && !stack.isEmpty(); slot++)
{
stack = insertStack(source, destination, destInventory, stack, slot);
}
return stack;
}
/**
* Copied from TileEntityHopper#insertStack and added capability support
*/
private static ItemStack insertStack(TileEntity source, Object destination, IItemHandler destInventory, ItemStack stack, int slot)
{
ItemStack itemstack = destInventory.getStackInSlot(slot);
if (destInventory.insertItem(slot, stack, true).isEmpty())
{
boolean insertedItem = false;
boolean inventoryWasEmpty = isEmpty(destInventory);
if (itemstack.isEmpty())
{
destInventory.insertItem(slot, stack, false);
stack = ItemStack.EMPTY;
insertedItem = true;
}
else if (ItemHandlerHelper.canItemStacksStack(itemstack, stack))
{
int originalSize = stack.getCount();
stack = destInventory.insertItem(slot, stack, false);
insertedItem = originalSize < stack.getCount();
}
if (insertedItem)
{
if (inventoryWasEmpty && destination instanceof TileEntityHopper)
{
TileEntityHopper destinationHopper = (TileEntityHopper)destination;
if (!destinationHopper.mayTransfer())
{
int k = 0;
if (source instanceof TileEntityHopper)
{
if (destinationHopper.getLastUpdateTime() >= ((TileEntityHopper) source).getLastUpdateTime())
{
k = 1;
}
}
destinationHopper.setTransferCooldown(8 - k);
}
}
}
}
return stack;
}
@Nullable
private static Pair<IItemHandler, Object> getItemHandler(IHopper hopper, EnumFacing hopperFacing)
{
double x = hopper.getXPos() + (double) hopperFacing.getFrontOffsetX();
double y = hopper.getYPos() + (double) hopperFacing.getFrontOffsetY();
double z = hopper.getZPos() + (double) hopperFacing.getFrontOffsetZ();
return getItemHandler(hopper.getWorld(), x, y, z, hopperFacing.getOpposite());
}
private static boolean isFull(IItemHandler itemHandler)
{
for (int slot = 0; slot < itemHandler.getSlots(); slot++)
{
ItemStack stackInSlot = itemHandler.getStackInSlot(slot);
if (stackInSlot.isEmpty() || stackInSlot.getCount() != stackInSlot.getMaxStackSize())
{
return false;
}
}
return true;
}
private static boolean isEmpty(IItemHandler itemHandler)
{
for (int slot = 0; slot < itemHandler.getSlots(); slot++)
{
ItemStack stackInSlot = itemHandler.getStackInSlot(slot);
if (stackInSlot.getCount() > 0)
{
return false;
}
}
return true;
}
@Nullable
public static Pair<IItemHandler, Object> getItemHandler(World worldIn, double x, double y, double z, final EnumFacing side)
{
Pair<IItemHandler, Object> destination = null;
int i = MathHelper.floor(x);
int j = MathHelper.floor(y);
int k = MathHelper.floor(z);
BlockPos blockpos = new BlockPos(i, j, k);
net.minecraft.block.state.IBlockState state = worldIn.getBlockState(blockpos);
Block block = state.getBlock();
if (block.hasTileEntity(state))
{
TileEntity tileentity = worldIn.getTileEntity(blockpos);
if (tileentity != null)
{
if (tileentity.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side))
{
IItemHandler capability = tileentity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side);
destination = ImmutablePair.<IItemHandler, Object>of(capability, tileentity);
}
}
}
return destination;
}
}

View File

@@ -0,0 +1,144 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items.wrapper;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandlerModifiable;
import javax.annotation.Nonnull;
// combines multiple IItemHandlerModifiable into one interface
public class CombinedInvWrapper implements IItemHandlerModifiable
{
protected final IItemHandlerModifiable[] itemHandler; // the handlers
protected final int[] baseIndex; // index-offsets of the different handlers
protected final int slotCount; // number of total slots
public CombinedInvWrapper(IItemHandlerModifiable... itemHandler)
{
this.itemHandler = itemHandler;
this.baseIndex = new int[itemHandler.length];
int index = 0;
for (int i = 0; i < itemHandler.length; i++)
{
index += itemHandler[i].getSlots();
baseIndex[i] = index;
}
this.slotCount = index;
}
// returns the handler index for the slot
protected int getIndexForSlot(int slot)
{
if (slot < 0)
return -1;
for (int i = 0; i < baseIndex.length; i++)
{
if (slot - baseIndex[i] < 0)
{
return i;
}
}
return -1;
}
protected IItemHandlerModifiable getHandlerFromIndex(int index)
{
if (index < 0 || index >= itemHandler.length)
{
return (IItemHandlerModifiable)EmptyHandler.INSTANCE;
}
return itemHandler[index];
}
protected int getSlotFromIndex(int slot, int index)
{
if (index <= 0 || index >= baseIndex.length)
{
return slot;
}
return slot - baseIndex[index - 1];
}
@Override
public void setStackInSlot(int slot, @Nonnull ItemStack stack)
{
int index = getIndexForSlot(slot);
IItemHandlerModifiable handler = getHandlerFromIndex(index);
slot = getSlotFromIndex(slot, index);
handler.setStackInSlot(slot, stack);
}
@Override
public int getSlots()
{
return slotCount;
}
@Override
@Nonnull
public ItemStack getStackInSlot(int slot)
{
int index = getIndexForSlot(slot);
IItemHandlerModifiable handler = getHandlerFromIndex(index);
slot = getSlotFromIndex(slot, index);
return handler.getStackInSlot(slot);
}
@Override
@Nonnull
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate)
{
int index = getIndexForSlot(slot);
IItemHandlerModifiable handler = getHandlerFromIndex(index);
slot = getSlotFromIndex(slot, index);
return handler.insertItem(slot, stack, simulate);
}
@Override
@Nonnull
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
int index = getIndexForSlot(slot);
IItemHandlerModifiable handler = getHandlerFromIndex(index);
slot = getSlotFromIndex(slot, index);
return handler.extractItem(slot, amount, simulate);
}
@Override
public int getSlotLimit(int slot)
{
int index = getIndexForSlot(slot);
IItemHandlerModifiable handler = getHandlerFromIndex(index);
int localSlot = getSlotFromIndex(slot, index);
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

@@ -0,0 +1,76 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items.wrapper;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import javax.annotation.Nonnull;
public class EmptyHandler implements IItemHandlerModifiable
{
public static final IItemHandler INSTANCE = new EmptyHandler();
@Override
public int getSlots()
{
return 0;
}
@Override
@Nonnull
public ItemStack getStackInSlot(int slot)
{
return ItemStack.EMPTY;
}
@Override
@Nonnull
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate)
{
return stack;
}
@Override
@Nonnull
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
return ItemStack.EMPTY;
}
@Override
public void setStackInSlot(int slot, @Nonnull ItemStack stack)
{
// nothing to do here
}
@Override
public int getSlotLimit(int slot)
{
return 0;
}
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
return false;
}
}

View File

@@ -0,0 +1,36 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items.wrapper;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraftforge.items.IItemHandler;
/**
* Exposes the armor inventory of an {@link EntityLivingBase} as an {@link IItemHandler} using {@link EntityLivingBase#getItemStackFromSlot} and
* {@link EntityLivingBase#setItemStackToSlot}.
*/
public class EntityArmorInvWrapper extends EntityEquipmentInvWrapper
{
public EntityArmorInvWrapper(final EntityLivingBase entity)
{
super(entity, EntityEquipmentSlot.Type.ARMOR);
}
}

View File

@@ -0,0 +1,195 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items.wrapper;
import com.google.common.collect.ImmutableList;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
/**
* Exposes the armor or hands inventory of an {@link EntityLivingBase} as an {@link IItemHandler} using {@link EntityLivingBase#getItemStackFromSlot} and
* {@link EntityLivingBase#setItemStackToSlot}.
*/
public abstract class EntityEquipmentInvWrapper implements IItemHandlerModifiable
{
/**
* The entity.
*/
protected final EntityLivingBase entity;
/**
* The slots exposed by this wrapper, with {@link EntityEquipmentSlot#index} as the index.
*/
protected final List<EntityEquipmentSlot> slots;
/**
* @param entity The entity.
* @param slotType The slot type to expose.
*/
public EntityEquipmentInvWrapper(final EntityLivingBase entity, final EntityEquipmentSlot.Type slotType)
{
this.entity = entity;
final List<EntityEquipmentSlot> slots = new ArrayList<EntityEquipmentSlot>();
for (final EntityEquipmentSlot slot : EntityEquipmentSlot.values())
{
if (slot.getSlotType() == slotType)
{
slots.add(slot);
}
}
this.slots = ImmutableList.copyOf(slots);
}
@Override
public int getSlots()
{
return slots.size();
}
@Nonnull
@Override
public ItemStack getStackInSlot(final int slot)
{
return entity.getItemStackFromSlot(validateSlotIndex(slot));
}
@Nonnull
@Override
public ItemStack insertItem(final int slot, @Nonnull final ItemStack stack, final boolean simulate)
{
if (stack.isEmpty())
return ItemStack.EMPTY;
final EntityEquipmentSlot equipmentSlot = validateSlotIndex(slot);
final ItemStack existing = entity.getItemStackFromSlot(equipmentSlot);
int limit = getStackLimit(slot, stack);
if (!existing.isEmpty())
{
if (!ItemHandlerHelper.canItemStacksStack(stack, existing))
return stack;
limit -= existing.getCount();
}
if (limit <= 0)
return stack;
boolean reachedLimit = stack.getCount() > limit;
if (!simulate)
{
if (existing.isEmpty())
{
entity.setItemStackToSlot(equipmentSlot, reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, limit) : stack);
}
else
{
existing.grow(reachedLimit ? limit : stack.getCount());
}
}
return reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, stack.getCount() - limit) : ItemStack.EMPTY;
}
@Nonnull
@Override
public ItemStack extractItem(final int slot, final int amount, final boolean simulate)
{
if (amount == 0)
return ItemStack.EMPTY;
final EntityEquipmentSlot equipmentSlot = validateSlotIndex(slot);
final ItemStack existing = entity.getItemStackFromSlot(equipmentSlot);
if (existing.isEmpty())
return ItemStack.EMPTY;
final int toExtract = Math.min(amount, existing.getMaxStackSize());
if (existing.getCount() <= toExtract)
{
if (!simulate)
{
entity.setItemStackToSlot(equipmentSlot, ItemStack.EMPTY);
}
return existing;
}
else
{
if (!simulate)
{
entity.setItemStackToSlot(equipmentSlot, ItemHandlerHelper.copyStackWithSize(existing, existing.getCount() - toExtract));
}
return ItemHandlerHelper.copyStackWithSize(existing, toExtract);
}
}
@Override
public int getSlotLimit(final int slot)
{
final EntityEquipmentSlot equipmentSlot = validateSlotIndex(slot);
return equipmentSlot.getSlotType() == EntityEquipmentSlot.Type.ARMOR ? 1 : 64;
}
protected int getStackLimit(final int slot, @Nonnull final ItemStack stack)
{
return Math.min(getSlotLimit(slot), stack.getMaxStackSize());
}
@Override
public void setStackInSlot(final int slot, @Nonnull final ItemStack stack)
{
final EntityEquipmentSlot equipmentSlot = validateSlotIndex(slot);
if (ItemStack.areItemStacksEqual(entity.getItemStackFromSlot(equipmentSlot), stack))
return;
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)
{
if (slot < 0 || slot >= slots.size())
throw new IllegalArgumentException("Slot " + slot + " not in valid range - [0," + slots.size() + ")");
return slots.get(slot);
}
}

View File

@@ -0,0 +1,36 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items.wrapper;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraftforge.items.IItemHandler;
/**
* Exposes the hands inventory of an {@link EntityLivingBase} as an {@link IItemHandler} using {@link EntityLivingBase#getItemStackFromSlot} and
* {@link EntityLivingBase#setItemStackToSlot}.
*/
public class EntityHandsInvWrapper extends EntityEquipmentInvWrapper
{
public EntityHandsInvWrapper(EntityLivingBase entity)
{
super(entity, EntityEquipmentSlot.Type.HAND);
}
}

View File

@@ -0,0 +1,217 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
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;
import javax.annotation.Nonnull;
public class InvWrapper implements IItemHandlerModifiable
{
private 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 getInv().equals(that.getInv());
}
@Override
public int hashCode()
{
return getInv().hashCode();
}
@Override
public int getSlots()
{
return getInv().getSizeInventory();
}
@Override
@Nonnull
public ItemStack getStackInSlot(int slot)
{
return getInv().getStackInSlot(slot);
}
@Override
@Nonnull
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate)
{
if (stack.isEmpty())
return ItemStack.EMPTY;
ItemStack stackInSlot = getInv().getStackInSlot(slot);
int m;
if (!stackInSlot.isEmpty())
{
if (stackInSlot.getCount() >= Math.min(stackInSlot.getMaxStackSize(), getSlotLimit(slot)))
return stack;
if (!ItemHandlerHelper.canItemStacksStack(stack, stackInSlot))
return stack;
if (!getInv().isItemValidForSlot(slot, stack))
return stack;
m = Math.min(stack.getMaxStackSize(), getSlotLimit(slot)) - stackInSlot.getCount();
if (stack.getCount() <= m)
{
if (!simulate)
{
ItemStack copy = stack.copy();
copy.grow(stackInSlot.getCount());
getInv().setInventorySlotContents(slot, copy);
getInv().markDirty();
}
return ItemStack.EMPTY;
}
else
{
// copy the stack to not modify the original one
stack = stack.copy();
if (!simulate)
{
ItemStack copy = stack.splitStack(m);
copy.grow(stackInSlot.getCount());
getInv().setInventorySlotContents(slot, copy);
getInv().markDirty();
return stack;
}
else
{
stack.shrink(m);
return stack;
}
}
}
else
{
if (!getInv().isItemValidForSlot(slot, stack))
return stack;
m = Math.min(stack.getMaxStackSize(), getSlotLimit(slot));
if (m < stack.getCount())
{
// copy the stack to not modify the original one
stack = stack.copy();
if (!simulate)
{
getInv().setInventorySlotContents(slot, stack.splitStack(m));
getInv().markDirty();
return stack;
}
else
{
stack.shrink(m);
return stack;
}
}
else
{
if (!simulate)
{
getInv().setInventorySlotContents(slot, stack);
getInv().markDirty();
}
return ItemStack.EMPTY;
}
}
}
@Override
@Nonnull
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
if (amount == 0)
return ItemStack.EMPTY;
ItemStack stackInSlot = getInv().getStackInSlot(slot);
if (stackInSlot.isEmpty())
return ItemStack.EMPTY;
if (simulate)
{
if (stackInSlot.getCount() < amount)
{
return stackInSlot.copy();
}
else
{
ItemStack copy = stackInSlot.copy();
copy.setCount(amount);
return copy;
}
}
else
{
int m = Math.min(stackInSlot.getCount(), amount);
ItemStack decrStackSize = getInv().decrStackSize(slot, m);
getInv().markDirty();
return decrStackSize;
}
}
@Override
public void setStackInSlot(int slot, @Nonnull ItemStack stack)
{
getInv().setInventorySlotContents(slot, stack);
}
@Override
public int getSlotLimit(int slot)
{
return getInv().getInventoryStackLimit();
}
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
return getInv().isItemValidForSlot(slot, stack);
}
public IInventory getInv()
{
return inv;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items.wrapper;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull;
public class PlayerArmorInvWrapper extends RangedWrapper
{
private final InventoryPlayer inventoryPlayer;
public PlayerArmorInvWrapper(InventoryPlayer inv)
{
super(new InvWrapper(inv), inv.mainInventory.size(), inv.mainInventory.size() + inv.armorInventory.size());
inventoryPlayer = inv;
}
@Override
@Nonnull
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate)
{
EntityEquipmentSlot equ = null;
for (EntityEquipmentSlot s : EntityEquipmentSlot.values())
{
if (s.getSlotType() == EntityEquipmentSlot.Type.ARMOR && s.getIndex() == slot)
{
equ = s;
break;
}
}
// check if it's valid for the armor slot
if (equ != null && slot < 4 && !stack.isEmpty() && stack.getItem().isValidArmor(stack, equ, getInventoryPlayer().player))
{
return super.insertItem(slot, stack, simulate);
}
return stack;
}
public InventoryPlayer getInventoryPlayer()
{
return inventoryPlayer;
}
}

View File

@@ -0,0 +1,30 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items.wrapper;
import net.minecraft.entity.player.InventoryPlayer;
public class PlayerInvWrapper extends CombinedInvWrapper
{
public PlayerInvWrapper(InventoryPlayer inv)
{
super(new PlayerMainInvWrapper(inv), new PlayerArmorInvWrapper(inv), new PlayerOffhandInvWrapper(inv));
}
}

View File

@@ -0,0 +1,69 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items.wrapper;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull;
/**
* Exposes the player inventory WITHOUT the armor inventory as IItemHandler.
* Also takes core of inserting/extracting having the same logic as picking up items.
*/
public class PlayerMainInvWrapper extends RangedWrapper
{
private final InventoryPlayer inventoryPlayer;
public PlayerMainInvWrapper(InventoryPlayer inv)
{
super(new InvWrapper(inv), 0, inv.mainInventory.size());
inventoryPlayer = inv;
}
@Override
@Nonnull
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate)
{
ItemStack rest = super.insertItem(slot, stack, simulate);
if (rest.getCount()!= stack.getCount())
{
// the stack in the slot changed, animate it
ItemStack inSlot = getStackInSlot(slot);
if(!inSlot.isEmpty())
{
if (getInventoryPlayer().player.world.isRemote)
{
inSlot.setAnimationsToGo(5);
}
else if(getInventoryPlayer().player instanceof EntityPlayerMP) {
getInventoryPlayer().player.openContainer.detectAndSendChanges();
}
}
}
return rest;
}
public InventoryPlayer getInventoryPlayer()
{
return inventoryPlayer;
}
}

View File

@@ -0,0 +1,31 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items.wrapper;
import net.minecraft.entity.player.InventoryPlayer;
public class PlayerOffhandInvWrapper extends RangedWrapper
{
public PlayerOffhandInvWrapper(InventoryPlayer inv)
{
super(new InvWrapper(inv), inv.mainInventory.size() + inv.armorInventory.size(),
inv.mainInventory.size() + inv.armorInventory.size() + inv.offHandInventory.size());
}
}

View File

@@ -0,0 +1,124 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.items.wrapper;
import com.google.common.base.Preconditions;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandlerModifiable;
import javax.annotation.Nonnull;
/**
* A wrapper that composes another IItemHandlerModifiable, exposing only a range of the composed slots.
* Shifting of slot indices is handled automatically for you.
*/
public class RangedWrapper implements IItemHandlerModifiable {
private final IItemHandlerModifiable compose;
private final int minSlot;
private final int maxSlot;
public RangedWrapper(IItemHandlerModifiable compose, int minSlot, int maxSlotExclusive)
{
Preconditions.checkArgument(maxSlotExclusive > minSlot, "Max slot must be greater than min slot");
this.compose = compose;
this.minSlot = minSlot;
this.maxSlot = maxSlotExclusive;
}
@Override
public int getSlots()
{
return maxSlot - minSlot;
}
@Override
@Nonnull
public ItemStack getStackInSlot(int slot)
{
if (checkSlot(slot))
{
return compose.getStackInSlot(slot + minSlot);
}
return ItemStack.EMPTY;
}
@Override
@Nonnull
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate)
{
if (checkSlot(slot))
{
return compose.insertItem(slot + minSlot, stack, simulate);
}
return stack;
}
@Override
@Nonnull
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
if (checkSlot(slot))
{
return compose.extractItem(slot + minSlot, amount, simulate);
}
return ItemStack.EMPTY;
}
@Override
public void setStackInSlot(int slot, @Nonnull ItemStack stack)
{
if (checkSlot(slot))
{
compose.setStackInSlot(slot + minSlot, stack);
}
}
@Override
public int getSlotLimit(int slot)
{
if (checkSlot(slot))
{
return compose.getSlotLimit(slot + minSlot);
}
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)
{
return localSlot + minSlot < maxSlot;
}
}

View File

@@ -0,0 +1,239 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2018.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
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;
import javax.annotation.Nonnull;
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
@Nonnull
public ItemStack getStackInSlot(int slot)
{
int i = getSlot(inv, slot, side);
return i == -1 ? ItemStack.EMPTY : inv.getStackInSlot(i);
}
@Override
@Nonnull
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate)
{
if (stack.isEmpty())
return ItemStack.EMPTY;
int slot1 = getSlot(inv, slot, side);
if (slot1 == -1)
return stack;
ItemStack stackInSlot = inv.getStackInSlot(slot1);
int m;
if (!stackInSlot.isEmpty())
{
if (stackInSlot.getCount() >= Math.min(stackInSlot.getMaxStackSize(), getSlotLimit(slot)))
return stack;
if (!ItemHandlerHelper.canItemStacksStack(stack, stackInSlot))
return stack;
if (!inv.canInsertItem(slot1, stack, side) || !inv.isItemValidForSlot(slot1, stack))
return stack;
m = Math.min(stack.getMaxStackSize(), getSlotLimit(slot)) - stackInSlot.getCount();
if (stack.getCount() <= m)
{
if (!simulate)
{
ItemStack copy = stack.copy();
copy.grow(stackInSlot.getCount());
setInventorySlotContents(slot1, copy);
}
return ItemStack.EMPTY;
}
else
{
// copy the stack to not modify the original one
stack = stack.copy();
if (!simulate)
{
ItemStack copy = stack.splitStack(m);
copy.grow(stackInSlot.getCount());
setInventorySlotContents(slot1, copy);
return stack;
}
else
{
stack.shrink(m);
return stack;
}
}
}
else
{
if (!inv.canInsertItem(slot1, stack, side) || !inv.isItemValidForSlot(slot1, stack))
return stack;
m = Math.min(stack.getMaxStackSize(), getSlotLimit(slot));
if (m < stack.getCount())
{
// copy the stack to not modify the original one
stack = stack.copy();
if (!simulate)
{
setInventorySlotContents(slot1, stack.splitStack(m));
return stack;
}
else
{
stack.shrink(m);
return stack;
}
}
else
{
if (!simulate)
setInventorySlotContents(slot1, stack);
return ItemStack.EMPTY;
}
}
}
@Override
public void setStackInSlot(int slot, @Nonnull ItemStack stack)
{
int slot1 = getSlot(inv, slot, side);
if (slot1 != -1)
setInventorySlotContents(slot1, stack);
}
private void setInventorySlotContents(int slot, ItemStack stack) {
inv.markDirty(); //Notify vanilla of updates, We change the handler to be responsible for this instead of the caller. So mimic vanilla behavior
inv.setInventorySlotContents(slot, stack);
}
@Override
@Nonnull
public ItemStack extractItem(int slot, int amount, boolean simulate)
{
if (amount == 0)
return ItemStack.EMPTY;
int slot1 = getSlot(inv, slot, side);
if (slot1 == -1)
return ItemStack.EMPTY;
ItemStack stackInSlot = inv.getStackInSlot(slot1);
if (stackInSlot.isEmpty())
return ItemStack.EMPTY;
if (!inv.canExtractItem(slot1, stackInSlot, side))
return ItemStack.EMPTY;
if (simulate)
{
if (stackInSlot.getCount() < amount)
{
return stackInSlot.copy();
}
else
{
ItemStack copy = stackInSlot.copy();
copy.setCount(amount);
return copy;
}
}
else
{
int m = Math.min(stackInSlot.getCount(), amount);
ItemStack ret = inv.decrStackSize(slot1, m);
inv.markDirty();
return ret;
}
}
@Override
public int getSlotLimit(int slot)
{
return inv.getInventoryStackLimit();
}
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack)
{
return inv.isItemValidForSlot(slot, stack);
}
}