summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java6
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java44
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCharge.java134
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java170
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java392
-rw-r--r--src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java150
-rw-r--r--src/test/java/org/bukkit/DyeColorsTest.java8
-rw-r--r--src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaImplementationOverrideTest.java57
-rw-r--r--src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java30
-rw-r--r--src/test/java/org/bukkit/craftbukkit/inventory/ItemStackBookTest.java1
-rw-r--r--src/test/java/org/bukkit/craftbukkit/inventory/ItemStackEnchantStorageTest.java108
-rw-r--r--src/test/java/org/bukkit/craftbukkit/inventory/ItemStackFireworkChargeTest.java128
-rw-r--r--src/test/java/org/bukkit/craftbukkit/inventory/ItemStackFireworkTest.java184
-rw-r--r--src/test/java/org/bukkit/craftbukkit/inventory/ItemStackLeatherTest.java1
-rw-r--r--src/test/java/org/bukkit/craftbukkit/inventory/ItemStackLoreEnchantmentTest.java1
-rw-r--r--src/test/java/org/bukkit/craftbukkit/inventory/ItemStackPotionsTest.java1
-rw-r--r--src/test/java/org/bukkit/craftbukkit/inventory/ItemStackSkullTest.java1
-rw-r--r--src/test/java/org/bukkit/craftbukkit/inventory/ItemStackTest.java1
18 files changed, 1337 insertions, 80 deletions
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
index b2bcf344..81c6b72d 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
@@ -62,6 +62,12 @@ public final class CraftItemFactory implements ItemFactory {
return meta instanceof CraftMetaPotion ? meta : new CraftMetaPotion(meta);
case MAP:
return meta instanceof CraftMetaMap ? meta : new CraftMetaMap(meta);
+ case FIREWORK:
+ return meta instanceof CraftMetaFirework ? meta : new CraftMetaFirework(meta);
+ case FIREWORK_CHARGE:
+ return meta instanceof CraftMetaCharge ? meta : new CraftMetaCharge(meta);
+ case ENCHANTED_BOOK:
+ return meta instanceof CraftMetaEnchantedBook ? meta : new CraftMetaEnchantedBook(meta);
default:
return new CraftMetaItem(meta);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
index 7de7c1d0..5f2a6bd1 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
@@ -1,5 +1,9 @@
package org.bukkit.craftbukkit.inventory;
+import static org.bukkit.craftbukkit.inventory.CraftMetaItem.ENCHANTMENTS;
+import static org.bukkit.craftbukkit.inventory.CraftMetaItem.ENCHANTMENTS_ID;
+import static org.bukkit.craftbukkit.inventory.CraftMetaItem.ENCHANTMENTS_LVL;
+
import java.util.Map;
import net.minecraft.server.EnchantmentManager;
@@ -7,10 +11,10 @@ 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.enchantments.Enchantment;
+import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import com.google.common.collect.ImmutableMap;
@@ -162,24 +166,24 @@ public final class CraftItemStack extends ItemStack {
if (!makeTag(handle)) {
return;
}
- NBTTagList list = getEnchantmentList(handle), listCopy;
+ NBTTagList list = getEnchantmentList(handle);
if (list == null) {
- list = new NBTTagList("ench");
- handle.tag.set("ench", list);
+ list = new NBTTagList(ENCHANTMENTS.NBT);
+ handle.tag.set(ENCHANTMENTS.NBT, list);
}
int size = list.size();
for (int i = 0; i < size; i++) {
NBTTagCompound tag = (NBTTagCompound) list.get(i);
- short id = tag.getShort("id");
+ short id = tag.getShort(ENCHANTMENTS_ID.NBT);
if (id == ench.getId()) {
- tag.setShort("lvl", (short) level);
+ tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level);
return;
}
}
NBTTagCompound tag = new NBTTagCompound();
- tag.setShort("id", (short) ench.getId());
- tag.setShort("lvl", (short) level);
+ tag.setShort(ENCHANTMENTS_ID.NBT, (short) ench.getId());
+ tag.setShort(ENCHANTMENTS_LVL.NBT, (short) level);
list.add(tag);
}
@@ -219,7 +223,7 @@ public final class CraftItemStack extends ItemStack {
int index = Integer.MIN_VALUE, size = list.size(), level;
for (int i = 0; i < size; i++) {
- short id = ((NBTTagCompound) list.get(i)).getShort("id");
+ short id = ((NBTTagCompound) list.get(i)).getShort(ENCHANTMENTS_ID.NBT);
if (id == ench.getId()) {
index = i;
break;
@@ -230,22 +234,22 @@ public final class CraftItemStack extends ItemStack {
return 0;
}
if (index == 0 && size == 0) {
- handle.tag.o("ench");
+ handle.tag.o(ENCHANTMENTS.NBT);
if (handle.tag.d()) {
handle.tag = null;
}
}
- listCopy = new NBTTagList("ench");
+ listCopy = new NBTTagList(ENCHANTMENTS.NBT);
level = Integer.MAX_VALUE;
for (int i = 0; i < size; i++) {
if (i == index) {
- level = ((NBTTagCompound) list.get(i)).getShort("id");
+ level = ((NBTTagCompound) list.get(i)).getShort(ENCHANTMENTS_ID.NBT);
continue;
}
listCopy.add(list.get(i));
}
- handle.tag.set("ench", listCopy);
+ handle.tag.set(ENCHANTMENTS.NBT, listCopy);
return level;
}
@@ -263,10 +267,10 @@ public final class CraftItemStack extends ItemStack {
}
for (int i = 0; i < list.size(); i++) {
- short id = ((NBTTagCompound) list.get(i)).getShort("id");
- short level = ((NBTTagCompound) list.get(i)).getShort("lvl");
+ int id = 0xffff & ((NBTTagCompound) list.get(i)).getShort(ENCHANTMENTS_ID.NBT);
+ int level = 0xffff & ((NBTTagCompound) list.get(i)).getShort(ENCHANTMENTS_LVL.NBT);
- result.put(Enchantment.getById(id), (int) level);
+ result.put(Enchantment.getById(id), level);
}
return result.build();
@@ -309,6 +313,12 @@ public final class CraftItemStack extends ItemStack {
return new CraftMetaPotion(item.tag);
case MAP:
return new CraftMetaMap(item.tag);
+ case FIREWORK:
+ return new CraftMetaFirework(item.tag);
+ case FIREWORK_CHARGE:
+ return new CraftMetaCharge(item.tag);
+ case ENCHANTED_BOOK:
+ return new CraftMetaEnchantedBook(item.tag);
default:
return new CraftMetaItem(item.tag);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCharge.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCharge.java
new file mode 100644
index 00000000..84ce4bbd
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaCharge.java
@@ -0,0 +1,134 @@
+package org.bukkit.craftbukkit.inventory;
+
+import java.util.Map;
+
+import net.minecraft.server.NBTTagCompound;
+
+import org.bukkit.FireworkEffect;
+import org.bukkit.Material;
+import org.bukkit.configuration.serialization.DelegateDeserialization;
+import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
+import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta.Deserializers;
+import org.bukkit.inventory.meta.FireworkEffectMeta;
+
+import com.google.common.collect.ImmutableMap.Builder;
+
+@DelegateDeserialization(SerializableMeta.class)
+class CraftMetaCharge extends CraftMetaItem implements FireworkEffectMeta {
+ static final ItemMetaKey EXPLOSION = new ItemMetaKey("Explosion", "firework-effect");
+
+ private FireworkEffect effect;
+
+ CraftMetaCharge(CraftMetaItem meta) {
+ super(meta);
+
+ if (meta instanceof CraftMetaCharge) {
+ effect = ((CraftMetaCharge) meta).effect;
+ }
+ }
+
+ CraftMetaCharge(Map<String, Object> map) {
+ super(map);
+
+ effect = SerializableMeta.getObject(FireworkEffect.class, map, EXPLOSION.BUKKIT, true);
+ }
+
+ CraftMetaCharge(NBTTagCompound tag) {
+ super(tag);
+
+ if (tag.hasKey(EXPLOSION.NBT)) {
+ effect = CraftMetaFirework.getEffect(tag.getCompound(EXPLOSION.NBT));
+ }
+ }
+
+ public void setEffect(FireworkEffect effect) {
+ this.effect = effect;
+ }
+
+ public boolean hasEffect() {
+ return effect != null;
+ }
+
+ public FireworkEffect getEffect() {
+ return effect;
+ }
+
+ @Override
+ void applyToItem(NBTTagCompound itemTag) {
+ super.applyToItem(itemTag);
+
+ if (hasEffect()) {
+ itemTag.set(EXPLOSION.NBT, CraftMetaFirework.getExplosion(effect));
+ }
+ }
+
+ @Override
+ boolean applicableTo(Material type) {
+ switch (type) {
+ case FIREWORK_CHARGE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ boolean isEmpty() {
+ return super.isEmpty() && !hasChargeMeta();
+ }
+
+ boolean hasChargeMeta() {
+ return hasEffect();
+ }
+
+ @Override
+ boolean equalsCommon(CraftMetaItem meta) {
+ if (!super.equalsCommon(meta)) {
+ return false;
+ }
+ if (meta instanceof CraftMetaCharge) {
+ CraftMetaCharge that = (CraftMetaCharge) meta;
+
+ return (hasEffect() ? that.hasEffect() && this.effect.equals(that.effect) : !that.hasEffect());
+ }
+ return true;
+ }
+
+ @Override
+ boolean notUncommon(CraftMetaItem meta) {
+ return super.notUncommon(meta) && (meta instanceof CraftMetaCharge || !hasChargeMeta());
+ }
+
+ @Override
+ int applyHash() {
+ final int original;
+ int hash = original = super.applyHash();
+
+ if (hasEffect()) {
+ hash = 61 * hash + effect.hashCode();
+ }
+
+ return hash != original ? CraftMetaCharge.class.hashCode() ^ hash : hash;
+ }
+
+ @Override
+ public CraftMetaCharge clone() {
+ return (CraftMetaCharge) super.clone();
+ }
+
+ @Override
+ Builder<String, Object> serialize(Builder<String, Object> builder) {
+ super.serialize(builder);
+
+ if (hasEffect()) {
+ builder.put(EXPLOSION.BUKKIT, effect);
+ }
+
+ return builder;
+ }
+
+ @Override
+ Deserializers deserializer() {
+ return Deserializers.FIREWORK_EFFECT;
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java
new file mode 100644
index 00000000..4dd39444
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaEnchantedBook.java
@@ -0,0 +1,170 @@
+package org.bukkit.craftbukkit.inventory;
+
+import java.util.HashMap;
+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.craftbukkit.inventory.CraftMetaItem.SerializableMeta.Deserializers;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.inventory.meta.EnchantmentStorageMeta;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+
+@DelegateDeserialization(SerializableMeta.class)
+class CraftMetaEnchantedBook extends CraftMetaItem implements EnchantmentStorageMeta {
+ static final ItemMetaKey STORED_ENCHANTMENTS = new ItemMetaKey("StoredEnchantments", "stored-enchants");
+
+ private Map<Enchantment, Integer> enchantments;
+
+ CraftMetaEnchantedBook(CraftMetaItem meta) {
+ super(meta);
+
+ if (!(meta instanceof CraftMetaEnchantedBook)) {
+ return;
+ }
+
+ CraftMetaEnchantedBook that = (CraftMetaEnchantedBook) meta;
+
+ if (that.hasEnchants()) {
+ this.enchantments = new HashMap<Enchantment, Integer>(that.enchantments);
+ }
+ }
+
+ CraftMetaEnchantedBook(NBTTagCompound tag) {
+ super(tag);
+
+ if (!tag.hasKey(STORED_ENCHANTMENTS.NBT)) {
+ return;
+ }
+
+ enchantments = buildEnchantments(tag, STORED_ENCHANTMENTS);
+ }
+
+ CraftMetaEnchantedBook(Map<String, Object> map) {
+ super(map);
+
+ enchantments = buildEnchantments(map, STORED_ENCHANTMENTS);
+ }
+
+ @Override
+ void applyToItem(NBTTagCompound itemTag) {
+ super.applyToItem(itemTag);
+
+ applyEnchantments(enchantments, itemTag, STORED_ENCHANTMENTS);
+ }
+
+ @Override
+ boolean applicableTo(Material type) {
+ switch (type) {
+ case ENCHANTED_BOOK:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ boolean isEmpty() {
+ return super.isEmpty() && isEnchantedEmpty();
+ }
+
+ @Override
+ boolean equalsCommon(CraftMetaItem meta) {
+ if (!super.equalsCommon(meta)) {
+ return false;
+ }
+ if (meta instanceof CraftMetaEnchantedBook) {
+ CraftMetaEnchantedBook that = (CraftMetaEnchantedBook) meta;
+
+ return (hasStoredEnchants() ? that.hasStoredEnchants() && this.enchantments.equals(that.enchantments) : !that.hasStoredEnchants());
+ }
+ return true;
+ }
+
+ @Override
+ boolean notUncommon(CraftMetaItem meta) {
+ return super.notUncommon(meta) && (meta instanceof CraftMetaEnchantedBook || isEnchantedEmpty());
+ }
+
+ @Override
+ int applyHash() {
+ final int original;
+ int hash = original = super.applyHash();
+
+ if (hasStoredEnchants()) {
+ hash = 61 * hash + enchantments.hashCode();
+ }
+
+ return original != hash ? CraftMetaEnchantedBook.class.hashCode() ^ hash : hash;
+ }
+
+ @Override
+ public CraftMetaEnchantedBook clone() {
+ CraftMetaEnchantedBook meta = (CraftMetaEnchantedBook) super.clone();
+
+ if (hasStoredEnchants()) {
+ meta.enchantments = new HashMap<Enchantment, Integer>(enchantments);
+ }
+
+ return meta;
+ }
+
+ @Override
+ Builder<String, Object> serialize(Builder<String, Object> builder) {
+ super.serialize(builder);
+
+ serializeEnchantments(enchantments, builder, STORED_ENCHANTMENTS);
+
+ return builder;
+ }
+
+ @Override
+ Deserializers deserializer() {
+ return Deserializers.ENCHANTED;
+ }
+
+ boolean isEnchantedEmpty() {
+ return !hasStoredEnchants();
+ }
+
+ public boolean hasStoredEnchant(Enchantment ench) {
+ return hasStoredEnchants() ? enchantments.containsKey(ench) : false;
+ }
+
+ public int getStoredEnchantLevel(Enchantment ench) {
+ Integer level = hasStoredEnchants() ? enchantments.get(ench) : null;
+ if (level == null) {
+ return 0;
+ }
+ return level;
+ }
+
+ public Map<Enchantment, Integer> getStoredEnchants() {
+ return hasStoredEnchants() ? ImmutableMap.copyOf(enchantments) : ImmutableMap.<Enchantment, Integer>of();
+ }
+
+ public boolean addStoredEnchant(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 removeStoredEnchant(Enchantment ench) {
+ return hasStoredEnchants() ? enchantments.remove(ench) != null : false;
+ }
+
+ public boolean hasStoredEnchants() {
+ return !(enchantments == null || enchantments.isEmpty());
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java
new file mode 100644
index 00000000..67cc8b1c
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaFirework.java
@@ -0,0 +1,392 @@
+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 org.apache.commons.lang.Validate;
+import org.bukkit.Color;
+import org.bukkit.FireworkEffect;
+import org.bukkit.FireworkEffect.Type;
+import org.bukkit.Material;
+import org.bukkit.configuration.serialization.DelegateDeserialization;
+import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey.Specific;
+import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey.Specific.To;
+import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta;
+import org.bukkit.craftbukkit.inventory.CraftMetaItem.SerializableMeta.Deserializers;
+import org.bukkit.inventory.meta.FireworkMeta;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap.Builder;
+
+@DelegateDeserialization(SerializableMeta.class)
+class CraftMetaFirework extends CraftMetaItem implements FireworkMeta {
+ /*
+ "Fireworks", "Explosion", "Explosions", "Flight", "Type", "Trail", "Flicker", "Colors", "FadeColors";
+
+ Fireworks
+ - Compound: Fireworks
+ -- Byte: Flight
+ -- List: Explosions
+ --- Compound: Explosion
+ ---- IntArray: Colors
+ ---- Byte: Type
+ ---- Boolean: Trail
+ ---- Boolean: Flicker
+ ---- IntArray: FadeColors
+ */
+
+ @Specific(To.NBT)
+ static final ItemMetaKey FIREWORKS = new ItemMetaKey("Fireworks");
+ static final ItemMetaKey FLIGHT = new ItemMetaKey("Flight", "power");
+ static final ItemMetaKey EXPLOSIONS = new ItemMetaKey("Explosions", "firework-effects");
+ @Specific(To.NBT)
+ static final ItemMetaKey EXPLOSION_COLORS = new ItemMetaKey("Colors");
+ @Specific(To.NBT)
+ static final ItemMetaKey EXPLOSION_TYPE = new ItemMetaKey("Type");
+ @Specific(To.NBT)
+ static final ItemMetaKey EXPLOSION_TRAIL = new ItemMetaKey("Trail");
+ @Specific(To.NBT)
+ static final ItemMetaKey EXPLOSION_FLICKER = new ItemMetaKey("Flicker");
+ @Specific(To.NBT)
+ static final ItemMetaKey EXPLOSION_FADE = new ItemMetaKey("FadeColors");
+
+ private List<FireworkEffect> effects;
+ private int power;
+
+ CraftMetaFirework(CraftMetaItem meta) {
+ super(meta);
+
+ if (!(meta instanceof CraftMetaFirework)) {
+ return;
+ }
+
+ CraftMetaFirework that = (CraftMetaFirework) meta;
+
+ this.power = that.power;
+
+ if (that.hasEffects()) {
+ this.effects = new ArrayList<FireworkEffect>(that.effects);
+ }
+ }
+
+ CraftMetaFirework(NBTTagCompound tag) {
+ super(tag);
+
+ if (!tag.hasKey(FIREWORKS.NBT)) {
+ return;
+ }
+
+ NBTTagCompound fireworks = tag.getCompound(FIREWORKS.NBT);
+
+ power = 0xff & fireworks.getByte(FLIGHT.NBT);
+
+ if (!fireworks.hasKey(EXPLOSIONS.NBT)) {
+ return;
+ }
+
+ NBTTagList fireworkEffects = fireworks.getList(EXPLOSIONS.NBT);
+ List<FireworkEffect> effects = this.effects = new ArrayList<FireworkEffect>(fireworkEffects.size());
+
+ for (int i = 0; i < fireworkEffects.size(); i++) {
+ effects.add(getEffect((NBTTagCompound) fireworkEffects.get(i)));
+ }
+ }
+
+ static FireworkEffect getEffect(NBTTagCompound explosion) {
+ FireworkEffect.Builder effect = FireworkEffect.builder()
+ .flicker(explosion.getBoolean(EXPLOSION_FLICKER.NBT))
+ .trail(explosion.getBoolean(EXPLOSION_TRAIL.NBT))
+ .with(getEffectType(0xff & explosion.getByte(EXPLOSION_TYPE.NBT)));
+
+ for (int color : explosion.getIntArray(EXPLOSION_COLORS.NBT)) {
+ effect.withColor(Color.fromRGB(color));
+ }
+
+ for (int color : explosion.getIntArray(EXPLOSION_FADE.NBT)) {
+ effect.withFade(Color.fromRGB(color));
+ }
+
+ return effect.build();
+ }
+
+ static NBTTagCompound getExplosion(FireworkEffect effect) {
+ NBTTagCompound explosion = new NBTTagCompound();
+
+ if (effect.hasFlicker()) {
+ explosion.setBoolean(EXPLOSION_FLICKER.NBT, true);
+ }
+
+ if (effect.hasTrail()) {
+ explosion.setBoolean(EXPLOSION_TRAIL.NBT, true);
+ }
+
+ addColors(explosion, EXPLOSION_COLORS, effect.getColors());
+ addColors(explosion, EXPLOSION_FADE, effect.getFadeColors());
+
+ explosion.setByte(EXPLOSION_TYPE.NBT, (byte) getNBT(effect.getType()));
+
+ return explosion;
+ }
+
+ static int getNBT(Type type) {
+ switch (type) {
+ case BALL:
+ return 0;
+ case BALL_LARGE:
+ return 1;
+ case STAR:
+ return 2;
+ case CREEPER:
+ return 3;
+ case BURST:
+ return 4;
+ default:
+ throw new AssertionError(type);
+ }
+ }
+
+ static Type getEffectType(int nbt) {
+ switch (nbt) {
+ case 0:
+ return Type.BALL;
+ case 1:
+ return Type.BALL_LARGE;
+ case 2:
+ return Type.STAR;
+ case 3:
+ return Type.CREEPER;
+ case 4:
+ return Type.BURST;
+ default:
+ throw new AssertionError(nbt);
+ }
+ }
+
+ CraftMetaFirework(Map<String, Object> map) {
+ super(map);
+
+ Integer power = SerializableMeta.getObject(Integer.class, map, FLIGHT.BUKKIT, true);
+ if (power != null) {
+ this.power = power;
+ }
+
+ Iterable<?> effects = SerializableMeta.getObject(Iterable.class, map, EXPLOSIONS.BUKKIT, true);
+ safelyAddEffects(effects);
+ }
+
+ public boolean hasEffects() {
+ return !(effects == null || effects.isEmpty());
+ }
+
+ void safelyAddEffects(Iterable<?> collection) {
+ if (collection == null || (collection instanceof Collection && ((Collection<?>) collection).isEmpty())) {
+ return;
+ }
+
+ List<FireworkEffect> effects = this.effects;
+ if (effects == null) {
+ effects = this.effects = new ArrayList<FireworkEffect>();
+ }
+
+ for (Object obj : collection) {
+ if (obj instanceof FireworkEffect) {
+ effects.add((FireworkEffect) obj);
+ } else {
+ throw new IllegalArgumentException(obj + " in " + collection + " is not a FireworkEffect");
+ }
+ }
+ }
+
+ @Override
+ void applyToItem(NBTTagCompound itemTag) {
+ super.applyToItem(itemTag);
+ if (isFireworkEmpty()) {
+ return;
+ }
+
+ NBTTagCompound fireworks = itemTag.getCompound(FIREWORKS.NBT);
+ itemTag.setCompound(FIREWORKS.NBT, fireworks);
+
+ if (hasEffects()) {
+ NBTTagList effects = new NBTTagList(EXPLOSIONS.NBT);
+ for (FireworkEffect effect : this.effects) {
+ effects.add(getExplosion(effect));
+ }
+
+ if (effects.size() > 0) {
+ fireworks.set(EXPLOSIONS.NBT, effects);
+ }
+ }
+
+ if (hasPower()) {
+ fireworks.setByte(FLIGHT.NBT, (byte) power);
+ }
+ }
+
+ static void addColors(NBTTagCompound compound, ItemMetaKey key, List<Color> colors) {
+ if (colors.isEmpty()) {
+ return;
+ }
+
+ final int[] colorArray = new int[colors.size()];
+ int i = 0;
+ for (Color color : colors) {
+ colorArray[i++] = color.asRGB();
+ }
+
+ compound.setIntArray(key.NBT, colorArray);
+ }
+
+ @Override
+ boolean applicableTo(Material type) {
+ switch(type) {
+ case FIREWORK:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ boolean isEmpty() {
+ return super.isEmpty() && isFireworkEmpty();
+ }
+
+ boolean isFireworkEmpty() {
+ return !(hasEffects() || hasPower());
+ }
+
+ boolean hasPower() {
+ return power != 0;
+ }
+
+ @Override
+ boolean equalsCommon(CraftMetaItem meta) {
+ if (!super.equalsCommon(meta)) {
+ return false;
+ }
+
+ if (meta instanceof CraftMetaFirework) {
+ CraftMetaFirework that = (CraftMetaFirework) meta;
+
+ return (hasPower() ? that.hasPower() && this.power == that.power : !that.hasPower())
+ && (hasEffects() ? that.hasEffects() && this.effects.equals(that.effects) : !that.hasEffects());
+ }
+
+ return true;
+ }
+
+ @Override
+ boolean notUncommon(CraftMetaItem meta) {
+ return super.notUncommon(meta) && (meta instanceof CraftMetaFirework || isFireworkEmpty());
+ }
+
+ @Override
+ int applyHash() {
+ final int original;
+ int hash = original = super.applyHash();
+ if (hasPower()) {
+ hash = 61 * hash + power;
+ }
+ if (hasEffects()) {
+ hash = 61 * hash + 13 * effects.hashCode();
+ }
+ return hash != original ? CraftMetaFirework.class.hashCode() ^ hash : hash;
+ }
+
+ @Override
+ Builder<String, Object> serialize(Builder<String, Object> builder) {
+ super.serialize(builder);
+
+ if (hasEffects()) {
+ builder.put(EXPLOSIONS.BUKKIT, ImmutableList.copyOf(effects));
+ }
+
+ if (hasPower()) {
+ builder.put(FLIGHT.BUKKIT, power);
+ }
+
+ return builder;
+ }
+
+ @Override
+ Deserializers deserializer() {
+ return Deserializers.FIREWORK;
+ }
+
+ @Override
+ public CraftMetaFirework clone() {
+ CraftMetaFirework meta = (CraftMetaFirework) super.clone();
+
+ if (this.effects != null) {
+ meta.effects = new ArrayList<FireworkEffect>(this.effects);
+ }
+
+ return meta;
+ }
+
+ public void addEffect(FireworkEffect effect) {
+ Validate.notNull(effect, "Effect cannot be null");
+ if (this.effects == null) {
+ this.effects = new ArrayList<FireworkEffect>();
+ }
+ this.effects.add(effect);
+ }
+
+ public void addEffects(FireworkEffect...effects) {
+ Validate.notNull(effects, "Effects cannot be null");
+ if (effects.length == 0) {
+ return;
+ }
+
+ List<FireworkEffect> list = this.effects;
+ if (list == null) {
+ list = this.effects = new ArrayList<FireworkEffect>();
+ }
+
+ for (FireworkEffect effect : effects) {
+ Validate.notNull(effect, "Effect cannot be null");
+ list.add(effect);
+ }
+ }
+
+ public void addEffects(Iterable<FireworkEffect> effects) {
+ Validate.notNull(effects, "Effects cannot be null");
+ safelyAddEffects(effects);
+ }
+
+ public List<FireworkEffect> getEffects() {
+ return this.effects == null ? ImmutableList.<FireworkEffect>of() : ImmutableList.copyOf(this.effects);
+ }
+
+ public int getEffectsSize() {
+ return this.effects == null ? 0 : this.effects.size();
+ }
+
+ public void removeEffect(int index) {
+ if (this.effects == null) {
+ throw new IndexOutOfBoundsException("Index: " + index + ", Size: 0");
+ } else {
+ this.effects.remove(index);
+ }
+ }
+
+ public void clearEffects() {
+ this.effects = null;
+ }
+
+ public int getPower() {
+ return this.power;
+ }
+
+ public void setPower(int power) {
+ Validate.isTrue(power > 0, "Power cannot be less than zero: ", power);
+ Validate.isTrue(power < 0x80, "Power cannot be more than 127: ", power);
+ this.power = power;
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
index 7c52e853..f8f9f261 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
@@ -1,5 +1,9 @@
package org.bukkit.craftbukkit.inventory;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -18,6 +22,7 @@ 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.craftbukkit.inventory.CraftMetaItem.ItemMetaKey.Specific;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.Repairable;
@@ -50,7 +55,20 @@ import com.google.common.collect.ImmutableMap;
*/
@DelegateDeserialization(CraftMetaItem.SerializableMeta.class)
class CraftMetaItem implements ItemMeta, Repairable {
+
static class ItemMetaKey {
+
+ @Retention(RetentionPolicy.SOURCE)
+ @Target(ElementType.FIELD)
+ @interface Specific {
+ enum To {
+ BUKKIT,
+ NBT,
+ ;
+ }
+ To value();
+ }
+
final String BUKKIT;
final String NBT;
@@ -99,6 +117,24 @@ class CraftMetaItem implements ItemMeta, Repairable {
return new CraftMetaPotion(map);
}
},
+ ENCHANTED {
+ @Override
+ CraftMetaEnchantedBook deserialize(Map<String, Object> map) {
+ return new CraftMetaEnchantedBook(map);
+ }
+ },
+ FIREWORK {
+ @Override
+ CraftMetaFirework deserialize(Map<String, Object> map) {
+ return new CraftMetaFirework(map);
+ }
+ },
+ FIREWORK_EFFECT {
+ @Override
+ CraftMetaCharge deserialize(Map<String, Object> map) {
+ return new CraftMetaCharge(map);
+ }
+ },
UNSPECIFIC {
@Override
CraftMetaItem deserialize(Map<String, Object> map) {
@@ -155,10 +191,13 @@ class CraftMetaItem implements ItemMeta, Repairable {
}
static final ItemMetaKey NAME = new ItemMetaKey("Name", "display-name");
+ @Specific(Specific.To.NBT)
static final ItemMetaKey DISPLAY = new ItemMetaKey("display");
static final ItemMetaKey LORE = new ItemMetaKey("Lore", "lore");
static final ItemMetaKey ENCHANTMENTS = new ItemMetaKey("ench", "enchants");
+ @Specific(Specific.To.NBT)
static final ItemMetaKey ENCHANTMENTS_ID = new ItemMetaKey("id");
+ @Specific(Specific.To.NBT)
static final ItemMetaKey ENCHANTMENTS_LVL = new ItemMetaKey("lvl");
static final ItemMetaKey REPAIR = new ItemMetaKey("RepairCost", "repair-cost");
@@ -204,21 +243,29 @@ class CraftMetaItem implements ItemMeta, Repairable {
}
}
- if (tag.hasKey(ENCHANTMENTS.NBT)) {
- NBTTagList ench = tag.getList(ENCHANTMENTS.NBT);
- enchantments = new HashMap<Enchantment, Integer>(ench.size());
+ this.enchantments = buildEnchantments(tag, ENCHANTMENTS);
- 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);
+ if (tag.hasKey(REPAIR.NBT)) {
+ repairCost = tag.getInt(REPAIR.NBT);
+ }
+ }
- addEnchant(Enchantment.getById(id), (int) level, true);
- }
+ static Map<Enchantment, Integer> buildEnchantments(NBTTagCompound tag, ItemMetaKey key) {
+ if (!tag.hasKey(key.NBT)) {
+ return null;
}
- if (tag.hasKey(REPAIR.NBT)) {
- repairCost = tag.getInt(REPAIR.NBT);
+ NBTTagList ench = tag.getList(key.NBT);
+ Map<Enchantment, Integer> enchantments = new HashMap<Enchantment, Integer>(ench.size());
+
+ for (int i = 0; i < ench.size(); i++) {
+ int id = 0xffff & ((NBTTagCompound) ench.get(i)).getShort(ENCHANTMENTS_ID.NBT);
+ int level = 0xffff & ((NBTTagCompound) ench.get(i)).getShort(ENCHANTMENTS_LVL.NBT);
+
+ enchantments.put(Enchantment.getById(id), level);
}
+
+ return enchantments;
}
CraftMetaItem(Map<String, Object> map) {
@@ -228,23 +275,31 @@ class CraftMetaItem implements ItemMeta, Repairable {
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);
- }
- }
- }
+ enchantments = buildEnchantments(map, ENCHANTMENTS);
if (map.containsKey(REPAIR.BUKKIT)) {
repairCost = (Integer) map.get(REPAIR.BUKKIT);
}
}
+ static Map<Enchantment, Integer> buildEnchantments(Map<String, Object> map, ItemMetaKey key) {
+ Map<?, ?> ench = SerializableMeta.getObject(Map.class, map, key.BUKKIT, true);
+ if (ench == null) {
+ return null;
+ }
+
+ Map<Enchantment, Integer> 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)) {
+ enchantments.put(enchantment, (Integer) entry.getValue());
+ }
+ }
+
+ return enchantments;
+ }
+
@Overridden
void applyToItem(NBTTagCompound itemTag) {
if (hasDisplayName()) {
@@ -259,24 +314,30 @@ class CraftMetaItem implements ItemMeta, Repairable {
setDisplayTag(itemTag, LORE.NBT, list);
}
- if (hasEnchants()) {
- NBTTagList list = new NBTTagList(ENCHANTMENTS.NBT);
+ applyEnchantments(enchantments, itemTag, ENCHANTMENTS);
- for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
- NBTTagCompound subtag = new NBTTagCompound();
+ if (hasRepairCost()) {
+ itemTag.setInt(REPAIR.NBT, repairCost);
+ }
+ }
- subtag.setShort(ENCHANTMENTS_ID.NBT, (short) entry.getKey().getId());
- subtag.setShort(ENCHANTMENTS_LVL.NBT, (short) (int) entry.getValue());
+ static void applyEnchantments(Map<Enchantment, Integer> enchantments, NBTTagCompound tag, ItemMetaKey key) {
+ if (enchantments == null || enchantments.size() == 0) {
+ return;
+ }
- list.add(subtag);
- }
+ NBTTagList list = new NBTTagList(key.NBT);
- itemTag.set(ENCHANTMENTS.NBT, list);
- }
+ for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
+ NBTTagCompound subtag = new NBTTagCompound();
- if (hasRepairCost()) {
- itemTag.setInt(REPAIR.NBT, repairCost);
+ subtag.setShort(ENCHANTMENTS_ID.NBT, (short) entry.getKey().getId());
+ subtag.setShort(ENCHANTMENTS_LVL.NBT, entry.getValue().shortValue());
+
+ list.add(subtag);
}
+
+ tag.set(key.NBT, list);
}
void setDisplayTag(NBTTagCompound tag, String key, NBTBase value) {
@@ -459,13 +520,7 @@ class CraftMetaItem implements ItemMeta, Repairable {
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());
- }
+ serializeEnchantments(enchantments, builder, ENCHANTMENTS);
if (hasRepairCost()) {
builder.put(REPAIR.BUKKIT, repairCost);
@@ -474,6 +529,19 @@ class CraftMetaItem implements ItemMeta, Repairable {
return builder;
}
+ static void serializeEnchantments(Map<Enchantment, Integer> enchantments, ImmutableMap.Builder<String, Object> builder, ItemMetaKey key) {
+ if (enchantments == null || enchantments.isEmpty()) {
+ return;
+ }
+
+ ImmutableMap.Builder<String, Integer> enchants = ImmutableMap.builder();
+ for (Map.Entry<? extends Enchantment, Integer> enchant : enchantments.entrySet()) {
+ enchants.put(enchant.getKey().getName(), enchant.getValue());
+ }
+
+ builder.put(key.BUKKIT, enchants.build());
+ }
+
@Overridden
SerializableMeta.Deserializers deserializer() {
return SerializableMeta.Deserializers.UNSPECIFIC;
@@ -505,6 +573,6 @@ class CraftMetaItem implements ItemMeta, Repairable {
@Override
public final String toString() {
- return serialize().toString(); // TODO: cry
+ return deserializer().toString() + "_META:" + serialize(); // TODO: cry
}
}
diff --git a/src/test/java/org/bukkit/DyeColorsTest.java b/src/test/java/org/bukkit/DyeColorsTest.java
index 296f49a4..8b2e8a7c 100644
--- a/src/test/java/org/bukkit/DyeColorsTest.java
+++ b/src/test/java/org/bukkit/DyeColorsTest.java
@@ -7,6 +7,7 @@ import java.util.ArrayList;
import java.util.List;
import net.minecraft.server.EntitySheep;
+import net.minecraft.server.ItemDye;
import org.bukkit.support.AbstractTestingBase;
import org.junit.Test;
@@ -36,4 +37,11 @@ public class DyeColorsTest extends AbstractTestingBase {
Color nmsColor = Color.fromRGB((int) (nmsColorArray[0] * 255), (int) (nmsColorArray[1] * 255), (int) (nmsColorArray[2] * 255));
assertThat(color, is(nmsColor));
}
+
+ @Test
+ public void checkFireworkColor() {
+ Color color = dye.getFireworkColor();
+ int nmsColor = ItemDye.b[dye.getData()];
+ assertThat(color, is(Color.fromRGB(nmsColor)));
+ }
}
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaImplementationOverrideTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaImplementationOverrideTest.java
index ac0702a2..f1b4ec0d 100644
--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaImplementationOverrideTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaImplementationOverrideTest.java
@@ -1,10 +1,15 @@
package org.bukkit.craftbukkit.inventory;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Callable;
import org.bukkit.Material;
+import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.Overridden;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -15,14 +20,10 @@ import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class ItemMetaImplementationOverrideTest {
static final Class<CraftMetaItem> parent = CraftMetaItem.class;
- static final Class<Overridden> annotation = Overridden.class;
-
- static final List<Object[]> testData = new ArrayList<Object[]>();
- static final Method[] methods;
-
- static final Class<? extends CraftMetaItem>[] subclasses;
- static {
+ @Parameters(name="[{index}]:{1}")
+ public static List<Object[]> data() {
+ final List<Object[]> testData = new ArrayList<Object[]>();
List<Class<? extends CraftMetaItem>> classes = new ArrayList<Class<? extends CraftMetaItem>>();
for (Material material : ItemStackTest.COMPOUND_MATERIALS) {
@@ -31,37 +32,49 @@ public class ItemMetaImplementationOverrideTest {
classes.add(clazz);
}
}
- subclasses = classes.toArray(new Class[0]);
-
List<Method> list = new ArrayList<Method>();
for (Method method: parent.getDeclaredMethods()) {
- if (method.isAnnotationPresent(annotation)) {
+ if (method.isAnnotationPresent(Overridden.class)) {
list.add(method);
}
}
- for (Class<?> clazz : subclasses) {
- for (Method method : list) {
- testData.add(new Object[]{clazz, method, clazz.getSimpleName() + " contains " + method.getName()});
+ for (final Class<?> clazz : classes) {
+ for (final Method method : list) {
+ testData.add(
+ new Object[] {
+ new Callable<Method>() {
+ public Method call() throws Exception {
+ return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
+ }
+ },
+ clazz.getSimpleName() + " contains " + method.getName()
+ }
+ );
}
- }
- methods = list.toArray(new Method[list.size()]);
- }
+ testData.add(
+ new Object[] {
+ new Callable<DelegateDeserialization>() {
+ public DelegateDeserialization call() throws Exception {
+ return clazz.getAnnotation(DelegateDeserialization.class);
+ }
+ },
+ clazz.getSimpleName() + " contains annotation " + DelegateDeserialization.class
+ }
+ );
+ }
- @Parameters(name="[{index}]:{2}")
- public static List<Object[]> data() {
return testData;
}
- @Parameter(0) public Class clazz;
- @Parameter(1) public Method method;
- @Parameter(2) public String name;
+ @Parameter(0) public Callable<?> test;
+ @Parameter(1) public String name;
@Test
public void testClass() throws Throwable {
- clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
+ assertThat(name, test.call(), is(not(nullValue())));
}
}
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
index c95f499f..876cefc0 100644
--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java
@@ -7,13 +7,19 @@ import java.util.Arrays;
import java.util.List;
import org.bukkit.Color;
+import org.bukkit.FireworkEffect;
import org.bukkit.Material;
+import org.bukkit.FireworkEffect.Type;
import org.bukkit.craftbukkit.inventory.ItemStackTest.StackProvider;
import org.bukkit.craftbukkit.inventory.ItemStackTest.StackWrapper;
import org.bukkit.craftbukkit.inventory.ItemStackTest.BukkitWrapper;
import org.bukkit.craftbukkit.inventory.ItemStackTest.CraftWrapper;
+import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
+import org.bukkit.inventory.meta.EnchantmentStorageMeta;
+import org.bukkit.inventory.meta.FireworkEffectMeta;
+import org.bukkit.inventory.meta.FireworkMeta;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import org.bukkit.inventory.meta.MapMeta;
import org.bukkit.inventory.meta.PotionMeta;
@@ -77,6 +83,30 @@ public class ItemMetaTest extends AbstractTestingBase {
cleanStack.setItemMeta(meta);
return cleanStack;
}
+ },
+ new StackProvider(Material.FIREWORK) {
+ @Override ItemStack operate(final ItemStack cleanStack) {
+ final FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.addEffect(FireworkEffect.builder().withColor(Color.GREEN).withFade(Color.OLIVE).with(Type.BALL_LARGE).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new StackProvider(Material.ENCHANTED_BOOK) {
+ @Override ItemStack operate(final ItemStack cleanStack) {
+ final EnchantmentStorageMeta meta = (EnchantmentStorageMeta) cleanStack.getItemMeta();
+ meta.addStoredEnchant(Enchantment.ARROW_FIRE, 1, true);
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new StackProvider(Material.FIREWORK_CHARGE) {
+ @Override ItemStack operate(final ItemStack cleanStack) {
+ final FireworkEffectMeta meta = (FireworkEffectMeta) cleanStack.getItemMeta();
+ meta.setEffect(FireworkEffect.builder().withColor(Color.MAROON, Color.BLACK).with(Type.CREEPER).withFlicker().build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
}
);
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackBookTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackBookTest.java
index 8321eefe..a7edc048 100644
--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackBookTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackBookTest.java
@@ -20,6 +20,7 @@ public class ItemStackBookTest extends ItemStackTest {
return StackProvider.compound(operators(), "%s %s", NAME_PARAMETER, Material.WRITTEN_BOOK, Material.BOOK_AND_QUILL);
}
+ @SuppressWarnings("unchecked")
static List<Object[]> operators() {
return CompoundOperator.compound(
Joiner.on('+'),
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackEnchantStorageTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackEnchantStorageTest.java
new file mode 100644
index 00000000..a0499b8a
--- /dev/null
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackEnchantStorageTest.java
@@ -0,0 +1,108 @@
+package org.bukkit.craftbukkit.inventory;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.bukkit.Material;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.EnchantmentStorageMeta;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.base.Joiner;
+
+@RunWith(Parameterized.class)
+public class ItemStackEnchantStorageTest extends ItemStackTest {
+
+ @Parameters(name="[{index}]:{" + NAME_PARAMETER + "}")
+ public static List<Object[]> data() {
+ return StackProvider.compound(operators(), "%s %s", NAME_PARAMETER, Material.ENCHANTED_BOOK);
+ }
+
+ @SuppressWarnings("unchecked")
+ static List<Object[]> operators() {
+ return CompoundOperator.compound(
+ Joiner.on('+'),
+ NAME_PARAMETER,
+ Long.parseLong("10", 2),
+ ItemStackLoreEnchantmentTest.operators(),
+ Arrays.asList(
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ EnchantmentStorageMeta meta = (EnchantmentStorageMeta) cleanStack.getItemMeta();
+ meta.addStoredEnchant(Enchantment.DURABILITY, 1, true);
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ EnchantmentStorageMeta meta = (EnchantmentStorageMeta) cleanStack.getItemMeta();
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Enchantable vs Blank"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ EnchantmentStorageMeta meta = (EnchantmentStorageMeta) cleanStack.getItemMeta();
+ meta.addStoredEnchant(Enchantment.KNOCKBACK, 1, true);
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ return cleanStack;
+ }
+ },
+ "Enchantable vs Null"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ EnchantmentStorageMeta meta = (EnchantmentStorageMeta) cleanStack.getItemMeta();
+ meta.addStoredEnchant(Enchantment.DAMAGE_UNDEAD, 1, true);
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ EnchantmentStorageMeta meta = (EnchantmentStorageMeta) cleanStack.getItemMeta();
+ meta.addStoredEnchant(Enchantment.DAMAGE_UNDEAD, 1, true);
+ meta.addStoredEnchant(Enchantment.FIRE_ASPECT, 1, true);
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Enchantable vs More"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ EnchantmentStorageMeta meta = (EnchantmentStorageMeta) cleanStack.getItemMeta();
+ meta.addStoredEnchant(Enchantment.PROTECTION_FIRE, 1, true);
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ EnchantmentStorageMeta meta = (EnchantmentStorageMeta) cleanStack.getItemMeta();
+ meta.addEnchant(Enchantment.PROTECTION_FIRE, 2, true);
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Enchantable vs Other"
+ }
+ )
+ );
+ }
+}
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackFireworkChargeTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackFireworkChargeTest.java
new file mode 100644
index 00000000..cb38cd27
--- /dev/null
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackFireworkChargeTest.java
@@ -0,0 +1,128 @@
+package org.bukkit.craftbukkit.inventory;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.bukkit.Color;
+import org.bukkit.FireworkEffect;
+import org.bukkit.FireworkEffect.Type;
+import org.bukkit.Material;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.FireworkEffectMeta;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.base.Joiner;
+
+@RunWith(Parameterized.class)
+public class ItemStackFireworkChargeTest extends ItemStackTest {
+
+ @Parameters(name="[{index}]:{" + NAME_PARAMETER + "}")
+ public static List<Object[]> data() {
+ return StackProvider.compound(operators(), "%s %s", NAME_PARAMETER, Material.FIREWORK_CHARGE);
+ }
+
+ @SuppressWarnings("unchecked")
+ static List<Object[]> operators() {
+ return CompoundOperator.compound(
+ Joiner.on('+'),
+ NAME_PARAMETER,
+ Long.parseLong("10", 2),
+ ItemStackLoreEnchantmentTest.operators(),
+ Arrays.asList(
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkEffectMeta meta = (FireworkEffectMeta) cleanStack.getItemMeta();
+ meta.setEffect(FireworkEffect.builder().withColor(Color.WHITE).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkEffectMeta meta = (FireworkEffectMeta) cleanStack.getItemMeta();
+ meta.setEffect(FireworkEffect.builder().withColor(Color.BLACK).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Effect Color 1 vs. Effect Color 2"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkEffectMeta meta = (FireworkEffectMeta) cleanStack.getItemMeta();
+ meta.setEffect(FireworkEffect.builder().withColor(Color.WHITE).with(Type.CREEPER).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkEffectMeta meta = (FireworkEffectMeta) cleanStack.getItemMeta();
+ meta.setEffect(FireworkEffect.builder().withColor(Color.WHITE).with(Type.BURST).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Effect type 1 vs. Effect type 2"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkEffectMeta meta = (FireworkEffectMeta) cleanStack.getItemMeta();
+ meta.setEffect(FireworkEffect.builder().withColor(Color.WHITE).withFade(Color.BLUE).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkEffectMeta meta = (FireworkEffectMeta) cleanStack.getItemMeta();
+ meta.setEffect(FireworkEffect.builder().withColor(Color.WHITE).withFade(Color.RED).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Effect fade 1 vs. Effect fade 2"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkEffectMeta meta = (FireworkEffectMeta) cleanStack.getItemMeta();
+ meta.setEffect(FireworkEffect.builder().withColor(Color.WHITE).withFlicker().build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkEffectMeta meta = (FireworkEffectMeta) cleanStack.getItemMeta();
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Effect vs. Null"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkEffectMeta meta = (FireworkEffectMeta) cleanStack.getItemMeta();
+ meta.setEffect(FireworkEffect.builder().withColor(Color.WHITE).withTrail().build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ return cleanStack;
+ }
+ },
+ "Effect vs. None"
+ }
+ )
+ );
+ }
+}
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackFireworkTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackFireworkTest.java
new file mode 100644
index 00000000..afacf3b7
--- /dev/null
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackFireworkTest.java
@@ -0,0 +1,184 @@
+package org.bukkit.craftbukkit.inventory;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.bukkit.Color;
+import org.bukkit.FireworkEffect;
+import org.bukkit.Material;
+import org.bukkit.FireworkEffect.Type;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.FireworkMeta;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.google.common.base.Joiner;
+
+@RunWith(Parameterized.class)
+public class ItemStackFireworkTest extends ItemStackTest {
+
+ @Parameters(name="[{index}]:{" + NAME_PARAMETER + "}")
+ public static List<Object[]> data() {
+ return StackProvider.compound(operators(), "%s %s", NAME_PARAMETER, Material.FIREWORK);
+ }
+
+ @SuppressWarnings("unchecked")
+ static List<Object[]> operators() {
+ return CompoundOperator.compound(
+ Joiner.on('+'),
+ NAME_PARAMETER,
+ Long.parseLong("110", 2),
+ ItemStackLoreEnchantmentTest.operators(),
+ Arrays.asList(
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.addEffect(FireworkEffect.builder().withColor(Color.WHITE).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.addEffect(FireworkEffect.builder().withColor(Color.BLACK).build());
+ meta.addEffect(FireworkEffect.builder().withColor(Color.GREEN).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Effect Color 1 vs. Effect Color 2"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.addEffect(FireworkEffect.builder().withColor(Color.WHITE).with(Type.CREEPER).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.addEffect(FireworkEffect.builder().withColor(Color.WHITE).with(Type.BURST).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Effect type 1 vs. Effect type 2"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.addEffect(FireworkEffect.builder().withColor(Color.WHITE).withFade(Color.BLUE).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.addEffect(FireworkEffect.builder().withColor(Color.WHITE).withFade(Color.RED).build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Effect fade 1 vs. Effect fade 2"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.addEffect(FireworkEffect.builder().withColor(Color.WHITE).withFlicker().build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Effect vs. Null"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.addEffect(FireworkEffect.builder().withColor(Color.WHITE).withTrail().build());
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ return cleanStack;
+ }
+ },
+ "Effect vs. None"
+ }
+ ),
+ Arrays.asList(
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.setPower(150);
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.setPower(100);
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Height vs. Other"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.setPower(200);
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ "Height vs. Null"
+ },
+ new Object[] {
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ FireworkMeta meta = (FireworkMeta) cleanStack.getItemMeta();
+ meta.setPower(10);
+ cleanStack.setItemMeta(meta);
+ return cleanStack;
+ }
+ },
+ new Operator() {
+ public ItemStack operate(ItemStack cleanStack) {
+ return cleanStack;
+ }
+ },
+ "Height vs. None"
+ }
+ )
+ );
+ }
+}
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackLeatherTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackLeatherTest.java
index a6f95831..6d68e1f4 100644
--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackLeatherTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackLeatherTest.java
@@ -22,6 +22,7 @@ public class ItemStackLeatherTest extends ItemStackTest {
return StackProvider.compound(operators(), "%s %s", NAME_PARAMETER, Material.LEATHER_BOOTS, Material.LEATHER_CHESTPLATE, Material.LEATHER_HELMET, Material.LEATHER_LEGGINGS);
}
+ @SuppressWarnings("unchecked")
static List<Object[]> operators() {
return CompoundOperator.compound(
Joiner.on('+'),
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackLoreEnchantmentTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackLoreEnchantmentTest.java
index d3604fbc..7de61aaa 100644
--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackLoreEnchantmentTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackLoreEnchantmentTest.java
@@ -20,6 +20,7 @@ public class ItemStackLoreEnchantmentTest extends ItemStackTest {
return StackProvider.compound(operators(), "%s %s", NAME_PARAMETER, ItemStackTest.COMPOUND_MATERIALS);
}
+ @SuppressWarnings("unchecked")
static List<Object[]> operators() {
return CompoundOperator.compound(
Joiner.on('+'),
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackPotionsTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackPotionsTest.java
index e6aa2c46..c1f9fb74 100644
--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackPotionsTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackPotionsTest.java
@@ -21,6 +21,7 @@ public class ItemStackPotionsTest extends ItemStackTest {
return StackProvider.compound(operators(), "%s %s", NAME_PARAMETER, Material.POTION);
}
+ @SuppressWarnings("unchecked")
static List<Object[]> operators() {
return CompoundOperator.compound(
Joiner.on('+'),
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackSkullTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackSkullTest.java
index ea6381fa..a79d443e 100644
--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackSkullTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackSkullTest.java
@@ -20,6 +20,7 @@ public class ItemStackSkullTest extends ItemStackTest {
return StackProvider.compound(operators(), "%s %s", NAME_PARAMETER, Material.SKULL_ITEM);
}
+ @SuppressWarnings("unchecked")
static List<Object[]> operators() {
return CompoundOperator.compound(
Joiner.on('+'),
diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackTest.java
index 4592e1dc..5d174e20 100644
--- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackTest.java
+++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemStackTest.java
@@ -184,6 +184,7 @@ public class ItemStackTest extends AbstractTestingBase {
out.addAll(primarySingleton);
}
+ @SuppressWarnings("unchecked")
final List<Object[]>[] lists = new List[notSingletons.size() + 1];
notSingletons.toArray(lists);
lists[lists.length - 1] = out;