package com.supaham.commons.bukkit; import com.google.common.base.Preconditions; import com.supaham.commons.bukkit.items.ItemEnchantment; import com.supaham.commons.bukkit.utils.EnchantmentUtils; import org.bukkit.Color; import org.bukkit.DyeColor; import org.bukkit.FireworkEffect; import org.bukkit.Material; import org.bukkit.block.banner.Pattern; import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BannerMeta; import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.FireworkEffectMeta; import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.inventory.meta.MapMeta; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.inventory.meta.Repairable; import org.bukkit.inventory.meta.SkullMeta; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; /** * Represents an {@link ItemStack} builder. This class has unsafe methods which can throw * exceptions, though such exceptions can be suppressed using the silent fail option that is * provided in the builder methods. * <p /> * Methods that are <b>UNSAFE</b> are mentioned as a suffix to the * method's documentation. An example of an unsafe method is {@link #bookTitle(String)}. * * @since 0.1 */ public class ItemBuilder { private final ItemStack itemStack; private final boolean failSilently; private ItemMeta itemMeta; /** * Creates a new {@link ItemBuilder} to start building an item. This is equivalent to calling * {@link #builder(Material, boolean)} with the boolean as false. * * @param type type of item to build, can be changed at any point during the building process * through {@link #type(Material)} * * @return item builder instance */ public static ItemBuilder builder(Material type) { return builder(type, false); } /** * Creates a new {@link ItemBuilder} to start building an item. * * @param type type of item to build, can be changed at any point during the building process * through {@link #type(Material)} * @param failSilently whether to fail silently (suppress exceptions) when an <b>UNSAFE</b> * method * throws an exception * * @return item builder instance */ public static ItemBuilder builder(Material type, boolean failSilently) { // default item amount because 1.8 displays the number 0 on itemstacks that have 0 as amount. return builder(new ItemStack(type, 1), failSilently); } /** * Creates a new {@link ItemBuilder} to start building an item. This is equivalent to calling * {@link #builder(ItemStack, boolean)} with the boolean as false. * * @param item base item to start building * * @return item builder instance */ public static ItemBuilder builder(ItemStack item) { return builder(item, false); } /** * Creates a new {@link ItemBuilder} to start building an item. * * @param item base item to start building * @param failSilently whether to fail silently (suppress exceptions) when an <b>UNSAFE</b> * method * throws an exception * * @return item builder instance */ public static ItemBuilder builder(ItemStack item, boolean failSilently) { return new ItemBuilder(item, failSilently); } private ItemBuilder(ItemStack itemStack, boolean failSilently) { this.itemStack = itemStack.clone(); this.itemMeta = itemStack.getItemMeta(); this.failSilently = failSilently; } /** * Makes a complete copy of an {@link ItemBuilder} with its latest changes. * * @param itemBuilder item builder to copy */ public ItemBuilder(ItemBuilder itemBuilder) { this.itemStack = new ItemStack(itemBuilder.itemStack.getType(), itemBuilder.itemStack.getAmount(), itemBuilder.itemStack.getDurability()); this.itemMeta = itemBuilder.itemMeta.clone(); this.failSilently = itemBuilder.failSilently; } /** * Returns a complete copy of this {@link ItemBuilder} instance. * * @return new item builder instance */ public ItemBuilder copy() { return new ItemBuilder(this); } /** * Builds this item builder, producing an {@link ItemStack}. * * @return the built itemstack */ public ItemStack build() { this.itemStack.setItemMeta(this.itemMeta); return this.itemStack.clone(); // Hang on to the item } /** * Sets the type of item to build. * <p /> * <b>WARNING: This method WILL call {@link ItemMetaCopyCat#copy(Material, ItemMeta)} to copy the * previous item meta.</b> * * @param type type to set * * @return this item builder instance, for chaining */ public ItemBuilder type(@Nonnull Material type) { if (type == null) { if (!this.failSilently) { throw new IllegalArgumentException("type cannot be null."); } return this; } try { if (this.itemStack.getType() != type) { this.itemStack.setItemMeta(this.itemMeta); this.itemStack.setType(type); this.itemMeta = ItemMetaCopyCat.copy(type, this.itemMeta); if (this.itemMeta == null) { this.itemMeta = this.itemStack.getItemMeta(); } } } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Sets the item's amount. * * @param amount amount to set * * @return this item builder instance, for chaining */ public ItemBuilder amount(int amount) { try { this.itemStack.setAmount(amount); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Sets the item's durability. * * @param durability durability to set * * @return this item builder instance, for chaining */ public ItemBuilder durability(int durability) { if (!this.failSilently) { Preconditions.checkArgument(durability <= Short.MAX_VALUE, "durability cannot exceed " + Short.MAX_VALUE); } try { this.itemStack.setDurability((short) durability); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Sets the item's color using {@link DyeColor}. * * @param color dye to color this item with * * @return this item builder instance, for chaining */ public ItemBuilder dye(@Nullable DyeColor color) { try { if (color == null) { this.itemStack.setDurability((short) 0); return this; } if (this.itemStack.getType() == Material.INK_SACK) { this.itemStack.setDurability((short) color.getDyeData()); } else { this.itemStack.setDurability((short) color.getWoolData()); } } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Sets the item's display name. * * @param name display name to set * * @return this item builder instance, for chaining */ public ItemBuilder name(@Nullable Colors name) { return name(name == null ? null : name.toString()); } /** * Sets the item's display name. * * @param name display name to set * * @return this item builder instance, for chaining */ public ItemBuilder name(@Nullable String name) { try { this.itemMeta.setDisplayName(name); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Adds lore to this item. * * @param lore lore to add * * @return this item builder instance, for chaining */ public ItemBuilder lore(@Nonnull Colors... lore) { List<String> list = new ArrayList<>(lore.length); for (Colors colors : lore) { list.add(colors.toString()); } return lore(list); } /** * Adds lore to this item. * * @param lore lore to add * * @return this item builder instance, for chaining */ public ItemBuilder lore(@Nonnull String... lore) { lore(Arrays.asList(lore)); return this; } /** * Adds lore to this item. * * @param lore lore to add * * @return this item builder instance, for chaining */ public ItemBuilder lore(@Nonnull Collection<String> lore) { if (lore == null) { if (!this.failSilently) { throw new IllegalArgumentException("lore cannot be null."); } return this; } try { if (lore.size() != 0) { List<String> loreList = this.itemMeta.getLore(); if (loreList == null) { loreList = new ArrayList<>(lore.size()); } loreList.addAll(lore); this.itemMeta.setLore(loreList); } } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Returns an unmodifiable {@link List} of this ItemBuilder's lore. * * @return list of lore */ public List<String> getLore() { return Collections.unmodifiableList(this.itemMeta.getLore()); } /** * Sets this item's lore. This method effectively clears the already existing lore and adds the * given lore. * * @param lore lore to set * * @return this item builder instance, for chaining */ public ItemBuilder setLore(@Nonnull Collection<String> lore) { if (lore == null) { if (!this.failSilently) { throw new IllegalArgumentException("lore cannot be null."); } return this; } try { this.itemMeta.setLore(!(lore instanceof List) ? new ArrayList<>(lore) : ((List<String>) lore)); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Removes a lore, by index, from this item. * * @param index lore index to remove * * @return this item builder instance, for chaining */ public ItemBuilder removeLore(int index) { try { if (this.itemMeta.hasLore()) { List<String> lore = this.itemMeta.getLore(); lore.remove(index); this.itemMeta.setLore(lore); } } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Clears all lore from this item. * * @return this item builder instance, for chaining */ public ItemBuilder clearLore() { try { this.itemMeta.setLore(null); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Adds the {@link EnchantmentUtils#GLOW_ENCHANTMENT} to this item, making it glow as enchanted, * without the enchantment label. * * @return this item builder instance, for chaining */ public ItemBuilder glow() { return glow(true); } /** * Sets whether this item is to glow using {@link EnchantmentUtils#GLOW_ENCHANTMENT}, making it * glow as enchanted, without the enchantment label. * * @param glow whether this item should glow * * @return this item builder instance, for chaining */ public ItemBuilder glow(boolean glow) { if (glow) { return enchant(EnchantmentUtils.GLOW_ENCHANTMENT, 1, true); } else { return removeEnchant(EnchantmentUtils.GLOW_ENCHANTMENT); } } /** * Adds an {@link ItemEnchantment} to this item. This WILL overwrite the existing * enchantment, if it does exist. This is equivalent to calling {@link #enchant(ItemEnchantment, * boolean)} with the boolean as true. * * @param enchantment enchantment to add * * @return this item builder instance, for chaining */ public ItemBuilder enchant(@Nonnull ItemEnchantment enchantment) { return enchant(enchantment, true); } /** * Adds an {@link ItemEnchantment} to this item. This is equivalent to calling {@link * #enchant(Enchantment, int, boolean)}. * * @param enchantment enchantment to add * * @return this item builder instance, for chaining */ public ItemBuilder enchant(@Nonnull ItemEnchantment enchantment, boolean overwrite) { try { return enchant(enchantment.getEnchantment(), enchantment.getLevel(), overwrite); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } return this; } } /** * Adds an {@link Enchantment} to this item with level set to 1. This WILL overwrite the existing * enchantment, if it does exist. This is equivalent to calling {@link #enchant(Enchantment, int, * boolean)} with the * int as 1 and the boolean as true. * * @param enchantment enchantment to add * * @return this item builder instance, for chaining */ public ItemBuilder enchant(@Nonnull Enchantment enchantment) { return enchant(enchantment, 1, true); } /** * Adds an {@link Enchantment} to this item. This WILL overwrite the existing enchantment, if it * does exist. * * @param enchantment enchantment to add * @param level level of the {@code enchantment} * * @return this item builder instance, for chaining */ public ItemBuilder enchant(@Nonnull Enchantment enchantment, int level) { return enchant(enchantment, level, true); } /** * Adds an {@link Enchantment} to this item. * * @param enchantment enchantment to add * @param level level of the {@code enchantment} * @param overwrite whether to overwrite the existing enchantment, if it does exist * * @return this item builder instance, for chaining */ public ItemBuilder enchant(@Nonnull Enchantment enchantment, int level, boolean overwrite) { try { this.itemMeta.addEnchant(enchantment, level, overwrite); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Removes an {@link Enchantment} from this item. * * @param enchantment enchantment to remove * * @return this item builder instance, for chaining */ public ItemBuilder removeEnchant(@Nonnull Enchantment enchantment) { try { this.itemMeta.removeEnchant(enchantment); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Sets this item's repair cost. * * @param cost repair cost * * @return this item builder instance, for chaining */ public ItemBuilder repairCost(int cost) { try { ((Repairable) this.itemMeta).setRepairCost(cost); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Adds {@link ItemFlag}s to this item. * * @param itemFlags item flags to add to this item * * @return this item builder instance, for chaining */ public ItemBuilder flag(ItemFlag... itemFlags) { try { this.itemMeta.addItemFlags(itemFlags); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Sets this item to be unbreakable. * * @return this item builder instance, for chaining */ public ItemBuilder unbreakable() { return unbreakable(true); } /** * Sets whether this item is to be unbreakable. * * @param unbreakable whether this item should be unbreakable * * @return this item builder instance, for chaining */ public ItemBuilder unbreakable(boolean unbreakable) { try { this.itemMeta.spigot().setUnbreakable(unbreakable); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } return this; } /** * Sets this book's title, assuming it is a book. * <p /> * <b>UNSAFE</b> * * @param title title to set * * @return this item builder instance, for chaining */ public ItemBuilder bookTitle(@Nullable Colors title) { return bookTitle(title == null ? null : title.toString()); } /** * Sets this book's title, assuming it is a book. * <p /> * <b>UNSAFE</b> * * @param title title to set * * @return this item builder instance, for chaining */ public ItemBuilder bookTitle(@Nullable String title) { if (isBookMeta()) { try { ((BookMeta) this.itemMeta).setTitle(title); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Sets this book's author, assuming it is a book. * <p /> * <b>UNSAFE</b> * * @param author author to set * * @return this item builder instance, for chaining */ public ItemBuilder bookAuthor(@Nullable Colors author) { return bookAuthor(author == null ? null : author.toString()); } /** * Sets this book's author, assuming it is a book. * <p /> * <b>UNSAFE</b> * * @param author author to set * * @return this item builder instance, for chaining */ public ItemBuilder bookAuthor(@Nullable String author) { if (isBookMeta()) { try { ((BookMeta) this.itemMeta).setAuthor(author); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Sets this a page index in this book, assuming it is a book. * <p /> * <b>UNSAFE</b> * * @param index index of the page to set * @param data page data to set * * @return this item builder instance, for chaining */ public ItemBuilder bookSetPage(int index, @Nullable Colors data) { return bookSetPage(index, data == null ? null : data.toString()); } /** * Sets this a page index in this book, assuming it is a book. * <p /> * <b>UNSAFE</b> * * @param index index of the page to set * @param data page data to set * * @return this item builder instance, for chaining */ public ItemBuilder bookSetPage(int index, @Nullable String data) { if (isBookMeta()) { try { ((BookMeta) this.itemMeta).setPage(index, data); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Sets this book's pages, assuming it is a book. * <p /> * <b>Note: This is a clear and write operation, for appending, see {@link * #bookAdd(String...)}</b> * <p /> * <b>UNSAFE</b> * * @param pages pages to set * * @return this item builder instance, for chaining */ public ItemBuilder bookSet(@Nullable Colors... pages) { String[] array = new String[pages == null ? 0 : pages.length]; for (int i = 0; i < array.length; i++) { array[i] = pages[i].toString(); } return bookSet(array); } /** * Sets this book's pages, assuming it is a book. * <p /> * <b>Note: This is a clear and write operation, for appending, see {@link * #bookAdd(String...)}</b> * <p /> * <b>UNSAFE</b> * * @param pages pages to set * * @return this item builder instance, for chaining */ public ItemBuilder bookSet(@Nonnull String... pages) { if (pages == null) { if (!this.failSilently) { throw new IllegalArgumentException("pages cannot be null."); } return this; } if (isBookMeta()) { try { ((BookMeta) this.itemMeta).setPages(pages); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Adds pages to this book, assuming it is a book. * <p /> * <b>UNSAFE</b> * * @param pages pages to add * * @return this item builder instance, for chaining */ public ItemBuilder bookAdd(@Nonnull Colors... pages) { List<String> list = new ArrayList<>(pages.length); for (Colors colors : pages) { list.add(colors.toString()); } return lore(list); } /** * Adds pages to this book, assuming it is a book. * <p /> * <b>UNSAFE</b> * * @param pages pages to add * * @return this item builder instance, for chaining */ public ItemBuilder bookAdd(@Nonnull String... pages) { if (pages == null) { if (!this.failSilently) { throw new IllegalArgumentException("pages cannot be null."); } return this; } if (isBookMeta()) { try { ((BookMeta) this.itemMeta).addPage(pages); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Adds {@link FireworkEffect}s to this item, assuming it is a firework or firework charge. * <p /> * <b>UNSAFE</b> * * @param effects effects to add * * @return this item builder instance, for chaining */ public ItemBuilder fireworkAdd(@Nonnull FireworkEffect... effects) { if (effects == null) { if (!this.failSilently) { throw new IllegalArgumentException("effects cannot be null."); } return this; } boolean b = isFireworkEffectMeta(); if (b || isFireworkMeta()) { try { if (b) { ((FireworkEffectMeta) this.itemMeta).setEffect(effects[0]); } else { ((FireworkMeta) this.itemMeta).addEffects(effects); } } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Removes the first {@link FireworkEffect} on this item, assuming it is a firework or firework * charge. This is equivalent to calling {@link #fireworkRemove(int)} with int as 0. * <p /> * <b>UNSAFE</b> * * @return this item builder instance, for chaining * * @see #fireworkRemove(int) */ public ItemBuilder fireworkRemove() { return fireworkRemove(0); } /** * Removes a {@link FireworkEffect} by index from this item, assuming it is a firework. If it is * a * firework charge, its one and only effect is removed, disregarding the index given. * <p /> * <b>UNSAFE</b> * * @param index index of the firework to remove * * @return this item builder instance, for chaining */ public ItemBuilder fireworkRemove(int index) { boolean b = isFireworkEffectMeta(); if (b || isFireworkMeta()) { try { if (b) { ((FireworkEffectMeta) this.itemMeta).setEffect(null); } else { ((FireworkMeta) this.itemMeta).removeEffect(index); } } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Clears all {@link FireworkEffect}s on this item, assuming it is a firework or firework charge. * <p /> * <b>UNSAFE</b> * * @return this item builder instance, for chaining */ public ItemBuilder fireworkClear() { boolean b = isFireworkEffectMeta(); if (b || isFireworkMeta()) { try { if (b) { ((FireworkEffectMeta) this.itemMeta).setEffect(null); } else { ((FireworkMeta) this.itemMeta).clearEffects(); } } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Sets this firework's power, assuming it is a firework. * <p /> * <b>UNSAFE</b> * * @param power power to set * * @return this item builder instance, for chaining */ public ItemBuilder fireworkPower(int power) { if (isFireworkMeta()) { try { ((FireworkMeta) this.itemMeta).setPower(power); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Sets this leather armor's color, assuming the item is leather armor. * <p /> * <b>UNSAFE</b> * * @param color color to set * * @return this item builder instance, for chaining */ public ItemBuilder armorColor(@Nonnull Color color) { if (isLeatherArmorMeta()) { try { ((LeatherArmorMeta) this.itemMeta).setColor(color); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Sets whether this map scales, assuming the item is a map. * <p /> * <b>UNSAFE</b> * * @param scale whether to scale * * @return this item builder instance, for chaining */ public ItemBuilder mapScale(boolean scale) { if (isMapMeta()) { try { ((MapMeta) this.itemMeta).setScaling(scale); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Sets this item's main effect, assuming it is a potion. * <p /> * <b>UNSAFE</b> * * @param effectType effect type to set * * @return this item builder instance, for chaining */ public ItemBuilder potionMain(@Nonnull PotionEffectType effectType) { if (isPotionMeta()) { try { ((PotionMeta) this.itemMeta).setMainEffect(effectType); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Adds a {@link PotionEffect} to this item, assuming it is a potion. This is equivalent to * calling {@link #potionAdd(PotionEffect, boolean)} with boolean as true. * <p /> * <b>UNSAFE</b> * * @param effect effect to add * * @return this item builder instance, for chaining */ public ItemBuilder potionAdd(@Nonnull PotionEffect effect) { return potionAdd(effect, true); } /** * Adds a {@link PotionEffect} to this item, assuming it is a potion. * <p /> * <b>UNSAFE</b> * * @param effect effect to add * @param overwrite whether to overwrite any previous potions of the same effect type * * @return this item builder instance, for chaining */ public ItemBuilder potionAdd(@Nonnull PotionEffect effect, boolean overwrite) { if (isPotionMeta()) { try { ((PotionMeta) this.itemMeta).addCustomEffect(effect, overwrite); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Removes a {@link PotionEffect} from this item, assuming it is a potion. * <p /> * <b>UNSAFE</b> * * @param effectType effect type to remove * * @return this item builder instance, for chaining */ public ItemBuilder potionRemove(@Nonnull PotionEffectType effectType) { if (isPotionMeta()) { try { ((PotionMeta) this.itemMeta).removeCustomEffect(effectType); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Clears all custom (added) {@link PotionEffect}s from this item, assuming it is a potion. * <p /> * <b>UNSAFE</b> * * @return this item builder instance, for chaining */ public ItemBuilder potionClear() { if (isPotionMeta()) { try { ((PotionMeta) this.itemMeta).clearCustomEffects(); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Sets this item's skull owner (player head), assuming it is a skull. * <p /> * <b>UNSAFE</b> * * @param owner owner to set * * @return this item builder instance, for chaining */ public ItemBuilder skull(@Nullable String owner) { if (isSkullMeta()) { try { ((SkullMeta) this.itemMeta).setOwner(owner); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Sets this banner's base color, assuming it is a banner. * <p /> * <b>UNSAFE</b> * * @param color base color to set * * @return this item builder instance, for chaining */ public ItemBuilder bannerColor(DyeColor color) { if (isBannerMeta()) { try { ((BannerMeta) this.itemMeta).setBaseColor(color); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Adds a {@link Pattern} to a specific index to this banner, assuming it is a banner. * <p /> * <b>UNSAFE</b> * * @param index index to set * @param pattern pattern to add * * @return this item builder instance, for chaining */ public ItemBuilder bannerSet(int index, Pattern pattern) { if (isBannerMeta()) { try { ((BannerMeta) this.itemMeta).setPattern(index, pattern); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Sets this banner's patterns, assuming it is a banner. * <p /> * <b>UNSAFE</b> * * @param patterns patterns to set * * @return this item builder instance, for chaining */ public ItemBuilder bannerSet(List<Pattern> patterns) { if (isBannerMeta()) { try { ((BannerMeta) this.itemMeta).setPatterns(patterns); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Adds {@link Pattern}s to this banner, assuming it is a banner. * <p /> * <b>UNSAFE</b> * * @param patterns patterns to add * * @return this item builder instance, for chaining */ public ItemBuilder bannerAdd(Pattern... patterns) { if (patterns == null) { if (!this.failSilently) { throw new IllegalArgumentException("patterns cannot be null."); } return this; } if (isBannerMeta()) { try { for (Pattern pattern : patterns) { if (pattern != null) { ((BannerMeta) this.itemMeta).addPattern(pattern); } else { throw new NullPointerException("pattern element is null."); } } } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } /** * Removes a pattern by index from this banner, assuming it is a banner. * <p /> * <b>UNSAFE</b> * * @param index index of pattern to remove * * @return this item builder instance, for chaining */ public ItemBuilder bannerRemove(int index) { if (isBannerMeta()) { try { ((BannerMeta) this.itemMeta).removePattern(index); } catch (Exception e) { if (!this.failSilently) { e.printStackTrace(); } } } return this; } private boolean isBookMeta() { if (!(this.itemMeta instanceof BookMeta)) { if (!this.failSilently) { throw new IllegalStateException("ItemMeta is not of BookMeta."); } return false; } return true; } private boolean isFireworkMeta() { if (!(this.itemMeta instanceof FireworkMeta)) { if (!this.failSilently) { throw new IllegalStateException("ItemMeta is not of FireworkMeta."); } return false; } return true; } private boolean isFireworkEffectMeta() { if (!(this.itemMeta instanceof FireworkEffectMeta)) { if (!this.failSilently) { throw new IllegalStateException("ItemMeta is not of FireworkEffectMeta."); } return false; } return true; } private boolean isLeatherArmorMeta() { if (!(this.itemMeta instanceof LeatherArmorMeta)) { if (!this.failSilently) { throw new IllegalStateException("ItemMeta is not of LeatherArmorMeta."); } return false; } return true; } private boolean isMapMeta() { if (!(this.itemMeta instanceof MapMeta)) { if (!this.failSilently) { throw new IllegalStateException("ItemMeta is not of MapMeta."); } return false; } return true; } private boolean isPotionMeta() { if (!(this.itemMeta instanceof PotionMeta)) { if (!this.failSilently) { throw new IllegalStateException("ItemMeta is not of PotionMeta."); } return false; } return true; } private boolean isSkullMeta() { if (!(this.itemMeta instanceof SkullMeta)) { if (!this.failSilently) { throw new IllegalStateException("ItemMeta is not of SkullMeta."); } return false; } return true; } private boolean isBannerMeta() { if (!(this.itemMeta instanceof BannerMeta)) { if (!this.failSilently) { throw new IllegalStateException("ItemMeta is not of BannerMeta."); } return false; } return true; } }