All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.triumphteam.gui.builder.item.BaseItemBuilder Maven / Gradle / Ivy

There is a newer version: 3.1.11
Show newest version
/**
 * MIT License
 * 

* Copyright (c) 2021 TriumphTeam *

* Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: *

* The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. *

* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package dev.triumphteam.gui.builder.item; import dev.triumphteam.gui.components.GuiAction; import dev.triumphteam.gui.components.exception.GuiException; import dev.triumphteam.gui.components.util.ItemNbt; import dev.triumphteam.gui.components.util.Legacy; import dev.triumphteam.gui.components.util.VersionHelper; import dev.triumphteam.gui.guis.GuiItem; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.LeatherArmorMeta; import org.bukkit.persistence.PersistentDataContainer; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.List; import java.util.Objects; import java.util.function.Consumer; import java.util.stream.Collectors; /** * Contains all the common methods for the future ItemBuilders * * @param The ItemBuilder type so the methods can cast to the subtype */ @SuppressWarnings("unchecked") public abstract class BaseItemBuilder> { private static final EnumSet LEATHER_ARMOR = EnumSet.of( Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS ); private static final GsonComponentSerializer GSON = GsonComponentSerializer.gson(); private static final Field DISPLAY_NAME_FIELD; private static final Field LORE_FIELD; static { try { final Class metaClass = VersionHelper.craftClass("inventory.CraftMetaItem"); DISPLAY_NAME_FIELD = metaClass.getDeclaredField("displayName"); DISPLAY_NAME_FIELD.setAccessible(true); LORE_FIELD = metaClass.getDeclaredField("lore"); LORE_FIELD.setAccessible(true); } catch (NoSuchFieldException | ClassNotFoundException exception) { exception.printStackTrace(); throw new GuiException("Could not retrieve displayName nor lore field for ItemBuilder."); } } private ItemStack itemStack; private ItemMeta meta; protected BaseItemBuilder(@NotNull final ItemStack itemStack) { Validate.notNull(itemStack, "Item can't be null!"); this.itemStack = itemStack; meta = itemStack.hasItemMeta() ? itemStack.getItemMeta() : Bukkit.getItemFactory().getItemMeta(itemStack.getType()); } /** * Sets the display name of the item using {@link Component} * * @param name The {@link Component} name * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_ -> this") public B name(@NotNull final Component name) { if (meta == null) return (B) this; if (VersionHelper.IS_ITEM_LEGACY) { meta.setDisplayName(Legacy.SERIALIZER.serialize(name)); return (B) this; } try { DISPLAY_NAME_FIELD.set(meta, GSON.serialize(name)); } catch (IllegalAccessException exception) { exception.printStackTrace(); } return (B) this; } /** * Sets the amount of items * * @param amount the amount of items * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_ -> this") public B amount(final int amount) { itemStack.setAmount(amount); return (B) this; } /** * Set the lore lines of an item * * @param lore Lore lines as varargs * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_ -> this") public B lore(@Nullable final Component @NotNull ... lore) { return lore(Arrays.asList(lore)); } /** * Set the lore lines of an item * * @param lore A {@link List} with the lore lines * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_ -> this") public B lore(@NotNull final List<@Nullable Component> lore) { if (meta == null) return (B) this; if (VersionHelper.IS_ITEM_LEGACY) { meta.setLore(lore.stream().filter(Objects::nonNull).map(Legacy.SERIALIZER::serialize).collect(Collectors.toList())); return (B) this; } final List jsonLore = lore.stream().filter(Objects::nonNull).map(GSON::serialize).collect(Collectors.toList()); try { LORE_FIELD.set(meta, jsonLore); } catch (IllegalAccessException exception) { exception.printStackTrace(); } return (B) this; } /** * Consumer for freely adding to the lore * * @param lore A {@link Consumer} with the {@link List} of lore {@link Component} * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_ -> this") public B lore(@NotNull final Consumer> lore) { if (meta == null) return (B) this; List components; if (VersionHelper.IS_ITEM_LEGACY) { final List stringLore = meta.getLore(); if (stringLore == null) return (B) this; components = stringLore.stream().map(Legacy.SERIALIZER::deserialize).collect(Collectors.toList()); } else { try { final List jsonLore = (List) LORE_FIELD.get(meta); components = jsonLore.stream().map(GSON::deserialize).collect(Collectors.toList()); } catch (IllegalAccessException exception) { components = new ArrayList<>(); exception.printStackTrace(); } } lore.accept(components); return lore(components); } /** * Enchants the {@link ItemStack} * * @param enchantment The {@link Enchantment} to add * @param level The level of the {@link Enchantment} * @param ignoreLevelRestriction If should or not ignore it * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_, _, _ -> this") public B enchant(@NotNull final Enchantment enchantment, final int level, final boolean ignoreLevelRestriction) { meta.addEnchant(enchantment, level, ignoreLevelRestriction); return (B) this; } /** * Enchants the {@link ItemStack} * * @param enchantment The {@link Enchantment} to add * @param level The level of the {@link Enchantment} * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_, _ -> this") public B enchant(@NotNull final Enchantment enchantment, final int level) { return enchant(enchantment, level, true); } /** * Enchants the {@link ItemStack} * * @param enchantment The {@link Enchantment} to add * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_ -> this") public B enchant(@NotNull final Enchantment enchantment) { return enchant(enchantment, 1, true); } /** * Disenchants a certain {@link Enchantment} from the {@link ItemStack} * * @param enchantment The {@link Enchantment} to remove * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_ -> this") public B disenchant(@NotNull final Enchantment enchantment) { itemStack.removeEnchantment(enchantment); return (B) this; } /** * Add an {@link ItemFlag} to the item * * @param flags The {@link ItemFlag} to add * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_ -> this") public B flags(@NotNull final ItemFlag... flags) { meta.addItemFlags(flags); return (B) this; } /** * Makes the {@link ItemStack} unbreakable * * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract(" -> this") public B unbreakable() { return unbreakable(true); } /** * Sets the item as unbreakable * * @param unbreakable If should or not be unbreakable * @return {@link ItemBuilder} */ @NotNull @Contract("_ -> this") public B unbreakable(boolean unbreakable) { if (VersionHelper.IS_UNBREAKABLE_LEGACY) { return setNbt("Unbreakable", unbreakable); } meta.setUnbreakable(unbreakable); return (B) this; } /** * Makes the {@link ItemStack} glow * * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract(" -> this") public B glow() { return glow(true); } /** * Adds or removes the {@link ItemStack} glow * * @param glow Should the item glow * @return {@link ItemBuilder} */ @NotNull @Contract("_ -> this") public B glow(boolean glow) { if (glow) { meta.addEnchant(Enchantment.LURE, 1, false); meta.addItemFlags(ItemFlag.HIDE_ENCHANTS); return (B) this; } for (final Enchantment enchantment : meta.getEnchants().keySet()) { meta.removeEnchant(enchantment); } return (B) this; } /** * Consumer for applying {@link PersistentDataContainer} to the item * This method will only work on versions above 1.14 * * @param consumer The {@link Consumer} with the PDC * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_ -> this") public B pdc(@NotNull final Consumer consumer) { consumer.accept(meta.getPersistentDataContainer()); return (B) this; } /** * Sets the custom model data of the item * Added in 1.13 * * @param modelData The custom model data from the resource pack * @return {@link ItemBuilder} * @since 3.0.0 */ @NotNull @Contract("_ -> this") public B model(final int modelData) { if (VersionHelper.IS_CUSTOM_MODEL_DATA) { meta.setCustomModelData(modelData); } return (B) this; } /** * Color an {@link org.bukkit.inventory.ItemStack} * * @param color color * @return {@link B} * @see org.bukkit.inventory.meta.LeatherArmorMeta#setColor(Color) * @see org.bukkit.inventory.meta.MapMeta#setColor(Color) * @since 3.0.3 */ @NotNull @Contract("_ -> this") public B color(@NotNull final Color color) { if (LEATHER_ARMOR.contains(itemStack.getType())) { final LeatherArmorMeta leatherArmorMeta = (LeatherArmorMeta) getMeta(); leatherArmorMeta.setColor(color); setMeta(leatherArmorMeta); } return (B) this; } /** * Sets NBT tag to the {@link ItemStack} * * @param key The NBT key * @param value The NBT value * @return {@link ItemBuilder} */ @NotNull @Contract("_, _ -> this") public B setNbt(@NotNull final String key, @Nullable final String value) { itemStack.setItemMeta(meta); itemStack = ItemNbt.setString(itemStack, key, value); meta = itemStack.getItemMeta(); return (B) this; } /** * Sets NBT tag to the {@link ItemStack} * * @param key The NBT key * @param value The NBT value * @return {@link ItemBuilder} */ @NotNull @Contract("_, _ -> this") public B setNbt(@NotNull final String key, final boolean value) { itemStack.setItemMeta(meta); itemStack = ItemNbt.setBoolean(itemStack, key, value); meta = itemStack.getItemMeta(); return (B) this; } /** * Removes NBT tag from the {@link ItemStack} * * @param key The NBT key * @return {@link ItemBuilder} */ @NotNull @Contract("_ -> this") public B removeNbt(@NotNull final String key) { itemStack.setItemMeta(meta); itemStack = ItemNbt.removeTag(itemStack, key); meta = itemStack.getItemMeta(); return (B) this; } /** * Builds the item into {@link ItemStack} * * @return The fully built {@link ItemStack} */ @NotNull public ItemStack build() { itemStack.setItemMeta(meta); return itemStack; } /** * Creates a {@link GuiItem} instead of an {@link ItemStack} * * @return A {@link GuiItem} with no {@link GuiAction} */ @NotNull @Contract(" -> new") public GuiItem asGuiItem() { return new GuiItem(build()); } /** * Creates a {@link GuiItem} instead of an {@link ItemStack} * * @param action The {@link GuiAction} to apply to the item * @return A {@link GuiItem} with {@link GuiAction} */ @NotNull @Contract("_ -> new") public GuiItem asGuiItem(@NotNull final GuiAction action) { return new GuiItem(build(), action); } /** * Package private getter for extended builders * * @return The ItemStack */ @NotNull protected ItemStack getItemStack() { return itemStack; } /** * Package private setter for the extended builders * * @param itemStack The ItemStack */ protected void setItemStack(@NotNull final ItemStack itemStack) { this.itemStack = itemStack; } /** * Package private getter for extended builders * * @return The ItemMeta */ @NotNull protected ItemMeta getMeta() { return meta; } /** * Package private setter for the extended builders * * @param meta The ItemMeta */ protected void setMeta(@NotNull final ItemMeta meta) { this.meta = meta; } // DEPRECATED, TO BE REMOVED METHODS // TODO Remove deprecated methods /** * Set display name of the item * * @param name the display name of the item * @return {@link ItemBuilder} * @deprecated In favor of {@link BaseItemBuilder#name(Component)}, will be removed in 3.0.1 */ @Deprecated public B setName(@NotNull final String name) { getMeta().setDisplayName(name); return (B) this; } /** * Sets the amount of items * * @param amount the amount of items * @return {@link ItemBuilder} * @deprecated In favor of {@link BaseItemBuilder#amount(int)}, nothing changed just the name, will be removed in 3.0.1 */ @Deprecated public B setAmount(final int amount) { getItemStack().setAmount(amount); return (B) this; } /** * Add lore lines of an item * * @param lore the lore lines to add * @return {@link ItemBuilder} * @deprecated In favor of {@link ItemBuilder#lore(Consumer)}, will be removed in 3.0.1 */ @Deprecated public B addLore(@NotNull final String... lore) { return addLore(Arrays.asList(lore)); } /** * Set lore lines of an item * * @param lore A {@link List} with the lore lines to add * @return {@link ItemBuilder} * @deprecated In favor of {@link ItemBuilder#lore(Consumer)}, will be removed in 3.0.1 */ @Deprecated public B addLore(@NotNull final List lore) { final List newLore = getMeta().hasLore() ? getMeta().getLore() : new ArrayList<>(); newLore.addAll(lore); return setLore(newLore); } /** * Set the lore lines of an item * * @param lore the lore lines to set * @return {@link ItemBuilder} * @deprecated In favor of {@link ItemBuilder#lore(Component...)}, will be removed in 3.0.1 */ @Deprecated public B setLore(@NotNull final String... lore) { return setLore(Arrays.asList(lore)); } /** * Set the lore lines of an item * * @param lore A {@link List} with the lore lines * @return {@link ItemBuilder} * @deprecated In favor of {@link ItemBuilder#lore(List)}, will be removed in 3.0.1 */ @Deprecated public B setLore(@NotNull final List lore) { getMeta().setLore(lore); return (B) this; } /** * Add enchantment to an item * * @param enchantment the {@link Enchantment} to add * @param level the level of the {@link Enchantment} * @param ignoreLevelRestriction If should or not ignore it * @return {@link ItemBuilder} * @deprecated In favor of {@link ItemBuilder#enchant(Enchantment, int, boolean)}, nothing changed just the name, will be removed in 3.0.1 */ @Deprecated public B addEnchantment(@NotNull final Enchantment enchantment, final int level, final boolean ignoreLevelRestriction) { getMeta().addEnchant(enchantment, level, ignoreLevelRestriction); return (B) this; } /** * Add enchantment to an item * * @param enchantment the {@link Enchantment} to add * @param level the level of the {@link Enchantment} * @return {@link ItemBuilder} * @deprecated In favor of {@link ItemBuilder#enchant(Enchantment, int)}, nothing changed just the name, will be removed in 3.0.1 */ @Deprecated public B addEnchantment(@NotNull final Enchantment enchantment, final int level) { return addEnchantment(enchantment, level, true); } /** * Add enchantment to an item * * @param enchantment the {@link Enchantment} to add * @return {@link ItemBuilder} * @deprecated In favor of {@link ItemBuilder#enchant(Enchantment)}, nothing changed just the name, will be removed in 3.0.1 */ @Deprecated public B addEnchantment(@NotNull final Enchantment enchantment) { return addEnchantment(enchantment, 1, true); } /** * Removes a certain {@link Enchantment} from the item * * @param enchantment The {@link Enchantment} to remove * @return {@link ItemBuilder} * @deprecated In favor of {@link ItemBuilder#disenchant(Enchantment)}, nothing changed just the name, will be removed in 3.0.1 */ @Deprecated public B removeEnchantment(@NotNull final Enchantment enchantment) { getItemStack().removeEnchantment(enchantment); return (B) this; } /** * Add a custom {@link ItemFlag} to the item * * @param flags the {@link ItemFlag} to add * @return {@link ItemBuilder} * @deprecated In favor of {@link ItemBuilder#flags(ItemFlag...)}, nothing changed just the name, will be removed in 3.0.1 */ @Deprecated public B addItemFlags(@NotNull final ItemFlag... flags) { getMeta().addItemFlags(flags); return (B) this; } /** * Sets the item as unbreakable * * @param unbreakable If should or not be unbreakable * @return {@link ItemBuilder} * @deprecated In favor of {@link ItemBuilder#unbreakable()}, nothing changed just the name, will be removed in 3.0.1 */ @Deprecated public B setUnbreakable(boolean unbreakable) { return unbreakable(unbreakable); } }