Add ItemMeta factory and interfaces. This adds BUKKIT-15

Included with ItemMeta is a new serializable class Color.

PotionEffects are now serializable.

By: Wesley Wolfe <weswolf@aol.com>
This commit is contained in:
Bukkit/Spigot
2012-12-17 01:16:28 -06:00
parent 2bf21e7e18
commit ac66053f35
25 changed files with 1656 additions and 189 deletions

View File

@@ -0,0 +1,82 @@
package org.bukkit.inventory;
import org.bukkit.Material;
import org.bukkit.Server;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
/**
* An instance of the ItemFactory can be obtained with {@link Server#getItemFactory()}.
* The ItemFactory is solely responsible for creating item meta containers to apply on item stacks.
*/
public interface ItemFactory {
/**
* This creates a new item meta for the material.
* @param material The material to consider as base for the meta
* @return a new ItemMeta that could be applied to an item stack of the specified material
*/
ItemMeta getItemMeta(final Material material);
/**
* This method checks the item meta to confirm that it is applicable (no data lost if applied) to the specified ItemStack.
* A {@link SkullMeta} would not be valid for a sword, but a normal {@link ItemMeta} from an enchanted dirt block would.
* @param meta Meta to check
* @param stack Item that meta will be applied to
* @return true if the meta can be applied without losing data, false otherwise
* @throws IllegalArgumentException if the meta was not created by this factory
*/
boolean isApplicable(final ItemMeta meta, final ItemStack stack) throws IllegalArgumentException;
/**
* This method checks the item meta to confirm that it is applicable (no data lost if applied) to the specified Material.
* A {@link SkullMeta} would not be valid for a sword, but a normal {@link ItemMeta} from an enchanted dirt block would.
* @param meta Meta to check
* @param material Material that meta will be applied to
* @return true if the meta can be applied without losing data, false otherwise
* @throws IllegalArgumentException if the meta was not created by this factory
*/
boolean isApplicable(final ItemMeta meta, final Material material) throws IllegalArgumentException;
/**
* This method is used to compare two item meta data objects.
* @param meta1 First meta to compare, and may be null to indicate no data
* @param meta2 Second meta to compare, and may be null to indicate no data
* @return false if one of the meta has data the other does not, otherwise true
* @throws IllegalArgumentException if either meta was not created by this factory
*/
boolean equals(final ItemMeta meta1, final ItemMeta meta2) throws IllegalArgumentException;
/**
* Returns an appropriate item meta for the specified stack.
* The item meta returned will always be a valid meta for a given item stack of the specified material.
* It may be a more or less specific meta, and could also be the same meta or meta type as the parameter.
* The item meta returned will also always be the most appropriate meta. <br>
* <br>
* Example, if a {@link SkullMeta} is being applied to a book, this method would return a {@link BookMeta} containing all
* information in the specified meta that is applicable to an {@link ItemMeta}, the highest common interface.
*
* @param meta the meta to convert
* @param stack the stack to convert the meta for
* @return An appropriate item meta for the specified item stack. No guarantees are made as to if a copy is returned. This will be null for a stack of air.
* @throws IllegalArgumentException if the specified meta was not created by this factory
*/
ItemMeta asMetaFor(final ItemMeta meta, final ItemStack stack) throws IllegalArgumentException;
/**
* Returns an appropriate item meta for the specified material.
* The item meta returned will always be a valid meta for a given item stack of the specified material.
* It may be a more or less specific meta, and could also be the same meta or meta type as the parameter.
* The item meta returned will also always be the most appropriate meta. <br>
* <br>
* Example, if a {@link SkullMeta} is being applied to a book, this method would return a {@link BookMeta} containing all
* information in the specified meta that is applicable to an {@link ItemMeta}, the highest common interface.
*
* @param meta the meta to convert
* @param material the material to convert the meta for
* @return An appropriate item meta for the specified item material. No guarantees are made as to if a copy is returned. This will be null for air.
* @throws IllegalArgumentException if the specified meta was not created by this factory
*/
ItemMeta asMetaFor(final ItemMeta meta, final Material material) throws IllegalArgumentException;
}

View File

@@ -1,48 +1,97 @@
package org.bukkit.inventory;
import com.google.common.collect.ImmutableMap;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.Utility;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.MaterialData;
/**
* Represents a stack of items
*/
public class ItemStack implements Cloneable, ConfigurationSerializable {
private int type;
private int type = 0;
private int amount = 0;
private MaterialData data = null;
private short durability = 0;
private Map<Enchantment, Integer> enchantments = new HashMap<Enchantment, Integer>();
private ItemMeta meta;
@Utility
protected ItemStack() {}
/**
* Defaults stack size to 1, with no extra data
*
* @param type item material id
*/
public ItemStack(final int type) {
this(type, 1);
}
/**
* Defaults stack size to 1, with no extra data
*
* @param type item material
*/
public ItemStack(final Material type) {
this(type, 1);
}
/**
* An item stack with no extra data
*
* @param type item material id
* @param amount stack size
*/
public ItemStack(final int type, final int amount) {
this(type, amount, (short) 0);
}
/**
* An item stack with no extra data
*
* @param type item material
* @param amount stack size
*/
public ItemStack(final Material type, final int amount) {
this(type.getId(), amount);
}
/**
* An item stack with the specified damage / durability
*
* @param type item material id
* @param amount stack size
* @param damage durability / damage
*/
public ItemStack(final int type, final int amount, final short damage) {
this(type, amount, damage, null);
this.type = type;
this.amount = amount;
this.durability = damage;
}
/**
* An item stack with the specified damage / durabiltiy
*
* @param type item material
* @param amount stack size
* @param damage durability / damage
*/
public ItemStack(final Material type, final int amount, final short damage) {
this(type.getId(), amount, damage);
}
/**
* @deprecated this method uses an ambiguous data byte object
*/
@Deprecated
public ItemStack(final int type, final int amount, final short damage, final Byte data) {
this.type = type;
this.amount = amount;
@@ -53,18 +102,29 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
}
}
/**
* @deprecated this method uses an ambiguous data byte object
*/
@Deprecated
public ItemStack(final Material type, final int amount, final short damage, final Byte data) {
this(type.getId(), amount, damage, data);
}
public ItemStack(final ItemStack stack) {
this.type = stack.type;
this.amount = stack.amount;
this.durability = stack.durability;
if (stack.data != null) {
this.data = stack.data.clone();
/**
* Creates a new item stack derived from the specified stack
*
* @param stack the stack to copy
* @throws IllegalArgumentException if the specified stack is null or returns an item meta not created by the item factory
*/
public ItemStack(final ItemStack stack) throws IllegalArgumentException {
Validate.notNull(stack, "Cannot copy null stack");
this.type = stack.getTypeId();
this.amount = stack.getAmount();
this.durability = stack.getDurability();
this.data = stack.getData();
if (stack.hasItemMeta()) {
setItemMeta0(stack.getItemMeta(), getType0());
}
this.addUnsafeEnchantments(stack.getEnchantments());
}
/**
@@ -72,8 +132,18 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
*
* @return Type of the items in this stack
*/
@Utility
public Material getType() {
return Material.getMaterial(type);
return getType0(getTypeId());
}
private Material getType0() {
return getType0(this.type);
}
private static Material getType0(int id) {
Material material = Material.getMaterial(id);
return material == null ? Material.AIR : material;
}
/**
@@ -83,7 +153,9 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
*
* @param type New type to set the items in this stack to
*/
@Utility
public void setType(Material type) {
Validate.notNull(type, "Material cannot be null");
setTypeId(type.getId());
}
@@ -105,6 +177,9 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
*/
public void setTypeId(int type) {
this.type = type;
if (this.meta != null) {
this.meta = Bukkit.getItemFactory().asMetaFor(meta, getType0());
}
createData((byte) 0);
}
@@ -132,9 +207,9 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
* @return MaterialData for this item
*/
public MaterialData getData() {
Material mat = Material.getMaterial(getTypeId());
if (mat != null && mat.getData() != null) {
data = mat.getNewData((byte) this.durability);
Material mat = getType();
if (data == null && mat != null && mat.getData() != null) {
data = mat.getNewData((byte) this.getDurability());
}
return data;
@@ -148,7 +223,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
public void setData(MaterialData data) {
Material mat = getType();
if ((mat == null) || (mat.getData() == null)) {
if (data == null || mat == null || mat.getData() == null) {
this.data = data;
} else {
if ((data.getClass() == mat.getData()) || (data.getClass() == MaterialData.class)) {
@@ -183,12 +258,12 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
*
* @return The maximum you can stack this material to.
*/
@Utility
public int getMaxStackSize() {
Material material = getType();
if (material != null) {
return material.getMaxStackSize();
}
return -1;
}
@@ -203,19 +278,44 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
}
@Override
@Utility
public String toString() {
return "ItemStack{" + getType().name() + " x " + getAmount() + "}";
StringBuilder toString = new StringBuilder("ItemStack{").append(getType().name()).append(" x ").append(getAmount());
if (hasItemMeta()) {
toString.append(", ").append(getItemMeta());
}
return toString.append('}').toString();
}
@Override
@Utility
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof ItemStack)) {
return false;
}
ItemStack item = (ItemStack) obj;
ItemStack stack = (ItemStack) obj;
return getAmount() == stack.getAmount() && isSimilar(stack);
}
return item.getAmount() == getAmount() && item.getTypeId() == getTypeId() && getDurability() == item.getDurability() && getEnchantments().equals(item.getEnchantments());
/**
* This method is the same as equals, but does not consider stack size (amount).
*
* @param stack the item stack to compare to
* @return true if the two stacks are equal, ignoring the amount
*/
@Utility
public boolean isSimilar(ItemStack stack) {
if (stack == null) {
return false;
}
if (stack == this) {
return true;
}
return getTypeId() == stack.getTypeId() && getDurability() == stack.getDurability() && hasItemMeta() == stack.hasItemMeta() && (hasItemMeta() ? Bukkit.getItemFactory().equals(getItemMeta(), stack.getItemMeta()) : true);
}
@Override
@@ -223,7 +323,10 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
try {
ItemStack itemStack = (ItemStack) super.clone();
itemStack.enchantments = new HashMap<Enchantment, Integer>(this.enchantments);
if (this.meta != null) {
itemStack.meta = this.meta.clone();
}
if (this.data != null) {
itemStack.data = this.data.clone();
}
@@ -235,11 +338,15 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
}
@Override
public int hashCode() {
int hash = 11;
@Utility
public final int hashCode() {
int hash = 1;
hash = hash * 31 + getTypeId();
hash = hash * 31 + getAmount();
hash = hash * 31 + (getDurability() & 0xffff);
hash = hash * 31 + (hasItemMeta() ? (meta == null ? getItemMeta().hashCode() : meta.hashCode()) : 0);
hash = hash * 19 + 7 * getTypeId(); // Overriding hashCode since equals is overridden, it's just
hash = hash * 7 + 23 * getAmount(); // too bad these are mutable values... Q_Q
return hash;
}
@@ -250,7 +357,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
* @return True if this has the given enchantment
*/
public boolean containsEnchantment(Enchantment ench) {
return enchantments.containsKey(ench);
return meta == null ? false : meta.hasEnchant(ench);
}
/**
@@ -260,7 +367,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
* @return Level of the enchantment, or 0
*/
public int getEnchantmentLevel(Enchantment ench) {
return enchantments.get(ench);
return meta == null ? 0 : meta.getEnchantLevel(ench);
}
/**
@@ -269,7 +376,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
* @return Map of enchantments.
*/
public Map<Enchantment, Integer> getEnchantments() {
return ImmutableMap.copyOf(enchantments);
return meta == null ? ImmutableMap.<Enchantment, Integer>of() : meta.getEnchants();
}
/**
@@ -279,8 +386,13 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
* for each element of the map.
*
* @param enchantments Enchantments to add
* @throws IllegalArgumentException if the specified enchantments is null
* @throws IllegalArgumentException if any specific enchantment or level is null.
* <b>Warning</b>: Some enchantments may be added before this exception is thrown.
*/
@Utility
public void addEnchantments(Map<Enchantment, Integer> enchantments) {
Validate.notNull(enchantments, "Enchantments cannot be null");
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
addEnchantment(entry.getKey(), entry.getValue());
}
@@ -293,8 +405,11 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
*
* @param ench Enchantment to add
* @param level Level of the enchantment
* @throws IllegalArgumentException if enchantment null, or enchantment is not applicable
*/
@Utility
public void addEnchantment(Enchantment ench, int level) {
Validate.notNull(ench, "Enchantment cannot be null");
if ((level < ench.getStartLevel()) || (level > ench.getMaxLevel())) {
throw new IllegalArgumentException("Enchantment level is either too low or too high (given " + level + ", bounds are " + ench.getStartLevel() + " to " + ench.getMaxLevel());
} else if (!ench.canEnchantItem(this)) {
@@ -312,6 +427,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
*
* @param enchantments Enchantments to add
*/
@Utility
public void addUnsafeEnchantments(Map<Enchantment, Integer> enchantments) {
for (Map.Entry<Enchantment, Integer> entry : enchantments.entrySet()) {
addUnsafeEnchantment(entry.getKey(), entry.getValue());
@@ -330,7 +446,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
* @param level Level of the enchantment
*/
public void addUnsafeEnchantment(Enchantment ench, int level) {
enchantments.put(ench, level);
(meta == null ? meta = Bukkit.getItemFactory().getItemMeta(getType0()) : meta).addEnchant(ench, level, true);
}
/**
@@ -340,38 +456,43 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
* @return Previous level, or 0
*/
public int removeEnchantment(Enchantment ench) {
Integer previous = enchantments.remove(ench);
return (previous == null) ? 0 : previous;
int level = getEnchantmentLevel(ench);
if (level == 0 || meta == null) {
return level;
}
meta.removeEnchant(ench);
return level;
}
@Utility
public Map<String, Object> serialize() {
Map<String, Object> result = new LinkedHashMap<String, Object>();
result.put("type", getType().name());
if (durability != 0) {
result.put("damage", durability);
if (getDurability() != 0) {
result.put("damage", getDurability());
}
if (amount != 1) {
result.put("amount", amount);
if (getAmount() != 1) {
result.put("amount", getAmount());
}
Map<Enchantment, Integer> enchants = getEnchantments();
if (enchants.size() > 0) {
Map<String, Integer> safeEnchants = new HashMap<String, Integer>();
for (Map.Entry<Enchantment, Integer> entry : enchants.entrySet()) {
safeEnchants.put(entry.getKey().getName(), entry.getValue());
}
result.put("enchantments", safeEnchants);
ItemMeta meta = getItemMeta();
if (!Bukkit.getItemFactory().equals(meta, null)) {
result.put("meta", meta);
}
return result;
}
/**
* Required method for configuration serialization
*
* @param args map to deserialize
* @return deserialized item stack
* @see ConfigurationSerializable
*/
public static ItemStack deserialize(Map<String, Object> args) {
Material type = Material.getMaterial((String) args.get("type"));
short damage = 0;
@@ -387,7 +508,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
ItemStack result = new ItemStack(type, amount, damage);
if (args.containsKey("enchantments")) {
if (args.containsKey("enchantments")) { // Backward compatiblity, @deprecated
Object raw = args.get("enchantments");
if (raw instanceof Map) {
@@ -401,8 +522,61 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
}
}
}
} else if (args.containsKey("meta")) { // We cannot and will not have meta when enchantments (pre-ItemMeta) exist
Object raw = args.get("meta");
if (raw instanceof ItemMeta) {
result.setItemMeta((ItemMeta) raw);
}
}
return result;
}
/**
* Get a copy of this ItemStack's {@link ItemMeta}.
*
* @return a copy of the current ItemStack's ItemData
*/
public ItemMeta getItemMeta() {
return this.meta == null ? Bukkit.getItemFactory().getItemMeta(getType0()) : this.meta.clone();
}
/**
* Checks to see if any meta data has been defined.
*
* @return Returns true if some meta data has been set for this item
*/
public boolean hasItemMeta() {
return !Bukkit.getItemFactory().equals(meta, null);
}
/**
* Set the ItemMeta of this ItemStack.
*
* @param itemMeta new ItemMeta, or null to indicate meta data be cleared.
* @return True if successfully applied ItemMeta, see {@link ItemFactory#isApplicable(ItemMeta, ItemStack)}
* @throws IllegalArgumentException if the item meta was not created by the {@link ItemFactory}
*/
public boolean setItemMeta(ItemMeta itemMeta) {
return setItemMeta0(itemMeta, getType0());
}
/*
* Cannot be overridden, so it's safe for constructor call
*/
private boolean setItemMeta0(ItemMeta itemMeta, Material material) {
if (itemMeta == null) {
this.meta = null;
return true;
}
if (!Bukkit.getItemFactory().isApplicable(itemMeta, material)) {
return false;
}
this.meta = Bukkit.getItemFactory().asMetaFor(itemMeta, material);
if (this.meta == itemMeta) {
this.meta = itemMeta.clone();
}
return true;
}
}

View File

@@ -0,0 +1,114 @@
package org.bukkit.inventory.meta;
import java.util.List;
import org.bukkit.Material;
/**
* Represents a book ({@link Material#BOOK_AND_QUILL} or {@link Material#WRITTEN_BOOK}) that can have a title, an author, and pages.
*/
public interface BookMeta extends ItemMeta {
/**
* Checks for the existence of a title in the book.
*
* @return true if the book has a title
*/
boolean hasTitle();
/**
* Gets the title of the book.
*
* @return the title of the book
*/
String getTitle();
/**
* Sets the title of the book. Limited to 16 characters.
*
* @param title the title to set
* @return true if the title was successfully set
*/
boolean setTitle(String title);
/**
* Checks for the existence of an author in the book.
*
* @return the author of the book
*/
boolean hasAuthor();
/**
* Gets the author of the book.
*
* @return the author of the book
*/
String getAuthor();
/**
* Sets the author of the book.
*
* @param author the author of the book
*/
void setAuthor(String author);
/**
* Checks for the existence of pages in the book.
*
* @return true if the book has pages
*/
boolean hasPages();
/**
* Gets the specified page in the book.
*
* @param page the page number to get
* @return the page from the book
*/
String getPage(int page);
/**
* Sets the specified page in the book.
*
* @param page the page number to set
* @param data the data to set for that page
*/
void setPage(int page, String data);
/**
* Gets all the pages in the book.
*
* @return list of all the pages in the book
*/
List<String> getPages();
/**
* Clears the existing book pages, and sets the book to use the provided pages. Maximum 50 pages with 256 characters per page.
*
* @param pages A list of pages to set the book to use
*/
void setPages(List<String> pages);
/**
* Clears the existing book pages, and sets the book to use the provided pages. Maximum 50 pages with 256 characters per page.
*
* @param pages A list of strings, each being a page
*/
void setPages(String... pages);
/**
* Adds new pages to the end of the book.
*
* @param pages A list of strings, each being a page
*/
void addPage(String... pages);
/**
* Gets the number of pages in the book.
*
* @return the number of pages in the book
*/
int getPageCount();
BookMeta clone();
}

View File

@@ -0,0 +1,108 @@
package org.bukkit.inventory.meta;
import java.util.List;
import java.util.Map;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.enchantments.Enchantment;
/**
* This type represents the storage mechanism for auxiliary item data.
* An implementation will handle the creation and application for ItemMeta.
* This class should not be implemented by a plugin in a live environment.
*/
public interface ItemMeta extends Cloneable, ConfigurationSerializable {
/**
* Checks for existence of a display name
*
* @return true if this has a display name
*/
boolean hasDisplayName();
/**
* Gets the display name that is set
*
* @return the display name that is set
*/
String getDisplayName();
/**
* Sets the display name
*
* @param name the name to set
*/
void setDisplayName(String name);
/**
* Checks for existence of lore
*
* @return true if this has lore
*/
boolean hasLore();
/**
* Gets the lore that is set
*
* @return a list of lore that is set
*/
List<String> getLore();
/**
* Sets the lore for this item
*
* @param lore the lore that will be set
*/
void setLore(List<String> lore);
/**
* Checks for the existence of any enchantments
*
* @return true if an enchantment exists on this meta
*/
boolean hasEnchants();
/**
* Checks for existence of the specified enchantment
*
* @param ench enchantment to check
* @return true if this enchantment exists for this meta
*/
boolean hasEnchant(Enchantment ench);
/**
* Checks for the level of the specified enchantment
*
* @param ench enchantment to check
* @return The level that the specified enchantment has, or 0 if none
*/
int getEnchantLevel(Enchantment ench);
/**
* This method gets a copy the enchantments in this ItemMeta
*
* @return An immutable copy of the enchantments
*/
Map<Enchantment, Integer> getEnchants();
/**
* This method adds the specified enchantment to this item meta
*
* @param ench Enchantment to add
* @param level Level for the enchantment
* @param ignoreLevelRestriction this indicates the enchantment should be applied, ignoring the level limit
* @return true if the item meta changed as a result of this call, false otherwise
*/
boolean addEnchant(Enchantment ench, int level, boolean ignoreLevelRestriction);
/**
* This method removes the specified enchantment from this item meta
*
* @param ench Enchantment to remove
* @return true if the item meta changed as a result of this call, false otherwise
*/
boolean removeEnchant(Enchantment ench);
@SuppressWarnings("javadoc")
ItemMeta clone();
}

View File

@@ -0,0 +1,26 @@
package org.bukkit.inventory.meta;
import org.bukkit.Color;
import org.bukkit.Material;
/**
* Represents leather armor ({@link Material#LEATHER_BOOTS}, {@link Material#LEATHER_CHESTPLATE}, {@link Material#LEATHER_HELMET}, or {@link Material#LEATHER_LEGGINGS}) that can be colored.
*/
public interface LeatherArmorMeta extends ItemMeta {
/**
* Gets the color of the armor
*
* @return the color of the armor, never null
*/
Color getColor();
/**
* Sets the color of the armor
*
* @param color the color to set, null makes it the default leather color
*/
void setColor(Color color);
LeatherArmorMeta clone();
}

View File

@@ -0,0 +1,23 @@
package org.bukkit.inventory.meta;
/**
* Represents a map that can be scalable.
*/
public interface MapMeta extends ItemMeta {
/**
* Checks to see if this map is scaling
*
* @return true if this map is scaling
*/
boolean isScaling();
/**
* Sets if this map is scaling or not
*
* @param value true to scale
*/
void setScaling(boolean value);
MapMeta clone();
}

View File

@@ -0,0 +1,69 @@
package org.bukkit.inventory.meta;
import org.bukkit.Material;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import java.util.List;
/**
* Represents a potion ({@link Material#POTION}) that can have custom effects.
*/
public interface PotionMeta extends ItemMeta {
/**
* Checks for the presence of custom potion effects
*
* @return true if custom potion effects are applied
*/
boolean hasCustomEffects();
/**
* Gets an immutable list containing all custom potion effects applied to this potion
*
* @return the immutable list of custom potion effects
*/
List<PotionEffect> getCustomEffects();
/**
* Adds a custom potion effect to this potion
*
* @param effect the potion effect to add
* @param overwrite true if any existing effect of the same type should be overwritten
* @return true if the potion meta changed as a result of this call
*/
boolean addCustomEffect(PotionEffect effect, boolean overwrite);
/**
* Removes a custom potion effect from this potion
*
* @param type the potion effect type to remove
* @return true if the potion meta changed as a result of this call
*/
boolean removeCustomEffect(PotionEffectType type);
/**
* Checks for a specific custom potion effect type on this potion
* @param type the potion effect type to check for
* @return true if the potion has this effect
*/
boolean hasCustomEffect(PotionEffectType type);
/**
* Moves a potion effect to the top of the potion effect list.
* This causes the client to display the potion effect in the potion's name.
*
* @param type the potion effect type to move
* @return true if the potion meta changed as a result of this call
*/
boolean setMainEffect(PotionEffectType type);
/**
* Removes all custom potion effects from this potion
*
* @return true if the potion meta changed as a result of this call
*/
boolean clearCustomEffects();
PotionMeta clone();
}

View File

@@ -0,0 +1,31 @@
package org.bukkit.inventory.meta;
/**
* Represents an item that can be repaired at an anvil.
*/
public interface Repairable {
/**
* Checks to see if this has a repair penalty
*
* @return true if this has a repair penalty
*/
boolean hasRepairCost();
/**
* Gets the repair penalty
*
* @return the repair penalty
*/
int getRepairCost();
/**
* Sets the repair penalty
*
* @param cost repair penalty
*/
void setRepairCost(int cost);
@SuppressWarnings("javadoc")
Repairable clone();
}

View File

@@ -0,0 +1,33 @@
package org.bukkit.inventory.meta;
import org.bukkit.Material;
/**
* Represents a skull ({@link Material#SKULL_ITEM}) that can have an owner.
*/
public interface SkullMeta extends ItemMeta {
/**
* Gets the owner of the skull
*
* @return the owner if the skull
*/
String getOwner();
/**
* Checks to see if the skull has an owner
*
* @return true if the skull has an owner
*/
boolean hasOwner();
/**
* Sets the owner of the skull
*
* @param owner the new owner of the skull
* @return true if the owner was successfully set
*/
boolean setOwner(String owner);
SkullMeta clone();
}