ForgePatch/src/main/java/net/minecraftforge/items/VanillaInventoryCodeHooks.java

282 lines
10 KiB
Java

/*
* Minecraft Forge
* Copyright (c) 2016.
*
* 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
*/
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;
}
}