Tutorial Custom Enchants

Discussion in 'Resources' started by PhantomUnicorns, Aug 18, 2016.

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

    PhantomUnicorns

    Now before I begin I want to say, these are not technically enchants these are going to be lore's that will look like enchants. And before any one says there is a better way to do this, I prefer this way because it's easy and doesn't create any bugs (if done right). So lets get into it.

    First we have to register the events, in this case am going to register all events to the Main class.
    Code:
    Bukkit.getServer().getPluginManager().registerEvents(this, this); 
    Now that we have registered events to the Main class, what ever your main class is named. Now we create a EnchantItemEvent function. With some variables to help us.
    Code:
    @EventHandler
    public void onEnchantEvent (EnchantItemEvent event) {
        Player player = event.getEnchanter();
        ItemStack item = event.getItem();
        Material mat = item.getMaterial();
    }
    
    We then have to test if the enchanted item is the type we want, example if its pickaxe, sword, or bow. For this tutorial we are doing a Bow enchantment.
    Code:
    if (mat.equals(Material.BOW)) {
    
    }
    
    Now that we have tested if they are enchant a bow, lets create a function to handle everytime we want a new enchantment.
    Code:
    public ItemMeta addEnchantment (ItemStack item, String enchantmentName,, int xp, int chance, int maxLevel) {
    
    }
    
    Lets make sure not to get any errors but testing if the item stack is null, and testing if the enchantmentName is null
    Code:
    if (item==null || enchantmentName==null) {
        return null;
    }
    
    Now we can start the actual code for adding the enchantment (lore). Lets add code for the chance of this being successful.
    Code:
    int successRate = Math.round(Math.random()*100)
    
    We now test if that is under or equal to the chance that the function requires.
    Code:
    if (successRate<=chance) {
    
    }
    
    Now we handler what level it is going to be, we use the xp and maxLevel variables required by the function.
    Code:
    int level = Math.round(xp/Math.round(30/maxLevel))
    
    That will return a level corresponding to the xp and maxLevel, at level 30 you will always get the max level.
    Code:
    ArrayList<String> newLores = new ArrayList<String>();
    if (item.hasItemMeta()) {
        if (item.getItemMeta().hasLore()) {
            newLores.addAll(item.getItemMeta().getLore());
        }
    }
    
    This allows it to be compatible with all enchantments that you make or another plugin makes (if they use lores). Now we simply add the enchantment to the arraylist, newLores. While making it color code compatible w/ the level.
    Code:
    newLores.add(ChatColor.translateAlternateColorCodes("&", enchantmentName) + " " + level);
    
    Last but not least, to finish function we must make a itemmeta, set its lore's to the one we just created, and return it.
    Code:
    ItemMeta itemMeta = item.getItemMeta();
    itemMeta.setLore(newLores);
    return itemMeta;
    
    Add a return statement at the end returning
    Code:
    return item.getItemMeta();
    
    and your done. Now we must apply that to EnchantItemEvent function. To apply it we just have go inside where we tested for the material, and do:
    Code:
    item.setItemMeta (addEnchantment (item, "&7MyCoolEnchantment", event.getExpLevelCost(), 50, 5));
    
    That has a 50% chance to add an enchantment called MyCoolEnchantment with a max level of 5
    Now to use it we have to test if they have that enchantment/lore.
    Code:
    if (item.hasItemMeta()) {
        if (item.getItemMeta().hasLore()) {
            for (int i = 0;i<item.getItemMeta().getLore().size();i++) {
                String[] fLore = ChatColor.stripColor(item.getItemMeta().getLore().get(i)).split(" ");
                String testLore = fLore[0];
                if (testLore.equals("MyCoolEnchantment")) {
                    //SOME CODE HERE
                }
            }
        }
    }
    
    And there you go, a way to make custom enchantments. You can compress the testing if they have the enchantment to a simple function but am going to leave that out so people can test around with it. If there is any errors just tell me about. This specific code is not tested but I was reading off my custom enchantment plugin while typing this. This is a link to the roman numerals
     
    Last edited: Aug 19, 2016
  2. Offline

    Zombie_Striker

    Why not just create an actual enchantment using this:
    https://bukkit.org/threads/how-to-make-an-item-glow-with-no-enchant.374594/
     
  3. Offline

    PhantomUnicorns

    Like I said I prefer my way because I find it easier and was never able to 'vibe' like I do with my way, then like what you linked. My way compresses custom enchants to one line to add it, for actual enchantments you have to make a whole class (I believe).
     
    Last edited: Aug 18, 2016
  4. Offline

    ChipDev

    I believe this isn't a resource. :/
     
  5. Offline

    I Al Istannen

    @Zombie_Striker
    I can think of a few ways why to prefer the lore:
    1. Not having to worry about enchantment ids.
    2. Not having to worry about registering it twice (I think the custom enchantment stays rgistered if you reload the server. Correct me if not.)
    3. Not having to rely on NMS/Craftbukkit code that can easily change in the future. Using the lore worked from the day items could have one, to the day items can't.

    Only downside I can think of:
    1. No enchantment glow, if you only have lore enchantments.
     
  6. Can still be added easily with 1 custom enchant, you wont need to worry about ids either since you can just make it pick one that is available. I do prefer lore personally but I also use enchants for the glow.
     
  7. @bwfcwalshy
    The thing is though, if you're going to register an enchant anyway, why not use it like it's intended?
     
  8. @AlvinB You mean register all the other custom wants I want? Well, it is just easier in my opinion and means that I don't have to add a bunch of enchants through MC. Like @I Al Istannen stated things can changed, I'd prefer to change 1 class than 20. It isn't hard to make methods to get the enchants and make a handler for them. You'd have to do the same for MC anyway.
     
    I Al Istannen likes this.
  9. Offline

    PhantomUnicorns

    Because then you would only have to use one class for the glow, I personally only apply custom enchants when they enchant an item so there is going to be a glow any ways.
     
  10. @bwfcwalshy
    Maybe that's a better approach. My mindset is always to use the methods provided, instead of writing new ones.
     
  11. Offline

    Zombie_Striker

    Ids are not that big of a deal. If your problem is with ids conflicting, then you can use the method I posted (on that thread) which makes sure no IDs can conflict. If it is with memorizing the ID, then you may have forgotten that you can save the ID somewhere and reference that ID when you need.

    If you are a competant coder, this should not be an issue.

    Not one line of that tutorial had anything to do with NMS. They all were using bukkit's methods.

    Not only is this a a plus to have, but you can also remove the glow if you want.
     
  12. Offline

    PhantomUnicorns

    @Zombie_Striker Bukkit could change is what Al Istannen was trying to say, while this relays on Java and only use's Bukkit methods when needed, there is a lower probability of you needing to edit in future updates. Some people don't have time to code it with a whole class per enchantment, so even if your a 'competant' coder that doesn't mean you have the time. I hate spending a lot of time on one plugin, it gets boring and it takes the fun out of coding for me. So I wouldn't sit there and make 20 class's for each enchantment when I used lore's and it took a short amount of time.
     
  13. Offline

    I Al Istannen

    @Zombie_Striker
    I know that method. I still think it is uneeded to register the same enchantment twice if you reload the server though.


    I am not quite sure what I should answer here.


    Sorry, wrote that reply from my memory of the method. Turns out to not be too accurate, but to save me, I probably confused it with the reflection (granted, on things that will probably never change).

    Noted.

    My main reason would be the id. If it does not get cleared after a server reload, and I use your method, I end up with the same enchantment twice. Which probably could cause some issues. I am sure there are ways around that though.


    I might be stubborn, but I think I would still use the lore for enchantments, but I certainly see where you are coming from. And my answer could have been a lot more well researched, which I apologize for.

    I will probably really reconsider my opinion on this when I get any first-hand experience with it, so I will save you from my unqualified respones about that matter.
     
  14. @I Al Istannen
    The thing is, the Bukkit method prevents you from even adding the same enchantment twice.
    Code:java
    1.  
    2. public static void registerEnchantment(Enchantment enchantment) {
    3. if(!byId.containsKey(Integer.valueOf(enchantment.id)) && !byName.containsKey(enchantment.getName())) {
    4. if(!isAcceptingRegistrations()) {
    5. throw new IllegalStateException("No longer accepting new enchantments (can only be done by the server implementation)");
    6. } else {
    7. byId.put(Integer.valueOf(enchantment.id), enchantment);
    8. byName.put(enchantment.getName(), enchantment);
    9. }
    10. } else {
    11. throw new IllegalArgumentException("Cannot set already-set enchantment");
    12. }
    13. }
     
  15. Offline

    I Al Istannen

    @AlvinB
    I know that. Guess you could check if the set enchantment is yours or not and react accordingly. What I wrote in my post:
    That is not the way @Zombie_Striker proposed though. His way is a bit more "stupid" and doesn't account for that. You can change it to do probably.

    However I don't know, so discussing this right now with me will probably lead to no new information for you, you know?

    I will maybe get some first hand experience at that matter, and then I will probably be informed enough to make a reasonable decision. I have both ways in mind, I don't know what fits better.
     
  16. Offline

    Zombie_Striker

    Since static objects stay between reloads, you could add the following bit of code to fix this issue:
    Code:
    private static int iD = id;
    private static boolean isLoaded = false;
    
    public void onEnable(){
    if(!isLoaded){
       isLoaded = true;
      //Add enchantment
      id = ....
     }
    }
    
    I understand that there is not only one way to add enchantments. In my opinion however, I feel that built-in features should be used instead of custom ones. Using the lore just feels like a "hack" to achieve the same effect (It's not an actual object that is stored like other enchantments. It has to be checked for and treated differently than other enchantments. It is an entirely separate thing that achieve the same effect).
     
    I Al Istannen likes this.
  17. Offline

    I Al Istannen

    @Zombie_Striker
    I would recommend adding something like this, or the idea of this at least, to your post in the thread linked by you.

    I understand your viewpoint, I probably even agree. I have never really thought of using the Bukkit enchantment system for this, but I never had the need to create a new enchantment. If I need it, I will give your way a shot and use it if I find it working well enough. So thank you for that :)
     
  18. Offline

    PhantomUnicorns

    Using multiple classes for 5 enchantments (5 classes) would waste more space then doing this, overall you are achieving the same thing but wasting less space. However I have found some 'bugs' with my system:
    1) If a plugin can add lores they could add the enchantment.
    2) If a plugin can remove lores they could remove the enchantment.
    3) It requires a separate command to add lores (I don't know with actual enchantments if it's compatible with the /enchant command)
     
Thread Status:
Not open for further replies.

Share This Page