package net.minecraft.item;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentDurability;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.item.EntityItemFrame;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.stats.StatList;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.Icon;
import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
public final class ItemStack
{
/** Size of the stack. */
public int stackSize;
/**
* Number of animation frames to go when receiving an item (by walking into it, for example).
*/
public int animationsToGo;
/** ID of the item. */
public int itemID;
/**
* A NBTTagMap containing data about an ItemStack. Can only be used for non stackable items
*/
public NBTTagCompound stackTagCompound;
/** Damage dealt to the item or number of use. Raise when using items. */
int itemDamage;
/** Item frame this stack is on, or null if not on an item frame. */
private EntityItemFrame itemFrame;
public ItemStack(Block par1Block)
{
this(par1Block, 1);
}
public ItemStack(Block par1Block, int par2)
{
this(par1Block.blockID, par2, 0);
}
public ItemStack(Block par1Block, int par2, int par3)
{
this(par1Block.blockID, par2, par3);
}
public ItemStack(Item par1Item)
{
this(par1Item.itemID, 1, 0);
}
public ItemStack(Item par1Item, int par2)
{
this(par1Item.itemID, par2, 0);
}
public ItemStack(Item par1Item, int par2, int par3)
{
this(par1Item.itemID, par2, par3);
}
public ItemStack(int par1, int par2, int par3)
{
this.stackSize = 0;
this.itemFrame = null;
this.itemID = par1;
this.stackSize = par2;
this.itemDamage = par3;
if (this.itemDamage < 0)
{
this.itemDamage = 0;
}
}
public static ItemStack loadItemStackFromNBT(NBTTagCompound par0NBTTagCompound)
{
ItemStack itemstack = new ItemStack();
itemstack.readFromNBT(par0NBTTagCompound);
return itemstack.getItem() != null ? itemstack : null;
}
private ItemStack()
{
this.stackSize = 0;
this.itemFrame = null;
}
/**
* Remove the argument from the stack size. Return a new stack object with argument size.
*/
public ItemStack splitStack(int par1)
{
ItemStack itemstack = new ItemStack(this.itemID, par1, this.itemDamage);
if (this.stackTagCompound != null)
{
itemstack.stackTagCompound = (NBTTagCompound)this.stackTagCompound.copy();
}
this.stackSize -= par1;
return itemstack;
}
/**
* Returns the object corresponding to the stack.
*/
public Item getItem()
{
return Item.itemsList[this.itemID];
}
@SideOnly(Side.CLIENT)
/**
* Returns the icon index of the current stack.
*/
public Icon getIconIndex()
{
return this.getItem().getIconIndex(this);
}
@SideOnly(Side.CLIENT)
public int getItemSpriteNumber()
{
return this.getItem().getSpriteNumber();
}
public boolean tryPlaceItemIntoWorld(EntityPlayer par1EntityPlayer, World par2World, int par3, int par4, int par5, int par6, float par7, float par8, float par9)
{
boolean flag = this.getItem().onItemUse(this, par1EntityPlayer, par2World, par3, par4, par5, par6, par7, par8, par9);
if (flag)
{
par1EntityPlayer.addStat(StatList.objectUseStats[this.itemID], 1);
}
return flag;
}
/**
* Returns the strength of the stack against a given block.
*/
public float getStrVsBlock(Block par1Block)
{
return this.getItem().getStrVsBlock(this, par1Block);
}
/**
* Called whenever this item stack is equipped and right clicked. Returns the new item stack to put in the position
* where this item is. Args: world, player
*/
public ItemStack useItemRightClick(World par1World, EntityPlayer par2EntityPlayer)
{
return this.getItem().onItemRightClick(this, par1World, par2EntityPlayer);
}
public ItemStack onFoodEaten(World par1World, EntityPlayer par2EntityPlayer)
{
return this.getItem().onEaten(this, par1World, par2EntityPlayer);
}
/**
* Write the stack fields to a NBT object. Return the new NBT object.
*/
public NBTTagCompound writeToNBT(NBTTagCompound par1NBTTagCompound)
{
par1NBTTagCompound.setShort("id", (short)this.itemID);
par1NBTTagCompound.setByte("Count", (byte)this.stackSize);
par1NBTTagCompound.setShort("Damage", (short)this.itemDamage);
if (this.stackTagCompound != null)
{
par1NBTTagCompound.setTag("tag", this.stackTagCompound);
}
return par1NBTTagCompound;
}
/**
* Read the stack fields from a NBT object.
*/
public void readFromNBT(NBTTagCompound par1NBTTagCompound)
{
this.itemID = par1NBTTagCompound.getShort("id");
this.stackSize = par1NBTTagCompound.getByte("Count");
this.itemDamage = par1NBTTagCompound.getShort("Damage");
if (this.itemDamage < 0)
{
this.itemDamage = 0;
}
if (par1NBTTagCompound.hasKey("tag"))
{
this.stackTagCompound = par1NBTTagCompound.getCompoundTag("tag");
}
}
/**
* Returns maximum size of the stack.
*/
public int getMaxStackSize()
{
return this.getItem().getItemStackLimit();
}
/**
* Returns true if the ItemStack can hold 2 or more units of the item.
*/
public boolean isStackable()
{
return this.getMaxStackSize() > 1 && (!this.isItemStackDamageable() || !this.isItemDamaged());
}
/**
* true if this itemStack is damageable
*/
public boolean isItemStackDamageable()
{
return Item.itemsList[this.itemID].getMaxDamage() > 0;
}
public boolean getHasSubtypes()
{
return Item.itemsList[this.itemID].getHasSubtypes();
}
/**
* returns true when a damageable item is damaged
*/
public boolean isItemDamaged()
{
return this.isItemStackDamageable() && this.getItem().isItemStackDamaged(this);
}
/**
* gets the damage of an itemstack, for displaying purposes
*/
public int getItemDamageForDisplay()
{
return this.getItem().getItemDamageFromStackForDisplay(this);
}
/**
* gets the damage of an itemstack
*/
public int getItemDamage()
{
return this.getItem().getItemDamageFromStack(this);
}
/**
* Sets the item damage of the ItemStack.
*/
public void setItemDamage(int par1)
{
this.getItem().setItemDamageForStack(this, par1);
}
/**
* Returns the max damage an item in the stack can take.
*/
public int getMaxDamage()
{
return this.getItem().getItemMaxDamageFromStack(this);
}
/**
* Attempts to damage the ItemStack with par1 amount of damage, If the ItemStack has the Unbreaking enchantment
* there is a chance for each point of damage to be negated. Returns true if it takes more damage than
* getMaxDamage(). Returns false otherwise or if the ItemStack can't be damaged or if all points of damage are
* negated.
*/
public boolean attemptDamageItem(int par1, Random par2Random)
{
if (!this.isItemStackDamageable())
{
return false;
}
else
{
if (par1 > 0)
{
int j = EnchantmentHelper.getEnchantmentLevel(Enchantment.unbreaking.effectId, this);
int k = 0;
for (int l = 0; j > 0 && l < par1; ++l)
{
if (EnchantmentDurability.negateDamage(this, j, par2Random))
{
++k;
}
}
par1 -= k;
if (par1 <= 0)
{
return false;
}
}
this.itemDamage += par1;
return this.itemDamage > this.getMaxDamage();
}
}
/**
* Damages the item in the ItemStack
*/
public void damageItem(int par1, EntityLiving par2EntityLiving)
{
if (!(par2EntityLiving instanceof EntityPlayer) || !((EntityPlayer)par2EntityLiving).capabilities.isCreativeMode)
{
if (this.isItemStackDamageable())
{
if (this.attemptDamageItem(par1, par2EntityLiving.getRNG()))
{
par2EntityLiving.renderBrokenItemStack(this);
if (par2EntityLiving instanceof EntityPlayer)
{
((EntityPlayer)par2EntityLiving).addStat(StatList.objectBreakStats[this.itemID], 1);
}
--this.stackSize;
if (this.stackSize < 0)
{
this.stackSize = 0;
}
this.itemDamage = 0;
}
}
}
}
/**
* Calls the corresponding fct in di
*/
public void hitEntity(EntityLiving par1EntityLiving, EntityPlayer par2EntityPlayer)
{
boolean flag = Item.itemsList[this.itemID].hitEntity(this, par1EntityLiving, par2EntityPlayer);
if (flag)
{
par2EntityPlayer.addStat(StatList.objectUseStats[this.itemID], 1);
}
}
public void onBlockDestroyed(World par1World, int par2, int par3, int par4, int par5, EntityPlayer par6EntityPlayer)
{
boolean flag = Item.itemsList[this.itemID].onBlockDestroyed(this, par1World, par2, par3, par4, par5, par6EntityPlayer);
if (flag)
{
par6EntityPlayer.addStat(StatList.objectUseStats[this.itemID], 1);
}
}
/**
* Returns the damage against a given entity.
*/
public int getDamageVsEntity(Entity par1Entity)
{
return Item.itemsList[this.itemID].getDamageVsEntity(par1Entity, this);
}
/**
* Checks if the itemStack object can harvest a specified block
*/
public boolean canHarvestBlock(Block par1Block)
{
return Item.itemsList[this.itemID].canHarvestBlock(par1Block);
}
public boolean interactWith(EntityLiving par1EntityLiving)
{
return Item.itemsList[this.itemID].itemInteractionForEntity(this, par1EntityLiving);
}
/**
* Returns a new stack with the same properties.
*/
public ItemStack copy()
{
ItemStack itemstack = new ItemStack(this.itemID, this.stackSize, this.itemDamage);
if (this.stackTagCompound != null)
{
itemstack.stackTagCompound = (NBTTagCompound)this.stackTagCompound.copy();
}
return itemstack;
}
public static boolean areItemStackTagsEqual(ItemStack par0ItemStack, ItemStack par1ItemStack)
{
return par0ItemStack == null && par1ItemStack == null ? true : (par0ItemStack != null && par1ItemStack != null ? (par0ItemStack.stackTagCompound == null && par1ItemStack.stackTagCompound != null ? false : par0ItemStack.stackTagCompound == null || par0ItemStack.stackTagCompound.equals(par1ItemStack.stackTagCompound)) : false);
}
/**
* compares ItemStack argument1 with ItemStack argument2; returns true if both ItemStacks are equal
*/
public static boolean areItemStacksEqual(ItemStack par0ItemStack, ItemStack par1ItemStack)
{
return par0ItemStack == null && par1ItemStack == null ? true : (par0ItemStack != null && par1ItemStack != null ? par0ItemStack.isItemStackEqual(par1ItemStack) : false);
}
/**
* compares ItemStack argument to the instance ItemStack; returns true if both ItemStacks are equal
*/
private boolean isItemStackEqual(ItemStack par1ItemStack)
{
return this.stackSize != par1ItemStack.stackSize ? false : (this.itemID != par1ItemStack.itemID ? false : (this.itemDamage != par1ItemStack.itemDamage ? false : (this.stackTagCompound == null && par1ItemStack.stackTagCompound != null ? false : this.stackTagCompound == null || this.stackTagCompound.equals(par1ItemStack.stackTagCompound))));
}
/**
* compares ItemStack argument to the instance ItemStack; returns true if the Items contained in both ItemStacks are
* equal
*/
public boolean isItemEqual(ItemStack par1ItemStack)
{
return this.itemID == par1ItemStack.itemID && this.itemDamage == par1ItemStack.itemDamage;
}
public String getItemName()
{
return Item.itemsList[this.itemID].getUnlocalizedName(this);
}
/**
* Creates a copy of a ItemStack, a null parameters will return a null.
*/
public static ItemStack copyItemStack(ItemStack par0ItemStack)
{
return par0ItemStack == null ? null : par0ItemStack.copy();
}
public String toString()
{
return this.stackSize + "x" + Item.itemsList[this.itemID].getUnlocalizedName() + "@" + this.itemDamage;
}
/**
* Called each tick as long the ItemStack in on player inventory. Used to progress the pickup animation and update
* maps.
*/
public void updateAnimation(World par1World, Entity par2Entity, int par3, boolean par4)
{
if (this.animationsToGo > 0)
{
--this.animationsToGo;
}
Item.itemsList[this.itemID].onUpdate(this, par1World, par2Entity, par3, par4);
}
public void onCrafting(World par1World, EntityPlayer par2EntityPlayer, int par3)
{
par2EntityPlayer.addStat(StatList.objectCraftStats[this.itemID], par3);
Item.itemsList[this.itemID].onCreated(this, par1World, par2EntityPlayer);
}
public int getMaxItemUseDuration()
{
return this.getItem().getMaxItemUseDuration(this);
}
public EnumAction getItemUseAction()
{
return this.getItem().getItemUseAction(this);
}
/**
* Called when the player releases the use item button. Args: world, entityplayer, itemInUseCount
*/
public void onPlayerStoppedUsing(World par1World, EntityPlayer par2EntityPlayer, int par3)
{
this.getItem().onPlayerStoppedUsing(this, par1World, par2EntityPlayer, par3);
}
/**
* Returns true if the ItemStack has an NBTTagCompound. Currently used to store enchantments.
*/
public boolean hasTagCompound()
{
return this.stackTagCompound != null;
}
/**
* Returns the NBTTagCompound of the ItemStack.
*/
public NBTTagCompound getTagCompound()
{
return this.stackTagCompound;
}
public NBTTagList getEnchantmentTagList()
{
return this.stackTagCompound == null ? null : (NBTTagList)this.stackTagCompound.getTag("ench");
}
/**
* Assigns a NBTTagCompound to the ItemStack, minecraft validates that only non-stackable items can have it.
*/
public void setTagCompound(NBTTagCompound par1NBTTagCompound)
{
this.stackTagCompound = par1NBTTagCompound;
}
/**
* returns the display name of the itemstack
*/
public String getDisplayName()
{
String s = this.getItem().getItemDisplayName(this);
if (this.stackTagCompound != null && this.stackTagCompound.hasKey("display"))
{
NBTTagCompound nbttagcompound = this.stackTagCompound.getCompoundTag("display");
if (nbttagcompound.hasKey("Name"))
{
s = nbttagcompound.getString("Name");
}
}
return s;
}
/**
* Sets the item's name (used by anvil to rename the items).
*/
public void setItemName(String par1Str)
{
if (this.stackTagCompound == null)
{
this.stackTagCompound = new NBTTagCompound("tag");
}
if (!this.stackTagCompound.hasKey("display"))
{
this.stackTagCompound.setCompoundTag("display", new NBTTagCompound());
}
this.stackTagCompound.getCompoundTag("display").setString("Name", par1Str);
}
/**
* Returns true if the itemstack has a display name
*/
public boolean hasDisplayName()
{
return this.stackTagCompound == null ? false : (!this.stackTagCompound.hasKey("display") ? false : this.stackTagCompound.getCompoundTag("display").hasKey("Name"));
}
@SideOnly(Side.CLIENT)
/**
* Return a list of strings containing information about the item
*/
public List getTooltip(EntityPlayer par1EntityPlayer, boolean par2)
{
ArrayList arraylist = new ArrayList();
Item item = Item.itemsList[this.itemID];
String s = this.getDisplayName();
if (this.hasDisplayName())
{
s = EnumChatFormatting.ITALIC + s + EnumChatFormatting.RESET;
}
if (par2)
{
String s1 = "";
if (s.length() > 0)
{
s = s + " (";
s1 = ")";
}
if (this.getHasSubtypes())
{
s = s + String.format("#%04d/%d%s", new Object[] {Integer.valueOf(this.itemID), Integer.valueOf(this.itemDamage), s1});
}
else
{
s = s + String.format("#%04d%s", new Object[] {Integer.valueOf(this.itemID), s1});
}
}
else if (!this.hasDisplayName() && this.itemID == Item.map.itemID)
{
s = s + " #" + this.itemDamage;
}
arraylist.add(s);
item.addInformation(this, par1EntityPlayer, arraylist, par2);
if (this.hasTagCompound())
{
NBTTagList nbttaglist = this.getEnchantmentTagList();
if (nbttaglist != null)
{
for (int i = 0; i < nbttaglist.tagCount(); ++i)
{
short short1 = ((NBTTagCompound)nbttaglist.tagAt(i)).getShort("id");
short short2 = ((NBTTagCompound)nbttaglist.tagAt(i)).getShort("lvl");
if (Enchantment.enchantmentsList[short1] != null)
{
arraylist.add(Enchantment.enchantmentsList[short1].getTranslatedName(short2));
}
}
}
if (this.stackTagCompound.hasKey("display"))
{
NBTTagCompound nbttagcompound = this.stackTagCompound.getCompoundTag("display");
if (nbttagcompound.hasKey("color"))
{
if (par2)
{
arraylist.add("Color: #" + Integer.toHexString(nbttagcompound.getInteger("color")).toUpperCase());
}
else
{
arraylist.add(EnumChatFormatting.ITALIC + StatCollector.translateToLocal("item.dyed"));
}
}
if (nbttagcompound.hasKey("Lore"))
{
NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore");
if (nbttaglist1.tagCount() > 0)
{
for (int j = 0; j < nbttaglist1.tagCount(); ++j)
{
arraylist.add(EnumChatFormatting.DARK_PURPLE + "" + EnumChatFormatting.ITALIC + ((NBTTagString)nbttaglist1.tagAt(j)).data);
}
}
}
}
}
if (par2 && this.isItemDamaged())
{
arraylist.add("Durability: " + (this.getMaxDamage() - this.getItemDamageForDisplay()) + " / " + this.getMaxDamage());
}
return arraylist;
}
@SideOnly(Side.CLIENT)
public boolean hasEffect()
{
return this.getItem().hasEffect(this);
}
@SideOnly(Side.CLIENT)
public EnumRarity getRarity()
{
return this.getItem().getRarity(this);
}
/**
* True if it is a tool and has no enchantments to begin with
*/
public boolean isItemEnchantable()
{
return !this.getItem().isItemTool(this) ? false : !this.isItemEnchanted();
}
/**
* Adds an enchantment with a desired level on the ItemStack.
*/
public void addEnchantment(Enchantment par1Enchantment, int par2)
{
if (this.stackTagCompound == null)
{
this.setTagCompound(new NBTTagCompound());
}
if (!this.stackTagCompound.hasKey("ench"))
{
this.stackTagCompound.setTag("ench", new NBTTagList("ench"));
}
NBTTagList nbttaglist = (NBTTagList)this.stackTagCompound.getTag("ench");
NBTTagCompound nbttagcompound = new NBTTagCompound();
nbttagcompound.setShort("id", (short)par1Enchantment.effectId);
nbttagcompound.setShort("lvl", (short)((byte)par2));
nbttaglist.appendTag(nbttagcompound);
}
/**
* True if the item has enchantment data
*/
public boolean isItemEnchanted()
{
return this.stackTagCompound != null && this.stackTagCompound.hasKey("ench");
}
public void setTagInfo(String par1Str, NBTBase par2NBTBase)
{
if (this.stackTagCompound == null)
{
this.setTagCompound(new NBTTagCompound());
}
this.stackTagCompound.setTag(par1Str, par2NBTBase);
}
public boolean func_82835_x()
{
return this.getItem().func_82788_x();
}
/**
* Return whether this stack is on an item frame.
*/
public boolean isOnItemFrame()
{
return this.itemFrame != null;
}
/**
* Set the item frame this stack is on.
*/
public void setItemFrame(EntityItemFrame par1EntityItemFrame)
{
this.itemFrame = par1EntityItemFrame;
}
/**
* Return the item frame this stack is on. Returns null if not on an item frame.
*/
public EntityItemFrame getItemFrame()
{
return this.itemFrame;
}
/**
* Get this stack's repair cost, or 0 if no repair cost is defined.
*/
public int getRepairCost()
{
return this.hasTagCompound() && this.stackTagCompound.hasKey("RepairCost") ? this.stackTagCompound.getInteger("RepairCost") : 0;
}
/**
* Set this stack's repair cost.
*/
public void setRepairCost(int par1)
{
if (!this.hasTagCompound())
{
this.stackTagCompound = new NBTTagCompound("tag");
}
this.stackTagCompound.setInteger("RepairCost", par1);
}
}