package net.mcft.copy.core.api;

import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;

public class ItemIdentifier {
	
	private final Item item;
	private final int damage;
	private final NBTTagCompound data;
	
	private int hashCode;
	private boolean calculatedHashCode = false;
	
	public ItemIdentifier(Item item, int damage, NBTTagCompound data) {
		this.item = item;
		this.damage = damage;
		this.data = data;
	}
	public ItemIdentifier(ItemStack stack) {
		this(stack.getItem(), Items.diamond.getDamage(stack),
		     (stack.hasTagCompound() ? (NBTTagCompound)stack.getTagCompound().copy() : null));
	}
	
	public ItemStack createStack(int size) {
		ItemStack stack = new ItemStack(item, size, damage);
		if (data != null)
			stack.stackTagCompound = (NBTTagCompound)data.copy();
		return stack;
	}
	
	public boolean matches(Item item, int damage, NBTTagCompound data) {
		return ((item == this.item) && (damage == this.damage) &&
		        ((data == this.data) || ((data != null) && data.equals(this.data))));
	}
	
	public boolean matches(ItemStack stack) {
		return matches(stack.getItem(), Items.diamond.getDamage(stack), stack.getTagCompound());
	}
	
	@Override
	public int hashCode() {
		if (!calculatedHashCode) {
			hashCode = Item.getIdFromItem(item) ^ (damage << 8);
			if (data != null) hashCode ^= data.hashCode();
			calculatedHashCode = true;
		}
		return hashCode;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (obj == null || !(obj instanceof ItemIdentifier)) return false;
		ItemIdentifier other = (ItemIdentifier)obj;
		return matches(other.item, other.damage, other.data);
	}
	
	@Override
	public String toString() {
		return item.getUnlocalizedName() + ":" + damage;
	}
	
}

@@ -363,16 +363,236 @@
 alse;%0A%09%0A
+%09// Since, in my opinion, null data and an empty compound are%0A%09// equivalent, ItemIdentifiers should not be created with an%0A%09// empty compound. Otherwise, hashcodes might not match even%0A%09// though equals returns true.%0A%09%0A
 %09public 
@@ -824,16 +824,17 @@
 %0A%09%09     
+(
 (stack.h
@@ -848,16 +848,65 @@
 mpound()
+ && !stack.getTagCompound().hasNoTags())%0A%09%09    %09%09
  ? (NBTT
@@ -953,32 +953,113 @@
  : null));%0A%09%7D%0A%09%0A
+%09/** Creates an item stack from the identifier with the specified stack size. */%0A
 %09public ItemStac
@@ -1233,24 +1233,98 @@
 stack;%0A%09%7D%0A%09%0A
+%09/** Returns if the identifier matches this item, damage and NBT data. */%0A
 %09public bool
@@ -1465,38 +1465,85 @@
  == 
-this.data) %7C%7C ((
+null) ? (this.data == null)%0A%09%09                        : ((this.
 data 
-!
+=
 = null) 
 && d
@@ -1542,42 +1542,168 @@
 ll) 
-&& data.equals(this.data))));%0A%09%7D%0A%09
+? data.hasNoTags()%0A%09%09                                               : data.equals(this.data))));%0A%09%7D%0A%09%0A%09/** Returns if the identifier matches this item stack. */
 %0A%09pu

Comment and update ItemIdentifier