11package me .xginko .aef .modules .chunklimits ;
22
33import com .cryptomorin .xseries .XMaterial ;
4+ import com .github .benmanes .caffeine .cache .Cache ;
5+ import com .github .benmanes .caffeine .cache .Caffeine ;
46import io .github .thatsmusic99 .configurationmaster .api .ConfigSection ;
57import me .xginko .aef .modules .AEFModule ;
68import me .xginko .aef .utils .WorldUtil ;
1416import org .bukkit .event .block .BlockPlaceEvent ;
1517import org .bukkit .event .player .PlayerInteractEvent ;
1618
19+ import java .time .Duration ;
1720import java .util .EnumMap ;
1821import java .util .Map ;
1922import java .util .TreeMap ;
2023
2124public class BlockLimit extends AEFModule implements Listener {
2225
2326 private final Map <Material , Integer > blockLimits = new EnumMap <>(Material .class );
27+ private final long materialCountCacheMillis ;
28+
29+ private Cache <Chunk , Cache <Material , Integer >> chunkMaterialCache ;
2430
2531 public BlockLimit () {
2632 super ("chunk-limits.block-limit" , false );
33+ this .materialCountCacheMillis = config .getLong (configPath + ".material-count-cache-millis" , 5000 );
2734
2835 Map <XMaterial , Integer > universal = new EnumMap <>(XMaterial .class );
2936 universal .put (XMaterial .ENCHANTING_TABLE , 16 );
@@ -146,12 +153,22 @@ public BlockLimit() {
146153
147154 @ Override
148155 public void enable () {
156+ chunkMaterialCache = Caffeine .newBuilder ().expireAfterWrite (Duration .ofMinutes (1 )).build ();
149157 plugin .getServer ().getPluginManager ().registerEvents (this , plugin );
150158 }
151159
152160 @ Override
153161 public void disable () {
154162 HandlerList .unregisterAll (this );
163+ if (chunkMaterialCache != null ) {
164+ for (Map .Entry <Chunk , Cache <Material , Integer >> entry : chunkMaterialCache .asMap ().entrySet ()) {
165+ entry .getValue ().invalidateAll ();
166+ entry .getValue ().cleanUp ();
167+ }
168+ chunkMaterialCache .invalidateAll ();
169+ chunkMaterialCache .cleanUp ();
170+ chunkMaterialCache = null ;
171+ }
155172 }
156173
157174 @ EventHandler (priority = EventPriority .HIGHEST , ignoreCancelled = true )
@@ -172,23 +189,30 @@ && exceedsPerChunkLimit(event.getMaterial(), event.getPlayer().getChunk())) {
172189 }
173190 }
174191
175- private boolean exceedsPerChunkLimit (Material material , Chunk chunk ) {
176- final int materialLimit = blockLimits .get (material );
192+ private boolean exceedsPerChunkLimit (Material blockType , Chunk chunk ) {
177193 final int minY = WorldUtil .getMinWorldHeight (chunk .getWorld ());
178194 final int maxY = chunk .getWorld ().getMaxHeight ();
179- int count = 0 ;
180- for (int x = 0 ; x < 16 ; x ++) {
181- for (int z = 0 ; z < 16 ; z ++) {
182- for (int y = minY ; y < maxY ; y ++) {
183- if (chunk .getBlock (x , y , z ).getType () == material ) {
184- count ++;
185- if (count > materialLimit ) {
186- return true ;
195+
196+ Cache <Material , Integer > materialCountCache = chunkMaterialCache .getIfPresent (chunk );
197+ if (materialCountCache == null ) {
198+ materialCountCache = Caffeine .newBuilder ().expireAfterWrite (Duration .ofMillis (materialCountCacheMillis )).build ();
199+ }
200+
201+ Integer materialCount = materialCountCache .get (blockType , material -> {
202+ int count = 0 ;
203+ for (int x = 0 ; x < 16 ; x ++) {
204+ for (int z = 0 ; z < 16 ; z ++) {
205+ for (int y = minY ; y < maxY ; y ++) {
206+ if (chunk .getBlock (x , y , z ).getType () == material ) {
207+ count ++;
187208 }
188209 }
189210 }
190211 }
191- }
192- return false ;
212+ return count ;
213+ });
214+
215+ chunkMaterialCache .put (chunk , materialCountCache );
216+ return materialCount > blockLimits .get (blockType );
193217 }
194218}
0 commit comments