From 1e489683d7f54d42b6f57c5414638dea01d9de56 Mon Sep 17 00:00:00 2001 From: OPmasterLEO <98689894+OPmasterLEO@users.noreply.github.com> Date: Sat, 19 Sep 2026 00:49:08 +0200 Subject: [PATCH 1/3] optimize ChunkUID --- .../chunklimits/FallingBlockLimit.java | 91 ++++++++----------- .../chunklimits/FallingBlockLimit.java | 91 ++++++++----------- .../me/xginko/aef/utils/models/ChunkUID.java | 14 ++- 3 files changed, 90 insertions(+), 106 deletions(-) diff --git a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java index 58f8f26a1..6d48a2897 100644 --- a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java @@ -5,25 +5,29 @@ import me.xginko.aef.utils.ChunkUtil; import me.xginko.aef.utils.LocationUtil; import me.xginko.aef.utils.models.ChunkUID; -import me.xginko.aef.utils.models.ExpiringSet; import org.bukkit.Chunk; +import org.bukkit.Location; import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; 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.BlockPhysicsEvent; import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntitySpawnEvent; -import java.time.Duration; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; public class FallingBlockLimit extends AEFModule implements Listener { + private static final EntityType FALLING_BLOCK_TYPE = Objects.requireNonNull(XEntityType.FALLING_BLOCK.get()); + private final long chunkCheckDelay; private final int maxFallingGravityBlockPerChunk; private final boolean logIsEnabled; - private ExpiringSet checkedChunks; + private ConcurrentHashMap checkedChunksUntil; public FallingBlockLimit() { super("chunk-limits.falling-block-limit", true, """ @@ -41,74 +45,57 @@ public FallingBlockLimit() { @Override public void enable() { - checkedChunks = new ExpiringSet<>(Duration.ofMillis(chunkCheckDelay)); + checkedChunksUntil = new ConcurrentHashMap<>(); plugin.getServer().getPluginManager().registerEvents(this, plugin); } @Override public void disable() { HandlerList.unregisterAll(this); - if (checkedChunks != null) { - checkedChunks.clear(); - checkedChunks.cleanUp(); - checkedChunks = null; + if (checkedChunksUntil != null) { + checkedChunksUntil.clear(); + checkedChunksUntil = null; } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - private void onBlockPhysics(BlockPhysicsEvent event) { - Chunk chunk = event.getBlock().getChunk(); - if (ChunkUtil.isRetrievalUnsafe(chunk)) return; - - final ChunkUID chunkUID = ChunkUID.of(chunk); - if (checkedChunks.contains(chunkUID)) return; - - int count = 0; - boolean removed_falling = false; - - for (Entity entity : chunk.getEntities()) { - if (entity.getType() == XEntityType.FALLING_BLOCK.get()) { - count++; - if (count > maxFallingGravityBlockPerChunk) { - entity.remove(); - removed_falling = true; - } - } - } - - checkedChunks.add(chunkUID); - - if (logIsEnabled && removed_falling) info("Removed falling block(s) at " + - LocationUtil.toString(event.getSourceBlock().getLocation()) + " because reached limit of " + - maxFallingGravityBlockPerChunk + " falling gravity blocks per chunk"); + private void onEntitySpawn(EntitySpawnEvent event) { + if (event.getEntityType() != FALLING_BLOCK_TYPE) return; + tryEnforceLimit(event.getEntity().getChunk(), event.getEntity().getLocation()); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onChangeBlock(EntityChangeBlockEvent event) { - if (event.getEntityType() != XEntityType.FALLING_BLOCK.get()) return; - Chunk chunk = event.getBlock().getChunk(); - if (ChunkUtil.isRetrievalUnsafe(chunk)) return; + if (event.getEntityType() != FALLING_BLOCK_TYPE) return; + tryEnforceLimit(event.getBlock().getChunk(), event.getBlock().getLocation()); + } + + private void tryEnforceLimit(Chunk chunk, Location logLocation) { + if (ChunkUtil.isRetrievalUnsafe(chunk) || !ChunkUtil.isEntitiesLoaded(chunk)) return; - final ChunkUID chunkUID = ChunkUID.of(chunk); - if (checkedChunks.contains(chunkUID)) return; + long chunkKey = ChunkUID.toKey(chunk); + long now = System.currentTimeMillis(); + Long cooldownUntil = checkedChunksUntil.get(chunkKey); + if (cooldownUntil != null && cooldownUntil > now) return; + + checkedChunksUntil.put(chunkKey, now + chunkCheckDelay); int count = 0; - boolean removed_falling = false; + boolean removedFalling = false; for (Entity entity : chunk.getEntities()) { - if (entity.getType() == XEntityType.FALLING_BLOCK.get()) { - count++; - if (count > maxFallingGravityBlockPerChunk) { - entity.remove(); - removed_falling = true; - } + if (entity.getType() != FALLING_BLOCK_TYPE) continue; + + count++; + if (count > maxFallingGravityBlockPerChunk) { + entity.remove(); + removedFalling = true; } } - checkedChunks.add(chunkUID); - - if (logIsEnabled && removed_falling) info("Removed falling block(s) at " + - LocationUtil.toString(event.getBlock().getLocation()) + " because reached limit of " + - maxFallingGravityBlockPerChunk + " falling gravity blocks per chunk"); + if (logIsEnabled && removedFalling) { + info("Removed falling block(s) at " + LocationUtil.toString(logLocation) + " because reached limit of " + + maxFallingGravityBlockPerChunk + " falling gravity blocks per chunk"); + } } -} \ No newline at end of file +} diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java index 3118d771d..2f7959264 100644 --- a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java @@ -5,25 +5,29 @@ import me.xginko.aef.utils.ChunkUtil; import me.xginko.aef.utils.LocationUtil; import me.xginko.aef.utils.models.ChunkUID; -import me.xginko.aef.utils.models.ExpiringSet; import org.bukkit.Chunk; +import org.bukkit.Location; import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; 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.BlockPhysicsEvent; import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntitySpawnEvent; -import java.time.Duration; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; public class FallingBlockLimit extends AEFModule implements Listener { + private static final EntityType FALLING_BLOCK_TYPE = Objects.requireNonNull(XEntityType.FALLING_BLOCK.get()); + private final long chunkCheckDelay; private final int maxFallingGravityBlockPerChunk; private final boolean logIsEnabled; - private ExpiringSet checkedChunks; + private ConcurrentHashMap checkedChunksUntil; public FallingBlockLimit() { super("chunk-limits.falling-block-limit", true, @@ -41,74 +45,57 @@ public FallingBlockLimit() { @Override public void enable() { - checkedChunks = new ExpiringSet<>(Duration.ofMillis(chunkCheckDelay)); + checkedChunksUntil = new ConcurrentHashMap<>(); plugin.getServer().getPluginManager().registerEvents(this, plugin); } @Override public void disable() { HandlerList.unregisterAll(this); - if (checkedChunks != null) { - checkedChunks.clear(); - checkedChunks.cleanUp(); - checkedChunks = null; + if (checkedChunksUntil != null) { + checkedChunksUntil.clear(); + checkedChunksUntil = null; } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - private void onBlockPhysics(BlockPhysicsEvent event) { - Chunk chunk = event.getBlock().getChunk(); - if (ChunkUtil.isRetrievalUnsafe(chunk)) return; - - final ChunkUID chunkUID = ChunkUID.of(chunk); - if (checkedChunks.contains(chunkUID)) return; - - int count = 0; - boolean removed_falling = false; - - for (Entity entity : chunk.getEntities()) { - if (entity.getType() == XEntityType.FALLING_BLOCK.get()) { - count++; - if (count > maxFallingGravityBlockPerChunk) { - entity.remove(); - removed_falling = true; - } - } - } - - checkedChunks.add(chunkUID); - - if (logIsEnabled && removed_falling) info("Removed falling block(s) at " + - LocationUtil.toString(event.getSourceBlock().getLocation()) + " because reached limit of " + - maxFallingGravityBlockPerChunk + " falling gravity blocks per chunk"); + private void onEntitySpawn(EntitySpawnEvent event) { + if (event.getEntityType() != FALLING_BLOCK_TYPE) return; + tryEnforceLimit(event.getEntity().getChunk(), event.getEntity().getLocation()); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onChangeBlock(EntityChangeBlockEvent event) { - if (event.getEntityType() != XEntityType.FALLING_BLOCK.get()) return; - Chunk chunk = event.getBlock().getChunk(); - if (ChunkUtil.isRetrievalUnsafe(chunk)) return; + if (event.getEntityType() != FALLING_BLOCK_TYPE) return; + tryEnforceLimit(event.getBlock().getChunk(), event.getBlock().getLocation()); + } + + private void tryEnforceLimit(Chunk chunk, Location logLocation) { + if (ChunkUtil.isRetrievalUnsafe(chunk) || !ChunkUtil.isEntitiesLoaded(chunk)) return; - final ChunkUID chunkUID = ChunkUID.of(chunk); - if (checkedChunks.contains(chunkUID)) return; + long chunkKey = ChunkUID.toKey(chunk); + long now = System.currentTimeMillis(); + Long cooldownUntil = checkedChunksUntil.get(chunkKey); + if (cooldownUntil != null && cooldownUntil > now) return; + + checkedChunksUntil.put(chunkKey, now + chunkCheckDelay); int count = 0; - boolean removed_falling = false; + boolean removedFalling = false; for (Entity entity : chunk.getEntities()) { - if (entity.getType() == XEntityType.FALLING_BLOCK.get()) { - count++; - if (count > maxFallingGravityBlockPerChunk) { - entity.remove(); - removed_falling = true; - } + if (entity.getType() != FALLING_BLOCK_TYPE) continue; + + count++; + if (count > maxFallingGravityBlockPerChunk) { + entity.remove(); + removedFalling = true; } } - checkedChunks.add(chunkUID); - - if (logIsEnabled && removed_falling) info("Removed falling block(s) at " + - LocationUtil.toString(event.getBlock().getLocation()) + " because reached limit of " + - maxFallingGravityBlockPerChunk + " falling gravity blocks per chunk"); + if (logIsEnabled && removedFalling) { + info("Removed falling block(s) at " + LocationUtil.toString(logLocation) + " because reached limit of " + + maxFallingGravityBlockPerChunk + " falling gravity blocks per chunk"); + } } -} \ No newline at end of file +} diff --git a/shared/src/main/java/me/xginko/aef/utils/models/ChunkUID.java b/shared/src/main/java/me/xginko/aef/utils/models/ChunkUID.java index e30a94902..c5f65972b 100644 --- a/shared/src/main/java/me/xginko/aef/utils/models/ChunkUID.java +++ b/shared/src/main/java/me/xginko/aef/utils/models/ChunkUID.java @@ -5,7 +5,6 @@ import org.bukkit.World; import org.jetbrains.annotations.Nullable; -import java.util.Objects; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -18,6 +17,17 @@ public static ChunkUID of(Chunk chunk) { return new ChunkUID(chunk.getWorld().getUID(), chunk.getX(), chunk.getZ()); } + public static long toKey(Chunk chunk) { + return toKey(chunk.getWorld().getUID(), chunk.getX(), chunk.getZ()); + } + + public static long toKey(UUID worldUID, int x, int z) { + return worldUID.getMostSignificantBits() + ^ worldUID.getLeastSignificantBits() + ^ ((long) x << 32) + ^ (z & 0xFFFFFFFFL); + } + private ChunkUID(UUID worldUID, int x, int z) { this.worldUID = worldUID; this.x = x; @@ -48,7 +58,7 @@ public String toString() { @Override public int hashCode() { - return Objects.hash(this.worldUID, this.x, this.z); + return 31 * (31 * this.worldUID.hashCode() + this.x) + this.z; } @Override From 1ec93405e8bbcc3507bc4696ecb0e324924d9d2a Mon Sep 17 00:00:00 2001 From: OPmasterLEO <98689894+OPmasterLEO@users.noreply.github.com> Date: Sun, 20 Sep 2026 15:51:46 +0200 Subject: [PATCH 2/3] fix criticals --- .../aef/modules/chunklimits/FallingBlockLimit.java | 12 ++++++------ .../aef/modules/chunklimits/FallingBlockLimit.java | 12 ++++++------ .../java/me/xginko/aef/utils/models/ChunkUID.java | 11 ----------- 3 files changed, 12 insertions(+), 23 deletions(-) diff --git a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java index 6d48a2897..edaa2f0c9 100644 --- a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java @@ -27,7 +27,7 @@ public class FallingBlockLimit extends AEFModule implements Listener { private final int maxFallingGravityBlockPerChunk; private final boolean logIsEnabled; - private ConcurrentHashMap checkedChunksUntil; + private ConcurrentHashMap checkedChunksUntil; public FallingBlockLimit() { super("chunk-limits.falling-block-limit", true, """ @@ -61,26 +61,26 @@ public void disable() { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onEntitySpawn(EntitySpawnEvent event) { if (event.getEntityType() != FALLING_BLOCK_TYPE) return; - tryEnforceLimit(event.getEntity().getChunk(), event.getEntity().getLocation()); + tryEnforceLimit(event.getEntity().getChunk(), event.getEntity().getLocation(), 1); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onChangeBlock(EntityChangeBlockEvent event) { if (event.getEntityType() != FALLING_BLOCK_TYPE) return; - tryEnforceLimit(event.getBlock().getChunk(), event.getBlock().getLocation()); + tryEnforceLimit(event.getBlock().getChunk(), event.getBlock().getLocation(), 0); } - private void tryEnforceLimit(Chunk chunk, Location logLocation) { + private void tryEnforceLimit(Chunk chunk, Location logLocation, int initialCount) { if (ChunkUtil.isRetrievalUnsafe(chunk) || !ChunkUtil.isEntitiesLoaded(chunk)) return; - long chunkKey = ChunkUID.toKey(chunk); + ChunkUID chunkKey = ChunkUID.of(chunk); long now = System.currentTimeMillis(); Long cooldownUntil = checkedChunksUntil.get(chunkKey); if (cooldownUntil != null && cooldownUntil > now) return; checkedChunksUntil.put(chunkKey, now + chunkCheckDelay); - int count = 0; + int count = initialCount; boolean removedFalling = false; for (Entity entity : chunk.getEntities()) { diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java index 2f7959264..5428b6c8e 100644 --- a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java @@ -27,7 +27,7 @@ public class FallingBlockLimit extends AEFModule implements Listener { private final int maxFallingGravityBlockPerChunk; private final boolean logIsEnabled; - private ConcurrentHashMap checkedChunksUntil; + private ConcurrentHashMap checkedChunksUntil; public FallingBlockLimit() { super("chunk-limits.falling-block-limit", true, @@ -61,26 +61,26 @@ public void disable() { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onEntitySpawn(EntitySpawnEvent event) { if (event.getEntityType() != FALLING_BLOCK_TYPE) return; - tryEnforceLimit(event.getEntity().getChunk(), event.getEntity().getLocation()); + tryEnforceLimit(event.getEntity().getChunk(), event.getEntity().getLocation(), 1); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) private void onChangeBlock(EntityChangeBlockEvent event) { if (event.getEntityType() != FALLING_BLOCK_TYPE) return; - tryEnforceLimit(event.getBlock().getChunk(), event.getBlock().getLocation()); + tryEnforceLimit(event.getBlock().getChunk(), event.getBlock().getLocation(), 0); } - private void tryEnforceLimit(Chunk chunk, Location logLocation) { + private void tryEnforceLimit(Chunk chunk, Location logLocation, int initialCount) { if (ChunkUtil.isRetrievalUnsafe(chunk) || !ChunkUtil.isEntitiesLoaded(chunk)) return; - long chunkKey = ChunkUID.toKey(chunk); + ChunkUID chunkKey = ChunkUID.of(chunk); long now = System.currentTimeMillis(); Long cooldownUntil = checkedChunksUntil.get(chunkKey); if (cooldownUntil != null && cooldownUntil > now) return; checkedChunksUntil.put(chunkKey, now + chunkCheckDelay); - int count = 0; + int count = initialCount; boolean removedFalling = false; for (Entity entity : chunk.getEntities()) { diff --git a/shared/src/main/java/me/xginko/aef/utils/models/ChunkUID.java b/shared/src/main/java/me/xginko/aef/utils/models/ChunkUID.java index c5f65972b..4a77899ad 100644 --- a/shared/src/main/java/me/xginko/aef/utils/models/ChunkUID.java +++ b/shared/src/main/java/me/xginko/aef/utils/models/ChunkUID.java @@ -17,17 +17,6 @@ public static ChunkUID of(Chunk chunk) { return new ChunkUID(chunk.getWorld().getUID(), chunk.getX(), chunk.getZ()); } - public static long toKey(Chunk chunk) { - return toKey(chunk.getWorld().getUID(), chunk.getX(), chunk.getZ()); - } - - public static long toKey(UUID worldUID, int x, int z) { - return worldUID.getMostSignificantBits() - ^ worldUID.getLeastSignificantBits() - ^ ((long) x << 32) - ^ (z & 0xFFFFFFFFL); - } - private ChunkUID(UUID worldUID, int x, int z) { this.worldUID = worldUID; this.x = x; From ce2330bed9af2d6ae67493f514e16cc5c875c734 Mon Sep 17 00:00:00 2001 From: OPmasterLEO <98689894+OPmasterLEO@users.noreply.github.com> Date: Sun, 20 Sep 2026 16:14:31 +0200 Subject: [PATCH 3/3] clean up chunk key --- .../chunklimits/FallingBlockLimit.java | 19 +++++++++---------- .../chunklimits/FallingBlockLimit.java | 19 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java index edaa2f0c9..239b7621c 100644 --- a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java @@ -5,6 +5,7 @@ import me.xginko.aef.utils.ChunkUtil; import me.xginko.aef.utils.LocationUtil; import me.xginko.aef.utils.models.ChunkUID; +import me.xginko.aef.utils.models.ExpiringSet; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.entity.Entity; @@ -16,8 +17,8 @@ import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.event.entity.EntitySpawnEvent; +import java.time.Duration; import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; public class FallingBlockLimit extends AEFModule implements Listener { @@ -27,7 +28,7 @@ public class FallingBlockLimit extends AEFModule implements Listener { private final int maxFallingGravityBlockPerChunk; private final boolean logIsEnabled; - private ConcurrentHashMap checkedChunksUntil; + private ExpiringSet checkedChunks; public FallingBlockLimit() { super("chunk-limits.falling-block-limit", true, """ @@ -45,16 +46,16 @@ public FallingBlockLimit() { @Override public void enable() { - checkedChunksUntil = new ConcurrentHashMap<>(); + checkedChunks = new ExpiringSet<>(Duration.ofMillis(chunkCheckDelay)); plugin.getServer().getPluginManager().registerEvents(this, plugin); } @Override public void disable() { HandlerList.unregisterAll(this); - if (checkedChunksUntil != null) { - checkedChunksUntil.clear(); - checkedChunksUntil = null; + if (checkedChunks != null) { + checkedChunks.clear(); + checkedChunks = null; } } @@ -74,11 +75,9 @@ private void tryEnforceLimit(Chunk chunk, Location logLocation, int initialCount if (ChunkUtil.isRetrievalUnsafe(chunk) || !ChunkUtil.isEntitiesLoaded(chunk)) return; ChunkUID chunkKey = ChunkUID.of(chunk); - long now = System.currentTimeMillis(); - Long cooldownUntil = checkedChunksUntil.get(chunkKey); - if (cooldownUntil != null && cooldownUntil > now) return; + if (checkedChunks.contains(chunkKey)) return; - checkedChunksUntil.put(chunkKey, now + chunkCheckDelay); + checkedChunks.add(chunkKey); int count = initialCount; boolean removedFalling = false; diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java index 5428b6c8e..4abcd6676 100644 --- a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/FallingBlockLimit.java @@ -5,6 +5,7 @@ import me.xginko.aef.utils.ChunkUtil; import me.xginko.aef.utils.LocationUtil; import me.xginko.aef.utils.models.ChunkUID; +import me.xginko.aef.utils.models.ExpiringSet; import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.entity.Entity; @@ -16,8 +17,8 @@ import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.event.entity.EntitySpawnEvent; +import java.time.Duration; import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; public class FallingBlockLimit extends AEFModule implements Listener { @@ -27,7 +28,7 @@ public class FallingBlockLimit extends AEFModule implements Listener { private final int maxFallingGravityBlockPerChunk; private final boolean logIsEnabled; - private ConcurrentHashMap checkedChunksUntil; + private ExpiringSet checkedChunks; public FallingBlockLimit() { super("chunk-limits.falling-block-limit", true, @@ -45,16 +46,16 @@ public FallingBlockLimit() { @Override public void enable() { - checkedChunksUntil = new ConcurrentHashMap<>(); + checkedChunks = new ExpiringSet<>(Duration.ofMillis(chunkCheckDelay)); plugin.getServer().getPluginManager().registerEvents(this, plugin); } @Override public void disable() { HandlerList.unregisterAll(this); - if (checkedChunksUntil != null) { - checkedChunksUntil.clear(); - checkedChunksUntil = null; + if (checkedChunks != null) { + checkedChunks.clear(); + checkedChunks = null; } } @@ -74,11 +75,9 @@ private void tryEnforceLimit(Chunk chunk, Location logLocation, int initialCount if (ChunkUtil.isRetrievalUnsafe(chunk) || !ChunkUtil.isEntitiesLoaded(chunk)) return; ChunkUID chunkKey = ChunkUID.of(chunk); - long now = System.currentTimeMillis(); - Long cooldownUntil = checkedChunksUntil.get(chunkKey); - if (cooldownUntil != null && cooldownUntil > now) return; + if (checkedChunks.contains(chunkKey)) return; - checkedChunksUntil.put(chunkKey, now + chunkCheckDelay); + checkedChunks.add(chunkKey); int count = initialCount; boolean removedFalling = false;