base mod created
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user