Browse Source

Fix arrow dupe bug
Fixes #4430

nossr50 4 years ago
parent
commit
735a90fb35

+ 1 - 0
Changelog.txt

@@ -1,5 +1,6 @@
 Version 2.1.175
     Fixed a bug where mcMMO would occasionally give a 65 item stack from a double smelt on a furnace
+    Fixed a bug where arrows could be duped when fired from a crossbow with piercing enchantment
 
 Version 2.1.174
     Some legacy color codes in our locale file were swapped to &-code equivalents (thanks ViaSnake)

+ 5 - 6
src/main/java/com/gmail/nossr50/listeners/EntityListener.java

@@ -19,6 +19,7 @@ import com.gmail.nossr50.skills.taming.Taming;
 import com.gmail.nossr50.skills.taming.TamingManager;
 import com.gmail.nossr50.skills.unarmed.UnarmedManager;
 import com.gmail.nossr50.util.BlockUtils;
+import com.gmail.nossr50.util.ItemUtils;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.compat.layers.persistentdata.AbstractPersistentDataLayer;
@@ -156,8 +157,7 @@ public class EntityListener implements Listener {
             Player player = (Player) event.getEntity().getShooter();
 
             /* WORLD GUARD MAIN FLAG CHECK */
-            if(WorldGuardUtils.isWorldGuardLoaded())
-            {
+            if(WorldGuardUtils.isWorldGuardLoaded()) {
                 if(!WorldGuardManager.getInstance().hasMainFlag(player))
                     return;
             }
@@ -174,10 +174,9 @@ public class EntityListener implements Listener {
                 if(!projectile.hasMetadata(mcMMO.arrowDistanceKey))
                     projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(pluginRef, projectile.getLocation()));
 
-                for (Enchantment enchantment : player.getInventory().getItemInMainHand().getEnchantments().keySet()) {
-                    if (enchantment.getKey().equals(piercingEnchantment)) {
-                        return;
-                    }
+                //Check both hands
+                if(ItemUtils.doesPlayerHaveEnchantmentInHands(player, "piercing")) {
+                    return;
                 }
 
                 if (RandomChanceUtil.isActivationSuccessful(SkillActivationType.RANDOM_LINEAR_100_SCALE_WITH_CAP, SubSkillType.ARCHERY_ARROW_RETRIEVAL, player)) {

+ 87 - 1
src/main/java/com/gmail/nossr50/util/ItemUtils.java

@@ -10,6 +10,7 @@ import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.mcMMO;
 import org.bukkit.ChatColor;
 import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
 import org.bukkit.enchantments.Enchantment;
 import org.bukkit.entity.Player;
 import org.bukkit.inventory.FurnaceRecipe;
@@ -18,6 +19,7 @@ import org.bukkit.inventory.Recipe;
 import org.bukkit.inventory.meta.EnchantmentStorageMeta;
 import org.bukkit.inventory.meta.ItemMeta;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Collections;
 import java.util.List;
@@ -35,14 +37,98 @@ public final class ItemUtils {
      * @param item Item to check
      * @return true if the item is a bow, false otherwise
      */
-    public static boolean isBow(ItemStack item) {
+    public static boolean isBow(@NotNull ItemStack item) {
         return mcMMO.getMaterialMapStore().isBow(item.getType().getKey().getKey());
     }
 
+    public static boolean isCrossbow(@NotNull ItemStack item) {
+        return mcMMO.getMaterialMapStore().isCrossbow(item.getType().getKey().getKey());
+    }
+
     public static boolean hasItemInEitherHand(@NotNull Player player, Material material) {
         return player.getInventory().getItemInMainHand().getType() == material || player.getInventory().getItemInOffHand().getType() == material;
     }
 
+    public static boolean doesPlayerHaveEnchantmentOnArmor(@NotNull Player player, @NotNull String enchantmentByName) {
+        Enchantment enchantment = getEnchantment(enchantmentByName);
+
+        if(enchantment == null)
+            return false;
+
+        return doesPlayerHaveEnchantmentOnArmor(player, enchantment);
+    }
+
+    public static boolean doesPlayerHaveEnchantmentOnArmor(@NotNull Player player, @NotNull Enchantment enchantment) {
+        for(ItemStack itemStack : player.getInventory().getArmorContents()) {
+            if(itemStack != null) {
+                if(hasEnchantment(itemStack, enchantment))
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    public static boolean doesPlayerHaveEnchantmentOnArmorOrHands(@NotNull Player player, @NotNull String enchantmentName) {
+        Enchantment enchantment = getEnchantment(enchantmentName);
+
+        if(enchantment == null)
+            return false;
+
+        return doesPlayerHaveEnchantmentOnArmorOrHands(player, enchantment);
+    }
+
+    public static boolean doesPlayerHaveEnchantmentOnArmorOrHands(@NotNull Player player, @NotNull Enchantment enchantment) {
+        if(doesPlayerHaveEnchantmentOnArmor(player, enchantment))
+            return true;
+
+        if(doesPlayerHaveEnchantmentInHands(player, enchantment))
+            return true;
+
+        return false;
+    }
+
+    public static boolean doesPlayerHaveEnchantmentInHands(@NotNull Player player, @NotNull NamespacedKey enchantmentNameKey) {
+        Enchantment enchantment = Enchantment.getByKey(enchantmentNameKey);
+
+        if(enchantment == null)
+            return false;
+
+        return doesPlayerHaveEnchantmentInHands(player, enchantment);
+    }
+
+    public static boolean doesPlayerHaveEnchantmentInHands(@NotNull Player player, @NotNull String enchantmentName) {
+        Enchantment enchantment = getEnchantment(enchantmentName);
+
+        if(enchantment == null)
+            return false;
+
+        return doesPlayerHaveEnchantmentInHands(player, enchantment);
+    }
+
+    public static boolean doesPlayerHaveEnchantmentInHands(@NotNull Player player, @NotNull Enchantment enchantment) {
+        return hasEnchantment(player.getInventory().getItemInMainHand(), enchantment) ||
+            hasEnchantment(player.getInventory().getItemInOffHand(), enchantment);
+    }
+
+    public static boolean hasEnchantment(@NotNull ItemStack itemStack, @NotNull Enchantment enchantment) {
+        if(itemStack.getItemMeta() != null) {
+            return itemStack.getItemMeta().hasEnchant(enchantment);
+        }
+
+        return false;
+    }
+
+    public static @Nullable Enchantment getEnchantment(@NotNull String enchantmentName) {
+        for(Enchantment enchantment : Enchantment.values()) {
+            if(enchantment.getKey().getKey().equalsIgnoreCase(enchantmentName)) {
+                return enchantment;
+            }
+        }
+
+        return null;
+    }
+
     /**
      * Checks if the item is a sword.
      *

+ 15 - 0
src/main/java/com/gmail/nossr50/util/MaterialMapStore.java

@@ -49,6 +49,7 @@ public class MaterialMapStore {
     private final @NotNull HashSet<String> pickAxes;
     private final @NotNull HashSet<String> tridents;
     private final @NotNull HashSet<String> bows;
+    private final @NotNull HashSet<String> crossbows;
     private final @NotNull HashSet<String> tools;
 
     private final @NotNull HashSet<String> enchantables;
@@ -88,6 +89,7 @@ public class MaterialMapStore {
         diamondTools = new HashSet<>();
         netheriteTools = new HashSet<>();
         bows = new HashSet<>();
+        crossbows = new HashSet<>();
         stringTools = new HashSet<>();
         tools = new HashSet<>();
 
@@ -447,6 +449,7 @@ public class MaterialMapStore {
         fillTridents();
         fillStringTools();
         fillBows();
+        fillCrossbows();
 
         //Tools collection
         tools.addAll(woodTools);
@@ -464,6 +467,10 @@ public class MaterialMapStore {
         bows.add("bow");
     }
 
+    private void fillCrossbows() {
+        crossbows.add("crossbow");
+    }
+
     private void fillStringTools() {
         stringTools.add("bow");
         stringTools.add("fishing_rod");
@@ -771,6 +778,14 @@ public class MaterialMapStore {
         return bows.contains(id);
     }
 
+    public boolean isCrossbow(@NotNull Material material) {
+        return isCrossbow(material.getKey().getKey());
+    }
+
+    public boolean isCrossbow(@NotNull String id) {
+        return crossbows.contains(id);
+    }
+
     public boolean isLeatherArmor(@NotNull Material material) {
         return isLeatherArmor(material.getKey().getKey());
     }