diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/FallingBlockStasis.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/FallingBlockStasis.java index fb170e462..338e5d193 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/FallingBlockStasis.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/FallingBlockStasis.java @@ -18,9 +18,12 @@ public FallingBlockStasis() { shouldEnable(); this.plugin = AnarchyExploitFixes.getInstance(); Config config = AnarchyExploitFixes.getConfiguration(); - config.addComment("lag-preventions.prevent-falling-block-stasis-exploit.enable", "Patches a lag exploit using falling blocks and glitched piston heads: https://www.youtube.com/watch?v=y2CjPlvtj58"); - this.max_alive_time = config.getInt("lag-preventions.prevent-falling-block-stasis-exploit.falling-blocks-max-alive-time-in-ticks", 300, "(20 ticks = 1 second)"); - this.check_period_in_ticks = config.getInt("lag-preventions.prevent-falling-block-stasis-exploit.check-period-in-seconds", 120, "How frequently we should check for all projectile's alive time") * 20L; + config.addComment("lag-preventions.prevent-falling-block-stasis-exploit.enable", + "Patches a lag exploit using falling blocks and glitched piston heads: https://www.youtube.com/watch?v=y2CjPlvtj58"); + this.max_alive_time = config.getInt("lag-preventions.prevent-falling-block-stasis-exploit.falling-blocks-max-alive-time-in-ticks", 300, + "(20 ticks = 1 second)"); + this.check_period_in_ticks = config.getInt("lag-preventions.prevent-falling-block-stasis-exploit.check-period-in-seconds", 120, + "How frequently we should check for all projectile's alive time") * 20L; } @Override @@ -51,11 +54,9 @@ public void disable() { private void run() { for (World world : plugin.getServer().getWorlds()) { for (FallingBlock fallingBlock : world.getEntitiesByClass(FallingBlock.class)) { - plugin.getServer().getRegionScheduler().run(plugin, fallingBlock.getLocation(), task -> { - if (fallingBlock.getTicksLived() > max_alive_time) { - fallingBlock.remove(); - } - }); + if (fallingBlock.getTicksLived() > max_alive_time) { + fallingBlock.getScheduler().run(plugin, delete -> fallingBlock.remove(), null); + } } } } diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LeverSpam.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LeverSpam.java index b3fee76c4..9bfe53946 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LeverSpam.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LeverSpam.java @@ -1,9 +1,13 @@ package me.moomoo.anarchyexploitfixes.modules.lagpreventions; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; import me.moomoo.anarchyexploitfixes.config.Config; import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; +import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -11,18 +15,16 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import java.util.HashMap; +import java.time.Duration; import java.util.UUID; public class LeverSpam implements AnarchyExploitFixesModule, Listener { - private final HashMap cooldowns = new HashMap<>(); - private final HashMap leverCounts = new HashMap<>(); - private final boolean shouldKickPlayer, sendActionBar; + private final Cache leverLocationCooldowns; + private final Cache playersUsingLeversCooldowns; private final int leverUsageLimit; - private final long leverCooldownInMillis; + private final boolean shouldKickPlayer, sendActionBar; public LeverSpam() { shouldEnable(); @@ -30,8 +32,10 @@ public LeverSpam() { config.addComment("lag-preventions.prevent-lever-spam.enable", "Rate Limit levers to prevent a lag exploit."); this.sendActionBar = config.getBoolean("lag-preventions.prevent-lever-spam.show-actionbar", true); this.shouldKickPlayer = config.getBoolean("lag-preventions.prevent-lever-spam.kick-player", false); - this.leverUsageLimit = config.getInt("lag-preventions.prevent-lever-spam.max-lever-usages-per-time", 10); - this.leverCooldownInMillis = config.getInt("lag-preventions.prevent-lever-spam.lever-time-in-ticks", 180) * 50L; + this.leverUsageLimit = config.getInt("lag-preventions.prevent-lever-spam.max-lever-usages-per-time", 15); + final long cacheTimeMillis = config.getInt("lag-preventions.prevent-lever-spam.lever-time-in-ticks", 40) * 50L; + this.leverLocationCooldowns = Caffeine.newBuilder().expireAfterWrite(Duration.ofMillis(cacheTimeMillis)).build(); + this.playersUsingLeversCooldowns = Caffeine.newBuilder().expireAfterWrite(Duration.ofMillis(cacheTimeMillis)).build(); } @Override @@ -60,46 +64,53 @@ public void disable() { HandlerList.unregisterAll(this); } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onInteract(PlayerInteractEvent event) { if (!event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) return; - if (!event.getClickedBlock().getType().equals(Material.LEVER)) return; + Block clicked = event.getClickedBlock(); + if (!clicked.getType().equals(Material.LEVER)) return; - Player player = event.getPlayer(); - final UUID playerUniqueId = player.getUniqueId(); - final long currentTime = System.currentTimeMillis(); - - if (!leverCounts.containsKey(playerUniqueId) || !cooldowns.containsKey(playerUniqueId)) { - leverCounts.put(playerUniqueId, 1); - cooldowns.put(playerUniqueId, currentTime); - return; - } + final Player player = event.getPlayer(); - int leverUseCount = leverCounts.get(playerUniqueId); + final Location leverLoc = clicked.getLocation(); + Integer activationCount = leverLocationCooldowns.getIfPresent(leverLoc); - if (leverUseCount >= leverUsageLimit) { - if (currentTime - cooldowns.get(playerUniqueId) < leverCooldownInMillis) { + if (activationCount == null) { + leverLocationCooldowns.put(leverLoc, 1); + } else { + activationCount++; + leverLocationCooldowns.put(leverLoc, activationCount); + if (activationCount > leverUsageLimit) { event.setCancelled(true); - if (sendActionBar) - player.sendActionBar(AnarchyExploitFixes.getLang(player.locale()).lagpreventions_stopSpammingLevers); - if (shouldKickPlayer) + if (shouldKickPlayer) { player.kick(AnarchyExploitFixes.getLang(player.locale()).lagpreventions_stopSpammingLevers); + return; + } + if (sendActionBar) { + player.sendActionBar(AnarchyExploitFixes.getLang(player.locale()).lagpreventions_stopSpammingLevers); + } return; } - - leverUseCount = 1; } - leverUseCount++; - - leverCounts.put(playerUniqueId, leverUseCount); - cooldowns.put(playerUniqueId, currentTime); - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - private void onPlayerQuit(PlayerQuitEvent event) { - final UUID playerUniqueId = event.getPlayer().getUniqueId(); - cooldowns.remove(playerUniqueId); - leverCounts.remove(playerUniqueId); + final UUID playerUniqueId = player.getUniqueId(); + Integer leverFlickCount = playersUsingLeversCooldowns.getIfPresent(playerUniqueId); + + if (leverFlickCount == null) { + playersUsingLeversCooldowns.put(playerUniqueId, 1); + } else { + leverFlickCount++; + playersUsingLeversCooldowns.put(playerUniqueId, leverFlickCount); + if (leverFlickCount > leverUsageLimit) { + event.setCancelled(true); + if (shouldKickPlayer) { + player.kick(AnarchyExploitFixes.getLang(player.locale()).lagpreventions_stopSpammingLevers); + return; + } + if (sendActionBar) { + player.sendActionBar(AnarchyExploitFixes.getLang(player.locale()).lagpreventions_stopSpammingLevers); + } + } + } } -} +} \ No newline at end of file diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LiquidUpdateLag.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LiquidUpdateLag.java index 55d66c4c6..082cd4c7b 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LiquidUpdateLag.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LiquidUpdateLag.java @@ -1,6 +1,7 @@ package me.moomoo.anarchyexploitfixes.modules.lagpreventions; -import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; import me.moomoo.anarchyexploitfixes.config.Config; import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; @@ -13,25 +14,25 @@ import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockFromToEvent; -import org.bukkit.event.world.ChunkUnloadEvent; -import java.util.HashMap; +import java.time.Duration; import java.util.logging.Level; public class LiquidUpdateLag implements AnarchyExploitFixesModule, Listener { - private ScheduledTask scheduledTask; - private final HashMap cooldowns = new HashMap<>(); - private final HashMap liquidEventCounts = new HashMap<>(); + private final Cache liquidSpreadEventCountCache; private final boolean logIsEnabled; private final int maxLiquidSpreadEventsPerChunk; - private final long liquidSpreadCooldownInMillis; public LiquidUpdateLag() { shouldEnable(); Config config = AnarchyExploitFixes.getConfiguration(); - this.maxLiquidSpreadEventsPerChunk = config.getInt("lag-preventions.prevent-liquid-update-lag.max-liquid-events-in-same-chunk-per-time", 1200, "amount of liquid source blocks * sides it can spread to * block spread length"); - this.liquidSpreadCooldownInMillis = config.getInt("lag-preventions.prevent-liquid-update-lag.time-in-ticks", 100, "Record time after first liquid spread. \nWhen this time runs out, the spread counter resets") * 50L; + this.maxLiquidSpreadEventsPerChunk = config.getInt("lag-preventions.prevent-liquid-update-lag.max-liquid-events-in-same-chunk-per-time", 1200, + "amount of liquid source blocks * sides it can spread to * block spread length"); + this.liquidSpreadEventCountCache = Caffeine.newBuilder().expireAfterWrite(Duration.ofMillis( + config.getInt("lag-preventions.prevent-liquid-update-lag.time-in-ticks", 100, + "Record time after first liquid spread. \nWhen this time runs out, the spread counter resets") * 50L + )).build(); this.logIsEnabled = config.getBoolean("lag-preventions.prevent-liquid-update-lag.log", false, "very spammy, use for testing only"); } @@ -49,10 +50,6 @@ public String category() { public void enable() { AnarchyExploitFixes plugin = AnarchyExploitFixes.getInstance(); plugin.getServer().getPluginManager().registerEvents(this, plugin); - this.scheduledTask = plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, task -> { - cooldowns.clear(); - liquidEventCounts.clear(); - }, 2000L, 2000L); } @Override @@ -62,48 +59,32 @@ public boolean shouldEnable() { @Override public void disable() { - if (scheduledTask != null) scheduledTask.cancel(); HandlerList.unregisterAll(this); } - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onLiquidSpread(BlockFromToEvent event) { - Block sourceBlock = event.getBlock(); + final Block sourceBlock = event.getBlock(); if (sourceBlock.getType().equals(Material.DRAGON_EGG)) return; // Event fires only for liquids and the dragon egg final Chunk chunk = sourceBlock.getChunk(); - final String chunkId = String.valueOf(chunk.getWorld().getUID()) + chunk.getChunkKey(); - final long currentTime = System.currentTimeMillis(); - - if (!liquidEventCounts.containsKey(chunkId) || !cooldowns.containsKey(chunkId)) { - liquidEventCounts.put(chunkId, 1); - cooldowns.put(chunkId, currentTime); - return; - } - - int liquidEventCount = liquidEventCounts.get(chunkId); - - if (liquidEventCount >= maxLiquidSpreadEventsPerChunk) { - if (currentTime - cooldowns.get(chunkId) < liquidSpreadCooldownInMillis) { + Integer liquidSpreadCount = liquidSpreadEventCountCache.getIfPresent(chunk); + + if (liquidSpreadCount == null) { + liquidSpreadEventCountCache.put(chunk, 1); + } else { + liquidSpreadCount++; + liquidSpreadEventCountCache.put(chunk, liquidSpreadCount); + if (liquidSpreadCount > maxLiquidSpreadEventsPerChunk) { event.setCancelled(true); - if (logIsEnabled) LogUtils.moduleLog(Level.INFO, name(), "Cancelled liquid events for chunk x:" + chunk.getX() + ", z:" + chunk.getZ() + "in world: " + chunk.getWorld().getName()); + if (logIsEnabled) LogUtils.moduleLog(Level.INFO, name(), + "Cancelled liquid events for chunk x:" + chunk.getX() + ", z:" + chunk.getZ() + + "in world: " + chunk.getWorld().getName()); return; } - - liquidEventCount = 1; } - liquidEventCount++; - if (logIsEnabled) LogUtils.moduleLog(Level.INFO, name(), " Recorded " + liquidEventCount + " liquid updates in chunk x:" + chunk.getX() + ", z:" + chunk.getZ() + ", world: " + chunk.getWorld().getName()); - - liquidEventCounts.put(chunkId, liquidEventCount); - cooldowns.put(chunkId, currentTime); - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - private void onChunkUnload(ChunkUnloadEvent event) { - final String chunkId = String.valueOf(event.getChunk().getWorld().getUID()) + event.getChunk().getChunkKey(); - liquidEventCounts.remove(chunkId); - cooldowns.remove(chunkId); + if (logIsEnabled) LogUtils.moduleLog(Level.INFO, name(), " Recorded " + liquidSpreadCount + + " liquid updates in chunk x:" + chunk.getX() + ", z:" + chunk.getZ() + ", world: " + chunk.getWorld().getName()); } -} +} \ No newline at end of file diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/PreventFloodingMachines.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/PreventFloodingMachines.java index cc3303219..5ad12685c 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/PreventFloodingMachines.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/PreventFloodingMachines.java @@ -46,7 +46,7 @@ public boolean shouldEnable() { return AnarchyExploitFixes.getConfiguration().getBoolean("lag-preventions.prevent-flooding-machines.enable", false); } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) private void onPistonExtend(BlockPistonExtendEvent event) { for (Block block : event.getBlocks()) { if ( diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/SnowballExploit.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/SnowballExploit.java index 60246071d..08769560d 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/SnowballExploit.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/SnowballExploit.java @@ -51,18 +51,17 @@ public void disable() { private void run() { for (World world : plugin.getServer().getWorlds()) { for (Projectile projectile : world.getEntitiesByClass(Projectile.class)) { - projectile.getScheduler().run(plugin, removeOld -> { - if ( - projectile instanceof EnderPearl - || projectile instanceof WitherSkull - || projectile instanceof FishHook - || projectile instanceof EnderSignal - ) return; + final EntityType projectileType = projectile.getType(); + if ( + projectileType.equals(EntityType.ENDER_PEARL) + || projectileType.equals(EntityType.WITHER_SKULL) + || projectileType.equals(EntityType.FISHING_HOOK) + || projectileType.equals(EntityType.ENDER_SIGNAL) + ) continue; - if (projectile.getTicksLived() > max_alive_time) { - projectile.remove(); - } - }, null); + if (projectile.getTicksLived() > max_alive_time) { + projectile.getScheduler().run(plugin, removeOld -> projectile.remove(), null); + } } } } diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LeverSpam.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LeverSpam.java index 27eac6069..401c1e2d2 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LeverSpam.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LeverSpam.java @@ -1,41 +1,43 @@ package me.moomoo.anarchyexploitfixes.modules.lagpreventions; import com.cryptomorin.xseries.XMaterial; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; import me.moomoo.anarchyexploitfixes.config.Config; import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; -import org.bukkit.ChatColor; +import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import java.util.HashMap; +import java.time.Duration; import java.util.UUID; public class LeverSpam implements AnarchyExploitFixesModule, Listener { - private final HashMap cooldowns = new HashMap<>(); - private final HashMap leverCounts = new HashMap<>(); - private final Material lever; - - private final boolean shouldKickPlayer, sendActionBar; + private final Cache leverLocationCooldowns; + private final Cache playersUsingLeversCooldowns; + private final Material LEVER; private final int leverUsageLimit; - private final long leverCooldownInMillis; + private final boolean shouldKickPlayer, sendActionBar; public LeverSpam() { shouldEnable(); + this.LEVER = XMaterial.LEVER.parseMaterial(); Config config = AnarchyExploitFixes.getConfiguration(); config.addComment("lag-preventions.prevent-lever-spam.enable", "Rate Limit levers to prevent a lag exploit."); this.sendActionBar = config.getBoolean("lag-preventions.prevent-lever-spam.show-actionbar", true); this.shouldKickPlayer = config.getBoolean("lag-preventions.prevent-lever-spam.kick-player", false); - this.leverUsageLimit = config.getInt("lag-preventions.prevent-lever-spam.max-lever-usages-per-time", 10); - this.leverCooldownInMillis = config.getInt("lag-preventions.prevent-lever-spam.lever-time-in-ticks", 180) * 50L; - this.lever = XMaterial.LEVER.parseMaterial(); + this.leverUsageLimit = config.getInt("lag-preventions.prevent-lever-spam.max-lever-usages-per-time", 15); + final long cacheTimeMillis = config.getInt("lag-preventions.prevent-lever-spam.lever-time-in-ticks", 40) * 50L; + this.leverLocationCooldowns = Caffeine.newBuilder().expireAfterWrite(Duration.ofMillis(cacheTimeMillis)).build(); + this.playersUsingLeversCooldowns = Caffeine.newBuilder().expireAfterWrite(Duration.ofMillis(cacheTimeMillis)).build(); } @Override @@ -59,48 +61,53 @@ public boolean shouldEnable() { return AnarchyExploitFixes.getConfiguration().getBoolean("lag-preventions.prevent-lever-spam.enable", false); } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onInteract(PlayerInteractEvent event) { if (!event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) return; - if (!event.getClickedBlock().getType().equals(lever)) return; + Block clicked = event.getClickedBlock(); + if (!clicked.getType().equals(LEVER)) return; - Player player = event.getPlayer(); - final UUID playerUniqueId = player.getUniqueId(); - final long currentTime = System.currentTimeMillis(); + final Player player = event.getPlayer(); - if (!leverCounts.containsKey(playerUniqueId) || !cooldowns.containsKey(playerUniqueId)) { - leverCounts.put(playerUniqueId, 1); - cooldowns.put(playerUniqueId, currentTime); - return; - } - - int leverUseCount = leverCounts.get(playerUniqueId); + final Location leverLoc = clicked.getLocation(); + Integer activationCount = leverLocationCooldowns.getIfPresent(leverLoc); - if (leverUseCount >= leverUsageLimit) { - if (currentTime - cooldowns.get(playerUniqueId) < leverCooldownInMillis) { + if (activationCount == null) { + leverLocationCooldowns.put(leverLoc, 1); + } else { + activationCount++; + leverLocationCooldowns.put(leverLoc, activationCount); + if (activationCount > leverUsageLimit) { event.setCancelled(true); - if (sendActionBar) player.sendActionBar(ChatColor.translateAlternateColorCodes('&', - AnarchyExploitFixes.getLang(player.getLocale()).lagpreventions_stopSpammingLevers) - ); - if (shouldKickPlayer) player.kickPlayer(ChatColor.translateAlternateColorCodes('&', - AnarchyExploitFixes.getLang(player.getLocale()).lagpreventions_stopSpammingLevers) - ); + if (shouldKickPlayer) { + player.kickPlayer(AnarchyExploitFixes.getLang(player.getLocale()).lagpreventions_stopSpammingLevers); + return; + } + if (sendActionBar) { + player.sendActionBar(AnarchyExploitFixes.getLang(player.getLocale()).lagpreventions_stopSpammingLevers); + } return; } - - leverUseCount = 1; } - leverUseCount++; - - leverCounts.put(playerUniqueId, leverUseCount); - cooldowns.put(playerUniqueId, currentTime); - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - private void onPlayerQuit(PlayerQuitEvent event) { - UUID playerUniqueId = event.getPlayer().getUniqueId(); - cooldowns.remove(playerUniqueId); - leverCounts.remove(playerUniqueId); + final UUID playerUniqueId = player.getUniqueId(); + Integer leverFlickCount = playersUsingLeversCooldowns.getIfPresent(playerUniqueId); + + if (leverFlickCount == null) { + playersUsingLeversCooldowns.put(playerUniqueId, 1); + } else { + leverFlickCount++; + playersUsingLeversCooldowns.put(playerUniqueId, leverFlickCount); + if (leverFlickCount > leverUsageLimit) { + event.setCancelled(true); + if (shouldKickPlayer) { + player.kickPlayer(AnarchyExploitFixes.getLang(player.getLocale()).lagpreventions_stopSpammingLevers); + return; + } + if (sendActionBar) { + player.sendActionBar(AnarchyExploitFixes.getLang(player.getLocale()).lagpreventions_stopSpammingLevers); + } + } + } } -} +} \ No newline at end of file diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LiquidUpdateLag.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LiquidUpdateLag.java index 4dd0ecb8a..a62c9a12a 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LiquidUpdateLag.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/LiquidUpdateLag.java @@ -1,6 +1,8 @@ package me.moomoo.anarchyexploitfixes.modules.lagpreventions; import com.cryptomorin.xseries.XMaterial; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; import me.moomoo.anarchyexploitfixes.config.Config; import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; @@ -12,27 +14,29 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockFromToEvent; -import org.bukkit.event.world.ChunkUnloadEvent; -import java.util.HashMap; +import java.time.Duration; import java.util.logging.Level; public class LiquidUpdateLag implements AnarchyExploitFixesModule, Listener { - private final HashMap cooldowns = new HashMap<>(); - private final HashMap liquidEventCounts = new HashMap<>(); - private final boolean logIsEnabled; + private final Cache liquidSpreadEventCountCache; + private final Material DRAGON_EGG; private final int maxLiquidSpreadEventsPerChunk; - private final long liquidSpreadCooldownInMillis; - private final Material dragon_egg; + private final boolean logIsEnabled; public LiquidUpdateLag() { shouldEnable(); + this.DRAGON_EGG = XMaterial.DRAGON_EGG.parseMaterial(); Config config = AnarchyExploitFixes.getConfiguration(); - this.maxLiquidSpreadEventsPerChunk = config.getInt("lag-preventions.prevent-liquid-update-lag.max-liquid-events-in-same-chunk-per-time", 1200, "amount of liquid source blocks * sides it can spread to * block spread length"); - this.liquidSpreadCooldownInMillis = config.getInt("lag-preventions.prevent-liquid-update-lag.time-in-ticks", 100, "Record time after first liquid spread. \nWhen this time runs out, the spread counter resets") * 50L; - this.logIsEnabled = config.getBoolean("lag-preventions.prevent-liquid-update-lag.log", false, "very spammy, use for testing only"); - this.dragon_egg = XMaterial.DRAGON_EGG.parseMaterial(); + this.maxLiquidSpreadEventsPerChunk = config.getInt("lag-preventions.prevent-liquid-update-lag.max-liquid-events-in-same-chunk-per-time", 1200, + "Amount of liquid source blocks * sides it can spread to * block spread length"); + this.liquidSpreadEventCountCache = Caffeine.newBuilder().expireAfterWrite(Duration.ofMillis( + config.getInt("lag-preventions.prevent-liquid-update-lag.time-in-ticks", 100, + "Record time after first liquid spread. \nWhen this time runs out, the spread counter resets") * 50L + )).build(); + this.logIsEnabled = config.getBoolean("lag-preventions.prevent-liquid-update-lag.log", false, + "very spammy, use for testing only"); } @Override @@ -49,10 +53,6 @@ public String category() { public void enable() { AnarchyExploitFixes plugin = AnarchyExploitFixes.getInstance(); plugin.getServer().getPluginManager().registerEvents(this, plugin); - plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, () -> { - cooldowns.clear(); - liquidEventCounts.clear(); - }, 2000L, 2000L); } @Override @@ -60,44 +60,29 @@ public boolean shouldEnable() { return AnarchyExploitFixes.getConfiguration().getBoolean("lag-preventions.prevent-liquid-update-lag.enable", false); } - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onLiquidSpread(BlockFromToEvent event) { - Block sourceBlock = event.getBlock(); - if (sourceBlock.getType().equals(dragon_egg)) return; // Event fires only for liquids and the dragon egg + final Block sourceBlock = event.getBlock(); + if (sourceBlock.getType().equals(DRAGON_EGG)) return; // Event fires only for liquids and the dragon egg final Chunk chunk = sourceBlock.getChunk(); - final String chunkId = String.valueOf(chunk.getWorld().getUID()) + chunk.getChunkKey(); - final long currentTime = System.currentTimeMillis(); - - if (!liquidEventCounts.containsKey(chunkId) || !cooldowns.containsKey(chunkId)) { - liquidEventCounts.put(chunkId, 1); - cooldowns.put(chunkId, currentTime); - return; - } - - int liquidEventCount = liquidEventCounts.get(chunkId); - - if (liquidEventCount >= maxLiquidSpreadEventsPerChunk) { - if (currentTime - cooldowns.get(chunkId) < liquidSpreadCooldownInMillis) { + Integer liquidSpreadCount = liquidSpreadEventCountCache.getIfPresent(chunk); + + if (liquidSpreadCount == null) { + liquidSpreadEventCountCache.put(chunk, 1); + } else { + liquidSpreadCount++; + liquidSpreadEventCountCache.put(chunk, liquidSpreadCount); + if (liquidSpreadCount > maxLiquidSpreadEventsPerChunk) { event.setCancelled(true); - if (logIsEnabled) LogUtils.moduleLog(Level.INFO, name(), "Cancelled liquid events for chunk x:" + chunk.getX() + ", z:" + chunk.getZ() + "in world: " + chunk.getWorld().getName()); + if (logIsEnabled) LogUtils.moduleLog(Level.INFO, name(), + "Cancelled liquid events for chunk x:" + chunk.getX() + ", z:" + chunk.getZ() + + "in world: " + chunk.getWorld().getName()); return; } - - liquidEventCount = 1; } - liquidEventCount++; - if (logIsEnabled) LogUtils.moduleLog(Level.INFO, name(), " Recorded " + liquidEventCount + " liquid updates in chunk x:" + chunk.getX() + ", z:" + chunk.getZ() + ", world: " + chunk.getWorld().getName()); - - liquidEventCounts.put(chunkId, liquidEventCount); - cooldowns.put(chunkId, currentTime); - } - - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) - private void onChunkUnload(ChunkUnloadEvent event) { - String chunkId = String.valueOf(event.getChunk().getWorld().getUID()) + event.getChunk().getChunkKey(); - liquidEventCounts.remove(chunkId); - cooldowns.remove(chunkId); + if (logIsEnabled) LogUtils.moduleLog(Level.INFO, name(), " Recorded " + liquidSpreadCount + + " liquid updates in chunk x:" + chunk.getX() + ", z:" + chunk.getZ() + ", world: " + chunk.getWorld().getName()); } -} +} \ No newline at end of file diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/SnowballExploit.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/SnowballExploit.java index a9b0a5d25..41392fbc8 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/SnowballExploit.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/lagpreventions/SnowballExploit.java @@ -17,8 +17,10 @@ public SnowballExploit() { this.plugin = AnarchyExploitFixes.getInstance(); Config config = AnarchyExploitFixes.getConfiguration(); config.addComment("lag-preventions.prevent-snowball-exploit.enable", "Patches a lag exploit."); - this.max_alive_time = config.getInt("lag-preventions.prevent-snowball-exploit.projectiles-max-alive-time-in-ticks", 300, "(20 ticks = 1 second) Will not touch Ender Pearls"); - this.check_period_in_ticks = config.getInt("lag-preventions.prevent-snowball-exploit.check-period-in-seconds", 20, "How frequently we should check for all projectile's alive time") * 20L; + this.max_alive_time = config.getInt("lag-preventions.prevent-snowball-exploit.projectiles-max-alive-time-in-ticks", 300, + "(20 ticks = 1 second) Will not touch Ender Pearls"); + this.check_period_in_ticks = config.getInt("lag-preventions.prevent-snowball-exploit.check-period-in-seconds", 20, + "How frequently we should check for all projectile's alive time") * 20L; } @Override @@ -46,11 +48,12 @@ public boolean shouldEnable() { public void run() { for (World world : plugin.getServer().getWorlds()) { for (Projectile projectile : world.getEntitiesByClass(Projectile.class)) { + final EntityType projectileType = projectile.getType(); if ( - projectile instanceof EnderPearl - || projectile instanceof WitherSkull - || projectile instanceof FishHook - || projectile instanceof EnderSignal + projectileType.equals(EntityType.ENDER_PEARL) + || projectileType.equals(EntityType.WITHER_SKULL) + || projectileType.equals(EntityType.FISHING_HOOK) + || projectileType.equals(EntityType.ENDER_SIGNAL) ) continue; if (projectile.getTicksLived() > max_alive_time) {