Util How to: Custom Enchantment

Discussion in 'Resources' started by PhantomUnicorns, Jul 13, 2017.

Thread Status:
Not open for further replies.
  1. Offline

    PhantomUnicorns

    This tutorial is pretty simple, a class that makes it easier to make custom enchantment plugins! Right now it doesn't do much, but does reduce the amount of code used when making custom enchantments.

    Here is how to use it:
    Code:
    // In onEnable, creating enchantment:
    Enchant superSharp = new Enchant("Super Sharp", 6, 10);
    superSharp.setMaterials(Enchant.getSwords(false));
    superSharp.setConflictingEnchantments(Enchantment.DAMAGE_ALL);
    
    // How to use enchantment
    ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
    superSharp.enchant(item, 6);
    
    // In onDisable: To not cause errors:
    Enchant.onDisable();
    
    Without further ado here is the code:
    Code:
    import java.lang.reflect.Field;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Map;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.enchantments.Enchantment;
    import org.bukkit.enchantments.EnchantmentTarget;
    import org.bukkit.inventory.ItemStack;
    import org.bukkit.inventory.meta.ItemMeta;
    
    import net.md_5.bungee.api.ChatColor;
    
    public class Enchant extends Enchantment {
    
        private static Field BYID_FIELD, BYNAME_FIELD, ACCEPTINGNEW_FIELD;
        private static ArrayList<Enchant> enchants;
        private static ArrayList<Material> helmets, chestplates, leggings, boots;
        private static ArrayList<Material> swords, bows, pickaxes, axes, shovels, hoes;
        private ArrayList<Enchantment> enchantments;
        private ArrayList<Material> mats;
        private int startLevel, maxLevel;
        private boolean treasure, cursed;
        private String name;
    
        static {
            enchants = new ArrayList<Enchant>();
            helmets = new ArrayList<>();
            chestplates = new ArrayList<>();
            leggings = new ArrayList<>();
            boots = new ArrayList<>();
            swords = new ArrayList<>();
            bows = new ArrayList<>();
            pickaxes = new ArrayList<>();
            axes = new ArrayList<>();
            shovels = new ArrayList<>();
            hoes = new ArrayList<>();
            for (Material mat : Material.values()) {
                if (mat.name().contains("HELMET")) {
                    helmets.add(mat);
                } else if (mat.name().contains("CHESTPLATE")) {
                    chestplates.add(mat);
                } else if (mat.name().contains("LEGGINGS")) {
                    leggings.add(mat);
                } else if (mat.name().contains("BOOTS")) {
                    boots.add(mat);
                } else if (mat.name().contains("SWORD")) {
                    swords.add(mat);
                } else if (mat.name().contains("BOW")) {
                    bows.add(mat);
                } else if (mat.name().contains("PICKAXE")) {
                    pickaxes.add(mat);
                } else if (mat.name().contains("AXE")) {
                    axes.add(mat);
                } else if (mat.name().contains("SHOVEL")) {
                    shovels.add(mat);
                } else if (mat.name().contains("HOE")) {
                    hoes.add(mat);
                }
            }
            try {
                BYID_FIELD = Enchantment.class.getDeclaredField("byId");
                BYID_FIELD.setAccessible(true);
                BYNAME_FIELD = Enchantment.class.getDeclaredField("byName");
                BYNAME_FIELD.setAccessible(true);
                ACCEPTINGNEW_FIELD = Enchantment.class.getDeclaredField("acceptingNew");
                ACCEPTINGNEW_FIELD.setAccessible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @SuppressWarnings(value = { "deprecation", "unchecked" })
        public Enchant(String name, int startLevel, int maxLevel) {
            super(getNewEnchantID());
            this.name = name;
            this.startLevel = startLevel;
            this.maxLevel = maxLevel;
            try {
                if (!((boolean) ACCEPTINGNEW_FIELD.get(null))) {
                    ACCEPTINGNEW_FIELD.set(null, true);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                Map<Integer, Enchantment> byId = (HashMap<Integer, Enchantment>) BYID_FIELD.get(null);
                Map<String, Enchantment> byName = (HashMap<String, Enchantment>) BYNAME_FIELD.get(null);
    
                if (byId.containsKey(getId())) {
                    byId.remove(getId());
                }
                if (byName.containsKey(getName())) {
                    byName.remove(getName());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            Enchantment.registerEnchantment(this);
            enchants.add(this);
        }
    
        public void setMaterials(Material... mats) {
            ArrayList<Material> tempMats = new ArrayList<>();
            for (Material mat : mats) {
                tempMats.add(mat);
            }
            this.mats = tempMats;
        }
    
        public void setMaterials(ArrayList<Material> mats) {
            this.mats = mats;
        }
    
        public void setConflictingEnchantments(ArrayList<Enchantment> enchantments) {
            this.enchantments = enchantments;
        }
    
        public void setConflictingEnchantments(Enchantment... enchantments) {
            ArrayList<Enchantment> tempEnchants = new ArrayList<>();
            for (Enchantment mat : enchantments) {
                tempEnchants.add(mat);
            }
            this.enchantments = tempEnchants;
        }
    
        public void setTreasure(boolean treasure) {
            this.treasure = treasure;
        }
    
        public void setCursed(boolean cursed) {
            this.cursed = cursed;
        }
    
        @Override
        public boolean canEnchantItem(ItemStack item) {
            Material itemMat = item.getType();
            for (Material mat : mats) {
                if (itemMat == mat) {
                    return true;
                }
            }
            return true;
        }
    
        @Override
        public boolean conflictsWith(Enchantment enchant) {
            if (enchantments != null) {
                return enchantments.contains(enchant);
            }
            return false;
        }
    
        @Override
        public EnchantmentTarget getItemTarget() {
            return null;
        }
    
        @Override
        public int getMaxLevel() {
            return maxLevel;
        }
    
        @Override
        public String getName() {
            return name;
        }
    
        @Override
        public int getStartLevel() {
            return startLevel;
        }
    
        @Override
        public boolean isCursed() {
            return cursed;
        }
    
        @Override
        public boolean isTreasure() {
            return treasure;
        }
       
        public ItemStack enchant(ItemStack item, int level) {
            int lvl = level;
            if (startLevel == maxLevel) {
                lvl = 0;
            }
            if (level < startLevel) {
                lvl = startLevel;
            } else if (level > maxLevel) {
                lvl = maxLevel;
            }
            String lvls = " " + lvl;
            if (lvl == 0) {
                lvls = "";
            }
            ArrayList<String> lore = new ArrayList<>();
            lore.add(ChatColor.translateAlternateColorCodes('&', "&7") + name + lvls);
            if (item.hasItemMeta() && item.getItemMeta().hasLore()) {
                lore.addAll(item.getItemMeta().getLore());
            }
            if (item.hasItemMeta()) {
                ItemMeta itemMeta = item.getItemMeta();
                itemMeta.setLore(lore);
                item.setItemMeta(itemMeta);
                itemMeta.addEnchant(this, level, true);
            } else {
                ItemMeta itemMeta = Bukkit.getItemFactory().getItemMeta(item.getType());
                itemMeta.setLore(lore);
                itemMeta.addEnchant(this, level, true);
                item.setItemMeta(itemMeta);
            }
            return item;
        }
    
        public boolean hasEnchant(ItemStack item) {
            for (Enchantment enchantment : item.getEnchantments().keySet()) {
                if (enchantment.getName().equals(name)) {
                    return true;
                }
            }
            return false;
        }
    
        public int getEnchantLevel(ItemStack item) {
            for (Enchantment enchantment : item.getEnchantments().keySet()) {
                if (enchantment.getName().equals(name)) {
                    return item.getEnchantments().get(enchantment);
                }
            }
            return -1;
        }
    
        public static boolean hasEnchantment(ItemStack item, Enchantment enchant) {
            for (Enchantment enchantment : item.getEnchantments().keySet()) {
                if (enchantment.getName().equals(enchant.getName())) {
                    return true;
                }
            }
            return false;
        }
    
        public static int getEnchantmentLevel(ItemStack item, Enchantment enchant) {
            for (Enchantment enchantment : item.getEnchantments().keySet()) {
                if (enchantment.getName().equals(enchant.getName())) {
                    return item.getEnchantments().get(enchantment);
                }
            }
            return -1;
        }
    
        public static Enchant getEnchantByName(String name, boolean caseSensitive) {
            if (caseSensitive) {
                for (Enchant enchant : enchants) {
                    if (enchant.getName().equals(name)) {
                        return enchant;
                    }
                }
            } else {
                for (Enchant enchant : enchants) {
                    if (enchant.getName().equalsIgnoreCase(name)) {
                        return enchant;
                    }
                }
            }
            return null;
        }
    
        @SuppressWarnings(value = { "deprecation" })
        public static Enchant getEnchantById(int id) {
            for (Enchant enchant : enchants) {
                if (enchant.getId() == id) {
                    return enchant;
                }
            }
            return null;
        }
    
        @SuppressWarnings(value = { "unchecked", "deprecation" })
        public static void onDisable() {
            try {
                Map<Integer, Enchantment> byId = (HashMap<Integer, Enchantment>) BYID_FIELD.get(null);
                Map<String, Enchantment> byName = (HashMap<String, Enchantment>) BYNAME_FIELD.get(null);
    
                for (Enchant enchant : enchants) {
                    if (byId.containsKey(enchant.getId())) {
                        byId.remove(enchant.getId());
                    }
                    if (byName.containsKey(enchant.getName())) {
                        byName.remove(enchant.getName());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @SuppressWarnings("deprecation")
        private static int getNewEnchantID() {
            ArrayList<Integer> numbers = new ArrayList<Integer>();
            for (Enchantment enchants : Enchantment.values())
                numbers.add(enchants.getId());
            int returnNumber = 0;
            while (numbers.contains(returnNumber))
                returnNumber++;
            return returnNumber;
        }
    
        public static ArrayList<Material> getHelmets(boolean book) {
            ArrayList<Material> mats = helmets;
            if (book) {
                mats.add(Material.BOOK);
            }
            return mats;
        }
    
        public static ArrayList<Material> getChestplates(boolean book) {
            ArrayList<Material> mats = chestplates;
            if (book) {
                mats.add(Material.BOOK);
            }
            return mats;
        }
    
        public static ArrayList<Material> getLeggings(boolean book) {
            ArrayList<Material> mats = leggings;
            if (book) {
                mats.add(Material.BOOK);
            }
            return mats;
        }
    
        public static ArrayList<Material> getBoots(boolean book) {
            ArrayList<Material> mats = boots;
            if (book) {
                mats.add(Material.BOOK);
            }
            return mats;
        }
    
        public static ArrayList<Material> getSwords(boolean book) {
            ArrayList<Material> mats = swords;
            if (book) {
                mats.add(Material.BOOK);
            }
            return mats;
        }
    
        public static ArrayList<Material> getBows(boolean book) {
            ArrayList<Material> mats = bows;
            if (book) {
                mats.add(Material.BOOK);
            }
            return mats;
        }
    
        public static ArrayList<Material> getPickaxes(boolean book) {
            ArrayList<Material> mats = pickaxes;
            if (book) {
                mats.add(Material.BOOK);
            }
            return mats;
        }
    
        public static ArrayList<Material> getAxes(boolean book) {
            ArrayList<Material> mats = axes;
            if (book) {
                mats.add(Material.BOOK);
            }
            return mats;
        }
    
        public static ArrayList<Material> getShovels(boolean book) {
            ArrayList<Material> mats = shovels;
            if (book) {
                mats.add(Material.BOOK);
            }
            return mats;
        }
    
        public static ArrayList<Material> getHoes(boolean book) {
            ArrayList<Material> mats = hoes;
            if (book) {
                mats.add(Material.BOOK);
            }
            return mats;
        }
    }
    
    Suggestions are welcomed, as right now it's not a lot. It registers it and it's pretty much a class that is a flexible interface. Note it's not an interface. It's a class, but you can customize what each default method returns but one. (Which I don't know what's use is for yet, or how to properly set it)
     
    Last edited: Jul 16, 2017
Thread Status:
Not open for further replies.

Share This Page