From 8e5669e5a9c177e3c818fd4b9dd47a14a490e86e Mon Sep 17 00:00:00 2001 From: xGinko Date: Tue, 31 Dec 2024 23:23:16 +0100 Subject: [PATCH] cache blocklimiter result to prevent lag --- .../aef/modules/chunklimits/BlockLimit.java | 47 +++++++++++++----- .../aef/modules/chunklimits/BlockLimit.java | 48 ++++++++++++++----- 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/BlockLimit.java b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/BlockLimit.java index 801bfc2c..a0b384f0 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/BlockLimit.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/chunklimits/BlockLimit.java @@ -1,6 +1,8 @@ package me.xginko.aef.modules.chunklimits; import com.cryptomorin.xseries.XMaterial; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import io.github.thatsmusic99.configurationmaster.api.ConfigSection; import me.xginko.aef.modules.AEFModule; import org.bukkit.Chunk; @@ -12,6 +14,7 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerInteractEvent; +import java.time.Duration; import java.util.EnumMap; import java.util.Map; import java.util.TreeMap; @@ -19,9 +22,13 @@ public class BlockLimit extends AEFModule implements Listener { private final Map blockLimits = new EnumMap<>(Material.class); + private final long materialCountCacheMillis; + + private Cache> chunkMaterialCache; public BlockLimit() { super("chunk-limits.block-limit", false); + this.materialCountCacheMillis = config.getLong(configPath + ".material-count-cache-millis", 5000); Map universal = new EnumMap<>(XMaterial.class); universal.put(XMaterial.ENCHANTING_TABLE, 16); @@ -144,12 +151,22 @@ public BlockLimit() { @Override public void enable() { + chunkMaterialCache = Caffeine.newBuilder().expireAfterWrite(Duration.ofMinutes(1)).build(); plugin.getServer().getPluginManager().registerEvents(this, plugin); } @Override public void disable() { HandlerList.unregisterAll(this); + if (chunkMaterialCache != null) { + for (Map.Entry> entry : chunkMaterialCache.asMap().entrySet()) { + entry.getValue().invalidateAll(); + entry.getValue().cleanUp(); + } + chunkMaterialCache.invalidateAll(); + chunkMaterialCache.cleanUp(); + chunkMaterialCache = null; + } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @@ -170,24 +187,30 @@ && exceedsPerChunkLimit(event.getMaterial(), event.getPlayer().getChunk())) { } } - private boolean exceedsPerChunkLimit(Material material, Chunk chunk) { - final int materialLimit = blockLimits.get(material); + private boolean exceedsPerChunkLimit(Material blockType, Chunk chunk) { final int minY = chunk.getWorld().getMinHeight(); final int maxY = chunk.getWorld().getMaxHeight(); - int count = 0; - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - for (int y = minY; y < maxY; y++) { - if (chunk.getBlock(x, y, z).getType() == material) { - count++; - if (count > materialLimit) { - return true; + Cache materialCountCache = chunkMaterialCache.getIfPresent(chunk); + if (materialCountCache == null) { + materialCountCache = Caffeine.newBuilder().expireAfterWrite(Duration.ofMillis(materialCountCacheMillis)).build(); + } + + Integer materialCount = materialCountCache.get(blockType, material -> { + int count = 0; + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + for (int y = minY; y < maxY; y++) { + if (chunk.getBlock(x, y, z).getType() == material) { + count++; } } } } - } - return false; + return count; + }); + + chunkMaterialCache.put(chunk, materialCountCache); + return materialCount > blockLimits.get(blockType); } } diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/BlockLimit.java b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/BlockLimit.java index 5365c1ba..17cd0a48 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/BlockLimit.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/chunklimits/BlockLimit.java @@ -1,6 +1,8 @@ package me.xginko.aef.modules.chunklimits; import com.cryptomorin.xseries.XMaterial; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import io.github.thatsmusic99.configurationmaster.api.ConfigSection; import me.xginko.aef.modules.AEFModule; import me.xginko.aef.utils.WorldUtil; @@ -14,6 +16,7 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerInteractEvent; +import java.time.Duration; import java.util.EnumMap; import java.util.Map; import java.util.TreeMap; @@ -21,9 +24,13 @@ public class BlockLimit extends AEFModule implements Listener { private final Map blockLimits = new EnumMap<>(Material.class); + private final long materialCountCacheMillis; + + private Cache> chunkMaterialCache; public BlockLimit() { super("chunk-limits.block-limit", false); + this.materialCountCacheMillis = config.getLong(configPath + ".material-count-cache-millis", 5000); Map universal = new EnumMap<>(XMaterial.class); universal.put(XMaterial.ENCHANTING_TABLE, 16); @@ -146,12 +153,22 @@ public BlockLimit() { @Override public void enable() { + chunkMaterialCache = Caffeine.newBuilder().expireAfterWrite(Duration.ofMinutes(1)).build(); plugin.getServer().getPluginManager().registerEvents(this, plugin); } @Override public void disable() { HandlerList.unregisterAll(this); + if (chunkMaterialCache != null) { + for (Map.Entry> entry : chunkMaterialCache.asMap().entrySet()) { + entry.getValue().invalidateAll(); + entry.getValue().cleanUp(); + } + chunkMaterialCache.invalidateAll(); + chunkMaterialCache.cleanUp(); + chunkMaterialCache = null; + } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @@ -172,23 +189,30 @@ && exceedsPerChunkLimit(event.getMaterial(), event.getPlayer().getChunk())) { } } - private boolean exceedsPerChunkLimit(Material material, Chunk chunk) { - final int materialLimit = blockLimits.get(material); + private boolean exceedsPerChunkLimit(Material blockType, Chunk chunk) { final int minY = WorldUtil.getMinWorldHeight(chunk.getWorld()); final int maxY = chunk.getWorld().getMaxHeight(); - int count = 0; - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - for (int y = minY; y < maxY; y++) { - if (chunk.getBlock(x, y, z).getType() == material) { - count++; - if (count > materialLimit) { - return true; + + Cache materialCountCache = chunkMaterialCache.getIfPresent(chunk); + if (materialCountCache == null) { + materialCountCache = Caffeine.newBuilder().expireAfterWrite(Duration.ofMillis(materialCountCacheMillis)).build(); + } + + Integer materialCount = materialCountCache.get(blockType, material -> { + int count = 0; + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + for (int y = minY; y < maxY; y++) { + if (chunk.getBlock(x, y, z).getType() == material) { + count++; } } } } - } - return false; + return count; + }); + + chunkMaterialCache.put(chunk, materialCountCache); + return materialCount > blockLimits.get(blockType); } }