[SPIGOT-6630] replacing an enchantment on an item creates a conflict error Created: 07/Jul/21 Updated: 19/Oct/21 Resolved: 19/Oct/21 |
|
Status: | Resolved |
Project: | Spigot |
Component/s: | None |
Affects Version/s: | None |
Fix Version/s: | None |
Type: | Bug | Priority: | Minor |
Reporter: | Shane Martin | Assignee: | Unassigned |
Resolution: | Fixed | Votes: | 1 |
Labels: | None |
Version: | 07.07 22:45:50 [Server] Server thread/INFO This server is running CraftBukkit version 3172-Spigot-610a8c0-99561c2 (MC: 1.17.1) (Implementing API version 1.17.1-R0.1-SNAPSHOT) 07.07 22:45:50 [Server] Server thread/INFO Checking version, please wait... 07. |
Guidelines Read: | Yes |
Description |
If you use the API to remove an enchantment from an item, then re-add that same enchantment with a different level, then call getEnchantments() on that item the following error is thrown: https://hatebin.com/rbhqaqvqqn
If you drop the item and pick it back up the error does not re-appear. Thus it appears that maybe the old enchantment isn't properly being removed by removeEnchantment()
code example:
ItemStack is = plr.getInventory().getItemInMainHand(); is.addEnchantment(Enchantment.DURABILITY, 2); is.removeEnchantment(Enchantment.DURABILITY); is.addEnchantment(Enchantment.DURABILITY, 3); if(is.getEnchantments() != null) system.out.println("found enchantment");
The above sample would simulate adding an enchantment to an itemstack, then removing it, then adding back the same enchantment with a different level. This seems to leave two entries with the same key in the map, when getEnchantments() is called the error is thrown, this error will be thrown every time getEnchantments() is called until the item is dropped then picked back up, (it may also fix itself if the user logs out/in again).
|
Comments |
Comment by Arcane Warrior [ 18/Oct/21 ] |
Can someone double check this is no longer an issue? There was a commit that had this issue linked, but this issue was never closed. |
Comment by Marvin Rieple [ 24/Aug/21 ] |
Made a PR for this: craftbukkit#921 |
Comment by Shane Martin [ 08/Jul/21 ] |
Hmm, it would appear that maybe the removeEnchantment() isn’t properly removing the first? It should be able to remove either via the api. |
Comment by Doc [ 08/Jul/21 ] |
Checked this code in command and event... when execute the command the item result is like. [CHAT] MrDoc94 has the following entity data: {id: "minecraft:diamond_sword", Count: 1b, tag: {Damage: 0, Enchantments: [{lvl: 12, id: "sharpness"}, {lvl: 5s, id: "minecraft:sharpness"}]}} and... looks like the issue starts in remove... the enchant was not removed and if look the two enchants in the previous text looks different (the enchant by command has minecraft: in the enchant name) if you use the command: /give @s diamond_sword{Enchantments:[{id:"minecraft:sharpness",lvl:100}]}
then works fine. |
Comment by Shane Martin [ 08/Jul/21 ] |
Try this bit of code it should produce the error. Just give yourself a sword with sharp 14, which is over the vanilla limit, hold it in main hand and sneak. /give your_name diamond_sword{Enchantments:[ {id:sharpness,lvl:14}]} 1
@EventHandler public void onSneak(PlayerToggleSneakEvent e) { Player p = e.getPlayer(); if(p.getInventory().getItemInMainHand() == null) return; ItemStack is = p.getInventory().getItemInMainHand(); if (is == null || is.getEnchantments().isEmpty()) return; HashSet<Enchantment> replace = new HashSet<>(); for (Enchantment en : is.getEnchantments().keySet()) if (is.getEnchantmentLevel(en) > en.getMaxLevel()) { if (en.canEnchantItem(is)) System.out.println("Fixed " + en.getName() + " with level: " + is.getEnchantmentLevel(en)); else System.out.println("Enchantment " + en.getName() +" is not valid for this item."); replace.add(en); } else { if (!en.canEnchantItem(is)) { replace.add(en); } } for (Enchantment en : replace) { is.removeEnchantment(en); if (en.canEnchantItem(is)) is.addEnchantment(en, en.getMaxLevel()); } } |
Comment by Doc [ 08/Jul/21 ] |
ItemStack::getEnchantments cant return null better check using. is.getEnchantments().isEmpty() but i test this code in same version and not see this error with the example code, only the tipical error if try to apply a enchant in a not valid item (like dirt) |