Solved Effifency way to add Enchants

Discussion in 'Spigot Plugin Development' started by ChisleLP, Oct 12, 2021.

  1. Hey, my mind is currently blank, i don't have a good idea how could i improve the code.
    I would say my programming skill is still beginner, as im always trying to create the best, less, effifency code.
    Im up for any, that would help me to improve in future. Thanks im advance!

    I created a small functions that add Enchants depends on Chance.
    My problem is now: When there is a chance to have multiple Enchantments, it will, depends on luck, overwrite the Durability enchantments, Let's say, If you drop a Common Pickaxe, no enchantments will be added, if Uncommon, then 1. Rare 2, Legendary 3. So if i dropped a Rare pickaxe, it SHOULD be listed 2 enchantment, but it will be listed 1 enchantment because it was creating 2 times Durability.

    So any got a idea how i could improve the code? i thought of checking everytime if has enchamtent unbreaking, then change the chance of Loot Bonus to 100 or somethings like that...

    (If you don't want read the full code, the code that improve need it near last line, the "addEnchant()" functions)

    Code (Java):
    private void getLevel(Player player, ItemStack item, int Amount) {
            for (int i = 0; i != Amount; i++) {
                ItemStack is = item;
                ItemMeta im = is.getItemMeta();
                ArrayList<String> lore = new ArrayList<>();
                ItemMeta enchant = null;
                if (getChance(1)) {
                    lore.add("§6§lLEGENDARY");
                    enchant = addEnchant(im, 3);
                } else if (getChance(5)) {
                    lore.add("§bRare");
                    enchant = addEnchant(im, 2);
                } else if (getChance(40)) {
                    lore.add("§2Uncommon");
                    enchant = addEnchant(im, 1);
                } else {
                    lore.add("§7Common");
                }
                is.setItemMeta(enchant);
                im = is.getItemMeta();
                if (im.hasEnchants()) {
                    lore.add("");
                    im.addItemFlags(ItemFlag.HIDE_ENCHANTS);
                    if (im.hasEnchant(Enchantment.DURABILITY)) {
                        int lvl = im.getEnchantLevel(Enchantment.DURABILITY);
                        String color;
                        if (lvl == 1) {
                            color = "§7";
                        } else if (lvl == 2) {
                            color = "§b";
                        } else {
                            color = "§6§l";
                        }
                        lore.add(color+"Haltbarkeit "+lvl);
                    }
                    if (im.hasEnchant(Enchantment.MENDING)) {
                        lore.add("§6§lRepatur");
                    }
                    if (im.hasEnchant(Enchantment.LOOT_BONUS_BLOCKS)) {
                        int lvl = im.getEnchantLevel(Enchantment.LOOT_BONUS_BLOCKS);
                        String color;
                        if (lvl == 1) {
                            color = "§7";
                        } else if (lvl == 2) {
                            color = "§b";
                        } else {
                            color = "§6§l";
                        }
                        lore.add(color+"Glück "+lvl);
                    }
                    if (im.hasEnchant(Enchantment.DIG_SPEED)) {
                        int lvl = im.getEnchantLevel(Enchantment.DIG_SPEED);
                        String color;
                        if (lvl == 1 || lvl == 2) {
                            color = "§7";
                        } else if (lvl == 3) {
                            color = "§2";
                        } else if (lvl == 4) {
                            color = "§b";
                        } else {
                            color = "§6§l";
                        }
                        lore.add(color+"Effizienz "+lvl);
                    }          
                }
                im.setLore(lore);
                is.setItemMeta(im);
                player.getInventory().addItem(is);
            }
        }
     
        private ItemMeta addEnchant(ItemMeta im, int Amount) {
            Random rnd = new Random();
            for (int i = 0; i != Amount; i++) {
                if (getChance(1)) {
                    im.addEnchant(Enchantment.MENDING, 1, false);
                } else if (getChance(5)) {
                    im.addEnchant(Enchantment.DIG_SPEED, rnd.nextInt(4)+1, false);
                } else if (getChance(5)) {
                    im.addEnchant(Enchantment.LOOT_BONUS_BLOCKS, rnd.nextInt(2)+1, false);
                } else {
                    im.addEnchant(Enchantment.DURABILITY, rnd.nextInt(2)+1, false);
                }
            }
            return im;
        }
     
     
        private boolean getChance(int chance) {
            Random random = new Random();
            return random.nextInt(99) +1 <= chance;
        }
    What it looks: What is should be:
    [​IMG] [​IMG]



    #Edit:
    Meanwhile i found a way, but i don't think it very effifency.
    Its looped between 10-100 times for a "Rare Pickaxe"
    For Legendary it took ~50-400 times...
    Code (Java):
    private ItemMeta addEnchant(ItemMeta im, int Amount) {
            Random rnd = new Random();
            int a = 0;
            for (int i = 0; i != Amount; a++) {
                if (getChance(1)) {
                    if (!im.hasEnchant(Enchantment.MENDING)) {
                        im.addEnchant(Enchantment.MENDING, 1, false);
                        i++;
                    }
                } else if (getChance(5)) {
                    if (!im.hasEnchant(Enchantment.DIG_SPEED)) {
                        im.addEnchant(Enchantment.DIG_SPEED, rnd.nextInt(4)+1, false);
                        i++;
                    }
                } else if (getChance(5)) {
                    if (!im.hasEnchant(Enchantment.LOOT_BONUS_BLOCKS)) {
                        im.addEnchant(Enchantment.LOOT_BONUS_BLOCKS, rnd.nextInt(2)+1, false);
                        i++;
                    }
                } else {
                    if (!im.hasEnchant(Enchantment.DURABILITY)) {
                        im.addEnchant(Enchantment.DURABILITY, rnd.nextInt(2)+1, false);
                        i++;
                    }
                   
                }
            }
            Bukkit.broadcastMessage("After "+a+" try finally managed.");
            return im;
        }
     
    #1 ChisleLP, Oct 12, 2021
    Last edited: Oct 12, 2021
  2. Well for one, don't keep making a new Random object, that's so unnecessary. You can make it a class variable instead. As for the addEnchant method, I don't really understand what you're trying to accomplish. It looks like the only thing your "chance" is accomplishing is extending your loops based on a random number, since you said in your own words that based on the rarity it "SHOULD" always get a certain number of enchantments... that makes your entire chance system redundant since you're only adding to the "i" variable when an enchantment has successfully been applied. Why don't you just, based on your rarity, add random enchantments to the item. Maybe make a list of possible enchantment types and before getting a random one, filter out the list with the enchantments that are already on the item so you don't keep having to loop until you find one that the item doesn't already have.

    So something like this:


    Code (Text):

    Random random = new Random(); // Define this as a class variable. You only need one Random object.
    int amount = <your max enchant amount here>;
    ItemMeta itemMeta = <your item meta>;
    List<Enchantment> possibleEnchantments = <copy of your list here>;
    Set<Enchantment> itemEnchantments = itemMeta.getEnchants().keySet();

    possibleEnchantments.removeAll(itemEnchantments);

    for (int i = 0; i < amount; i++)
    {
        int size = possibleEnchantments.size();
        Enchantment enchantment = possibleEnchantments.get(random.nextInt(size));
        int maxLevel = enchantment.getMaxLevel();
        itemMeta.addEnchantment(possibleEnchantments.get(enchantment, random.nextInt(maxLevel) + 1, false);
    }

     
    So that's just something off the top of my head. Instead of looping 400 times for a legendary item, it loops 3 times. Now isn't that quite efficient! :oops: Let me know if this isn't what you wanted, because this is what I gathered from your post so maybe I was mistaken on what you wanted to accomplish.

    Note: Make sure you dont remove the enchantments from your master enchantment list, hence why i said <COPY of your list here>
     
    #2 Keroberos0, Oct 12, 2021
    Last edited: Oct 12, 2021
    • Winner Winner x 1
  3. Note: using paragraphs as color codes is a bad practice. Either use ChatColors, or a method that takes one string with ampersands and returns it's translated version (e.g. this):
    Code (Java):

    private String format(String arg) {
        return ChatColor.translateAlternateColorCodes('&', arg);
    }
    ..
    format("&cHello! &6Hi");
     
    returns Hello! Hi
     
  4. Thanks you so much for details.
    Right about Random, my bad.
    Yes, that looks excatly what i wanted, sooo simple and smooth. Wow, had to just add remove enchantments from possibleEnchantments when adding enchant. Since there might be low chance that they add twice time same enchanting. :D

    I was looking for best effifency ways somethings like that, but, i didn't think about the Lists add and remove. Now i learned somethings new.


    Thanks, i have seen about this, that a lot people use this, instead §, im still unsure why, there were a lot Youtube Tutorials, but i couldn't understand any of them, since im Deaf. i'll try to find a topic here if exists. I might should buy a Minecraft plugin book, so far i mostly watched the YouTube tutorials without understanding what it really does, so im a bit slow learner. Thanks!
     
  5. Also, variables have to camelCase. Use amount instead of Amount.
    Code (Java):
    ....
    private ItemMeta addEnchant(ItemMeta im, int Amount) {
    ....
     
    • Agree Agree x 1
  6. I suggest you use client-side lore for the item rarity lore, bukkit isn't aware of that lore, which plugins might check for.
    I did something similar here.
     
  7. Lists implements the Collections interface, so another way that you could do this is to use Collections.shuffle() on your list of enchantments, then take the first N elements of the shuffled list where N is the number of enchantments you want to add (this is good when your list is small like it is right now, as your list gets bigger it makes less and less sense to shuffle the whole thing and then only take 1 to 3 elements from it).
     
    • Like Like x 1