diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java index e3bb1dffd6..b154060146 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java @@ -263,6 +263,8 @@ public final class CraftItemFactory implements ItemFactory { return meta instanceof CraftMetaTropicalFishBucket ? meta : new CraftMetaTropicalFishBucket(meta); case CROSSBOW: return meta instanceof CraftMetaCrossbow ? meta : new CraftMetaCrossbow(meta); + case SUSPICIOUS_STEW: + return meta instanceof CraftMetaSuspiciousStew ? meta : new CraftMetaSuspiciousStew(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 c3a3fbde04..40cfe9f861 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java @@ -514,6 +514,8 @@ public final class CraftItemStack extends ItemStack { return new CraftMetaTropicalFishBucket(item.getTag()); case CROSSBOW: return new CraftMetaCrossbow(item.getTag()); + case SUSPICIOUS_STEW: + return new CraftMetaSuspiciousStew(item.getTag()); default: return new CraftMetaItem(item.getTag()); } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java index 814dab0c57..3a93e202b8 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java @@ -155,6 +155,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { .put(CraftMetaKnowledgeBook.class, "KNOWLEDGE_BOOK") .put(CraftMetaTropicalFishBucket.class, "TROPICAL_FISH_BUCKET") .put(CraftMetaCrossbow.class, "CROSSBOW") + .put(CraftMetaSuspiciousStew.class, "SUSPICIOUS_STEW") .put(CraftMetaItem.class, "UNSPECIFIC") .build(); @@ -1410,7 +1411,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta { CraftMetaKnowledgeBook.BOOK_RECIPES.NBT, CraftMetaTropicalFishBucket.VARIANT.NBT, CraftMetaCrossbow.CHARGED.NBT, - CraftMetaCrossbow.CHARGED_PROJECTILES.NBT + CraftMetaCrossbow.CHARGED_PROJECTILES.NBT, + CraftMetaSuspiciousStew.EFFECTS.NBT )); } return HANDLED_TAGS; diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java new file mode 100644 index 0000000000..1613fbfc19 --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java @@ -0,0 +1,239 @@ +package org.bukkit.craftbukkit.inventory; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap.Builder; +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.craftbukkit.util.CraftMagicNumbers; +import org.bukkit.inventory.meta.SuspiciousStewMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +@DelegateDeserialization(CraftMetaItem.SerializableMeta.class) +public class CraftMetaSuspiciousStew extends CraftMetaItem implements SuspiciousStewMeta { + + static final ItemMetaKey DURATION = new ItemMetaKey("EffectDuration", "duration"); + static final ItemMetaKey EFFECTS = new ItemMetaKey("Effects", "effects"); + static final ItemMetaKey ID = new ItemMetaKey("EffectId", "id"); + + private List customEffects; + + CraftMetaSuspiciousStew(CraftMetaItem meta) { + super(meta); + if (!(meta instanceof CraftMetaSuspiciousStew)) { + return; + } + CraftMetaSuspiciousStew stewMeta = ((CraftMetaSuspiciousStew) meta); + if (stewMeta.hasCustomEffects()) { + this.customEffects = new ArrayList(stewMeta.customEffects); + } + } + + CraftMetaSuspiciousStew(NBTTagCompound tag) { + super(tag); + if (tag.hasKey(EFFECTS.NBT)) { + NBTTagList list = tag.getList(EFFECTS.NBT, CraftMagicNumbers.NBT.TAG_COMPOUND); + int length = list.size(); + customEffects = new ArrayList(length); + + for (int i = 0; i < length; i++) { + NBTTagCompound effect = list.getCompound(i); + PotionEffectType type = PotionEffectType.getById(effect.getByte(ID.NBT)); + if (type == null) { + continue; + } + int duration = effect.getInt(DURATION.NBT); + customEffects.add(new PotionEffect(type, duration, 0)); + } + } + } + + CraftMetaSuspiciousStew(Map map) { + super(map); + + Iterable rawEffectList = SerializableMeta.getObject(Iterable.class, map, 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 (customEffects != null) { + NBTTagList effectList = new NBTTagList(); + tag.set(EFFECTS.NBT, effectList); + + for (PotionEffect effect : customEffects) { + NBTTagCompound effectData = new NBTTagCompound(); + effectData.setByte(ID.NBT, ((byte) effect.getType().getId())); + effectData.setInt(DURATION.NBT, effect.getDuration()); + effectList.add(effectData); + } + } + } + + @Override + boolean isEmpty() { + return super.isEmpty() && isStewEmpty(); + } + + boolean isStewEmpty() { + return !hasCustomEffects(); + } + + @Override + boolean applicableTo(Material type) { + return type == Material.SUSPICIOUS_STEW; + } + + @Override + public CraftMetaSuspiciousStew clone() { + CraftMetaSuspiciousStew clone = ((CraftMetaSuspiciousStew) super.clone()); + if (this.customEffects != null) { + clone.customEffects = new ArrayList(this.customEffects); + } + return clone; + } + + @Override + public boolean hasCustomEffects() { + return customEffects != null; + } + + @Override + public List getCustomEffects() { + if (hasCustomEffects()) { + return ImmutableList.copyOf(customEffects); + } + return ImmutableList.of(); + } + + @Override + 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.getDuration() == effect.getDuration()) { + return false; + } + customEffects.set(index, effect); + return true; + } else { + return false; + } + } else { + if (customEffects == null) { + customEffects = new ArrayList(); + } + customEffects.add(effect); + return true; + } + } + + @Override + public boolean removeCustomEffect(PotionEffectType type) { + Validate.notNull(type, "Potion effect type must not be null"); + + if (!hasCustomEffects()) { + return false; + } + + boolean changed = false; + Iterator iterator = customEffects.iterator(); + while (iterator.hasNext()) { + PotionEffect effect = iterator.next(); + if (type.equals(effect.getType())) { + iterator.remove(); + changed = true; + } + } + if (customEffects.isEmpty()) { + customEffects = null; + } + return changed; + } + + @Override + public boolean hasCustomEffect(PotionEffectType type) { + Validate.notNull(type, "Potion effect type must not be null"); + return indexOfEffect(type) != -1; + } + + 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; + } + + @Override + 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 ? CraftMetaSuspiciousStew.class.hashCode() ^ hash : hash; + } + + @Override + boolean equalsCommon(CraftMetaItem meta) { + if (!super.equalsCommon(meta)) { + return false; + } + if (meta instanceof CraftMetaSuspiciousStew) { + CraftMetaSuspiciousStew that = (CraftMetaSuspiciousStew) 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 || isStewEmpty()); + } + + @Override + Builder serialize(Builder builder) { + super.serialize(builder); + + if (hasCustomEffects()) { + builder.put(EFFECTS.BUKKIT, ImmutableList.copyOf(this.customEffects)); + } + + return builder; + } +} diff --git a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java index dd4ba38743..b07a3051ca 100644 --- a/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java +++ b/src/test/java/org/bukkit/craftbukkit/inventory/ItemMetaTest.java @@ -354,6 +354,14 @@ public class ItemMetaTest extends AbstractTestingBase { cleanStack.setItemMeta(meta); return cleanStack; } + }, + new StackProvider(Material.SUSPICIOUS_STEW) { + @Override ItemStack operate(ItemStack cleanStack) { + final CraftMetaSuspiciousStew meta = ((CraftMetaSuspiciousStew) cleanStack.getItemMeta()); + meta.addCustomEffect(PotionEffectType.CONFUSION.createEffect(1, 0), false); + cleanStack.setItemMeta(meta); + return cleanStack; + } } );