From e5433fcdf1257a32e95be32ec06d4985aaf11adc Mon Sep 17 00:00:00 2001 From: xGinko Date: Thu, 8 Aug 2024 16:24:10 +0200 Subject: [PATCH] better patch for silent switch --- .../combat/CrystalAuraHotbarSwitchDelay.java | 94 --------------- .../aef/modules/combat/SilentSwapDelay.java | 114 ++++++++++++++++++ .../combat/CrystalAuraHotbarSwitchDelay.java | 103 ---------------- .../aef/modules/combat/SilentSwapDelay.java | 114 ++++++++++++++++++ 4 files changed, 228 insertions(+), 197 deletions(-) delete mode 100755 AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/combat/CrystalAuraHotbarSwitchDelay.java create mode 100755 AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/combat/SilentSwapDelay.java delete mode 100755 AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/combat/CrystalAuraHotbarSwitchDelay.java create mode 100755 AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/combat/SilentSwapDelay.java diff --git a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/combat/CrystalAuraHotbarSwitchDelay.java b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/combat/CrystalAuraHotbarSwitchDelay.java deleted file mode 100755 index aee10334b..000000000 --- a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/combat/CrystalAuraHotbarSwitchDelay.java +++ /dev/null @@ -1,94 +0,0 @@ -package me.xginko.aef.modules.combat; - -import com.cryptomorin.xseries.XMaterial; -import me.xginko.aef.modules.AEFModule; -import me.xginko.aef.utils.models.ExpiringSet; -import org.bukkit.Material; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerItemHeldEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; - -import java.time.Duration; -import java.util.EnumSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; - -public class CrystalAuraHotbarSwitchDelay extends AEFModule implements Listener { - - private final ExpiringSet hotbarItemSwitchCooldowns; - private final Set blacklistedSwitchMaterials; - private final boolean onlyForSpecificMaterials; - - public CrystalAuraHotbarSwitchDelay() { - super("combat.crystal-aura.hotbar-switch-delay"); - final long switchAwayFromCrystalsDelayInMillis = Math.max(config.getInt(configPath + ".delay-in-ticks", 2, - "Delay between switching from an end crystal to other items in hotbar"), 1) * 50L; - this.hotbarItemSwitchCooldowns = new ExpiringSet<>(Duration.ofMillis(switchAwayFromCrystalsDelayInMillis)); - this.onlyForSpecificMaterials = config.getBoolean(configPath + ".only-delay-specific-materials", true, - "Only delay when switched to specific materials"); - List defaults = List.of( - "BOW", "DIAMOND_SWORD", "DIAMOND_AXE", "TRIDENT", - "GOLDEN_SWORD", "GOLDEN_AXE", "IRON_SWORD", "IRON_AXE", - "STONE_SWORD", "STONE_AXE", "WOODEN_SWORD", "WOODEN_AXE", - "BLACK_BED", "BLUE_BED", "BROWN_BED", "CYAN_BED", - "GRAY_BED", "GREEN_BED", "LIGHT_BLUE_BED", "LIGHT_GRAY_BED", - "LIME_BED", "MAGENTA_BED", "ORANGE_BED", "PINK_BED", - "PURPLE_BED", "RED_BED", "WHITE_BED", "YELLOW_BED", "CROSSBOW", - "NETHERITE_SWORD", "NETHERITE_AXE" - ); - this.blacklistedSwitchMaterials = config.getList(configPath + ".delayed-specific-materials", defaults) - .stream() - .map(configuredMaterial -> { - try { - return Material.valueOf(configuredMaterial); - } catch (IllegalArgumentException e) { - notRecognized(Material.class, configuredMaterial); - return null; - } - }) - .filter(Objects::nonNull) - .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); - } - - @Override - public void enable() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - } - - @Override - public boolean shouldEnable() { - return config.getBoolean(configPath + ".enable", false); - } - - @Override - public void disable() { - HandlerList.unregisterAll(this); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - private void onHotbarSwitch(PlayerItemHeldEvent event) { - if (!hotbarItemSwitchCooldowns.contains(event.getPlayer().getUniqueId())) { - hotbarItemSwitchCooldowns.add(event.getPlayer().getUniqueId()); - return; - } - - final PlayerInventory playerInventory = event.getPlayer().getInventory(); - - final ItemStack previouslyHeldItem = playerInventory.getItem(event.getPreviousSlot()); - if (previouslyHeldItem == null || previouslyHeldItem.getType() != XMaterial.END_CRYSTAL.parseMaterial()) return; - - final ItemStack newHeldItem = playerInventory.getItem(event.getNewSlot()); - if (newHeldItem == null || newHeldItem.getType() == XMaterial.END_CRYSTAL.parseMaterial()) return; - - if (onlyForSpecificMaterials && !blacklistedSwitchMaterials.contains(newHeldItem.getType())) return; - - event.setCancelled(true); - } -} \ No newline at end of file diff --git a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/combat/SilentSwapDelay.java b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/combat/SilentSwapDelay.java new file mode 100755 index 000000000..419fb121e --- /dev/null +++ b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/combat/SilentSwapDelay.java @@ -0,0 +1,114 @@ +package me.xginko.aef.modules.combat; + +import com.cryptomorin.xseries.XEntityType; +import me.xginko.aef.modules.AEFModule; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +public class SilentSwapDelay extends AEFModule implements Listener { + + private final Map playerDataMap; + private final long swapDelayMillis; + + public SilentSwapDelay() { + super("combat.crystal-aura.silent-swap-delay"); + this.playerDataMap = new ConcurrentHashMap<>(); + this.swapDelayMillis = config.getLong(configPath + ".min-swap-delay-millis", 50L, + "The delay in millis a player cant swap hotbar items after placing\n" + + "a block, clicking a block (for example to place a crystal) or\n" + + "damaging an entity. (50 ms = 1 tick)"); + } + + @Override + public void enable() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @Override + public boolean shouldEnable() { + return config.getBoolean(configPath + ".enable", false); + } + + @Override + public void disable() { + HandlerList.unregisterAll(this); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + private void onPlayerItemHeld(PlayerItemHeldEvent event) { // Fired when a hot bar item selection changes + PlayerData playerData = playerDataMap.computeIfAbsent(event.getPlayer().getUniqueId(), PlayerData::new); + + if (playerData.lastAttackEntityTimeMillis.get() + swapDelayMillis > System.currentTimeMillis()) { + event.setCancelled(true); + return; + } + + if (playerData.lastInteractBlockTimeMillis.get() + swapDelayMillis > System.currentTimeMillis()) { + event.setCancelled(true); + return; + } + + if (playerData.lastPlaceBlockTimeMillis.get() + swapDelayMillis > System.currentTimeMillis()) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (event.getDamager().getType() != XEntityType.PLAYER.get()) return; + + playerDataMap.computeIfAbsent(event.getDamager().getUniqueId(), PlayerData::new) + .lastAttackEntityTimeMillis.set(System.currentTimeMillis()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + + playerDataMap.computeIfAbsent(event.getPlayer().getUniqueId(), PlayerData::new) + .lastInteractBlockTimeMillis.set(System.currentTimeMillis()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onBlockPlace(BlockPlaceEvent event) { + playerDataMap.computeIfAbsent(event.getPlayer().getUniqueId(), PlayerData::new) + .lastPlaceBlockTimeMillis.set(System.currentTimeMillis()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onPlayerQuit(PlayerQuitEvent event) { + playerDataMap.remove(event.getPlayer().getUniqueId()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onPlayerKicked(PlayerKickEvent event) { + playerDataMap.remove(event.getPlayer().getUniqueId()); + } + + private static class PlayerData { + + public final UUID uuid; + public final AtomicLong lastInteractBlockTimeMillis, lastAttackEntityTimeMillis, lastPlaceBlockTimeMillis; + + public PlayerData(UUID uuid) { + this.uuid = uuid; + this.lastInteractBlockTimeMillis = new AtomicLong(); + this.lastAttackEntityTimeMillis = new AtomicLong(); + this.lastPlaceBlockTimeMillis = new AtomicLong(); + } + } +} \ No newline at end of file diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/combat/CrystalAuraHotbarSwitchDelay.java b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/combat/CrystalAuraHotbarSwitchDelay.java deleted file mode 100755 index db4493cfb..000000000 --- a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/combat/CrystalAuraHotbarSwitchDelay.java +++ /dev/null @@ -1,103 +0,0 @@ -package me.xginko.aef.modules.combat; - -import com.cryptomorin.xseries.XMaterial; -import com.cryptomorin.xseries.XTag; -import me.xginko.aef.modules.AEFModule; -import me.xginko.aef.utils.models.ExpiringSet; -import org.bukkit.Material; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerItemHeldEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; - -import java.time.Duration; -import java.util.Arrays; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; -import java.util.stream.Collectors; - -public class CrystalAuraHotbarSwitchDelay extends AEFModule implements Listener { - - private final ExpiringSet hotbarItemSwitchCooldowns; - private final Set blacklistedSwitchMaterials; - private final boolean onlyForSpecificMaterials; - - public CrystalAuraHotbarSwitchDelay() { - super("combat.crystal-aura.hotbar-switch-delay"); - final long switchAwayFromCrystalsDelayInMillis = Math.max(config.getInt(configPath + ".delay-in-ticks", 2, - "Delay between switching from an end crystal to other items in hotbar"), 1) * 50L; - this.hotbarItemSwitchCooldowns = new ExpiringSet<>(Duration.ofMillis(switchAwayFromCrystalsDelayInMillis)); - this.onlyForSpecificMaterials = config.getBoolean(configPath + ".only-delay-specific-materials", true, - "Only delay when switched to specific materials"); - - Set defaults = new HashSet<>(); - defaults.addAll(Arrays.stream(XMaterial.values()) - .filter(xMaterial -> xMaterial.name().endsWith("_AXE") || xMaterial.name().endsWith("_SWORD")) - .collect(Collectors.toSet())); - defaults.addAll(XTag.BEDS.getValues()); - defaults.add(XMaterial.BOW); - defaults.add(XMaterial.CROSSBOW); - - List versionDefaults = defaults.stream() - .filter(XMaterial::isSupported) - .map(xMaterial -> xMaterial.parseMaterial().name()) - .distinct() - .sorted() - .collect(Collectors.toList()); - - this.blacklistedSwitchMaterials = config.getList(configPath + ".delayed-specific-materials", versionDefaults) - .stream() - .map(configuredMaterial -> { - try { - return Material.valueOf(configuredMaterial); - } catch (IllegalArgumentException e) { - notRecognized(Material.class, configuredMaterial); - return null; - } - }) - .filter(Objects::nonNull) - .collect(Collectors.toCollection(() -> EnumSet.noneOf(Material.class))); - } - - @Override - public void enable() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - } - - @Override - public boolean shouldEnable() { - return config.getBoolean(configPath + ".enable", false); - } - - @Override - public void disable() { - HandlerList.unregisterAll(this); - } - - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - private void onHotbarSwitch(PlayerItemHeldEvent event) { - if (!hotbarItemSwitchCooldowns.contains(event.getPlayer().getUniqueId())) { - hotbarItemSwitchCooldowns.add(event.getPlayer().getUniqueId()); - return; - } - - final PlayerInventory playerInventory = event.getPlayer().getInventory(); - - final ItemStack previouslyHeldItem = playerInventory.getItem(event.getPreviousSlot()); - if (previouslyHeldItem == null || previouslyHeldItem.getType() != XMaterial.END_CRYSTAL.parseMaterial()) return; - - final ItemStack newHeldItem = playerInventory.getItem(event.getNewSlot()); - if (newHeldItem == null || newHeldItem.getType() == XMaterial.END_CRYSTAL.parseMaterial()) return; - - if (onlyForSpecificMaterials && !blacklistedSwitchMaterials.contains(newHeldItem.getType())) return; - - event.setCancelled(true); - } -} \ No newline at end of file diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/combat/SilentSwapDelay.java b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/combat/SilentSwapDelay.java new file mode 100755 index 000000000..419fb121e --- /dev/null +++ b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/combat/SilentSwapDelay.java @@ -0,0 +1,114 @@ +package me.xginko.aef.modules.combat; + +import com.cryptomorin.xseries.XEntityType; +import me.xginko.aef.modules.AEFModule; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; + +public class SilentSwapDelay extends AEFModule implements Listener { + + private final Map playerDataMap; + private final long swapDelayMillis; + + public SilentSwapDelay() { + super("combat.crystal-aura.silent-swap-delay"); + this.playerDataMap = new ConcurrentHashMap<>(); + this.swapDelayMillis = config.getLong(configPath + ".min-swap-delay-millis", 50L, + "The delay in millis a player cant swap hotbar items after placing\n" + + "a block, clicking a block (for example to place a crystal) or\n" + + "damaging an entity. (50 ms = 1 tick)"); + } + + @Override + public void enable() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @Override + public boolean shouldEnable() { + return config.getBoolean(configPath + ".enable", false); + } + + @Override + public void disable() { + HandlerList.unregisterAll(this); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + private void onPlayerItemHeld(PlayerItemHeldEvent event) { // Fired when a hot bar item selection changes + PlayerData playerData = playerDataMap.computeIfAbsent(event.getPlayer().getUniqueId(), PlayerData::new); + + if (playerData.lastAttackEntityTimeMillis.get() + swapDelayMillis > System.currentTimeMillis()) { + event.setCancelled(true); + return; + } + + if (playerData.lastInteractBlockTimeMillis.get() + swapDelayMillis > System.currentTimeMillis()) { + event.setCancelled(true); + return; + } + + if (playerData.lastPlaceBlockTimeMillis.get() + swapDelayMillis > System.currentTimeMillis()) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (event.getDamager().getType() != XEntityType.PLAYER.get()) return; + + playerDataMap.computeIfAbsent(event.getDamager().getUniqueId(), PlayerData::new) + .lastAttackEntityTimeMillis.set(System.currentTimeMillis()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + + playerDataMap.computeIfAbsent(event.getPlayer().getUniqueId(), PlayerData::new) + .lastInteractBlockTimeMillis.set(System.currentTimeMillis()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onBlockPlace(BlockPlaceEvent event) { + playerDataMap.computeIfAbsent(event.getPlayer().getUniqueId(), PlayerData::new) + .lastPlaceBlockTimeMillis.set(System.currentTimeMillis()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onPlayerQuit(PlayerQuitEvent event) { + playerDataMap.remove(event.getPlayer().getUniqueId()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onPlayerKicked(PlayerKickEvent event) { + playerDataMap.remove(event.getPlayer().getUniqueId()); + } + + private static class PlayerData { + + public final UUID uuid; + public final AtomicLong lastInteractBlockTimeMillis, lastAttackEntityTimeMillis, lastPlaceBlockTimeMillis; + + public PlayerData(UUID uuid) { + this.uuid = uuid; + this.lastInteractBlockTimeMillis = new AtomicLong(); + this.lastAttackEntityTimeMillis = new AtomicLong(); + this.lastPlaceBlockTimeMillis = new AtomicLong(); + } + } +} \ No newline at end of file