summaryrefslogtreecommitdiffstats
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/net/minecraft/server/ContainerEnchantTable.java4
-rw-r--r--src/main/java/net/minecraft/server/DispenseBehaviorBoat.java8
-rw-r--r--src/main/java/net/minecraft/server/DispenseBehaviorEmptyBucket.java8
-rw-r--r--src/main/java/net/minecraft/server/DispenseBehaviorFilledBucket.java10
-rw-r--r--src/main/java/net/minecraft/server/DispenseBehaviorFireball.java8
-rw-r--r--src/main/java/net/minecraft/server/DispenseBehaviorItem.java10
-rw-r--r--src/main/java/net/minecraft/server/DispenseBehaviorMinecart.java10
-rw-r--r--src/main/java/net/minecraft/server/DispenseBehaviorMonsterEgg.java10
-rw-r--r--src/main/java/net/minecraft/server/DispenseBehaviorProjectile.java10
-rw-r--r--src/main/java/net/minecraft/server/EntityCow.java4
-rw-r--r--src/main/java/net/minecraft/server/EntityGhast.java4
-rw-r--r--src/main/java/net/minecraft/server/EntityIronGolem.java4
-rw-r--r--src/main/java/net/minecraft/server/EntityLiving.java2
-rw-r--r--src/main/java/net/minecraft/server/EntityMinecart.java2
-rw-r--r--src/main/java/net/minecraft/server/EntityPigZombie.java6
-rw-r--r--src/main/java/net/minecraft/server/EntityPlayer.java4
-rw-r--r--src/main/java/net/minecraft/server/EntitySkeleton.java2
-rw-r--r--src/main/java/net/minecraft/server/ItemBucket.java14
-rw-r--r--src/main/java/net/minecraft/server/ItemStack.java15
-rw-r--r--src/main/java/net/minecraft/server/NBTTagCompound.java6
-rw-r--r--src/main/java/net/minecraft/server/NetServerHandler.java10
-rw-r--r--src/main/java/net/minecraft/server/ShapedRecipes.java2
-rw-r--r--src/main/java/net/minecraft/server/ShapelessRecipes.java2
-rw-r--r--src/main/java/net/minecraft/server/TileEntityFurnace.java8
-rw-r--r--src/main/java/org/bukkit/craftbukkit/CraftServer.java6
-rw-r--r--src/main/java/org/bukkit/craftbukkit/CraftWorld.java3
-rw-r--r--src/main/java/org/bukkit/craftbukkit/Overridden.java14
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java4
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java4
-rw-r--r--src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java4
-rw-r--r--src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java29
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java4
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftFurnaceRecipe.java2
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java13
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCrafting.java20
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java4
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java4
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java4
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java123
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java373
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java272
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java510
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java137
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMap.java139
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java260
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java134
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftShapedRecipe.java2
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java2
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java2
49 files changed, 1961 insertions, 271 deletions
diff --git a/src/main/java/net/minecraft/server/ContainerEnchantTable.java b/src/main/java/net/minecraft/server/ContainerEnchantTable.java
index bb5f1079..9f660607 100644
--- a/src/main/java/net/minecraft/server/ContainerEnchantTable.java
+++ b/src/main/java/net/minecraft/server/ContainerEnchantTable.java
@@ -124,7 +124,7 @@ public class ContainerEnchantTable extends Container {
}
// CraftBukkit start
- CraftItemStack item = new CraftItemStack(itemstack);
+ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack);
PrepareItemEnchantEvent event = new PrepareItemEnchantEvent(player, this.getBukkitView(), this.world.getWorld().getBlockAt(this.x, this.y, this.z), item, this.costs, i);
this.world.getServer().getPluginManager().callEvent(event);
@@ -160,7 +160,7 @@ public class ContainerEnchantTable extends Container {
EnchantmentInstance instance = (EnchantmentInstance) obj;
enchants.put(org.bukkit.enchantments.Enchantment.getById(instance.enchantment.id), instance.level);
}
- CraftItemStack item = new CraftItemStack(itemstack);
+ CraftItemStack item = CraftItemStack.asCraftMirror(itemstack);
EnchantItemEvent event = new EnchantItemEvent((Player) entityhuman.getBukkitEntity(), this.getBukkitView(), this.world.getWorld().getBlockAt(this.x, this.y, this.z), item, this.costs[i], enchants, i);
this.world.getServer().getPluginManager().callEvent(event);
diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorBoat.java b/src/main/java/net/minecraft/server/DispenseBehaviorBoat.java
index dfaf09ed..2840aa3e 100644
--- a/src/main/java/net/minecraft/server/DispenseBehaviorBoat.java
+++ b/src/main/java/net/minecraft/server/DispenseBehaviorBoat.java
@@ -41,9 +41,9 @@ public class DispenseBehaviorBoat extends DispenseBehaviorItem {
// CraftBukkit start
ItemStack itemstack1 = itemstack.a(1);
org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockX(), isourceblock.getBlockY(), isourceblock.getBlockZ());
- org.bukkit.inventory.ItemStack bukkitItem = new CraftItemStack(itemstack1).clone();
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
- BlockDispenseEvent event = new BlockDispenseEvent(block, bukkitItem, new org.bukkit.util.Vector(d0, d1 + d3, d2));
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d0, d1 + d3, d2));
if (!BlockDispenser.eventFired) {
world.getServer().getPluginManager().callEvent(event);
}
@@ -53,10 +53,10 @@ public class DispenseBehaviorBoat extends DispenseBehaviorItem {
return itemstack;
}
- if (!event.getItem().equals(bukkitItem)) {
+ if (!event.getItem().equals(craftItem)) {
itemstack.count++;
// Chain to handler for new item
- ItemStack eventStack = CraftItemStack.createNMSItemStack(event.getItem());
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.a.a(eventStack.getItem());
if (idispensebehavior != IDispenseBehavior.a && idispensebehavior != this) {
idispensebehavior.a(isourceblock, eventStack);
diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorEmptyBucket.java b/src/main/java/net/minecraft/server/DispenseBehaviorEmptyBucket.java
index 31348bd6..b381e223 100644
--- a/src/main/java/net/minecraft/server/DispenseBehaviorEmptyBucket.java
+++ b/src/main/java/net/minecraft/server/DispenseBehaviorEmptyBucket.java
@@ -38,9 +38,9 @@ public class DispenseBehaviorEmptyBucket extends DispenseBehaviorItem {
// CraftBukkit start
org.bukkit.block.Block block = world.getWorld().getBlockAt(i, j, k);
- org.bukkit.inventory.ItemStack bukkitItem = new CraftItemStack(itemstack).clone();
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
- BlockDispenseEvent event = new BlockDispenseEvent(block, bukkitItem, new org.bukkit.util.Vector(0, 0, 0));
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
if (!BlockDispenser.eventFired) {
world.getServer().getPluginManager().callEvent(event);
}
@@ -49,9 +49,9 @@ public class DispenseBehaviorEmptyBucket extends DispenseBehaviorItem {
return itemstack;
}
- if (!event.getItem().equals(bukkitItem)) {
+ if (!event.getItem().equals(craftItem)) {
// Chain to handler for new item
- ItemStack eventStack = CraftItemStack.createNMSItemStack(event.getItem());
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.a.a(eventStack.getItem());
if (idispensebehavior != IDispenseBehavior.a && idispensebehavior != this) {
idispensebehavior.a(isourceblock, eventStack);
diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorFilledBucket.java b/src/main/java/net/minecraft/server/DispenseBehaviorFilledBucket.java
index 8f1d9a84..309c1e62 100644
--- a/src/main/java/net/minecraft/server/DispenseBehaviorFilledBucket.java
+++ b/src/main/java/net/minecraft/server/DispenseBehaviorFilledBucket.java
@@ -29,9 +29,9 @@ public class DispenseBehaviorFilledBucket extends DispenseBehaviorItem {
int k2 = k + enumfacing.e();
if (world.isEmpty(i2, j, k2) || world.getMaterial(i2, j, k2).isBuildable()) {
org.bukkit.block.Block block = world.getWorld().getBlockAt(i, j, k);
- org.bukkit.inventory.ItemStack bukkitItem = new CraftItemStack(itemstack).clone();
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
- BlockDispenseEvent event = new BlockDispenseEvent(block, bukkitItem, new org.bukkit.util.Vector(0, 0, 0));
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(0, 0, 0));
if (!BlockDispenser.eventFired) {
world.getServer().getPluginManager().callEvent(event);
}
@@ -40,9 +40,9 @@ public class DispenseBehaviorFilledBucket extends DispenseBehaviorItem {
return itemstack;
}
- if (!event.getItem().equals(bukkitItem)) {
+ if (!event.getItem().equals(craftItem)) {
// Chain to handler for new item
- ItemStack eventStack = CraftItemStack.createNMSItemStack(event.getItem());
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.a.a(eventStack.getItem());
if (idispensebehavior != IDispenseBehavior.a && idispensebehavior != this) {
idispensebehavior.a(isourceblock, eventStack);
@@ -50,7 +50,7 @@ public class DispenseBehaviorFilledBucket extends DispenseBehaviorItem {
}
}
- itembucket = (ItemBucket) CraftItemStack.createNMSItemStack(event.getItem()).getItem();
+ itembucket = (ItemBucket) CraftItemStack.asNMSCopy(event.getItem()).getItem();
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java b/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java
index cc0bf8bb..9eb4ca2b 100644
--- a/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java
+++ b/src/main/java/net/minecraft/server/DispenseBehaviorFireball.java
@@ -30,9 +30,9 @@ public class DispenseBehaviorFireball extends DispenseBehaviorItem {
// CraftBukkit start
ItemStack itemstack1 = itemstack.a(1);
org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockX(), isourceblock.getBlockY(), isourceblock.getBlockZ());
- org.bukkit.inventory.ItemStack bukkitItem = new CraftItemStack(itemstack1).clone();
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
- BlockDispenseEvent event = new BlockDispenseEvent(block, bukkitItem, new org.bukkit.util.Vector(d3, d4, d5));
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d3, d4, d5));
if (!BlockDispenser.eventFired) {
world.getServer().getPluginManager().callEvent(event);
}
@@ -42,10 +42,10 @@ public class DispenseBehaviorFireball extends DispenseBehaviorItem {
return itemstack;
}
- if (!event.getItem().equals(bukkitItem)) {
+ if (!event.getItem().equals(craftItem)) {
itemstack.count++;
// Chain to handler for new item
- ItemStack eventStack = CraftItemStack.createNMSItemStack(event.getItem());
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.a.a(eventStack.getItem());
if (idispensebehavior != IDispenseBehavior.a && idispensebehavior != this) {
idispensebehavior.a(isourceblock, eventStack);
diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorItem.java b/src/main/java/net/minecraft/server/DispenseBehaviorItem.java
index 1337fefe..1e7161ac 100644
--- a/src/main/java/net/minecraft/server/DispenseBehaviorItem.java
+++ b/src/main/java/net/minecraft/server/DispenseBehaviorItem.java
@@ -50,9 +50,9 @@ public class DispenseBehaviorItem implements IDispenseBehavior {
// CraftBukkit start
org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockX(), isourceblock.getBlockY(), isourceblock.getBlockZ());
- org.bukkit.inventory.ItemStack bukkitItem = new CraftItemStack(itemstack).clone();
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack);
- BlockDispenseEvent event = new BlockDispenseEvent(block, bukkitItem, new org.bukkit.util.Vector(entityitem.motX, entityitem.motY, entityitem.motZ));
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(entityitem.motX, entityitem.motY, entityitem.motZ));
if (!BlockDispenser.eventFired) {
world.getServer().getPluginManager().callEvent(event);
}
@@ -61,14 +61,14 @@ public class DispenseBehaviorItem implements IDispenseBehavior {
return false;
}
- entityitem.itemStack = CraftItemStack.createNMSItemStack(event.getItem());
+ entityitem.itemStack = CraftItemStack.asNMSCopy(event.getItem());
entityitem.motX = event.getVelocity().getX();
entityitem.motY = event.getVelocity().getY();
entityitem.motZ = event.getVelocity().getZ();
- if (!event.getItem().equals(bukkitItem)) {
+ if (!event.getItem().equals(craftItem)) {
// Chain to handler for new item
- ItemStack eventStack = CraftItemStack.createNMSItemStack(event.getItem());
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.a.a(eventStack.getItem());
if (idispensebehavior != IDispenseBehavior.a && idispensebehavior.getClass() != DispenseBehaviorItem.class) {
idispensebehavior.a(isourceblock, eventStack);
diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorMinecart.java b/src/main/java/net/minecraft/server/DispenseBehaviorMinecart.java
index cc92846e..1ec5310e 100644
--- a/src/main/java/net/minecraft/server/DispenseBehaviorMinecart.java
+++ b/src/main/java/net/minecraft/server/DispenseBehaviorMinecart.java
@@ -41,9 +41,9 @@ public class DispenseBehaviorMinecart extends DispenseBehaviorItem {
// CraftBukkit start
ItemStack itemstack1 = itemstack.a(1);
org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockX(), isourceblock.getBlockY(), isourceblock.getBlockZ());
- org.bukkit.inventory.ItemStack bukkitItem = new CraftItemStack(itemstack1).clone();
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
- BlockDispenseEvent event = new BlockDispenseEvent(block, bukkitItem, new org.bukkit.util.Vector(d0, d1 + d3, d2));
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d0, d1 + d3, d2));
if (!BlockDispenser.eventFired) {
world.getServer().getPluginManager().callEvent(event);
}
@@ -53,10 +53,10 @@ public class DispenseBehaviorMinecart extends DispenseBehaviorItem {
return itemstack;
}
- if (!event.getItem().equals(bukkitItem)) {
+ if (!event.getItem().equals(craftItem)) {
itemstack.count++;
// Chain to handler for new item
- ItemStack eventStack = CraftItemStack.createNMSItemStack(event.getItem());
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.a.a(eventStack.getItem());
if (idispensebehavior != IDispenseBehavior.a && idispensebehavior != this) {
idispensebehavior.a(isourceblock, eventStack);
@@ -64,7 +64,7 @@ public class DispenseBehaviorMinecart extends DispenseBehaviorItem {
}
}
- itemstack1 = CraftItemStack.createNMSItemStack(event.getItem());
+ itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
EntityMinecart entityminecart = new EntityMinecart(world, event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ(), ((ItemMinecart) itemstack1.getItem()).a);
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorMonsterEgg.java b/src/main/java/net/minecraft/server/DispenseBehaviorMonsterEgg.java
index 25e21d25..66ad86ec 100644
--- a/src/main/java/net/minecraft/server/DispenseBehaviorMonsterEgg.java
+++ b/src/main/java/net/minecraft/server/DispenseBehaviorMonsterEgg.java
@@ -23,9 +23,9 @@ public class DispenseBehaviorMonsterEgg extends DispenseBehaviorItem {
World world = isourceblock.k();
ItemStack itemstack1 = itemstack.a(1);
org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockX(), isourceblock.getBlockY(), isourceblock.getBlockZ());
- org.bukkit.inventory.ItemStack bukkitItem = new CraftItemStack(itemstack1).clone();
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
- BlockDispenseEvent event = new BlockDispenseEvent(block, bukkitItem, new org.bukkit.util.Vector(d0, d1, d2));
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector(d0, d1, d2));
if (!BlockDispenser.eventFired) {
world.getServer().getPluginManager().callEvent(event);
}
@@ -35,10 +35,10 @@ public class DispenseBehaviorMonsterEgg extends DispenseBehaviorItem {
return itemstack;
}
- if (!event.getItem().equals(bukkitItem)) {
+ if (!event.getItem().equals(craftItem)) {
itemstack.count++;
// Chain to handler for new item
- ItemStack eventStack = CraftItemStack.createNMSItemStack(event.getItem());
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.a.a(eventStack.getItem());
if (idispensebehavior != IDispenseBehavior.a && idispensebehavior != this) {
idispensebehavior.a(isourceblock, eventStack);
@@ -46,7 +46,7 @@ public class DispenseBehaviorMonsterEgg extends DispenseBehaviorItem {
}
}
- itemstack1 = CraftItemStack.createNMSItemStack(event.getItem());
+ itemstack1 = CraftItemStack.asNMSCopy(event.getItem());
ItemMonsterEgg.a(isourceblock.k(), itemstack1.getData(), event.getVelocity().getX(), event.getVelocity().getY(), event.getVelocity().getZ());
// itemstack.a(1); // Handled during event processing
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/DispenseBehaviorProjectile.java b/src/main/java/net/minecraft/server/DispenseBehaviorProjectile.java
index 3968dd0c..984b1fc0 100644
--- a/src/main/java/net/minecraft/server/DispenseBehaviorProjectile.java
+++ b/src/main/java/net/minecraft/server/DispenseBehaviorProjectile.java
@@ -18,9 +18,9 @@ public abstract class DispenseBehaviorProjectile extends DispenseBehaviorItem {
// CraftBukkit start
ItemStack itemstack1 = itemstack.a(1);
org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockX(), isourceblock.getBlockY(), isourceblock.getBlockZ());
- org.bukkit.inventory.ItemStack bukkitItem = new CraftItemStack(itemstack1).clone();
+ CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1);
- BlockDispenseEvent event = new BlockDispenseEvent(block, bukkitItem, new org.bukkit.util.Vector((double) enumfacing.c(), 0.10000000149011612D, (double) enumfacing.e()));
+ BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) enumfacing.c(), 0.10000000149011612D, (double) enumfacing.e()));
if (!BlockDispenser.eventFired) {
world.getServer().getPluginManager().callEvent(event);
}
@@ -30,13 +30,13 @@ public abstract class DispenseBehaviorProjectile extends DispenseBehaviorItem {
return itemstack;
}
- if (!event.getItem().equals(bukkitItem)) {
+ if (!event.getItem().equals(craftItem)) {
itemstack.count++;
// Chain to handler for new item
- ItemStack eventStack = CraftItemStack.createNMSItemStack(event.getItem());
+ ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem());
IDispenseBehavior idispensebehavior = (IDispenseBehavior) BlockDispenser.a.a(eventStack.getItem());
if (idispensebehavior != IDispenseBehavior.a && idispensebehavior != this) {
- idispensebehavior.a(isourceblock, CraftItemStack.createNMSItemStack(event.getItem()));
+ idispensebehavior.a(isourceblock, eventStack);
return itemstack;
}
}
diff --git a/src/main/java/net/minecraft/server/EntityCow.java b/src/main/java/net/minecraft/server/EntityCow.java
index cc512b1b..3bbdb2fa 100644
--- a/src/main/java/net/minecraft/server/EntityCow.java
+++ b/src/main/java/net/minecraft/server/EntityCow.java
@@ -88,9 +88,9 @@ public class EntityCow extends EntityAnimal {
}
if (--itemstack.count <= 0) {
- entityhuman.inventory.setItem(entityhuman.inventory.itemInHandIndex, CraftItemStack.createNMSItemStack(event.getItemStack()));
+ entityhuman.inventory.setItem(entityhuman.inventory.itemInHandIndex, CraftItemStack.asNMSCopy(event.getItemStack()));
} else if (!entityhuman.inventory.pickup(new ItemStack(Item.MILK_BUCKET))) {
- entityhuman.drop(CraftItemStack.createNMSItemStack(event.getItemStack()));
+ entityhuman.drop(CraftItemStack.asNMSCopy(event.getItemStack()));
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/EntityGhast.java b/src/main/java/net/minecraft/server/EntityGhast.java
index 031ebb0e..3dc67c08 100644
--- a/src/main/java/net/minecraft/server/EntityGhast.java
+++ b/src/main/java/net/minecraft/server/EntityGhast.java
@@ -208,13 +208,13 @@ public class EntityGhast extends EntityFlying implements IMonster {
int k;
if (j > 0) {
- loot.add(new CraftItemStack(Item.GHAST_TEAR.id, j));
+ loot.add(CraftItemStack.asNewCraftStack(Item.GHAST_TEAR, j));
}
j = this.random.nextInt(3) + this.random.nextInt(1 + i);
if (j > 0) {
- loot.add(new CraftItemStack(Item.SULPHUR.id, j));
+ loot.add(CraftItemStack.asNewCraftStack(Item.SULPHUR, j));
}
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, loot);
diff --git a/src/main/java/net/minecraft/server/EntityIronGolem.java b/src/main/java/net/minecraft/server/EntityIronGolem.java
index 5b6ab93d..e6e260fa 100644
--- a/src/main/java/net/minecraft/server/EntityIronGolem.java
+++ b/src/main/java/net/minecraft/server/EntityIronGolem.java
@@ -150,13 +150,13 @@ public class EntityIronGolem extends EntityGolem {
int k;
if (j > 0) {
- loot.add(new CraftItemStack(Block.RED_ROSE.id, j));
+ loot.add(CraftItemStack.asNewCraftStack(Item.byId[Block.RED_ROSE.id], j));
}
k = 3 + this.random.nextInt(3);
if (k > 0) {
- loot.add(new CraftItemStack(Item.IRON_INGOT.id, k));
+ loot.add(CraftItemStack.asNewCraftStack(Item.IRON_INGOT, k));
}
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, loot);
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index 5f6a40bb..08ffc62c 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -894,7 +894,7 @@ public abstract class EntityLiving extends Entity {
if (k < 5) {
ItemStack itemstack = this.l(k <= 0 ? 1 : 0);
if (itemstack != null) {
- loot.add(new org.bukkit.craftbukkit.inventory.CraftItemStack(itemstack));
+ loot.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack));
}
}
}
diff --git a/src/main/java/net/minecraft/server/EntityMinecart.java b/src/main/java/net/minecraft/server/EntityMinecart.java
index 54c3584a..29edbc3d 100644
--- a/src/main/java/net/minecraft/server/EntityMinecart.java
+++ b/src/main/java/net/minecraft/server/EntityMinecart.java
@@ -188,7 +188,7 @@ public class EntityMinecart extends Entity implements IInventory {
itemstack.count -= k;
// CraftBukkit - include enchantments in the new itemstack
- EntityItem entityitem = new EntityItem(this.world, this.locX + (double) f, this.locY + (double) f1, this.locZ + (double) f2, new ItemStack(itemstack.id, k, itemstack.getData(), itemstack.getEnchantments()));
+ EntityItem entityitem = new EntityItem(this.world, this.locX + (double) f, this.locY + (double) f1, this.locZ + (double) f2, org.bukkit.craftbukkit.inventory.CraftItemStack.copyNMSStack(itemstack, k));
float f3 = 0.05F;
entityitem.motX = (double) ((float) this.random.nextGaussian() * f3);
diff --git a/src/main/java/net/minecraft/server/EntityPigZombie.java b/src/main/java/net/minecraft/server/EntityPigZombie.java
index 94c7ac00..d3bd681e 100644
--- a/src/main/java/net/minecraft/server/EntityPigZombie.java
+++ b/src/main/java/net/minecraft/server/EntityPigZombie.java
@@ -117,13 +117,13 @@ public class EntityPigZombie extends EntityZombie {
int j = this.random.nextInt(2 + i);
if (j > 0) {
- loot.add(new CraftItemStack(Item.ROTTEN_FLESH.id, j));
+ loot.add(CraftItemStack.asNewCraftStack(Item.ROTTEN_FLESH, j));
}
j = this.random.nextInt(2 + i);
if (j > 0) {
- loot.add(new CraftItemStack(Item.GOLD_NUGGET.id, j));
+ loot.add(CraftItemStack.asNewCraftStack(Item.GOLD_NUGGET, j));
}
// Determine rare item drops and add them to the loot
@@ -133,7 +133,7 @@ public class EntityPigZombie extends EntityZombie {
if (k < 5) {
ItemStack itemstack = this.l(k <= 0 ? 1 : 0);
if (itemstack != null) {
- loot.add(new CraftItemStack(itemstack));
+ loot.add(CraftItemStack.asCraftMirror(itemstack));
}
}
}
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 35a679ad..775e988b 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -240,13 +240,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
if (!keepInventory) {
for (int i = 0; i < this.inventory.items.length; ++i) {
if (this.inventory.items[i] != null) {
- loot.add(new CraftItemStack(this.inventory.items[i]));
+ loot.add(CraftItemStack.asCraftMirror(this.inventory.items[i]));
}
}
for (int i = 0; i < this.inventory.armor.length; ++i) {
if (this.inventory.armor[i] != null) {
- loot.add(new CraftItemStack(this.inventory.armor[i]));
+ loot.add(CraftItemStack.asCraftMirror(this.inventory.armor[i]));
}
}
}
diff --git a/src/main/java/net/minecraft/server/EntitySkeleton.java b/src/main/java/net/minecraft/server/EntitySkeleton.java
index 39296ae3..aba1e88c 100644
--- a/src/main/java/net/minecraft/server/EntitySkeleton.java
+++ b/src/main/java/net/minecraft/server/EntitySkeleton.java
@@ -167,7 +167,7 @@ public class EntitySkeleton extends EntityMonster implements IRangedEntity {
if (k < 5) {
ItemStack itemstack = this.l(k <= 0 ? 1 : 0);
if (itemstack != null) {
- loot.add(new org.bukkit.craftbukkit.inventory.CraftItemStack(itemstack));
+ loot.add(org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemstack));
}
}
}
diff --git a/src/main/java/net/minecraft/server/ItemBucket.java b/src/main/java/net/minecraft/server/ItemBucket.java
index 5aa39216..9a1ee774 100644
--- a/src/main/java/net/minecraft/server/ItemBucket.java
+++ b/src/main/java/net/minecraft/server/ItemBucket.java
@@ -56,13 +56,13 @@ public class ItemBucket extends Item {
return itemstack;
}
- ItemStack result = CraftItemStack.createNMSItemStack(event.getItemStack()); // CraftBukkit - TODO: Check this stuff later... Not sure how this behavior should work
+ ItemStack result = CraftItemStack.asNMSCopy(event.getItemStack()); // CraftBukkit - TODO: Check this stuff later... Not sure how this behavior should work
if (--itemstack.count <= 0) {
return result; // CraftBukkit
}
if (!entityhuman.inventory.pickup(result)) { // CraftBukkit
- entityhuman.drop(CraftItemStack.createNMSItemStack(event.getItemStack())); // CraftBukkit
+ entityhuman.drop(CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit
}
return itemstack;
@@ -81,13 +81,13 @@ public class ItemBucket extends Item {
return itemstack;
}
- ItemStack result = CraftItemStack.createNMSItemStack(event.getItemStack()); // CraftBukkit - TODO: Check this stuff later... Not sure how this behavior should work
+ ItemStack result = CraftItemStack.asNMSCopy(event.getItemStack()); // CraftBukkit - TODO: Check this stuff later... Not sure how this behavior should work
if (--itemstack.count <= 0) {
return result; // CraftBukkit
}
if (!entityhuman.inventory.pickup(result)) { // CraftBukkit
- entityhuman.drop(CraftItemStack.createNMSItemStack(event.getItemStack())); // CraftBukkit
+ entityhuman.drop(CraftItemStack.asNMSCopy(event.getItemStack())); // CraftBukkit
}
return itemstack;
@@ -101,7 +101,7 @@ public class ItemBucket extends Item {
return itemstack;
}
- return CraftItemStack.createNMSItemStack(event.getItemStack());
+ return CraftItemStack.asNMSCopy(event.getItemStack());
}
int clickedX = i, clickedY = j, clickedZ = k;
@@ -144,7 +144,7 @@ public class ItemBucket extends Item {
// CraftBukkit end
if (this.a(world, d0, d1, d2, i, j, k) && !entityhuman.abilities.canInstantlyBuild) {
- return CraftItemStack.createNMSItemStack(event.getItemStack()); // CraftBukkit
+ return CraftItemStack.asNMSCopy(event.getItemStack()); // CraftBukkit
}
}
} else if (this.a == 0 && movingobjectposition.entity instanceof EntityCow) {
@@ -156,7 +156,7 @@ public class ItemBucket extends Item {
return itemstack;
}
- return CraftItemStack.createNMSItemStack(event.getItemStack());
+ return CraftItemStack.asNMSCopy(event.getItemStack());
// CraftBukkit end
}
diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java
index ac6bc3c1..d0a60c2d 100644
--- a/src/main/java/net/minecraft/server/ItemStack.java
+++ b/src/main/java/net/minecraft/server/ItemStack.java
@@ -41,21 +41,6 @@ public final class ItemStack {
this.setData(k); // CraftBukkit
}
- // CraftBukkit start - used to create a new ItemStack, specifying the enchantments at time of creation.
- public ItemStack(int id, int count, int data, NBTTagList enchantments) {
- this(id, count, data);
- // taken from .addEnchantment
- if (enchantments != null && Item.byId[this.id].getMaxStackSize() == 1) {
- if (this.tag == null) {
- this.setTag(new NBTTagCompound());
- }
-
- this.tag.set("ench", enchantments.clone()); // modify this part to use passed in enchantments list
- // TODO Books, Skulls, Item Names, Item Lore
- }
- }
- // CraftBukkit end
-
public static ItemStack a(NBTTagCompound nbttagcompound) {
ItemStack itemstack = new ItemStack();
diff --git a/src/main/java/net/minecraft/server/NBTTagCompound.java b/src/main/java/net/minecraft/server/NBTTagCompound.java
index 0b9beb7d..0e021c66 100644
--- a/src/main/java/net/minecraft/server/NBTTagCompound.java
+++ b/src/main/java/net/minecraft/server/NBTTagCompound.java
@@ -35,13 +35,9 @@ public class NBTTagCompound extends NBTBase {
} catch (java.io.IOException ex) {
ex.printStackTrace();
}
+ // CraftBukkit end
}
- public void remove(String name) {
- map.remove(name);
- }
- // CraftBukkit end
-
void load(DataInput datainput) {
this.map.clear();
diff --git a/src/main/java/net/minecraft/server/NetServerHandler.java b/src/main/java/net/minecraft/server/NetServerHandler.java
index 084d0aff..88afae43 100644
--- a/src/main/java/net/minecraft/server/NetServerHandler.java
+++ b/src/main/java/net/minecraft/server/NetServerHandler.java
@@ -1230,11 +1230,11 @@ public class NetServerHandler extends NetHandler {
if (cursor == null) {
this.player.inventory.setCarried((ItemStack) null);
} else {
- this.player.inventory.setCarried(CraftItemStack.createNMSItemStack(cursor));
+ this.player.inventory.setCarried(CraftItemStack.asNMSCopy(cursor));
}
org.bukkit.inventory.ItemStack item = event.getCurrentItem();
if (item != null) {
- itemstack = CraftItemStack.createNMSItemStack(item);
+ itemstack = CraftItemStack.asNMSCopy(item);
if (packet102windowclick.slot == -999) {
this.player.drop(itemstack);
} else {
@@ -1307,16 +1307,16 @@ public class NetServerHandler extends NetHandler {
if (item == null) {
this.player.defaultContainer.setItem(packet107setcreativeslot.slot, (ItemStack) null);
} else {
- this.player.defaultContainer.setItem(packet107setcreativeslot.slot, CraftItemStack.createNMSItemStack(item));
+ this.player.defaultContainer.setItem(packet107setcreativeslot.slot, CraftItemStack.asNMSCopy(item));
}
} else if (item != null) {
- this.player.drop(CraftItemStack.createNMSItemStack(item));
+ this.player.drop(CraftItemStack.asNMSCopy(item));
}
return;
case DENY:
// TODO: Will this actually work?
if (packet107setcreativeslot.slot > -1) {
- this.player.netServerHandler.sendPacket(new Packet103SetSlot(this.player.defaultContainer.windowId, packet107setcreativeslot.slot, CraftItemStack.createNMSItemStack(item)));
+ this.player.netServerHandler.sendPacket(new Packet103SetSlot(this.player.defaultContainer.windowId, packet107setcreativeslot.slot, CraftItemStack.asNMSCopy(item)));
}
return;
case DEFAULT:
diff --git a/src/main/java/net/minecraft/server/ShapedRecipes.java b/src/main/java/net/minecraft/server/ShapedRecipes.java
index 0a48d45b..e3126b6b 100644
--- a/src/main/java/net/minecraft/server/ShapedRecipes.java
+++ b/src/main/java/net/minecraft/server/ShapedRecipes.java
@@ -23,7 +23,7 @@ public class ShapedRecipes implements IRecipe {
// CraftBukkit start
public org.bukkit.inventory.ShapedRecipe toBukkitRecipe() {
- CraftItemStack result = new CraftItemStack(this.result);
+ CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
CraftShapedRecipe recipe = new CraftShapedRecipe(result, this);
switch (this.height) {
case 1:
diff --git a/src/main/java/net/minecraft/server/ShapelessRecipes.java b/src/main/java/net/minecraft/server/ShapelessRecipes.java
index f14d78be..3c08c2a6 100644
--- a/src/main/java/net/minecraft/server/ShapelessRecipes.java
+++ b/src/main/java/net/minecraft/server/ShapelessRecipes.java
@@ -22,7 +22,7 @@ public class ShapelessRecipes implements IRecipe {
// CraftBukkit start
@SuppressWarnings("unchecked")
public org.bukkit.inventory.ShapelessRecipe toBukkitRecipe() {
- CraftItemStack result = new CraftItemStack(this.result);
+ CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
CraftShapelessRecipe recipe = new CraftShapelessRecipe(result, this);
for (ItemStack stack : (List<ItemStack>) this.ingredients) {
if (stack != null) {
diff --git a/src/main/java/net/minecraft/server/TileEntityFurnace.java b/src/main/java/net/minecraft/server/TileEntityFurnace.java
index bf4ed58d..17b9611a 100644
--- a/src/main/java/net/minecraft/server/TileEntityFurnace.java
+++ b/src/main/java/net/minecraft/server/TileEntityFurnace.java
@@ -172,7 +172,7 @@ public class TileEntityFurnace extends TileEntity implements IInventory {
if (!this.world.isStatic) {
// CraftBukkit start - handle multiple elapsed ticks
if (this.burnTime <= 0 && this.canBurn() && this.items[1] != null) { // CraftBukkit - == to <=
- CraftItemStack fuel = new CraftItemStack(this.items[1]);
+ CraftItemStack fuel = CraftItemStack.asCraftMirror(this.items[1]);
FurnaceBurnEvent furnaceBurnEvent = new FurnaceBurnEvent(this.world.getWorld().getBlockAt(this.x, this.y, this.z), fuel, fuelTime(this.items[1]));
this.world.getServer().getPluginManager().callEvent(furnaceBurnEvent);
@@ -237,8 +237,8 @@ public class TileEntityFurnace extends TileEntity implements IInventory {
ItemStack itemstack = RecipesFurnace.getInstance().getResult(this.items[0].getItem().id);
// CraftBukkit start
- CraftItemStack source = new CraftItemStack(this.items[0]);
- CraftItemStack result = new CraftItemStack(itemstack.cloneItemStack());
+ CraftItemStack source = CraftItemStack.asCraftMirror(this.items[0]);
+ CraftItemStack result = CraftItemStack.asCraftMirror(itemstack.cloneItemStack());
FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(this.world.getWorld().getBlockAt(this.x, this.y, this.z), source, result);
this.world.getServer().getPluginManager().callEvent(furnaceSmeltEvent);
@@ -247,7 +247,7 @@ public class TileEntityFurnace extends TileEntity implements IInventory {
return;
}
- itemstack = CraftItemStack.createNMSItemStack(furnaceSmeltEvent.getResult());
+ itemstack = CraftItemStack.asNMSCopy(furnaceSmeltEvent.getResult());
if (this.items[2] == null) {
this.items[2] = itemstack.cloneItemStack();
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index b0a2e697..6f957c53 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -71,6 +71,7 @@ import org.bukkit.conversations.Conversable;
import org.bukkit.craftbukkit.help.SimpleHelpMap;
import org.bukkit.craftbukkit.inventory.CraftFurnaceRecipe;
import org.bukkit.craftbukkit.inventory.CraftInventoryCustom;
+import org.bukkit.craftbukkit.inventory.CraftItemFactory;
import org.bukkit.craftbukkit.inventory.CraftRecipe;
import org.bukkit.craftbukkit.inventory.CraftShapedRecipe;
import org.bukkit.craftbukkit.inventory.CraftShapelessRecipe;
@@ -161,6 +162,7 @@ public final class CraftServer implements Server {
static {
ConfigurationSerialization.registerClass(CraftOfflinePlayer.class);
+ CraftItemFactory.instance();
}
public CraftServer(MinecraftServer console, ServerConfigurationManagerAbstract server) {
@@ -1320,4 +1322,8 @@ public final class CraftServer implements Server {
Collections.sort(completions, String.CASE_INSENSITIVE_ORDER);
return completions;
}
+
+ public CraftItemFactory getItemFactory() {
+ return CraftItemFactory.instance();
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 346b1833..19d891d7 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -283,8 +283,7 @@ public class CraftWorld implements World {
public org.bukkit.entity.Item dropItem(Location loc, ItemStack item) {
Validate.notNull(item, "Cannot drop a Null item.");
Validate.isTrue(item.getTypeId() != 0, "Cannot drop AIR.");
- CraftItemStack clone = new CraftItemStack(item);
- EntityItem entity = new EntityItem(world, loc.getX(), loc.getY(), loc.getZ(), clone.getHandle());
+ EntityItem entity = new EntityItem(world, loc.getX(), loc.getY(), loc.getZ(), CraftItemStack.asNMSCopy(item));
entity.pickupDelay = 10;
world.addEntity(entity);
// TODO this is inconsistent with how Entity.getBukkitEntity() works.
diff --git a/src/main/java/org/bukkit/craftbukkit/Overridden.java b/src/main/java/org/bukkit/craftbukkit/Overridden.java
new file mode 100644
index 00000000..1c19c69f
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/Overridden.java
@@ -0,0 +1,14 @@
+package org.bukkit.craftbukkit;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates a method needs to be overridden in sub classes
+ */
+@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Overridden {
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
index 7dcdc7d2..c4bd959a 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java
@@ -74,11 +74,11 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
}
public ItemStack getItemOnCursor() {
- return new CraftItemStack(getHandle().inventory.getCarried());
+ return CraftItemStack.asCraftMirror(getHandle().inventory.getCarried());
}
public void setItemOnCursor(ItemStack item) {
- net.minecraft.server.ItemStack stack = CraftItemStack.createNMSItemStack(item);
+ net.minecraft.server.ItemStack stack = CraftItemStack.asNMSCopy(item);
getHandle().inventory.setCarried(stack);
if (this instanceof CraftPlayer) {
((EntityPlayer) getHandle()).broadcastCarriedItem(); // Send set slot for cursor
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
index 049d52ee..6bdfe3e7 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItem.java
@@ -22,11 +22,11 @@ public class CraftItem extends CraftEntity implements Item {
}
public ItemStack getItemStack() {
- return new CraftItemStack(item.itemStack);
+ return CraftItemStack.asCraftMirror(item.itemStack);
}
public void setItemStack(ItemStack stack) {
- item.itemStack = CraftItemStack.createNMSItemStack(stack);
+ item.itemStack = CraftItemStack.asNMSCopy(stack);
}
public int getPickupDelay() {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java
index 9183e612..ef95acd6 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java
@@ -20,12 +20,12 @@ public class CraftItemFrame extends CraftHanging implements ItemFrame {
getHandle().getDataWatcher().a(2, 5);
getHandle().getDataWatcher().h(2);
} else {
- getHandle().a(CraftItemStack.createNMSItemStack(item));
+ getHandle().a(CraftItemStack.asNMSCopy(item));
}
}
public org.bukkit.inventory.ItemStack getItem() {
- return CraftItemStack.asBukkitStack(getHandle().i());
+ return CraftItemStack.asBukkitCopy(getHandle().i());
}
public Rotation getRotation() {
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index e225cbf4..106db16e 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -115,7 +115,7 @@ public class CraftEventFactory {
private static PlayerEvent getPlayerBucketEvent(boolean isFilling, EntityHuman who, int clickedX, int clickedY, int clickedZ, int clickedFace, ItemStack itemstack, net.minecraft.server.Item item) {
Player player = (who == null) ? null : (Player) who.getBukkitEntity();
- CraftItemStack itemInHand = new CraftItemStack(new ItemStack(item));
+ CraftItemStack itemInHand = CraftItemStack.asNewCraftStack(item);
Material bucket = Material.getMaterial(itemstack.id);
CraftWorld craftWorld = (CraftWorld) player.getWorld();
@@ -150,7 +150,7 @@ public class CraftEventFactory {
public static PlayerInteractEvent callPlayerInteractEvent(EntityHuman who, Action action, int clickedX, int clickedY, int clickedZ, int clickedFace, ItemStack itemstack) {
Player player = (who == null) ? null : (Player) who.getBukkitEntity();
- CraftItemStack itemInHand = new CraftItemStack(itemstack);
+ CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack);
CraftWorld craftWorld = (CraftWorld) player.getWorld();
CraftServer craftServer = (CraftServer) player.getServer();
@@ -185,7 +185,7 @@ public class CraftEventFactory {
*/
public static EntityShootBowEvent callEntityShootBowEvent(EntityLiving who, ItemStack itemstack, EntityArrow entityArrow, float force) {
LivingEntity shooter = (LivingEntity) who.getBukkitEntity();
- CraftItemStack itemInHand = new CraftItemStack(itemstack);
+ CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack);
Arrow arrow = (Arrow) entityArrow.getBukkitEntity();
if (itemInHand != null && (itemInHand.getType() == Material.AIR || itemInHand.getAmount() == 0)) {
@@ -203,7 +203,7 @@ public class CraftEventFactory {
*/
public static BlockDamageEvent callBlockDamageEvent(EntityHuman who, int x, int y, int z, ItemStack itemstack, boolean instaBreak) {
Player player = (who == null) ? null : (Player) who.getBukkitEntity();
- CraftItemStack itemInHand = new CraftItemStack(itemstack);
+ CraftItemStack itemInHand = CraftItemStack.asCraftMirror(itemstack);
CraftWorld craftWorld = (CraftWorld) player.getWorld();
CraftServer craftServer = (CraftServer) player.getServer();
@@ -317,13 +317,7 @@ public class CraftEventFactory {
for (org.bukkit.inventory.ItemStack stack : event.getDrops()) {
if (stack == null || stack.getType() == Material.AIR) continue;
- if (stack instanceof CraftItemStack) {
- // Use the internal item to preserve possible data.
- victim.a(((CraftItemStack) stack).getHandle(), 0.0f);
- }
- else {
- world.dropItemNaturally(entity.getLocation(), stack);
- }
+ world.dropItemNaturally(entity.getLocation(), stack);
}
return event;
@@ -344,12 +338,7 @@ public class CraftEventFactory {
for (org.bukkit.inventory.ItemStack stack : event.getDrops()) {
if (stack == null || stack.getType() == Material.AIR) continue;
- if (stack instanceof CraftItemStack) {
- // Use the internal item to preserve possible data.
- victim.a(((CraftItemStack) stack).getHandle(), 0.0f);
- } else {
- world.dropItemNaturally(entity.getLocation(), stack);
- }
+ world.dropItemNaturally(entity.getLocation(), stack);
}
return event;
@@ -519,14 +508,14 @@ public class CraftEventFactory {
public static ItemStack callPreCraftEvent(InventoryCrafting matrix, ItemStack result, InventoryView lastCraftView, boolean isRepair) {
CraftInventoryCrafting inventory = new CraftInventoryCrafting(matrix, matrix.resultInventory);
- inventory.setResult(new CraftItemStack(result));
+ inventory.setResult(CraftItemStack.asCraftMirror(result));
PrepareItemCraftEvent event = new PrepareItemCraftEvent(inventory, lastCraftView, isRepair);
Bukkit.getPluginManager().callEvent(event);
org.bukkit.inventory.ItemStack bitem = event.getInventory().getResult();
- return CraftItemStack.createNMSItemStack(bitem);
+ return CraftItemStack.asNMSCopy(bitem);
}
public static ProjectileLaunchEvent callProjectileLaunchEvent(Entity entity) {
@@ -556,7 +545,7 @@ public class CraftEventFactory {
}
public static void callPlayerItemBreakEvent(EntityHuman human, ItemStack brokenItem) {
- CraftItemStack item = new CraftItemStack(brokenItem);
+ CraftItemStack item = CraftItemStack.asCraftMirror(brokenItem);
PlayerItemBreakEvent event = new PlayerItemBreakEvent((Player) human.getBukkitEntity(), item);
Bukkit.getPluginManager().callEvent(event);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java
index c402cf8c..2aca0eae 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftEntityEquipment.java
@@ -75,11 +75,11 @@ public class CraftEntityEquipment implements EntityEquipment {
}
private ItemStack getEquipment(int slot) {
- return CraftItemStack.asBukkitStack(entity.getHandle().getEquipment(slot));
+ return CraftItemStack.asBukkitCopy(entity.getHandle().getEquipment(slot));
}
private void setEquipment(int slot, ItemStack stack) {
- entity.getHandle().setEquipment(slot, CraftItemStack.createNMSItemStack(stack));
+ entity.getHandle().setEquipment(slot, CraftItemStack.asNMSCopy(stack));
}
public void clear() {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftFurnaceRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftFurnaceRecipe.java
index 0df39891..34efe17e 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftFurnaceRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftFurnaceRecipe.java
@@ -20,6 +20,6 @@ public class CraftFurnaceRecipe extends FurnaceRecipe implements CraftRecipe {
public void addToCraftingManager() {
ItemStack result = this.getResult();
ItemStack input = this.getInput();
- RecipesFurnace.getInstance().registerRecipe(input.getTypeId(), CraftItemStack.createNMSItemStack(result), 0.1f);
+ RecipesFurnace.getInstance().registerRecipe(input.getTypeId(), CraftItemStack.asNMSCopy(result), 0.1f);
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
index d60b1d82..537a479a 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
@@ -44,7 +44,7 @@ public class CraftInventory implements Inventory {
public ItemStack getItem(int index) {
net.minecraft.server.ItemStack item = getInventory().getItem(index);
- return item == null ? null : new CraftItemStack(item);
+ return item == null ? null : CraftItemStack.asCraftMirror(item);
}
public ItemStack[] getContents() {
@@ -52,7 +52,7 @@ public class CraftInventory implements Inventory {
net.minecraft.server.ItemStack[] mcItems = getInventory().getContents();
for (int i = 0; i < mcItems.length; i++) {
- items[i] = mcItems[i] == null ? null : new CraftItemStack(mcItems[i]);
+ items[i] = mcItems[i] == null ? null : CraftItemStack.asCraftMirror(mcItems[i]);
}
return items;
@@ -69,13 +69,13 @@ public class CraftInventory implements Inventory {
if (i >= items.length) {
mcItems[i] = null;
} else {
- mcItems[i] = CraftItemStack.createNMSItemStack(items[i]);
+ mcItems[i] = CraftItemStack.asNMSCopy(items[i]);
}
}
}
public void setItem(int index, ItemStack item) {
- getInventory().setItem(index, ((item == null || item.getTypeId() == 0) ? null : CraftItemStack.createNMSItemStack(item)));
+ getInventory().setItem(index, ((item == null || item.getTypeId() == 0) ? null : CraftItemStack.asNMSCopy(item)));
}
public boolean contains(int materialId) {
@@ -229,7 +229,7 @@ public class CraftInventory implements Inventory {
public int firstPartial(ItemStack item) {
ItemStack[] inventory = getContents();
- ItemStack filteredItem = new CraftItemStack(item);
+ ItemStack filteredItem = CraftItemStack.asCraftCopy(item);
if (item == null) {
return -1;
}
@@ -269,8 +269,7 @@ public class CraftInventory implements Inventory {
} else {
// More than a single stack!
if (item.getAmount() > getMaxItemStack()) {
- CraftItemStack stack = new CraftItemStack(item.getTypeId(), getMaxItemStack(), item.getDurability());
- stack.addUnsafeEnchantments(item.getEnchantments());
+ CraftItemStack stack = CraftItemStack.asCraftCopy(item);
setItem(firstFree, stack);
item.setAmount(item.getAmount() - getMaxItemStack());
} else {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCrafting.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCrafting.java
index 81bde2c7..7bbf1df5 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCrafting.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCrafting.java
@@ -47,13 +47,13 @@ public class CraftInventoryCrafting extends CraftInventory implements CraftingIn
int i = 0;
for (i = 0; i < mcResultItems.length; i++ ) {
- items[i] = new CraftItemStack(mcResultItems[i]);
+ items[i] = CraftItemStack.asCraftMirror(mcResultItems[i]);
}
net.minecraft.server.ItemStack[] mcItems = getMatrixInventory().getContents();
for (int j = 0; j < mcItems.length; j++) {
- items[i + j] = new CraftItemStack(mcItems[j]);
+ items[i + j] = CraftItemStack.asCraftMirror(mcItems[j]);
}
return items;
@@ -68,19 +68,19 @@ public class CraftInventoryCrafting extends CraftInventory implements CraftingIn
public CraftItemStack getItem(int index) {
if (index < getResultInventory().getSize()) {
net.minecraft.server.ItemStack item = getResultInventory().getItem(index);
- return item == null ? null : new CraftItemStack(item);
+ return item == null ? null : CraftItemStack.asCraftMirror(item);
} else {
net.minecraft.server.ItemStack item = getMatrixInventory().getItem(index - getResultInventory().getSize());
- return item == null ? null : new CraftItemStack(item);
+ return item == null ? null : CraftItemStack.asCraftMirror(item);
}
}
@Override
public void setItem(int index, ItemStack item) {
if (index < getResultInventory().getSize()) {
- getResultInventory().setItem(index, (item == null ? null : CraftItemStack.createNMSItemStack(item)));
+ getResultInventory().setItem(index, (item == null ? null : CraftItemStack.asNMSCopy(item)));
} else {
- getMatrixInventory().setItem((index - getResultInventory().getSize()), (item == null ? null : CraftItemStack.createNMSItemStack(item)));
+ getMatrixInventory().setItem((index - getResultInventory().getSize()), (item == null ? null : CraftItemStack.asNMSCopy(item)));
}
}
@@ -89,7 +89,7 @@ public class CraftInventoryCrafting extends CraftInventory implements CraftingIn
net.minecraft.server.ItemStack[] matrix = getMatrixInventory().getContents();
for (int i = 0; i < matrix.length; i++ ) {
- items[i] = new CraftItemStack(matrix[i]);
+ items[i] = CraftItemStack.asCraftMirror(matrix[i]);
}
return items;
@@ -97,7 +97,7 @@ public class CraftInventoryCrafting extends CraftInventory implements CraftingIn
public ItemStack getResult() {
net.minecraft.server.ItemStack item = getResultInventory().getItem(0);
- if(item != null) return new CraftItemStack(item);
+ if(item != null) return CraftItemStack.asCraftMirror(item);
return null;
}
@@ -114,7 +114,7 @@ public class CraftInventoryCrafting extends CraftInventory implements CraftingIn
if (item == null || item.getTypeId() <= 0) {
mcItems[i] = null;
} else {
- mcItems[i] = CraftItemStack.createNMSItemStack(item);
+ mcItems[i] = CraftItemStack.asNMSCopy(item);
}
} else {
mcItems[i] = null;
@@ -127,7 +127,7 @@ public class CraftInventoryCrafting extends CraftInventory implements CraftingIn
if (item == null || item.getTypeId() <= 0) {
contents[0] = null;
} else {
- contents[0] = CraftItemStack.createNMSItemStack(item);
+ contents[0] = CraftItemStack.asNMSCopy(item);
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java
index f54df7c4..6fb6cb8b 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryCustom.java
@@ -66,7 +66,7 @@ public class CraftInventoryCustom extends CraftInventory {
this.setItem(i, null);
result = stack;
} else {
- result = new ItemStack(stack.id, j, stack.getData(), stack.getEnchantments());
+ result = CraftItemStack.copyNMSStack(stack, j);
stack.count -= j;
}
this.update();
@@ -81,7 +81,7 @@ public class CraftInventoryCustom extends CraftInventory {
this.setItem(i, null);
result = stack;
} else {
- result = new ItemStack(stack.id, 1, stack.getData(), stack.getEnchantments());
+ result = CraftItemStack.copyNMSStack(stack, 1);
stack.count -= 1;
}
return result;
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
index 9b7172d3..85bec9b7 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
@@ -22,7 +22,7 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
}
public ItemStack getItemInHand() {
- return new CraftItemStack(getInventory().getItemInHand());
+ return CraftItemStack.asCraftMirror(getInventory().getItemInHand());
}
public void setItemInHand(ItemStack stack) {
@@ -70,7 +70,7 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
ItemStack[] ret = new ItemStack[mcItems.length];
for (int i = 0; i < mcItems.length; i++) {
- ret[i] = new CraftItemStack(mcItems[i]);
+ ret[i] = CraftItemStack.asCraftMirror(mcItems[i]);
}
return ret;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java
index 0e930914..6ffc73de 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryView.java
@@ -49,7 +49,7 @@ public class CraftInventoryView extends InventoryView {
@Override
public void setItem(int slot, ItemStack item) {
- net.minecraft.server.ItemStack stack = CraftItemStack.createNMSItemStack(item);
+ net.minecraft.server.ItemStack stack = CraftItemStack.asNMSCopy(item);
if (slot != -999) {
container.getSlot(slot).set(stack);
} else {
@@ -62,7 +62,7 @@ public class CraftInventoryView extends InventoryView {
if (slot == -999) {
return null;
}
- return new CraftItemStack(container.getSlot(slot).getItem());
+ return CraftItemStack.asCraftMirror(container.getSlot(slot).getItem());
}
public boolean isInTop(int rawSlot) {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
new file mode 100644
index 00000000..b2bcf344
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
@@ -0,0 +1,123 @@
+package org.bukkit.craftbukkit.inventory;
+
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.Color;
+import org.bukkit.Material;
+import org.bukkit.configuration.serialization.ConfigurationSerialization;
+import org.bukkit.inventory.ItemFactory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+
+public final class CraftItemFactory implements ItemFactory {
+ static final Color DEFAULT_LEATHER_COLOR = Color.fromRGB(0xA06540);
+ private static final CraftItemFactory instance;
+
+ static {
+ instance = new CraftItemFactory();
+ ConfigurationSerialization.registerClass(CraftMetaItem.SerializableMeta.class);
+ }
+
+ private CraftItemFactory() {
+ }
+
+ public boolean isApplicable(ItemMeta meta, ItemStack itemstack) {
+ if (itemstack == null) {
+ return false;
+ }
+ return isApplicable(meta, itemstack.getType());
+ }
+
+ public boolean isApplicable(ItemMeta meta, Material type) {
+ if (type == null || meta == null) {
+ return false;
+ }
+ if (!(meta instanceof CraftMetaItem)) {
+ throw new IllegalArgumentException("Meta of " + meta.getClass().toString() + " not created by " + CraftItemFactory.class.getName());
+ }
+
+ return ((CraftMetaItem) meta).applicableTo(type);
+ }
+
+ public ItemMeta getItemMeta(Material material) {
+ Validate.notNull(material, "Material cannot be null");
+ return getItemMeta(material, null);
+ }
+
+ private ItemMeta getItemMeta(Material material, CraftMetaItem meta) {
+ switch (material) {
+ case AIR:
+ return null;
+ case WRITTEN_BOOK:
+ case BOOK_AND_QUILL:
+ return meta instanceof CraftMetaBook ? meta : new CraftMetaBook(meta);
+ case SKULL_ITEM:
+ return meta instanceof CraftMetaSkull ? meta : new CraftMetaSkull(meta);
+ case LEATHER_HELMET:
+ case LEATHER_CHESTPLATE:
+ case LEATHER_LEGGINGS:
+ case LEATHER_BOOTS:
+ return meta instanceof CraftMetaLeatherArmor ? meta : new CraftMetaLeatherArmor(meta);
+ case POTION:
+ return meta instanceof CraftMetaPotion ? meta : new CraftMetaPotion(meta);
+ case MAP:
+ return meta instanceof CraftMetaMap ? meta : new CraftMetaMap(meta);
+ default:
+ return new CraftMetaItem(meta);
+ }
+ }
+
+ public boolean equals(ItemMeta meta1, ItemMeta meta2) {
+ if (meta1 == meta2) {
+ return true;
+ }
+ if (meta1 != null && !(meta1 instanceof CraftMetaItem)) {
+ throw new IllegalArgumentException("First meta of " + meta1.getClass().getName() + " does not belong to " + CraftItemFactory.class.getName());
+ }
+ if (meta2 != null && !(meta2 instanceof CraftMetaItem)) {
+ throw new IllegalArgumentException("Second meta " + meta2.getClass().getName() + " does not belong to " + CraftItemFactory.class.getName());
+ }
+ if (meta1 == null) {
+ return ((CraftMetaItem) meta2).isEmpty();
+ }
+ if (meta2 == null) {
+ return ((CraftMetaItem) meta1).isEmpty();
+ }
+
+ return equals((CraftMetaItem) meta1, (CraftMetaItem) meta2);
+ }
+
+ boolean equals(CraftMetaItem meta1, CraftMetaItem meta2) {
+ /*
+ * This couldn't be done inside of the objects themselves, else force recursion.
+ * This is a fairly clean way of implementing it, by dividing the methods into purposes and letting each method perform its own function.
+ *
+ * The common and uncommon were split, as both could have variables not applicable to the other, like a skull and book.
+ * Each object needs its chance to say "hey wait a minute, we're not equal," but without the redundancy of using the 1.equals(2) && 2.equals(1) checking the 'commons' twice.
+ *
+ * Doing it this way fills all conditions of the .equals() method.
+ */
+ return meta1.equalsCommon(meta2) && meta1.notUncommon(meta2) && meta2.notUncommon(meta1);
+ }
+
+ public static CraftItemFactory instance() {
+ return instance;
+ }
+
+ public ItemMeta asMetaFor(ItemMeta meta, ItemStack stack) {
+ Validate.notNull(stack, "Stack cannot be null");
+ return asMetaFor(meta, stack.getType());
+ }
+
+ public ItemMeta asMetaFor(ItemMeta meta, Material material) {
+ Validate.notNull(material, "Material cannot be null");
+ if (!(meta instanceof CraftMetaItem)) {
+ throw new IllegalArgumentException("Meta of " + (meta != null ? meta.getClass().toString() : "null") + " not created by " + CraftItemFactory.class.getName());
+ }
+ return getItemMeta(material, (CraftMetaItem) meta);
+ }
+
+ public Color getDefaultLeatherColor() {
+ return DEFAULT_LEATHER_COLOR;
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
index 84b28a98..7de7c1d0 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
@@ -1,134 +1,150 @@
package org.bukkit.craftbukkit.inventory;
-import java.util.HashMap;
import java.util.Map;
+
import net.minecraft.server.EnchantmentManager;
import net.minecraft.server.NBTTagCompound;
import net.minecraft.server.NBTTagList;
+
+import org.apache.commons.lang.Validate;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import com.google.common.collect.ImmutableMap;
@DelegateDeserialization(ItemStack.class)
-public class CraftItemStack extends ItemStack {
- protected net.minecraft.server.ItemStack item;
+public final class CraftItemStack extends ItemStack {
- public CraftItemStack(net.minecraft.server.ItemStack item) {
- super(
- item != null ? item.id: 0,
- item != null ? item.count : 0,
- (short)(item != null ? item.getData() : 0)
- );
- this.item = item;
+ public static net.minecraft.server.ItemStack asNMSCopy(ItemStack original) {
+ if (original instanceof CraftItemStack) {
+ CraftItemStack stack = (CraftItemStack) original;
+ return stack.handle == null ? null : stack.handle.cloneItemStack();
+ }
+ if (original == null || original.getTypeId() <= 0) {
+ return null;
+ }
+ net.minecraft.server.ItemStack stack = new net.minecraft.server.ItemStack(original.getTypeId(), original.getAmount(), original.getDurability());
+ if (original.hasItemMeta()) {
+ setItemMeta(stack, original.getItemMeta());
+ }
+ return stack;
}
- public CraftItemStack(ItemStack item) {
- this(item.getTypeId(), item.getAmount(), item.getDurability());
- addUnsafeEnchantments(item.getEnchantments());
+ public static net.minecraft.server.ItemStack copyNMSStack(net.minecraft.server.ItemStack original, int amount) {
+ net.minecraft.server.ItemStack stack = original.cloneItemStack();
+ stack.count = amount;
+ return stack;
}
- /* 'Overwritten' constructors from ItemStack, yay for Java sucking */
- public CraftItemStack(final int type) {
- this(type, 1);
+ /**
+ * Copies the NMS stack to return as a strictly-Bukkit stack
+ */
+ public static ItemStack asBukkitCopy(net.minecraft.server.ItemStack original) {
+ if (original == null) {
+ return new ItemStack(Material.AIR);
+ }
+ ItemStack stack = new ItemStack(original.id, original.count, (short) original.getData());
+ if (hasItemMeta(original)) {
+ stack.setItemMeta(getItemMeta(original));
+ }
+ return stack;
}
- public CraftItemStack(final Material type) {
- this(type, 1);
+ public static CraftItemStack asCraftMirror(net.minecraft.server.ItemStack original) {
+ return new CraftItemStack(original);
}
- public CraftItemStack(final int type, final int amount) {
- this(type, amount, (byte) 0);
+ public static CraftItemStack asCraftCopy(ItemStack original) {
+ if (original instanceof CraftItemStack) {
+ CraftItemStack stack = (CraftItemStack) original;
+ return new CraftItemStack(stack.handle == null ? null : stack.handle.cloneItemStack());
+ }
+ return new CraftItemStack(original);
}
- public CraftItemStack(final Material type, final int amount) {
- this(type.getId(), amount);
+ public static CraftItemStack asNewCraftStack(net.minecraft.server.Item item) {
+ return asNewCraftStack(item, 1);
}
- public CraftItemStack(final int type, final int amount, final short damage) {
- this(type, amount, damage, null);
+ public static CraftItemStack asNewCraftStack(net.minecraft.server.Item item, int amount) {
+ return new CraftItemStack(item.id, amount, (short) 0, null);
}
- public CraftItemStack(final Material type, final int amount, final short damage) {
- this(type.getId(), amount, damage);
- }
+ net.minecraft.server.ItemStack handle;
- public CraftItemStack(final Material type, final int amount, final short damage, final Byte data) {
- this(type.getId(), amount, damage, data);
+ /**
+ * Mirror
+ */
+ private CraftItemStack(net.minecraft.server.ItemStack item) {
+ this.handle = item;
}
- public CraftItemStack(int type, int amount, short damage, Byte data) {
- this(new net.minecraft.server.ItemStack(type, amount, data != null ? data : damage));
+ private CraftItemStack(ItemStack item) {
+ this(item.getTypeId(), item.getAmount(), item.getDurability(), item.hasItemMeta() ? item.getItemMeta() : null);
}
- /*
- * Unsure if we have to sync before each of these calls the values in 'item'
- * are all public.
- */
-
- @Override
- public Material getType() {
- super.setTypeId(item != null ? item.id : 0); // sync, needed?
- return super.getType();
+ private CraftItemStack(int typeId, int amount, short durability, ItemMeta itemMeta) {
+ setTypeId(typeId);
+ setAmount(amount);
+ setDurability(durability);
+ setItemMeta(itemMeta);
}
@Override
public int getTypeId() {
- super.setTypeId(item != null ? item.id : 0); // sync, needed?
- return item != null ? item.id : 0;
+ return handle != null ? handle.id : 0;
}
@Override
public void setTypeId(int type) {
- if (type == 0) {
- super.setTypeId(0);
- super.setAmount(0);
- item = null;
+ if (getTypeId() == type) {
+ return;
+ } else if (type == 0) {
+ handle = null;
+ } else if (handle == null) {
+ handle = new net.minecraft.server.ItemStack(type, 1, 0);
} else {
- if (item == null) {
- item = new net.minecraft.server.ItemStack(type, 1, 0);
- super.setTypeId(type);
- super.setAmount(1);
- super.setDurability((short) 0);
- } else {
- item.id = type;
- super.setTypeId(item.id);
+ handle.id = type;
+ if (hasItemMeta()) {
+ // This will create the appropriate item meta, which will contain all the data we intend to keep
+ setItemMeta(handle, getItemMeta(handle));
}
}
+ setData(null);
}
@Override
public int getAmount() {
- super.setAmount(item != null ? item.count : 0); // sync, needed?
- return (item != null ? item.count : 0);
+ return handle != null ? handle.count : 0;
}
@Override
public void setAmount(int amount) {
+ if (handle == null) {
+ return;
+ }
if (amount == 0) {
- super.setTypeId(0);
- super.setAmount(0);
- item = null;
+ handle = null;
} else {
- super.setAmount(amount);
- item.count = amount;
+ handle.count = amount;
}
}
@Override
public void setDurability(final short durability) {
// Ignore damage if item is null
- if (item != null) {
- super.setDurability(durability);
- item.setData(durability);
+ if (handle != null) {
+ handle.setData(durability);
}
}
@Override
public short getDurability() {
- if (item != null) {
- super.setDurability((short) item.getData()); // sync, needed?
- return (short) item.getData();
+ if (handle != null) {
+ return (short) handle.getData();
} else {
return -1;
}
@@ -136,14 +152,46 @@ public class CraftItemStack extends ItemStack {
@Override
public int getMaxStackSize() {
- return (item == null) ? 0 : item.getItem().getMaxStackSize();
+ return (handle == null) ? Material.AIR.getMaxStackSize() : handle.getItem().getMaxStackSize();
}
@Override
public void addUnsafeEnchantment(Enchantment ench, int level) {
- Map<Enchantment, Integer> enchantments = getEnchantments();
- enchantments.put(ench, level);
- rebuildEnchantments(enchantments);
+ Validate.notNull(ench, "Cannot add null enchantment");
+
+ if (!makeTag(handle)) {
+ return;
+ }
+ NBTTagList list = getEnchantmentList(handle), listCopy;
+ if (list == null) {
+ list = new NBTTagList("ench");
+ handle.tag.set("ench", list);
+ }
+ int size = list.size();
+
+ for (int i = 0; i < size; i++) {
+ NBTTagCompound tag = (NBTTagCompound) list.get(i);
+ short id = tag.getShort("id");
+ if (id == ench.getId()) {
+ tag.setShort("lvl", (short) level);
+ return;
+ }
+ }
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setShort("id", (short) ench.getId());
+ tag.setShort("lvl", (short) level);
+ list.add(tag);
+ }
+
+ static boolean makeTag(net.minecraft.server.ItemStack item) {
+ if (item == null) {
+ return false;
+ }
+ if (item.tag != null) {
+ return true;
+ }
+ item.tag = new NBTTagCompound();
+ return true;
}
@Override
@@ -153,31 +201,65 @@ public class CraftItemStack extends ItemStack {
@Override
public int getEnchantmentLevel(Enchantment ench) {
- if (item == null) return 0;
- return EnchantmentManager.getEnchantmentLevel(ench.getId(), item);
+ Validate.notNull(ench, "Cannot find null enchantment");
+ if (handle == null) {
+ return 0;
+ }
+ return EnchantmentManager.getEnchantmentLevel(ench.getId(), handle);
}
@Override
public int removeEnchantment(Enchantment ench) {
- Map<Enchantment, Integer> enchantments = getEnchantments();
- Integer previous = enchantments.remove(ench);
+ Validate.notNull(ench, "Cannot remove null enchantment");
- rebuildEnchantments(enchantments);
+ NBTTagList list = getEnchantmentList(handle), listCopy;
+ if (list == null) {
+ return 0;
+ }
+ int index = Integer.MIN_VALUE, size = list.size(), level;
- return (previous == null) ? 0 : previous;
+ for (int i = 0; i < size; i++) {
+ short id = ((NBTTagCompound) list.get(i)).getShort("id");
+ if (id == ench.getId()) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index == Integer.MIN_VALUE) {
+ return 0;
+ }
+ if (index == 0 && size == 0) {
+ handle.tag.o("ench");
+ if (handle.tag.d()) {
+ handle.tag = null;
+ }
+ }
+
+ listCopy = new NBTTagList("ench");
+ level = Integer.MAX_VALUE;
+ for (int i = 0; i < size; i++) {
+ if (i == index) {
+ level = ((NBTTagCompound) list.get(i)).getShort("id");
+ continue;
+ }
+ listCopy.add(list.get(i));
+ }
+ handle.tag.set("ench", listCopy);
+ return level;
}
@Override
public Map<Enchantment, Integer> getEnchantments() {
- return getEnchantments(item);
+ return getEnchantments(handle);
}
- public static Map<Enchantment, Integer> getEnchantments(net.minecraft.server.ItemStack item) {
- Map<Enchantment, Integer> result = new HashMap<Enchantment, Integer>();
+ static Map<Enchantment, Integer> getEnchantments(net.minecraft.server.ItemStack item) {
+ ImmutableMap.Builder<Enchantment, Integer> result = ImmutableMap.builder();
NBTTagList list = (item == null) ? null : item.getEnchantments();
if (list == null) {
- return result;
+ return result.build();
}
for (int i = 0; i < list.size(); i++) {
@@ -187,66 +269,111 @@ public class CraftItemStack extends ItemStack {
result.put(Enchantment.getById(id), (int) level);
}
- return result;
+ return result.build();
}
- private void rebuildEnchantments(Map<Enchantment, Integer> enchantments) {
- if (item == null) return;
-
- NBTTagCompound tag = item.tag;
- NBTTagList list = new NBTTagList("ench");
+ static NBTTagList getEnchantmentList(net.minecraft.server.ItemStack item) {
+ return item == null ? null : item.getEnchantments();
+ }
- if (tag == null) {
- tag = item.tag = new NBTTagCompound();
+ @Override
+ public CraftItemStack clone() {
+ CraftItemStack itemStack = (CraftItemStack) super.clone();
+ if (this.handle != null) {
+ itemStack.handle = this.handle.cloneItemStack();
}
+ return itemStack;
+ }
- for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
- NBTTagCompound subtag = new NBTTagCompound();
-
- subtag.setShort("id", (short) entry.getKey().getId());
- subtag.setShort("lvl", (short) (int) entry.getValue());
+ @Override
+ public ItemMeta getItemMeta() {
+ return getItemMeta(handle);
+ }
- list.add(subtag);
+ static ItemMeta getItemMeta(net.minecraft.server.ItemStack item) {
+ if (!hasItemMeta(item)) {
+ return CraftItemFactory.instance().getItemMeta(getType(item));
}
-
- if (enchantments.isEmpty()) {
- tag.remove("ench");
- } else {
- tag.set("ench", list);
+ switch (getType(item)) {
+ case WRITTEN_BOOK:
+ case BOOK_AND_QUILL:
+ return new CraftMetaBook(item.tag);
+ case SKULL_ITEM:
+ return new CraftMetaSkull(item.tag);
+ case LEATHER_HELMET:
+ case LEATHER_CHESTPLATE:
+ case LEATHER_LEGGINGS:
+ case LEATHER_BOOTS:
+ return new CraftMetaLeatherArmor(item.tag);
+ case POTION:
+ return new CraftMetaPotion(item.tag);
+ case MAP:
+ return new CraftMetaMap(item.tag);
+ default:
+ return new CraftMetaItem(item.tag);
}
}
- public net.minecraft.server.ItemStack getHandle() {
- return item;
+ static Material getType(net.minecraft.server.ItemStack item) {
+ Material material = Material.getMaterial(item == null ? 0 : item.id);
+ return material == null ? Material.AIR : material;
}
@Override
- public CraftItemStack clone() {
- CraftItemStack itemStack = (CraftItemStack) super.clone();
- if (this.item != null) {
- itemStack.item = this.item.cloneItemStack();
- }
- return itemStack;
+ public boolean setItemMeta(ItemMeta itemMeta) {
+ return setItemMeta(handle, itemMeta);
}
- public static net.minecraft.server.ItemStack createNMSItemStack(ItemStack original) {
- if (original == null || original.getTypeId() <= 0) {
- return null;
- } else if (original instanceof CraftItemStack) {
- return ((CraftItemStack) original).getHandle();
+ static boolean setItemMeta(net.minecraft.server.ItemStack item, ItemMeta itemMeta) {
+ if (item == null) {
+ return false;
+ }
+ if (itemMeta == null) {
+ item.tag = null;
+ return true;
}
- return new CraftItemStack(original).getHandle();
+ if (!CraftItemFactory.instance().isApplicable(itemMeta, getType(item))) {
+ return false;
+ }
+
+ NBTTagCompound tag = new NBTTagCompound();
+ item.setTag(tag);
+
+ ((CraftMetaItem) itemMeta).applyToItem(tag);
+ return true;
}
- /**
- * Copies the NMS stack to return as a strictly-Bukkit stack
- */
- public static ItemStack asBukkitStack(net.minecraft.server.ItemStack original) {
- if (original == null) {
- return new ItemStack(Material.AIR);
+ @Override
+ public boolean isSimilar(ItemStack stack) {
+ if (stack == null) {
+ return false;
}
- ItemStack stack = new ItemStack(original.id, original.count, (short) original.getData());
- stack.addUnsafeEnchantments(getEnchantments(original));
- return stack;
+ if (stack == this) {
+ return true;
+ }
+ if (!(stack instanceof CraftItemStack)) {
+ return stack.getClass() == ItemStack.class && stack.isSimilar(this);
+ }
+
+ CraftItemStack that = (CraftItemStack) stack;
+ if (handle == that.handle) {
+ return true;
+ }
+ if (handle == null || that.handle == null) {
+ return false;
+ }
+ if (!(that.getTypeId() == getTypeId() && getDurability() == that.getDurability())) {
+ return false;
+ }
+ return hasItemMeta() ? that.hasItemMeta() && handle.tag.equals(that.handle.tag) : !that.hasItemMeta();
+ }
+
+ @Override
+ public boolean hasItemMeta() {
+ return hasItemMeta(handle);
+ }
+
+ static boolean hasItemMeta(net.minecraft.server.ItemStack item) {
+ return !(item == null || item.tag == null || item.tag.d());
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java
new file mode 100644
index 00000000..b49974b5
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java
@@ -0,0 +1,272 @@
+package org.bukkit.craftbukkit.inventory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import net.minecraft.server.NBTTagCompound;
+import net.minecraft.server.NBTTagList;
+import net.minecraft.server.NBTTagString;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.Material;
+import org.bukkit.configuration.serialization.DelegateDeserialization;
+import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
+import org.bukkit.inventory.meta.BookMeta;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap.Builder;
+
+@DelegateDeserialization(SerializableMeta.class)
+class CraftMetaBook extends CraftMetaItem implements BookMeta {
+ static final ItemMetaKey BOOK_TITLE = new ItemMetaKey("title");
+ static final ItemMetaKey BOOK_AUTHOR = new ItemMetaKey("author");
+ static final ItemMetaKey BOOK_PAGES = new ItemMetaKey("pages");
+ static final int MAX_PAGE_LENGTH = 256;
+ static final int MAX_TITLE_LENGTH = 0xffff;
+
+ private String title;
+ private String author;
+ private List<String> pages = new ArrayList<String>();
+
+ CraftMetaBook(CraftMetaItem meta) {
+ super(meta);
+
+ if (!(meta instanceof CraftMetaBook)) {
+ return;
+ }
+ CraftMetaBook bookMeta = (CraftMetaBook) meta;
+ this.title = bookMeta.title;
+ this.author = bookMeta.author;
+ pages.addAll(bookMeta.pages);
+ }
+
+ CraftMetaBook(NBTTagCompound tag) {
+ super(tag);
+
+ if (tag.hasKey(BOOK_TITLE.NBT)) {
+ this.title = tag.getString(BOOK_TITLE.NBT);
+ }
+
+ if (tag.hasKey(BOOK_AUTHOR.NBT)) {
+ this.author = tag.getString(BOOK_AUTHOR.NBT);
+ }
+
+ if (tag.hasKey(BOOK_PAGES.NBT)) {
+ NBTTagList pages = tag.getList(BOOK_PAGES.NBT);
+ String[] pageArray = new String[pages.size()];
+
+ for (int i = 0; i < pages.size(); i++) {
+ String page = ((NBTTagString) pages.get(i)).data;
+ pageArray[i] = page;
+ }
+
+ addPage(pageArray);
+ }
+ }
+
+ CraftMetaBook(Map<String, Object> map) {
+ super(map);
+
+ setAuthor(SerializableMeta.getString(map, BOOK_AUTHOR.BUKKIT, true));
+
+ setTitle(SerializableMeta.getString(map, BOOK_TITLE.BUKKIT, true));
+
+ Collection<?> pages = SerializableMeta.getObject(Collection.class, map, BOOK_PAGES.BUKKIT, true);
+ CraftMetaItem.safelyAdd(pages, this.pages, MAX_PAGE_LENGTH);
+ }
+
+ @Override
+ void applyToItem(NBTTagCompound itemData) {
+ super.applyToItem(itemData);
+
+ if (hasTitle()) {
+ itemData.setString(BOOK_TITLE.NBT, this.title);
+ }
+
+ if (hasAuthor()) {
+ itemData.setString(BOOK_AUTHOR.NBT, this.author);
+ }
+
+ if (hasPages()) {
+ NBTTagList itemPages = new NBTTagList(BOOK_PAGES.NBT);
+ for (int i = 1; i < pages.size() + 1; i++) {
+ itemPages.add(new NBTTagString(String.valueOf(i), pages.get(i - 1)));
+ }
+ itemData.set(BOOK_PAGES.NBT, itemPages);
+ }
+ }
+
+ @Override
+ boolean isEmpty() {
+ return super.isEmpty() && isBookEmpty();
+ }
+
+ boolean isBookEmpty() {
+ return !(hasPages() || hasAuthor() || hasTitle());
+ }
+
+ @Override
+ boolean applicableTo(Material type) {
+ switch (type) {
+ case WRITTEN_BOOK:
+ case BOOK_AND_QUILL:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public boolean hasAuthor() {
+ return !Strings.isNullOrEmpty(author);
+ }
+
+ public boolean hasTitle() {
+ return !Strings.isNullOrEmpty(title);
+ }
+
+ public boolean hasPages() {
+ return !pages.isEmpty();
+ }
+
+ public String getTitle() {
+ return this.title;
+ }
+
+ public boolean setTitle(final String title) {
+ if (title == null) {
+ this.title = null;
+ return true;
+ } else if (title.length() > MAX_TITLE_LENGTH) {
+ return false;
+ }
+
+ this.title = title;
+ return true;
+ }
+
+ public String getAuthor() {
+ return this.author;
+ }
+
+ public void setAuthor(final String author) {
+ this.author = author;
+ }
+
+ public String getPage(final int page) {
+ Validate.isTrue(isValidPage(page), "Invalid page number");
+ return pages.get(page - 1);
+ }
+
+ public void setPage(final int page, final String text) {
+ if (!isValidPage(page)) {
+ throw new IllegalArgumentException("Invalid page number " + page + "/" + pages.size());
+ }
+
+ pages.set(page - 1, text == null ? "" : text.length() > MAX_PAGE_LENGTH ? text.substring(0, MAX_PAGE_LENGTH) : text);
+ }
+
+ public void setPages(final String... pages) {
+ this.pages.clear();
+
+ addPage(pages);
+ }
+
+ public void addPage(final String... pages) {
+ for (String page : pages) {
+ if (page == null) {
+ page = "";
+ } else if (page.length() > MAX_PAGE_LENGTH) {
+ page = page.substring(0, MAX_PAGE_LENGTH);
+ }
+
+ this.pages.add(page);
+ }
+ }
+
+ public int getPageCount() {
+ return pages.size();
+ }
+
+ public List<String> getPages() {
+ return ImmutableList.copyOf(pages);
+ }
+
+ public void setPages(List<String> pages) {
+ this.pages.clear();
+ CraftMetaItem.safelyAdd(pages, this.pages, MAX_PAGE_LENGTH);
+ }
+
+ private boolean isValidPage(int page) {
+ return page > 0 && page <= pages.size();
+ }
+
+ @Override
+ public CraftMetaBook clone() {
+ CraftMetaBook meta = (CraftMetaBook) super.clone();
+ meta.pages = new ArrayList<String>(pages);
+ return meta;
+ }
+
+ @Override
+ int applyHash() {
+ final int original;
+ int hash = original = super.applyHash();
+ if (hasTitle()) {
+ hash = 61 * hash + this.title.hashCode();
+ }
+ if (hasAuthor()) {
+ hash = 61 * hash + 13 * this.author.hashCode();
+ }
+ if (hasPages()) {
+ hash = 61 * hash + 17 * this.pages.hashCode();
+ }
+ return original != hash ? CraftMetaBook.class.hashCode() ^ hash : hash;
+ }
+
+ @Override
+ boolean equalsCommon(CraftMetaItem meta) {
+ if (!super.equalsCommon(meta)) {
+ return false;
+ }
+ if (meta instanceof CraftMetaBook) {
+ CraftMetaBook that = (CraftMetaBook) meta;
+
+ return (hasTitle() ? that.hasTitle() && this.title.equals(that.title) : !that.hasTitle())
+ && (hasAuthor() ? that.hasAuthor() && this.author.equals(that.author) : !that.hasAuthor())
+ && (hasPages() ? that.hasPages() && this.pages.equals(that.pages) : !that.hasPages());
+ }
+ return true;
+ }
+
+ @Override
+ boolean notUncommon(CraftMetaItem meta) {
+ return super.notUncommon(meta) && (meta instanceof CraftMetaBook || isBookEmpty());
+ }
+
+ @Override
+ Builder<String, Object> serialize(Builder<String, Object> builder) {
+ super.serialize(builder);
+
+ if (hasTitle()) {
+ builder.put(BOOK_TITLE.BUKKIT, title);
+ }
+
+ if (hasAuthor()) {
+ builder.put(BOOK_AUTHOR.BUKKIT, author);
+ }
+
+ if (hasPages()) {
+ builder.put(BOOK_PAGES.BUKKIT, pages);
+ }
+
+ return builder;
+ }
+
+ @Override
+ SerializableMeta.Deserializers deserializer() {
+ return SerializableMeta.Deserializers.BOOK;
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
new file mode 100644
index 00000000..87709d73
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -0,0 +1,510 @@
+package org.bukkit.craftbukkit.inventory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import net.minecraft.server.NBTBase;
+import net.minecraft.server.NBTTagCompound;
+import net.minecraft.server.NBTTagList;
+import net.minecraft.server.NBTTagString;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.Material;
+import org.bukkit.configuration.serialization.ConfigurationSerializable;
+import org.bukkit.configuration.serialization.DelegateDeserialization;
+import org.bukkit.configuration.serialization.SerializableAs;
+import org.bukkit.craftbukkit.Overridden;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.inventory.meta.Repairable;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Children must include the following:
+ *
+ * <li> Constructor(CraftMetaItem meta)
+ * <li> Constructor(NBTTagCompound tag)
+ * <li> Constructor(Map<String, Object> map)
+ * <br><br>
+ * <li> void applyToItem(NBTTagCompound tag)
+ * <li> boolean applicableTo(Material type)
+ * <br><br>
+ * <li> boolean notUncommon(CraftMetaItem meta)
+ * <li> boolean equalsCommon(CraftMetaItem meta)
+ * <br><br>
+ * <li> boolean isEmpty()
+ * <li> boolean is{Type}Empty()
+ * <br><br>
+ * <li> int applyHash()
+ * <li> public Class clone()
+ * <br><br>
+ * <li> Builder<String, Object> serialize(Builder<String, Object> builder)
+ * <li> SerializableMeta.Deserializers deserializer()
+ */
+@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
+class CraftMetaItem implements ItemMeta, Repairable {
+ static class ItemMetaKey {
+ final String BUKKIT;
+ final String NBT;
+
+ ItemMetaKey(final String both) {
+ this(both, both);
+ }
+
+ ItemMetaKey(final String nbt, final String bukkit) {
+ this.NBT = nbt;
+ this.BUKKIT = bukkit;
+ }
+ }
+
+ @SerializableAs("ItemMeta")
+ public static class SerializableMeta implements ConfigurationSerializable {
+ static final String TYPE_FIELD = "meta-type";
+
+ enum Deserializers {
+ BOOK {
+ @Override
+ CraftMetaBook deserialize(Map<String, Object> map) {
+ return new CraftMetaBook(map);
+ }
+ },
+ SKULL {
+ @Override
+ CraftMetaSkull deserialize(Map<String, Object> map) {
+ return new CraftMetaSkull(map);
+ }
+ },
+ LEATHER_ARMOR {
+ @Override
+ CraftMetaLeatherArmor deserialize(Map<String, Object> map) {
+ return new CraftMetaLeatherArmor(map);
+ }
+ },
+ MAP {
+ @Override
+ CraftMetaMap deserialize(Map<String, Object> map) {
+ return new CraftMetaMap(map);
+ }
+ },
+ POTION {
+ @Override
+ CraftMetaPotion deserialize(Map<String, Object> map) {
+ return new CraftMetaPotion(map);
+ }
+ },
+ UNSPECIFIC {
+ @Override
+ CraftMetaItem deserialize(Map<String, Object> map) {
+ return new CraftMetaItem(map);
+ }
+ };
+
+ abstract CraftMetaItem deserialize(Map<String, Object> map);
+ }
+
+ private SerializableMeta() {
+ }
+
+ public static ItemMeta deserialize(Map<String, Object> map) {
+ Validate.notNull(map, "Cannot deserialize null map");
+
+ String type = getString(map, TYPE_FIELD, false);
+ Deserializers deserializer = Deserializers.valueOf(type);
+
+ if (deserializer == null) {
+ throw new IllegalArgumentException(type + " is not a valid " + TYPE_FIELD);
+ }
+
+ return deserializer.deserialize(map);
+ }
+
+ public Map<String, Object> serialize() {
+ throw new AssertionError();
+ }
+
+ static String getString(Map<?, ?> map, Object field, boolean nullable) {
+ return getObject(String.class, map, field, nullable);
+ }
+
+ static boolean getBoolean(Map<?, ?> map, Object field) {
+ Boolean value = getObject(Boolean.class, map, field, true);
+ return value != null && value;
+ }
+
+ static <T> T getObject(Class<T> clazz, Map<?, ?> map, Object field, boolean nullable) {
+ final Object object = map.get(field);
+
+ if (clazz.isInstance(object)) {
+ return clazz.cast(object);
+ }
+ if (object == null) {
+ if (!nullable) {
+ throw new NoSuchElementException(map + " does not contain " + field);
+ }
+ return null;
+ }
+ throw new IllegalArgumentException(field + "(" + object + ") is not a valid " + clazz);
+ }
+ }
+
+ static final ItemMetaKey NAME = new ItemMetaKey("Name", "display-name");
+ static final ItemMetaKey DISPLAY = new ItemMetaKey("display");
+ static final ItemMetaKey LORE = new ItemMetaKey("Lore", "lore");
+ static final ItemMetaKey ENCHANTMENTS = new ItemMetaKey("ench", "enchants");
+ static final ItemMetaKey ENCHANTMENTS_ID = new ItemMetaKey("id");
+ static final ItemMetaKey ENCHANTMENTS_LVL = new ItemMetaKey("lvl");
+ static final ItemMetaKey REPAIR = new ItemMetaKey("RepairCost", "repair-cost");
+
+ private String displayName;
+ private List<String> lore;
+ private Map<Enchantment, Integer> enchantments;
+ private int repairCost;
+
+ CraftMetaItem(CraftMetaItem meta) {
+ if (meta == null) {
+ return;
+ }
+
+ this.displayName = meta.displayName;
+
+ if (meta.hasLore()) {
+ this.lore = new ArrayList<String>(meta.lore);
+ }
+
+ if (meta.hasEnchants()) {
+ this.enchantments = new HashMap<Enchantment, Integer>(meta.enchantments);
+ }
+
+ this.repairCost = meta.repairCost;
+ }
+
+ CraftMetaItem(NBTTagCompound tag) {
+ if (tag.hasKey(DISPLAY.NBT)) {
+ NBTTagCompound display = tag.getCompound(DISPLAY.NBT);
+
+ if (display.hasKey(NAME.NBT)) {
+ displayName = display.getString(NAME.NBT);
+ }
+
+ if (display.hasKey(LORE.NBT)) {
+ NBTTagList list = display.getList(LORE.NBT);
+ lore = new ArrayList<String>(list.size());
+
+ for (int index = 0; index < list.size(); index++) {
+ String line = ((NBTTagString) list.get(index)).data;
+ lore.add(line);
+ }
+ }
+ }
+
+ if (tag.hasKey(ENCHANTMENTS.NBT)) {
+ NBTTagList ench = tag.getList(ENCHANTMENTS.NBT);
+ enchantments = new HashMap<Enchantment, Integer>(ench.size());
+
+ for (int i = 0; i < ench.size(); i++) {
+ short id = ((NBTTagCompound) ench.get(i)).getShort(ENCHANTMENTS_ID.NBT);
+ short level = ((NBTTagCompound) ench.get(i)).getShort(ENCHANTMENTS_LVL.NBT);
+
+ addEnchant(Enchantment.getById(id), (int) level, true);
+ }
+ }
+
+ if (tag.hasKey(REPAIR.NBT)) {
+ repairCost = tag.getInt(REPAIR.NBT);
+ }
+ }
+
+ CraftMetaItem(Map<String, Object> map) {
+ setDisplayName(SerializableMeta.getString(map, NAME.BUKKIT, true));
+
+ if (map.containsKey(LORE.BUKKIT)) {
+ lore = (List<String>) map.get(LORE.BUKKIT);
+ }
+
+ Map<?, ?> ench = SerializableMeta.getObject(Map.class, map, ENCHANTMENTS.BUKKIT, true);
+ if (ench != null) {
+ enchantments = new HashMap<Enchantment, Integer>(ench.size());
+ for (Map.Entry<?, ?> entry : ench.entrySet()) {
+ Enchantment enchantment = Enchantment.getByName(entry.getKey().toString());
+
+ if ((enchantment != null) && (entry.getValue() instanceof Integer)) {
+ addEnchant(enchantment, (Integer) entry.getValue(), true);
+ }
+ }
+ }
+
+ if (map.containsKey(REPAIR.BUKKIT)) {
+ repairCost = (Integer) map.get(REPAIR.BUKKIT);
+ }
+ }
+
+ @Overridden
+ void applyToItem(NBTTagCompound itemTag) {
+ if (hasDisplayName()) {
+ setDisplayTag(itemTag, NAME.NBT, new NBTTagString(NAME.NBT, displayName));
+ }
+
+ if (hasLore()) {
+ NBTTagList list = new NBTTagList(LORE.NBT);
+ for (int i = 0; i < lore.size(); i++) {
+ list.add(new NBTTagString(String.valueOf(i), lore.get(i)));
+ }
+ setDisplayTag(itemTag, LORE.NBT, list);
+ }
+
+ if (hasEnchants()) {
+ NBTTagList list = new NBTTagList(ENCHANTMENTS.NBT);
+
+ for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
+ NBTTagCompound subtag = new NBTTagCompound();
+
+ subtag.setShort(ENCHANTMENTS_ID.NBT, (short) entry.getKey().getId());
+ subtag.setShort(ENCHANTMENTS_LVL.NBT, (short) (int) entry.getValue());
+
+ list.add(subtag);
+ }
+
+ itemTag.set(ENCHANTMENTS.NBT, list);
+ }
+
+ if (hasRepairCost()) {
+ itemTag.setInt(REPAIR.NBT, repairCost);
+ }
+ }
+
+ void setDisplayTag(NBTTagCompound tag, String key, NBTBase value) {
+ final NBTTagCompound display = tag.getCompound(DISPLAY.NBT);
+
+ if (!tag.hasKey(DISPLAY.NBT)) {
+ tag.setCompound(DISPLAY.NBT, display);
+ }
+
+ display.set(key, value);
+ }
+
+ @Overridden
+ boolean applicableTo(Material type) {
+ return type != Material.AIR;
+ }
+
+ @Overridden
+ boolean isEmpty() {
+ return !(hasDisplayName() || hasEnchants() || hasLore());
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public final void setDisplayName(String name) {
+ this.displayName = name;
+ }
+
+ public boolean hasDisplayName() {
+ return !Strings.isNullOrEmpty(displayName);
+ }
+
+ public boolean hasLore() {
+ return this.lore != null && !this.lore.isEmpty();
+ }
+
+ public boolean hasRepairCost() {
+ return repairCost > 0;
+ }
+
+ public boolean hasEnchant(Enchantment ench) {
+ return hasEnchants() ? enchantments.containsKey(ench) : false;
+ }
+
+ public int getEnchantLevel(Enchantment ench) {
+ Integer level = hasEnchants() ? enchantments.get(ench) : null;
+ if (level == null) {
+ return 0;
+ }
+ return level;
+ }
+
+ public Map<Enchantment, Integer> getEnchants() {
+ return hasEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.<Enchantment, Integer>of();
+ }
+
+ public boolean addEnchant(Enchantment ench, int level, boolean ignoreRestrictions) {
+ if (enchantments == null) {
+ enchantments = new HashMap<Enchantment, Integer>(4);
+ }
+
+ if (ignoreRestrictions || level >= ench.getStartLevel() && level <= ench.getMaxLevel()) {
+ Integer old = enchantments.put(ench, level);
+ return old == null || old != level;
+ }
+ return false;
+ }
+
+ public boolean removeEnchant(Enchantment ench) {
+ return hasEnchants() ? enchantments.remove(ench) != null : false;
+ }
+
+ public boolean hasEnchants() {
+ return !(enchantments == null || enchantments.isEmpty());
+ }
+
+ public List<String> getLore() {
+ return this.lore == null ? null : new ArrayList<String>(this.lore);
+ }
+
+ public void setLore(List<String> lore) { // too tired to think if .clone is better
+ if (lore == null) {
+ this.lore = null;
+ } else {
+ if (this.lore == null) {
+ safelyAdd(lore, this.lore = new ArrayList<String>(lore.size()), Integer.MAX_VALUE);
+ } else {
+ this.lore.clear();
+ safelyAdd(lore, this.lore, Integer.MAX_VALUE);
+ }
+ }
+ }
+
+ public int getRepairCost() {
+ return repairCost;
+ }
+
+ public void setRepairCost(int cost) { // TODO: Does this have limits?
+ repairCost = cost;
+ }
+
+ @Override
+ public final boolean equals(Object object) {
+ if (object == null) {
+ return false;
+ }
+ if (object == this) {
+ return true;
+ }
+ if (!(object instanceof CraftMetaItem)) {
+ return false;
+ }
+ return CraftItemFactory.instance().equals(this, (ItemMeta) object);
+ }
+
+ /**
+ * This method is almost as weird as notUncommon.
+ * Only return false if your common internals are unequal.
+ * Checking your own internals is redundant if you are not common, as notUncommon is meant for checking those 'not common' variables.
+ */
+ @Overridden
+ boolean equalsCommon(CraftMetaItem that) {
+ return ((this.hasDisplayName() ? that.hasDisplayName() && this.displayName.equals(that.displayName) : !that.hasDisplayName()))
+ && (this.hasEnchants() ? that.hasEnchants() && this.enchantments.equals(that.enchantments) : !that.hasEnchants())
+ && (this.hasLore() ? that.hasLore() && this.lore.equals(that.lore) : !that.hasLore())
+ && (this.hasRepairCost() ? that.hasRepairCost() && this.repairCost == that.repairCost : !that.hasRepairCost());
+ }
+
+ /**
+ * This method is a bit weird...
+ * Return true if you are a common class OR your uncommon parts are empty.
+ * Empty uncommon parts implies the NBT data would be equivalent if both were applied to an item
+ */
+ @Overridden
+ boolean notUncommon(CraftMetaItem meta) {
+ return true;
+ }
+
+ @Override
+ public final int hashCode() {
+ return applyHash();
+ }
+
+ @Overridden
+ int applyHash() {
+ int hash = 3;
+ hash = 61 * hash + (hasDisplayName() ? this.displayName.hashCode() : 0);
+ hash = 61 * hash + (hasLore() ? this.lore.hashCode() : 0);
+ hash = 61 * hash + (hasEnchants() ? this.enchantments.hashCode() : 0);
+ hash = 61 * hash + (hasRepairCost() ? this.repairCost : 0);
+ return hash;
+ }
+
+ @Overridden
+ @Override
+ public CraftMetaItem clone() {
+ try {
+ return (CraftMetaItem) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new Error(e);
+ }
+ }
+
+ public final Map<String, Object> serialize() {
+ ImmutableMap.Builder<String, Object> map = ImmutableMap.builder();
+ map.put(SerializableMeta.TYPE_FIELD, deserializer().name());
+ serialize(map);
+ return map.build();
+ }
+
+ @Overridden
+ ImmutableMap.Builder<String, Object> serialize(ImmutableMap.Builder<String, Object> builder) {
+ if (hasDisplayName()) {
+ builder.put(NAME.BUKKIT, displayName);
+ }
+
+ if (hasLore()) {
+ builder.put(LORE.BUKKIT, ImmutableList.copyOf(lore));
+ }
+
+ if (hasEnchants()) {
+ ImmutableMap.Builder<String, Integer> enchantments = ImmutableMap.builder();
+ for (Map.Entry<Enchantment, Integer> enchant : this.enchantments.entrySet()) {
+ enchantments.put(enchant.getKey().getName(), enchant.getValue());
+ }
+ builder.put(ENCHANTMENTS.BUKKIT, enchantments.build());
+ }
+
+ if (hasRepairCost()) {
+ builder.put(REPAIR.BUKKIT, repairCost);
+ }
+
+ return builder;
+ }
+
+ @Overridden
+ SerializableMeta.Deserializers deserializer() {
+ return SerializableMeta.Deserializers.UNSPECIFIC;
+ }
+
+ static void safelyAdd(Collection<?> addFrom, Collection<String> addTo, int maxItemLength) {
+ if (addFrom == null) {
+ return;
+ }
+
+ for (Object object : addFrom) {
+ if (!(object instanceof String)) {
+ if (object != null) {
+ throw new IllegalArgumentException(addFrom + " cannot contain non-string " + object.getClass().getName());
+ }
+
+ addTo.add("");
+ } else {
+ String page = object.toString();
+
+ if (page.length() > maxItemLength) {
+ page = page.substring(0, maxItemLength);
+ }
+
+ addTo.add(page);
+ }
+ }
+ }
+
+ @Override
+ public final String toString() {
+ return serialize().toString(); // TODO: cry
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java
new file mode 100644
index 00000000..6cb3bb1f
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaLeatherArmor.java
@@ -0,0 +1,137 @@
+package org.bukkit.craftbukkit.inventory;
+
+import static org.bukkit.craftbukkit.inventory.CraftItemFactory.DEFAULT_LEATHER_COLOR;
+
+import java.util.Map;
+
+import net.minecraft.server.NBTTagCompound;
+import net.minecraft.server.NBTTagInt;
+
+import org.bukkit.Color;
+import org.bukkit.Material;
+import org.bukkit.configuration.serialization.DelegateDeserialization;
+import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
+import org.bukkit.inventory.meta.LeatherArmorMeta;
+
+import com.google.common.collect.ImmutableMap.Builder;
+
+@DelegateDeserialization(SerializableMeta.class)
+class CraftMetaLeatherArmor extends CraftMetaItem implements LeatherArmorMeta {
+ static final ItemMetaKey COLOR = new ItemMetaKey("color");
+
+ private Color color = DEFAULT_LEATHER_COLOR;
+
+ CraftMetaLeatherArmor(CraftMetaItem meta) {
+ super(meta);
+ if (!(meta instanceof CraftMetaLeatherArmor)) {
+ return;
+ }
+
+ CraftMetaLeatherArmor armorMeta = (CraftMetaLeatherArmor) meta;
+ this.color = armorMeta.color;
+ }
+
+ CraftMetaLeatherArmor(NBTTagCompound tag) {
+ super(tag);
+ if (tag.hasKey(DISPLAY.NBT)) {
+ NBTTagCompound display = tag.getCompound(DISPLAY.NBT);
+ if (display.hasKey(COLOR.NBT)) {
+ color = Color.fromRGB(display.getInt(COLOR.NBT));
+ }
+ }
+ }
+
+ CraftMetaLeatherArmor(Map<String, Object> map) {
+ super(map);
+ setColor(SerializableMeta.getObject(Color.class, map, COLOR.BUKKIT, true));
+ }
+
+ void applyToItem(NBTTagCompound itemTag) {
+ super.applyToItem(itemTag);
+
+ if (hasColor()) {
+ setDisplayTag(itemTag, COLOR.NBT, new NBTTagInt(COLOR.NBT, color.asRGB()));
+ }
+ }
+
+ @Override
+ boolean isEmpty() {
+ return super.isEmpty() && isLeatherArmorEmpty();
+ }
+
+ boolean isLeatherArmorEmpty() {
+ return !(hasColor());
+ }
+
+ boolean applicableTo(Material type) {
+ switch(type) {
+ case LEATHER_HELMET:
+ case LEATHER_CHESTPLATE:
+ case LEATHER_LEGGINGS:
+ case LEATHER_BOOTS:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public CraftMetaLeatherArmor clone() {
+ return (CraftMetaLeatherArmor) super.clone();
+ }
+
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color == null ? DEFAULT_LEATHER_COLOR : color;
+ }
+
+ boolean hasColor() {
+ return !DEFAULT_LEATHER_COLOR.equals(color);
+ }
+
+ @Override
+ Builder<String, Object> serialize(Builder<String, Object> builder) {
+ super.serialize(builder);
+
+ if (hasColor()) {
+ builder.put(COLOR.BUKKIT, color);
+ }
+
+ return builder;
+ }
+
+ @Override
+ SerializableMeta.Deserializers deserializer() {
+ return SerializableMeta.Deserializers.LEATHER_ARMOR;
+ }
+
+ @Override
+ boolean equalsCommon(CraftMetaItem meta) {
+ if (!super.equalsCommon(meta)) {
+ return false;
+ }
+ if (meta instanceof CraftMetaLeatherArmor) {
+ CraftMetaLeatherArmor that = (CraftMetaLeatherArmor) meta;
+
+ return color.equals(that.color);
+ }
+ return true;
+ }
+
+ @Override
+ boolean notUncommon(CraftMetaItem meta) {
+ return super.notUncommon(meta) && (meta instanceof CraftMetaLeatherArmor || isLeatherArmorEmpty());
+ }
+
+ int applyHash() {
+ final int original;
+ int hash = original = super.applyHash();
+ if (hasColor()) {
+ hash ^= color.hashCode();
+ }
+ return original != hash ? CraftMetaSkull.class.hashCode() ^ hash : hash;
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMap.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMap.java
new file mode 100644
index 00000000..0bd57c03
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaMap.java
@@ -0,0 +1,139 @@
+package org.bukkit.craftbukkit.inventory;
+
+import java.util.Map;
+
+import net.minecraft.server.NBTTagCompound;
+
+import org.bukkit.Material;
+import org.bukkit.configuration.serialization.DelegateDeserialization;
+import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
+import org.bukkit.inventory.meta.MapMeta;
+
+import com.google.common.collect.ImmutableMap;
+
+@DelegateDeserialization(SerializableMeta.class)
+class CraftMetaMap extends CraftMetaItem implements MapMeta {
+ static final ItemMetaKey MAP_SCALING = new ItemMetaKey("map_is_scaling", "scaling");
+ static final byte SCALING_EMPTY = (byte) 0;
+ static final byte SCALING_TRUE = (byte) 1;
+ static final byte SCALING_FALSE = (byte) 2;
+
+ private byte scaling = SCALING_EMPTY;
+
+ CraftMetaMap(CraftMetaItem meta) {
+ super(meta);
+
+ if (!(meta instanceof CraftMetaMap)) {
+ return;
+ }
+
+ CraftMetaMap map = (CraftMetaMap) meta;
+ this.scaling = map.scaling;
+ }
+
+ CraftMetaMap(NBTTagCompound tag) {
+ super(tag);
+
+ if (tag.hasKey(MAP_SCALING.NBT)) {
+ this.scaling = tag.getBoolean(MAP_SCALING.NBT) ? SCALING_TRUE : SCALING_FALSE;
+ }
+ }
+
+ CraftMetaMap(Map<String, Object> map) {
+ super(map);
+
+ if (map.containsKey(MAP_SCALING.BUKKIT)) {
+ this.scaling = SerializableMeta.getBoolean(map, MAP_SCALING.BUKKIT) ? SCALING_TRUE : SCALING_FALSE;
+ }
+ }
+
+ @Override
+ void applyToItem(NBTTagCompound tag) {
+ super.applyToItem(tag);
+
+ if (hasScaling()) {
+ tag.setBoolean(MAP_SCALING.NBT, isScaling());
+ }
+ }
+
+ @Override
+ boolean applicableTo(Material type) {
+ switch (type) {
+ case MAP:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ boolean isEmpty() {
+ return super.isEmpty() && isMapEmpty();
+ }
+
+ boolean isMapEmpty() {
+ return !hasScaling();
+ }
+
+ boolean hasScaling() {
+ return scaling != SCALING_EMPTY;
+ }
+
+ public boolean isScaling() {
+ return scaling == SCALING_TRUE;
+ }
+
+ public void setScaling(boolean scaling) {
+ this.scaling = scaling ? SCALING_TRUE : SCALING_FALSE;
+ }
+
+ @Override
+ boolean equalsCommon(CraftMetaItem meta) {
+ if (!super.equalsCommon(meta)) {
+ return false;
+ }
+ if (meta instanceof CraftMetaMap) {
+ CraftMetaMap that = (CraftMetaMap) meta;
+
+ return (this.scaling == that.scaling);
+ }
+ return true;
+ }
+
+ @Override
+ boolean notUncommon(CraftMetaItem meta) {
+ return super.notUncommon(meta) && (meta instanceof CraftMetaMap || isMapEmpty());
+ }
+
+ @Override
+ int applyHash() {
+ final int original;
+ int hash = original = super.applyHash();
+
+ if (hasScaling()) {
+ hash ^= 0x22222222 << (isScaling() ? 1 : -1);
+ }
+
+ return original != hash ? CraftMetaMap.class.hashCode() ^ hash : hash;
+ }
+
+ public CraftMetaMap clone() {
+ return (CraftMetaMap) super.clone();
+ }
+
+ @Override
+ ImmutableMap.Builder<String, Object> serialize(ImmutableMap.Builder<String, Object> builder) {
+ super.serialize(builder);
+
+ if (hasScaling()) {
+ builder.put(MAP_SCALING.BUKKIT, scaling);
+ }
+
+ return builder;
+ }
+
+ @Override
+ SerializableMeta.Deserializers deserializer() {
+ return SerializableMeta.Deserializers.MAP;
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
new file mode 100644
index 00000000..fa21f40d
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaPotion.java
@@ -0,0 +1,260 @@
+package org.bukkit.craftbukkit.inventory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.minecraft.server.NBTTagCompound;
+import net.minecraft.server.NBTTagList;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.Material;
+import org.bukkit.configuration.serialization.DelegateDeserialization;
+import org.bukkit.inventory.meta.PotionMeta;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap.Builder;
+
+@DelegateDeserialization(SerializableMeta.class)
+class CraftMetaPotion extends CraftMetaItem implements PotionMeta {
+ static final ItemMetaKey AMPLIFIER = new ItemMetaKey("Amplifier", "amplifier");
+ static final ItemMetaKey AMBIENT = new ItemMetaKey("Ambient", "ambient");
+ static final ItemMetaKey DURATION = new ItemMetaKey("Duration", "duration");
+ static final ItemMetaKey POTION_EFFECTS = new ItemMetaKey("CustomPotionEffects", "custom-effects");
+ static final ItemMetaKey ID = new ItemMetaKey("ID", "potion-id");
+
+ private List<PotionEffect> customEffects;
+
+ CraftMetaPotion(CraftMetaItem meta) {
+ super(meta);
+ if (!(meta instanceof CraftMetaPotion)) {
+ return;
+ }
+ CraftMetaPotion potionMeta = (CraftMetaPotion) meta;
+ if (potionMeta.hasCustomEffects()) {
+ this.customEffects = new ArrayList<PotionEffect>(potionMeta.customEffects);
+ }
+ }
+
+ CraftMetaPotion(NBTTagCompound tag) {
+ super(tag);
+
+ if (tag.hasKey(POTION_EFFECTS.NBT)) {
+ NBTTagList list = tag.getList(POTION_EFFECTS.NBT);
+ int length = list.size();
+ if (length > 0) {
+ customEffects = new ArrayList<PotionEffect>(length);
+
+ for (int i = 0; i < length; i++) {
+ NBTTagCompound effect = (NBTTagCompound) list.get(i);
+ PotionEffectType type = PotionEffectType.getById(effect.getByte(ID.NBT));
+ int amp = effect.getByte(AMPLIFIER.NBT);
+ int duration = effect.getInt(DURATION.NBT);
+ boolean ambient = effect.getBoolean(AMBIENT.NBT);
+ customEffects.add(new PotionEffect(type, duration, amp, ambient));
+ }
+ }
+ }
+ }
+
+ CraftMetaPotion(Map<String, Object> map) {
+ super(map);
+
+ List<?> rawEffectList = SerializableMeta.getObject(List.class, map, POTION_EFFECTS.BUKKIT, true);
+ if (rawEffectList == null) {
+ return;
+ }
+
+ for (Object obj : rawEffectList) {
+ if (!(obj instanceof PotionEffect)) {
+ throw new IllegalArgumentException("Object in effect list is not valid. " + obj.getClass());
+ }
+ addCustomEffect((PotionEffect) obj, true);
+ }
+ }
+
+ @Override
+ void applyToItem(NBTTagCompound tag) {
+ super.applyToItem(tag);
+ if (hasCustomEffects()) {
+ NBTTagList effectList = new NBTTagList();
+ tag.set(POTION_EFFECTS.NBT, effectList);
+
+ for (PotionEffect effect : customEffects) {
+ NBTTagCompound effectData = new NBTTagCompound();
+ effectData.setByte(ID.NBT, (byte) effect.getType().getId());
+ effectData.setByte(AMPLIFIER.NBT, (byte) effect.getAmplifier());
+ effectData.setInt(DURATION.NBT, effect.getDuration());
+ effectData.setBoolean(AMBIENT.NBT, effect.isAmbient());
+ effectList.add(effectData);
+ }
+ }
+ }
+
+ @Override
+ boolean isEmpty() {
+ return super.isEmpty() && isPotionEmpty();
+ }
+
+ boolean isPotionEmpty() {
+ return !(hasCustomEffects());
+ }
+
+ @Override
+ boolean applicableTo(Material type) {
+ switch(type) {
+ case POTION:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public CraftMetaPotion clone() {
+ CraftMetaPotion clone = (CraftMetaPotion) super.clone();
+ if (hasCustomEffects()) {
+ clone.customEffects = new ArrayList<PotionEffect>(customEffects);
+ }
+ return clone;
+ }
+
+ public boolean hasCustomEffects() {
+ return !(customEffects == null || customEffects.isEmpty());
+ }
+
+ public List<PotionEffect> getCustomEffects() {
+ if (hasCustomEffects()) {
+ return ImmutableList.copyOf(customEffects);
+ }
+ return ImmutableList.of();
+ }
+
+ public boolean addCustomEffect(PotionEffect effect, boolean overwrite) {
+ Validate.notNull(effect, "Potion effect must not be null");
+
+ int index = indexOfEffect(effect.getType());
+ if (index != -1) {
+ if (overwrite) {
+ PotionEffect old = customEffects.get(index);
+ if (old.getAmplifier() == effect.getAmplifier() && old.getDuration() == effect.getDuration() && old.isAmbient() == effect.isAmbient()) {
+ return false;
+ }
+ customEffects.set(index, effect);
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ if (customEffects == null) {
+ customEffects = new ArrayList<PotionEffect>();
+ }
+ customEffects.add(effect);
+ return true;
+ }
+ }
+
+ public boolean removeCustomEffect(PotionEffectType type) {
+ Validate.notNull(type, "Potion effect type must not be null");
+
+ if (!hasCustomEffects()) {
+ return false;
+ }
+
+ boolean changed = false;
+ Iterator<PotionEffect> iterator = customEffects.iterator();
+ while (iterator.hasNext()) {
+ PotionEffect effect = iterator.next();
+ if (effect.getType() == type) {
+ iterator.remove();
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
+ public boolean hasCustomEffect(PotionEffectType type) {
+ Validate.notNull(type, "Potion effect type must not be null");
+ return indexOfEffect(type) != -1;
+ }
+
+ public boolean setMainEffect(PotionEffectType type) {
+ Validate.notNull(type, "Potion effect type must not be null");
+ int index = indexOfEffect(type);
+ if (index == -1 || index == 0) {
+ return false;
+ }
+
+ PotionEffect old = customEffects.get(0);
+ customEffects.set(0, customEffects.get(index));
+ customEffects.set(index, old);
+ return true;
+ }
+
+ private int indexOfEffect(PotionEffectType type) {
+ if (!hasCustomEffects()) {
+ return -1;
+ }
+
+ for (int i = 0; i < customEffects.size(); i++) {
+ if (customEffects.get(i).getType().equals(type)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public boolean clearCustomEffects() {
+ boolean changed = hasCustomEffects();
+ customEffects = null;
+ return changed;
+ }
+
+ @Override
+ int applyHash() {
+ final int original;
+ int hash = original = super.applyHash();
+ if (hasCustomEffects()) {
+ hash = 73 * hash + customEffects.hashCode();
+ }
+ return original != hash ? CraftMetaPotion.class.hashCode() ^ hash : hash;
+ }
+
+ @Override
+ public boolean equalsCommon(CraftMetaItem meta) {
+ if (!super.equalsCommon(meta)) {
+ return false;
+ }
+ if (meta instanceof CraftMetaPotion) {
+ CraftMetaPotion that = (CraftMetaPotion) meta;
+
+ return (this.hasCustomEffects() ? that.hasCustomEffects() && this.customEffects.equals(that.customEffects) : !that.hasCustomEffects());
+ }
+ return true;
+ }
+
+ @Override
+ boolean notUncommon(CraftMetaItem meta) {
+ return super.notUncommon(meta) && (meta instanceof CraftMetaPotion || isPotionEmpty());
+ }
+
+ @Override
+ Builder<String, Object> serialize(Builder<String, Object> builder) {
+ super.serialize(builder);
+
+ if (hasCustomEffects()) {
+ builder.put(POTION_EFFECTS.BUKKIT, ImmutableList.copyOf(this.customEffects));
+ }
+
+ return builder;
+ }
+
+ @Override
+ SerializableMeta.Deserializers deserializer() {
+ return SerializableMeta.Deserializers.POTION;
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
new file mode 100644
index 00000000..2bef968e
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSkull.java
@@ -0,0 +1,134 @@
+package org.bukkit.craftbukkit.inventory;
+
+import java.util.Map;
+
+import net.minecraft.server.NBTTagCompound;
+
+import org.bukkit.Material;
+import org.bukkit.configuration.serialization.DelegateDeserialization;
+import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
+import org.bukkit.inventory.meta.SkullMeta;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap.Builder;
+
+@DelegateDeserialization(SerializableMeta.class)
+class CraftMetaSkull extends CraftMetaItem implements SkullMeta {
+ static final ItemMetaKey SKULL_OWNER = new ItemMetaKey("SkullOwner", "skull-owner");
+ static final int MAX_OWNER_LENGTH = 16;
+
+ private String player;
+
+ CraftMetaSkull(CraftMetaItem meta) {
+ super(meta);
+ if (!(meta instanceof CraftMetaSkull)) {
+ return;
+ }
+ CraftMetaSkull skullMeta = (CraftMetaSkull) meta;
+ this.player = skullMeta.player;
+ }
+
+ CraftMetaSkull(NBTTagCompound tag) {
+ super(tag);
+
+ if (tag.hasKey(SKULL_OWNER.NBT)) {
+ player = tag.getString(SKULL_OWNER.NBT);
+ }
+ }
+
+ CraftMetaSkull(Map<String, Object> map) {
+ super(map);
+ setOwner(SerializableMeta.getString(map, SKULL_OWNER.BUKKIT, true));
+ }
+
+ @Override
+ void applyToItem(NBTTagCompound tag) {
+ super.applyToItem(tag);
+
+ if (hasOwner()) {
+ tag.setString(SKULL_OWNER.NBT, player);
+ }
+ }
+
+ @Override
+ boolean isEmpty() {
+ return super.isEmpty() && isSkullEmpty();
+ }
+
+ boolean isSkullEmpty() {
+ return !(hasOwner());
+ }
+
+ @Override
+ boolean applicableTo(Material type) {
+ switch(type) {
+ case SKULL_ITEM:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public CraftMetaSkull clone() {
+ return (CraftMetaSkull) super.clone();
+ }
+
+ public boolean hasOwner() {
+ return !Strings.isNullOrEmpty(player);
+ }
+
+ public String getOwner() {
+ return player;
+ }
+
+ public boolean setOwner(String name) {
+ if (name != null && name.length() > MAX_OWNER_LENGTH) {
+ return false;
+ }
+ player = name;
+ return true;
+ }
+
+ @Override
+ int applyHash() {
+ final int original;
+ int hash = original = super.applyHash();
+ if (hasOwner()) {
+ hash = 61 * hash + player.hashCode();
+ }
+ return original != hash ? CraftMetaSkull.class.hashCode() ^ hash : hash;
+ }
+
+ @Override
+ boolean equalsCommon(CraftMetaItem meta) {
+ if (!super.equalsCommon(meta)) {
+ return false;
+ }
+ if (meta instanceof CraftMetaSkull) {
+ CraftMetaSkull that = (CraftMetaSkull) meta;
+
+ return (this.hasOwner() ? that.hasOwner() && this.player.equals(that.player) : !that.hasOwner());
+ }
+ return true;
+ }
+
+ @Override
+ boolean notUncommon(CraftMetaItem meta) {
+ return super.notUncommon(meta) && (meta instanceof CraftMetaSkull || isSkullEmpty());
+ }
+
+ @Override
+ Builder<String, Object> serialize(Builder<String, Object> builder) {
+ super.serialize(builder);
+ if (hasOwner()) {
+ return builder.put(SKULL_OWNER.BUKKIT, this.player);
+ }
+ return builder;
+ }
+
+ @Override
+ SerializableMeta.Deserializers deserializer() {
+ return SerializableMeta.Deserializers.SKULL;
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapedRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapedRecipe.java
index 5d89d79d..0f416a88 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapedRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapedRecipe.java
@@ -59,6 +59,6 @@ public class CraftShapedRecipe extends ShapedRecipe implements CraftRecipe {
data[i] = new net.minecraft.server.ItemStack(id, 1, dmg);
i++;
}
- CraftingManager.getInstance().registerShapedRecipe(CraftItemStack.createNMSItemStack(this.getResult()), data);
+ CraftingManager.getInstance().registerShapedRecipe(CraftItemStack.asNMSCopy(this.getResult()), data);
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
index 919df561..b06aa548 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
@@ -42,6 +42,6 @@ public class CraftShapelessRecipe extends ShapelessRecipe implements CraftRecipe
data[i] = new net.minecraft.server.ItemStack(id, 1, dmg);
i++;
}
- CraftingManager.getInstance().registerShapelessRecipe(CraftItemStack.createNMSItemStack(this.getResult()), data);
+ CraftingManager.getInstance().registerShapelessRecipe(CraftItemStack.asNMSCopy(this.getResult()), data);
}
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java b/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
index c1f21936..f8e864e4 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
@@ -34,7 +34,7 @@ public class RecipeIterator implements Iterator<Recipe> {
} else {
removeFrom = smelting;
int id = smelting.next();
- CraftItemStack stack = new CraftItemStack(RecipesFurnace.getInstance().getResult(id));
+ CraftItemStack stack = CraftItemStack.asCraftMirror(RecipesFurnace.getInstance().getResult(id));
CraftFurnaceRecipe recipe = new CraftFurnaceRecipe(stack, new ItemStack(id, 1, (short) -1));
return recipe;
}