diff --git a/Changelog.txt b/Changelog.txt index 0ad9d4d38..323dd3a7a 100644 --- a/Changelog.txt +++ b/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) diff --git a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java index ede2081e6..1d05c5eb6 100644 --- a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java +++ b/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)) { diff --git a/src/main/java/com/gmail/nossr50/util/ItemUtils.java b/src/main/java/com/gmail/nossr50/util/ItemUtils.java index 62c8d2165..46c68183b 100644 --- a/src/main/java/com/gmail/nossr50/util/ItemUtils.java +++ b/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. * diff --git a/src/main/java/com/gmail/nossr50/util/MaterialMapStore.java b/src/main/java/com/gmail/nossr50/util/MaterialMapStore.java index 8a0c378ed..3c88edd47 100644 --- a/src/main/java/com/gmail/nossr50/util/MaterialMapStore.java +++ b/src/main/java/com/gmail/nossr50/util/MaterialMapStore.java @@ -49,6 +49,7 @@ public class MaterialMapStore { private final @NotNull HashSet pickAxes; private final @NotNull HashSet tridents; private final @NotNull HashSet bows; + private final @NotNull HashSet crossbows; private final @NotNull HashSet tools; private final @NotNull HashSet 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()); }