From aa535375f404c01ee4e3125cd1d50582fbe0ed15 Mon Sep 17 00:00:00 2001 From: Auxilor Date: Mon, 30 Aug 2021 15:54:14 +0100 Subject: [PATCH] Extracted rehandleBreaking and fixed unbreaking --- .../ecoenchants/normal/BlastMining.java | 45 +------------- .../ecoenchants/normal/Lumberjack.java | 49 +-------------- .../enchantments/ecoenchants/normal/Vein.java | 17 +----- .../enchantments/util/EnchantmentUtils.java | 59 +++++++++++++++++++ 4 files changed, 67 insertions(+), 103 deletions(-) diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/BlastMining.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/BlastMining.java index 8f97e46f..fdbc0268 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/BlastMining.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/BlastMining.java @@ -2,23 +2,15 @@ package com.willfp.ecoenchants.enchantments.ecoenchants.normal; import com.willfp.eco.core.integrations.anticheat.AnticheatManager; import com.willfp.eco.core.integrations.antigrief.AntigriefManager; -import com.willfp.eco.util.BlockUtils; import com.willfp.ecoenchants.enchantments.EcoEnchant; import com.willfp.ecoenchants.enchantments.EcoEnchants; import com.willfp.ecoenchants.enchantments.meta.EnchantmentType; import com.willfp.ecoenchants.enchantments.util.EnchantmentUtils; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.Particle; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.player.PlayerItemBreakEvent; -import org.bukkit.event.player.PlayerItemDamageEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.Damageable; -import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import java.util.HashSet; @@ -53,8 +45,6 @@ public class BlastMining extends EcoEnchant { return; } - AnticheatManager.exemptPlayer(player); - Set toBreak = new HashSet<>(); for (int x = -1; x <= 1; x++) { @@ -91,39 +81,8 @@ public class BlastMining extends EcoEnchant { } } - ItemStack itemStack = player.getInventory().getItemInMainHand(); - ItemMeta beforeMeta = itemStack.getItemMeta(); - assert beforeMeta != null; - boolean hadUnbreak = beforeMeta.isUnbreakable() || player.getGameMode() == GameMode.CREATIVE; - beforeMeta.setUnbreakable(true); - itemStack.setItemMeta(beforeMeta); - int blocks = toBreak.size(); - - toBreak.forEach((block1 -> { - block1.setMetadata("block-ignore", this.getPlugin().getMetadataValueFactory().create(true)); - BlockUtils.breakBlock(player, block1); - block1.removeMetadata("block-ignore", this.getPlugin()); - })); - - ItemMeta afterMeta = itemStack.getItemMeta(); - assert afterMeta != null; - afterMeta.setUnbreakable(hadUnbreak); - itemStack.setItemMeta(afterMeta); - PlayerItemDamageEvent mockEvent = new PlayerItemDamageEvent(player, itemStack, blocks); - Bukkit.getPluginManager().callEvent(mockEvent); - - if (!hadUnbreak) { - ItemMeta wayAfterMeta = itemStack.getItemMeta(); - assert wayAfterMeta != null; - ((Damageable) wayAfterMeta).setDamage(((Damageable) wayAfterMeta).getDamage() + mockEvent.getDamage()); - itemStack.setItemMeta(wayAfterMeta); - if (((Damageable) wayAfterMeta).getDamage() >= itemStack.getType().getMaxDurability()) { - PlayerItemBreakEvent breakEvent = new PlayerItemBreakEvent(player, itemStack); - Bukkit.getPluginManager().callEvent(breakEvent); - itemStack.setAmount(0); - } - } - + AnticheatManager.exemptPlayer(player); + EnchantmentUtils.rehandleBreaking(player, toBreak, this.getPlugin()); AnticheatManager.unexemptPlayer(player); } } diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Lumberjack.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Lumberjack.java index e1987a44..12af9f50 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Lumberjack.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Lumberjack.java @@ -6,17 +6,11 @@ import com.willfp.eco.util.BlockUtils; import com.willfp.ecoenchants.enchantments.EcoEnchant; import com.willfp.ecoenchants.enchantments.EcoEnchants; import com.willfp.ecoenchants.enchantments.meta.EnchantmentType; -import org.bukkit.Bukkit; -import org.bukkit.GameMode; +import com.willfp.ecoenchants.enchantments.util.EnchantmentUtils; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.player.PlayerItemBreakEvent; -import org.bukkit.event.player.PlayerItemDamageEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.Damageable; -import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -54,47 +48,10 @@ public class Lumberjack extends EcoEnchant { int limit = level * blocksPerLevel; Set treeBlocks = BlockUtils.getVein(block, materials, limit); + treeBlocks.removeIf(block1 -> !AntigriefManager.canBreakBlock(player, block1)); AnticheatManager.exemptPlayer(player); - - ItemStack itemStack = player.getInventory().getItemInMainHand(); - ItemMeta beforeMeta = itemStack.getItemMeta(); - assert beforeMeta != null; - boolean hadUnbreak = beforeMeta.isUnbreakable() || player.getGameMode() == GameMode.CREATIVE; - beforeMeta.setUnbreakable(true); - itemStack.setItemMeta(beforeMeta); - int blocks = treeBlocks.size(); - - for (Block treeBlock : treeBlocks) { - treeBlock.setMetadata("block-ignore", this.getPlugin().getMetadataValueFactory().create(true)); - if (!AntigriefManager.canBreakBlock(player, treeBlock)) { - continue; - } - - BlockUtils.breakBlock(player, treeBlock); - - this.getPlugin().getScheduler().runLater(() -> treeBlock.removeMetadata("block-ignore", this.getPlugin()), 1); - } - - ItemMeta afterMeta = itemStack.getItemMeta(); - assert afterMeta != null; - afterMeta.setUnbreakable(hadUnbreak); - itemStack.setItemMeta(afterMeta); - PlayerItemDamageEvent mockEvent = new PlayerItemDamageEvent(player, itemStack, blocks); - Bukkit.getPluginManager().callEvent(mockEvent); - - if (!hadUnbreak) { - ItemMeta wayAfterMeta = itemStack.getItemMeta(); - assert wayAfterMeta != null; - ((Damageable) wayAfterMeta).setDamage(((Damageable) wayAfterMeta).getDamage() + mockEvent.getDamage()); - itemStack.setItemMeta(wayAfterMeta); - if (((Damageable) wayAfterMeta).getDamage() >= itemStack.getType().getMaxDurability()) { - PlayerItemBreakEvent breakEvent = new PlayerItemBreakEvent(player, itemStack); - Bukkit.getPluginManager().callEvent(breakEvent); - itemStack.setAmount(0); - } - } - + EnchantmentUtils.rehandleBreaking(player, treeBlocks, this.getPlugin()); AnticheatManager.unexemptPlayer(player); } } diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Vein.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Vein.java index 7e18b756..7fe5920d 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Vein.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Vein.java @@ -6,14 +6,13 @@ import com.willfp.eco.util.BlockUtils; import com.willfp.ecoenchants.enchantments.EcoEnchant; import com.willfp.ecoenchants.enchantments.EcoEnchants; import com.willfp.ecoenchants.enchantments.meta.EnchantmentType; +import com.willfp.ecoenchants.enchantments.util.EnchantmentUtils; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; @@ -48,20 +47,10 @@ public class Vein extends EcoEnchant { int limit = level * blocksPerLevel; Set blockSet = BlockUtils.getVein(block, materials, limit); + blockSet.removeIf(block1 -> !AntigriefManager.canBreakBlock(player, block1)); AnticheatManager.exemptPlayer(player); - - for (Block veinBlock : blockSet) { - veinBlock.setMetadata("block-ignore", this.getPlugin().getMetadataValueFactory().create(true)); - if (!AntigriefManager.canBreakBlock(player, veinBlock)) { - continue; - } - - BlockUtils.breakBlock(player, veinBlock); - - this.getPlugin().getScheduler().runLater(() -> veinBlock.removeMetadata("block-ignore", this.getPlugin()), 1); - } - + EnchantmentUtils.rehandleBreaking(player, blockSet, this.getPlugin()); AnticheatManager.unexemptPlayer(player); } } diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/util/EnchantmentUtils.java b/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/util/EnchantmentUtils.java index c3681272..78b38968 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/util/EnchantmentUtils.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecoenchants/enchantments/util/EnchantmentUtils.java @@ -1,22 +1,33 @@ package com.willfp.ecoenchants.enchantments.util; +import com.willfp.eco.core.EcoPlugin; import com.willfp.eco.core.integrations.placeholder.PlaceholderEntry; import com.willfp.eco.core.integrations.placeholder.PlaceholderManager; +import com.willfp.eco.util.BlockUtils; import com.willfp.eco.util.NumberUtils; import com.willfp.eco.util.StringUtils; import com.willfp.ecoenchants.EcoEnchantsPlugin; import com.willfp.ecoenchants.enchantments.EcoEnchant; import com.willfp.ecoenchants.enchantments.EcoEnchants; import lombok.experimental.UtilityClass; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; import org.bukkit.NamespacedKey; +import org.bukkit.block.Block; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerItemBreakEvent; +import org.bukkit.event.player.PlayerItemDamageEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; +import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; +import java.util.Set; @UtilityClass @SuppressWarnings({"unchecked", "deprecation"}) @@ -131,4 +142,52 @@ public class EnchantmentUtils { } catch (NoSuchFieldException | IllegalAccessException ignored) { } } + + /** + * Rehandle breaking in a fast way that doesn't call Player#updateInventory. + * + * @param player The player. + * @param toBreak The blocks to break. + * @param plugin Instance of EcoEnchants, required for meta. + */ + public static void rehandleBreaking(@NotNull final Player player, + @NotNull final Set toBreak, + @NotNull final EcoPlugin plugin) { + ItemStack itemStack = player.getInventory().getItemInMainHand(); + ItemMeta beforeMeta = itemStack.getItemMeta(); + assert beforeMeta != null; + boolean hadUnbreak = beforeMeta.isUnbreakable() || player.getGameMode() == GameMode.CREATIVE; + beforeMeta.setUnbreakable(true); + itemStack.setItemMeta(beforeMeta); + int blocks = toBreak.size(); + + for (Block block : toBreak) { + block.setMetadata("block-ignore", plugin.getMetadataValueFactory().create(true)); + BlockUtils.breakBlock(player, block); + block.removeMetadata("block-ignore", plugin); + } + + ItemMeta afterMeta = itemStack.getItemMeta(); + assert afterMeta != null; + afterMeta.setUnbreakable(hadUnbreak); + itemStack.setItemMeta(afterMeta); + PlayerItemDamageEvent mockEvent = new PlayerItemDamageEvent(player, itemStack, blocks); + Bukkit.getPluginManager().callEvent(mockEvent); + int unbLevel = EnchantChecks.getItemLevel(itemStack, Enchantment.DURABILITY); + double cancelChance = (100 / (double) (unbLevel + 1)); + + if (hadUnbreak || NumberUtils.randFloat(0, 100) > cancelChance) { + return; + } + + ItemMeta wayAfterMeta = itemStack.getItemMeta(); + assert wayAfterMeta != null; + ((Damageable) wayAfterMeta).setDamage(((Damageable) wayAfterMeta).getDamage() + mockEvent.getDamage()); + itemStack.setItemMeta(wayAfterMeta); + if (((Damageable) wayAfterMeta).getDamage() >= itemStack.getType().getMaxDurability()) { + PlayerItemBreakEvent breakEvent = new PlayerItemBreakEvent(player, itemStack); + Bukkit.getPluginManager().callEvent(breakEvent); + itemStack.setAmount(0); + } + } }