/* * Copyright (c) 2018 univento.eu - All rights reserved * You are not allowed to use, distribute or modify this code */ package eu.univento.core.api.items; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import eu.univento.commons.player.language.MessageConstant; import eu.univento.commons.player.user.UserInformation; import eu.univento.core.api.items.attribute.Attribute; import eu.univento.core.api.items.attribute.AttributeModifier; import eu.univento.core.api.items.attribute.ItemAttributes; import eu.univento.core.api.items.attribute.ItemSlot; import eu.univento.core.api.player.CustomPlayer; import eu.univento.core.api.utils.GameProfileBuilder; import org.bukkit.Color; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; 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.inventory.meta.SkullMeta; import org.bukkit.material.MaterialData; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; /** * NOTICE: This utility was developer as part of AeolusLib. While you can use it for your own projects, You are NOT allowed to delete or move this header comment. * * Utility: * Chainable {@link ItemStack}s * * Example Usage(s): * {@code ItemStack itemStack = new ItemBuilder(Material.SKULL_ITEM).amount(1).durability(3).skullOwner("MCAeolus").name(ChatColor.RED+"MCAeolus's Skull").make())} * {@code ItemStack itemStack = new ItemBuilder().type(Material.BEDROCK).lores(new String[]{"Lore1",ChatColor.RED+"Lore2"}).enchantment(Enchantment.DAMAGE_ALL, 99).make()} * * @author MCAeolus, joethei * @version 1.1 */ public class ItemBuilder { private CustomPlayer player; private ItemStack item; private ItemMeta meta; /** * Init item chainable via given Material parameter. * * @param itemType the {@link Material} to initiate the instance with. * * @since 1.0 */ public ItemBuilder(final Material itemType) { item = new ItemStack(itemType); meta = item.getItemMeta(); } /** * Init item chainable via given Material parameter. * * @param itemType the {@link Material} to initiate the instance with. * * @since 1.0 */ public ItemBuilder(final CustomPlayer player, final Material itemType) { this.player = player; item = new ItemStack(itemType); meta = item.getItemMeta(); } /** * Changes the Material type of the {@link ItemStack} * * @param material the new {@link Material} to set for the ItemStack. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder type(final Material material) { item.setType(material); return this; } /** * Changes the {@link ItemStack}s size. * * @param itemAmt the new Integer count of the ItemStack. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder amount(final Integer itemAmt) { item.setAmount(itemAmt); return this; } /** * Changes the {@link ItemStack}s display name. * * @param name the new String for the ItemStack's display name to be set to. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder name(final String name) { meta.setDisplayName(name); item.setItemMeta(meta); return this; } public ItemBuilder name(final MessageConstant messageConstant) { if(player == null) return this; meta.setDisplayName(player.getDatabasePlayer().getLanguage().getMessage(messageConstant)); item.setItemMeta(meta); return this; } /** * Adds a line of lore to the {@link ItemStack} * * @param lore String you want to add to the ItemStack's lore. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder lore(final String lore) { List lores = meta.getLore(); if(lores == null){lores = new ArrayList<>();} lores.add(lore); meta.setLore(lores); item.setItemMeta(meta); return this; } /** * Clears the {@link ItemStack}s lore and replaces it with the defined String array. * * @param lores String array you want to set the ItemStack's lore to. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder lores(final String[] lores) { List loresList = meta.getLore(); if(loresList == null) loresList = new ArrayList<>(); else{loresList.clear();} Collections.addAll(loresList, lores); meta.setLore(loresList); return this; } public ItemBuilder durability(short durability) { item.setDurability(durability); return this; } /** * Changes the data value of the {@link ItemStack} * * @param data the new int data value (parsed as byte) to set the ItemStack's durability to. * * @return the current instance for chainable application. * @since 1.0 */ @SuppressWarnings("deprecation") public ItemBuilder data(final int data) { item.setData(new MaterialData(build().getType(), (byte)data)); return this; } /** * Adds and UnsafeEnchantment to the {@link ItemStack} with a defined level int value. * * @param enchantment the {@link Enchantment} to add to the ItemStack. * * @param level the int amount that the Enchantment's level will be set to. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder enchantment(final Enchantment enchantment, final int level) { item.addUnsafeEnchantment(enchantment, level); return this; } /** * Adds and UnsafeEnchantment to the {@link} with a level int value of 1. * * @param enchantment the {@link Enchantment} to add to the ItemStack. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder enchantment(final Enchantment enchantment) { item.addUnsafeEnchantment(enchantment, 1); return this; } /** * Clears all {@link Enchantment}s from the current {@link ItemStack} then adds the defined array of Enchantments to the ItemStack. * * @param enchantments the Enchantment array to replace any current enchantments applied on the ItemStack. * * @param level the int level value for all Enchantments to be set to. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder enchantments(final Enchantment[] enchantments, final int level) { item.getEnchantments().clear(); for(Enchantment enchantment : enchantments){ item.addUnsafeEnchantment(enchantment, level); } return this; } /** * Clears all {@link Enchantment}s from the current {@link ItemStack} then adds the defined array of Enchantments to the ItemStack with a level int value of 1. * * @param enchantments the Enchantment array to replace any current enchantments applied on the ItemStack. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder enchantments(final Enchantment[] enchantments) { item.getEnchantments().clear(); for(Enchantment enchantment : enchantments){ item.addUnsafeEnchantment(enchantment, 1); } return this; } /** * Clears the defined {@link Enchantment} from the {@link ItemStack} * * @param enchantment the Enchantment to remove from the ItemStack. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder clearEnchantment(final Enchantment enchantment) { Map itemEnchantments = item.getEnchantments(); itemEnchantments.keySet().stream().filter(enchantmentC -> enchantment == enchantmentC).forEach(itemEnchantments::remove); return this; } /** * Clears all {@link Enchantment}s from the {@link ItemStack} * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder clearEnchantments() { item.getEnchantments().clear(); return this; } public ItemBuilder attribute(Attribute attribute, String name, ItemSlot slot, int operation, double amount) { ItemAttributes attributes = new ItemAttributes(); attributes.addModifier(new AttributeModifier(attribute, name, slot, operation, amount, UUID.randomUUID())); this.item = attributes.apply(this.item); return this; } public ItemBuilder glow() { meta.addEnchant(Enchantment.ARROW_DAMAGE, 10, false); return this; } /** * Clears the defined {@link String} of lore from the {@link ItemStack} * * @param lore the String to be removed from the ItemStack. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder clearLore(final String lore) { if(meta.getLore().contains(lore)){ meta.getLore().remove(lore); } item.setItemMeta(meta); return this; } /** * Clears all lore {@link String}s from the {@link ItemStack} * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder clearLores() { meta.getLore().clear(); item.setItemMeta(meta); return this; } /** * Sets the {@link Color} of any LEATHER_ARMOR {@link Material} types of the {@link ItemStack} * * @param color the Color to set the LEATHER_ARMOR ItemStack to. * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder color(final Color color) { if(item.getType() == Material.LEATHER_HELMET || item.getType() == Material.LEATHER_CHESTPLATE || item.getType() == Material.LEATHER_LEGGINGS || item.getType() == Material.LEATHER_BOOTS ){ LeatherArmorMeta meta = (LeatherArmorMeta) this.meta; meta.setColor(color); item.setItemMeta(meta); } return this; } /** * Clears the {@link Color} of any LEATHER_ARMOR {@link Material} types of the {@link ItemStack} * * @return the current instance for chainable application. * @since 1.0 */ public ItemBuilder clearColor() { if(item.getType() == Material.LEATHER_HELMET || item.getType() == Material.LEATHER_CHESTPLATE || item.getType() == Material.LEATHER_LEGGINGS || item.getType() == Material.LEATHER_BOOTS ){ LeatherArmorMeta meta = (LeatherArmorMeta) this.meta; meta.setColor(null); item.setItemMeta(meta); } return this; } /** * Sets the skullOwner {@link SkullMeta} of the current SKULL_ITEM {@link Material} type {@link ItemStack} * * @param uuid the {@link String} value to set the SkullOwner meta to for the SKULL_ITEM Material type ItemStack. * * @return the current instance for chainable application * @since 1.0 */ public ItemBuilder skullOwner(final UUID uuid) { if(item.getType() == Material.SKULL_ITEM && item.getDurability() == (byte) 3){ SkullMeta skullMeta = (SkullMeta) meta; try { GameProfile profile = GameProfileBuilder.fetch(uuid); Field field = skullMeta.getClass().getDeclaredField("profile"); field.setAccessible(true); field.set(skullMeta, profile); item.setItemMeta(meta); } catch (IOException | NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } return this; } public ItemBuilder skullOwner(final String name) { UserInformation.get(name).whenComplete((userInformation, throwable) -> skullOwner(userInformation.getUuid())); return this; } public ItemBuilder skullUrl(String url) { SkullMeta headMeta = (SkullMeta) meta(); GameProfile profile = new GameProfile(UUID.randomUUID(), null); byte[] encodedData = Base64.getEncoder().encode(String.format("{textures:{SKIN:{url:\"%s\"}}}", url).getBytes()); profile.getProperties().put("textures", new Property("textures", new String(encodedData))); Field profileField; try { profileField = headMeta.getClass().getDeclaredField("profile"); profileField.setAccessible(true); profileField.set(headMeta, profile); } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e1) { e1.printStackTrace(); } item.setItemMeta(headMeta); return this; } /** * Returns the {@link ItemMeta} of the {@link ItemStack} * * @return the ItemMeta of the ItemStack. */ private ItemMeta meta() { return meta; } /** * Returns the {@link ItemStack} of the {@link ItemBuilder} instance. * * @return the ItemStack of the ItemBuilder instance. */ public ItemStack build() { item.getItemMeta().addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_DESTROYS, ItemFlag.HIDE_UNBREAKABLE, ItemFlag.HIDE_ENCHANTS); return item; } }