Files
Mohammad-Ali Minaie b86dedad2f base mod created
2018-10-08 09:07:47 -04:00

695 lines
21 KiB
Java

package net.minecraft.tileentity;
import java.util.List;
import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockChest;
import net.minecraft.block.BlockHopper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.ContainerHopper;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EntitySelectors;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraft.util.NonNullList;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.datafix.FixTypes;
import net.minecraft.util.datafix.walkers.ItemStackDataLists;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
public class TileEntityHopper extends TileEntityLockableLoot implements IHopper, ITickable
{
private NonNullList<ItemStack> inventory = NonNullList.<ItemStack>withSize(5, ItemStack.EMPTY);
private int transferCooldown = -1;
private long tickedGameTime;
public static void registerFixesHopper(DataFixer fixer)
{
fixer.registerWalker(FixTypes.BLOCK_ENTITY, new ItemStackDataLists(TileEntityHopper.class, new String[] {"Items"}));
}
public void readFromNBT(NBTTagCompound compound)
{
super.readFromNBT(compound);
this.inventory = NonNullList.<ItemStack>withSize(this.getSizeInventory(), ItemStack.EMPTY);
if (!this.checkLootAndRead(compound))
{
ItemStackHelper.loadAllItems(compound, this.inventory);
}
if (compound.hasKey("CustomName", 8))
{
this.customName = compound.getString("CustomName");
}
this.transferCooldown = compound.getInteger("TransferCooldown");
}
public NBTTagCompound writeToNBT(NBTTagCompound compound)
{
super.writeToNBT(compound);
if (!this.checkLootAndWrite(compound))
{
ItemStackHelper.saveAllItems(compound, this.inventory);
}
compound.setInteger("TransferCooldown", this.transferCooldown);
if (this.hasCustomName())
{
compound.setString("CustomName", this.customName);
}
return compound;
}
/**
* Returns the number of slots in the inventory.
*/
public int getSizeInventory()
{
return this.inventory.size();
}
/**
* Removes up to a specified number of items from an inventory slot and returns them in a new stack.
*/
public ItemStack decrStackSize(int index, int count)
{
this.fillWithLoot((EntityPlayer)null);
ItemStack itemstack = ItemStackHelper.getAndSplit(this.getItems(), index, count);
return itemstack;
}
/**
* Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
*/
public void setInventorySlotContents(int index, ItemStack stack)
{
this.fillWithLoot((EntityPlayer)null);
this.getItems().set(index, stack);
if (stack.getCount() > this.getInventoryStackLimit())
{
stack.setCount(this.getInventoryStackLimit());
}
}
/**
* Get the name of this object. For players this returns their username
*/
public String getName()
{
return this.hasCustomName() ? this.customName : "container.hopper";
}
/**
* Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended.
*/
public int getInventoryStackLimit()
{
return 64;
}
/**
* Like the old updateEntity(), except more generic.
*/
public void update()
{
if (this.world != null && !this.world.isRemote)
{
--this.transferCooldown;
this.tickedGameTime = this.world.getTotalWorldTime();
if (!this.isOnTransferCooldown())
{
this.setTransferCooldown(0);
this.updateHopper();
}
}
}
protected boolean updateHopper()
{
if (this.world != null && !this.world.isRemote)
{
if (!this.isOnTransferCooldown() && BlockHopper.isEnabled(this.getBlockMetadata()))
{
boolean flag = false;
if (!this.isInventoryEmpty())
{
flag = this.transferItemsOut();
}
if (!this.isFull())
{
flag = pullItems(this) || flag;
}
if (flag)
{
this.setTransferCooldown(8);
this.markDirty();
return true;
}
}
return false;
}
else
{
return false;
}
}
private boolean isInventoryEmpty()
{
for (ItemStack itemstack : this.inventory)
{
if (!itemstack.isEmpty())
{
return false;
}
}
return true;
}
public boolean isEmpty()
{
return this.isInventoryEmpty();
}
private boolean isFull()
{
for (ItemStack itemstack : this.inventory)
{
if (itemstack.isEmpty() || itemstack.getCount() != itemstack.getMaxStackSize())
{
return false;
}
}
return true;
}
private boolean transferItemsOut()
{
if (net.minecraftforge.items.VanillaInventoryCodeHooks.insertHook(this)) { return true; }
IInventory iinventory = this.getInventoryForHopperTransfer();
if (iinventory == null)
{
return false;
}
else
{
EnumFacing enumfacing = BlockHopper.getFacing(this.getBlockMetadata()).getOpposite();
if (this.isInventoryFull(iinventory, enumfacing))
{
return false;
}
else
{
for (int i = 0; i < this.getSizeInventory(); ++i)
{
if (!this.getStackInSlot(i).isEmpty())
{
ItemStack itemstack = this.getStackInSlot(i).copy();
ItemStack itemstack1 = putStackInInventoryAllSlots(this, iinventory, this.decrStackSize(i, 1), enumfacing);
if (itemstack1.isEmpty())
{
iinventory.markDirty();
return true;
}
this.setInventorySlotContents(i, itemstack);
}
}
return false;
}
}
}
/**
* Returns false if the inventory has any room to place items in
*/
private boolean isInventoryFull(IInventory inventoryIn, EnumFacing side)
{
if (inventoryIn instanceof ISidedInventory)
{
ISidedInventory isidedinventory = (ISidedInventory)inventoryIn;
int[] aint = isidedinventory.getSlotsForFace(side);
for (int k : aint)
{
ItemStack itemstack1 = isidedinventory.getStackInSlot(k);
if (itemstack1.isEmpty() || itemstack1.getCount() != itemstack1.getMaxStackSize())
{
return false;
}
}
}
else
{
int i = inventoryIn.getSizeInventory();
for (int j = 0; j < i; ++j)
{
ItemStack itemstack = inventoryIn.getStackInSlot(j);
if (itemstack.isEmpty() || itemstack.getCount() != itemstack.getMaxStackSize())
{
return false;
}
}
}
return true;
}
/**
* Returns false if the specified IInventory contains any items
*/
private static boolean isInventoryEmpty(IInventory inventoryIn, EnumFacing side)
{
if (inventoryIn instanceof ISidedInventory)
{
ISidedInventory isidedinventory = (ISidedInventory)inventoryIn;
int[] aint = isidedinventory.getSlotsForFace(side);
for (int i : aint)
{
if (!isidedinventory.getStackInSlot(i).isEmpty())
{
return false;
}
}
}
else
{
int j = inventoryIn.getSizeInventory();
for (int k = 0; k < j; ++k)
{
if (!inventoryIn.getStackInSlot(k).isEmpty())
{
return false;
}
}
}
return true;
}
/**
* Pull dropped {@link net.minecraft.entity.item.EntityItem EntityItem}s from the world above the hopper and items
* from any inventory attached to this hopper into the hopper's inventory.
*
* @param hopper the hopper in question
* @return whether any items were successfully added to the hopper
*/
public static boolean pullItems(IHopper hopper)
{
Boolean ret = net.minecraftforge.items.VanillaInventoryCodeHooks.extractHook(hopper);
if (ret != null) return ret;
IInventory iinventory = getSourceInventory(hopper);
if (iinventory != null)
{
EnumFacing enumfacing = EnumFacing.DOWN;
if (isInventoryEmpty(iinventory, enumfacing))
{
return false;
}
if (iinventory instanceof ISidedInventory)
{
ISidedInventory isidedinventory = (ISidedInventory)iinventory;
int[] aint = isidedinventory.getSlotsForFace(enumfacing);
for (int i : aint)
{
if (pullItemFromSlot(hopper, iinventory, i, enumfacing))
{
return true;
}
}
}
else
{
int j = iinventory.getSizeInventory();
for (int k = 0; k < j; ++k)
{
if (pullItemFromSlot(hopper, iinventory, k, enumfacing))
{
return true;
}
}
}
}
else
{
for (EntityItem entityitem : getCaptureItems(hopper.getWorld(), hopper.getXPos(), hopper.getYPos(), hopper.getZPos()))
{
if (putDropInInventoryAllSlots((IInventory)null, hopper, entityitem))
{
return true;
}
}
}
return false;
}
/**
* Pulls from the specified slot in the inventory and places in any available slot in the hopper. Returns true if
* the entire stack was moved
*/
private static boolean pullItemFromSlot(IHopper hopper, IInventory inventoryIn, int index, EnumFacing direction)
{
ItemStack itemstack = inventoryIn.getStackInSlot(index);
if (!itemstack.isEmpty() && canExtractItemFromSlot(inventoryIn, itemstack, index, direction))
{
ItemStack itemstack1 = itemstack.copy();
ItemStack itemstack2 = putStackInInventoryAllSlots(inventoryIn, hopper, inventoryIn.decrStackSize(index, 1), (EnumFacing)null);
if (itemstack2.isEmpty())
{
inventoryIn.markDirty();
return true;
}
inventoryIn.setInventorySlotContents(index, itemstack1);
}
return false;
}
/**
* Attempts to place the passed EntityItem's stack into the inventory using as many slots as possible. Returns false
* if the stackSize of the drop was not depleted.
*/
public static boolean putDropInInventoryAllSlots(IInventory source, IInventory destination, EntityItem entity)
{
boolean flag = false;
if (entity == null)
{
return false;
}
else
{
ItemStack itemstack = entity.getItem().copy();
ItemStack itemstack1 = putStackInInventoryAllSlots(source, destination, itemstack, (EnumFacing)null);
if (itemstack1.isEmpty())
{
flag = true;
entity.setDead();
}
else
{
entity.setItem(itemstack1);
}
return flag;
}
}
protected net.minecraftforge.items.IItemHandler createUnSidedHandler()
{
return new net.minecraftforge.items.VanillaHopperItemHandler(this);
}
/**
* Attempts to place the passed stack in the inventory, using as many slots as required. Returns leftover items
*/
public static ItemStack putStackInInventoryAllSlots(IInventory source, IInventory destination, ItemStack stack, @Nullable EnumFacing direction)
{
if (destination instanceof ISidedInventory && direction != null)
{
ISidedInventory isidedinventory = (ISidedInventory)destination;
int[] aint = isidedinventory.getSlotsForFace(direction);
for (int k = 0; k < aint.length && !stack.isEmpty(); ++k)
{
stack = insertStack(source, destination, stack, aint[k], direction);
}
}
else
{
int i = destination.getSizeInventory();
for (int j = 0; j < i && !stack.isEmpty(); ++j)
{
stack = insertStack(source, destination, stack, j, direction);
}
}
return stack;
}
/**
* Can this hopper insert the specified item from the specified slot on the specified side?
*/
private static boolean canInsertItemInSlot(IInventory inventoryIn, ItemStack stack, int index, EnumFacing side)
{
if (!inventoryIn.isItemValidForSlot(index, stack))
{
return false;
}
else
{
return !(inventoryIn instanceof ISidedInventory) || ((ISidedInventory)inventoryIn).canInsertItem(index, stack, side);
}
}
/**
* Can this hopper extract the specified item from the specified slot on the specified side?
*/
private static boolean canExtractItemFromSlot(IInventory inventoryIn, ItemStack stack, int index, EnumFacing side)
{
return !(inventoryIn instanceof ISidedInventory) || ((ISidedInventory)inventoryIn).canExtractItem(index, stack, side);
}
/**
* Insert the specified stack to the specified inventory and return any leftover items
*/
private static ItemStack insertStack(IInventory source, IInventory destination, ItemStack stack, int index, EnumFacing direction)
{
ItemStack itemstack = destination.getStackInSlot(index);
if (canInsertItemInSlot(destination, stack, index, direction))
{
boolean flag = false;
boolean flag1 = destination.isEmpty();
if (itemstack.isEmpty())
{
destination.setInventorySlotContents(index, stack);
stack = ItemStack.EMPTY;
flag = true;
}
else if (canCombine(itemstack, stack))
{
int i = stack.getMaxStackSize() - itemstack.getCount();
int j = Math.min(stack.getCount(), i);
stack.shrink(j);
itemstack.grow(j);
flag = j > 0;
}
if (flag)
{
if (flag1 && destination instanceof TileEntityHopper)
{
TileEntityHopper tileentityhopper1 = (TileEntityHopper)destination;
if (!tileentityhopper1.mayTransfer())
{
int k = 0;
if (source != null && source instanceof TileEntityHopper)
{
TileEntityHopper tileentityhopper = (TileEntityHopper)source;
if (tileentityhopper1.tickedGameTime >= tileentityhopper.tickedGameTime)
{
k = 1;
}
}
tileentityhopper1.setTransferCooldown(8 - k);
}
}
destination.markDirty();
}
}
return stack;
}
/**
* Returns the IInventory that this hopper is pointing into
*/
private IInventory getInventoryForHopperTransfer()
{
EnumFacing enumfacing = BlockHopper.getFacing(this.getBlockMetadata());
return getInventoryAtPosition(this.getWorld(), this.getXPos() + (double)enumfacing.getFrontOffsetX(), this.getYPos() + (double)enumfacing.getFrontOffsetY(), this.getZPos() + (double)enumfacing.getFrontOffsetZ());
}
/**
* Gets the inventory that the provided hopper will transfer items from.
*/
public static IInventory getSourceInventory(IHopper hopper)
{
return getInventoryAtPosition(hopper.getWorld(), hopper.getXPos(), hopper.getYPos() + 1.0D, hopper.getZPos());
}
public static List<EntityItem> getCaptureItems(World worldIn, double p_184292_1_, double p_184292_3_, double p_184292_5_)
{
return worldIn.<EntityItem>getEntitiesWithinAABB(EntityItem.class, new AxisAlignedBB(p_184292_1_ - 0.5D, p_184292_3_, p_184292_5_ - 0.5D, p_184292_1_ + 0.5D, p_184292_3_ + 1.5D, p_184292_5_ + 0.5D), EntitySelectors.IS_ALIVE);
}
/**
* Returns the IInventory (if applicable) of the TileEntity at the specified position
*/
public static IInventory getInventoryAtPosition(World worldIn, double x, double y, double z)
{
IInventory iinventory = 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 instanceof IInventory)
{
iinventory = (IInventory)tileentity;
if (iinventory instanceof TileEntityChest && block instanceof BlockChest)
{
iinventory = ((BlockChest)block).getContainer(worldIn, blockpos, true);
}
}
}
if (iinventory == null)
{
List<Entity> list = worldIn.getEntitiesInAABBexcluding((Entity)null, new AxisAlignedBB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelectors.HAS_INVENTORY);
if (!list.isEmpty())
{
iinventory = (IInventory)list.get(worldIn.rand.nextInt(list.size()));
}
}
return iinventory;
}
private static boolean canCombine(ItemStack stack1, ItemStack stack2)
{
if (stack1.getItem() != stack2.getItem())
{
return false;
}
else if (stack1.getMetadata() != stack2.getMetadata())
{
return false;
}
else if (stack1.getCount() > stack1.getMaxStackSize())
{
return false;
}
else
{
return ItemStack.areItemStackTagsEqual(stack1, stack2);
}
}
/**
* Gets the world X position for this hopper entity.
*/
public double getXPos()
{
return (double)this.pos.getX() + 0.5D;
}
/**
* Gets the world Y position for this hopper entity.
*/
public double getYPos()
{
return (double)this.pos.getY() + 0.5D;
}
/**
* Gets the world Z position for this hopper entity.
*/
public double getZPos()
{
return (double)this.pos.getZ() + 0.5D;
}
public void setTransferCooldown(int ticks)
{
this.transferCooldown = ticks;
}
private boolean isOnTransferCooldown()
{
return this.transferCooldown > 0;
}
public boolean mayTransfer()
{
return this.transferCooldown > 8;
}
public String getGuiID()
{
return "minecraft:hopper";
}
public Container createContainer(InventoryPlayer playerInventory, EntityPlayer playerIn)
{
this.fillWithLoot(playerIn);
return new ContainerHopper(playerInventory, this, playerIn);
}
protected NonNullList<ItemStack> getItems()
{
return this.inventory;
}
public long getLastUpdateTime() { return tickedGameTime; } // Forge
}