From 3deff629b0a35743808ab3e10a40b1eabcb86b98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Tue, 12 May 2020 23:01:14 +0200 Subject: [PATCH 1/8] Add paper specific listener for limiting the amount of tile entities in a chunk during build, instead of just doing it during chunk unloading --- .../bukkit/listener/PaperListener.java | 25 +++++++++++++++++++ .../core/configuration/Captions.java | 1 + .../core/configuration/Settings.java | 2 ++ 3 files changed, 28 insertions(+) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java index f87050c88..870747c1a 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java @@ -33,6 +33,7 @@ import com.destroystokyo.paper.event.entity.SlimePathfindEvent; import com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.location.Location; import com.plotsquared.core.player.PlotPlayer; @@ -41,6 +42,7 @@ import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.flag.implementations.DoneFlag; import org.bukkit.Chunk; import org.bukkit.block.Block; +import org.bukkit.block.TileState; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; @@ -48,7 +50,9 @@ import org.bukkit.entity.Projectile; import org.bukkit.entity.Slime; import org.bukkit.entity.ThrownPotion; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.projectiles.ProjectileSource; @@ -252,6 +256,27 @@ public class PaperListener implements Listener { } } + @EventHandler(priority = EventPriority.HIGHEST) public void onBlockPlace(BlockPlaceEvent event) { + if (!Settings.Paper_Components.TILE_ENTITY_CHECK) { + return; + } + if (!(event.getBlock().getState(false) instanceof TileState)) { + return; + } + final Location location = BukkitUtil.getLocation(event.getBlock().getLocation()); + final PlotArea plotArea = location.getPlotArea(); + if (plotArea == null) { + return; + } + final int tileEntityCount = event.getBlock().getChunk().getTileEntities(false).length; + if (tileEntityCount >= Settings.Chunk_Processor.MAX_TILES) { + final PlotPlayer plotPlayer = BukkitUtil.getPlayer(event.getPlayer()); + Captions.TILE_ENTITY_CAP_REACHED.send(plotPlayer, Settings.Chunk_Processor.MAX_TILES); + event.setCancelled(true); + event.setBuild(false); + } + } + /** * Unsure if this will be any performance improvement over the spigot version, * but here it is anyway :) diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 5909b119f..17c0d7c4d 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -446,6 +446,7 @@ public enum Captions implements Caption { NOT_VALID_PLOT_WORLD("$2That is not a valid plot area (case sensitive)", "Errors"), NO_PLOTS("$2You don't have any plots", "Errors"), WAIT_FOR_TIMER("$2A set block timer is bound to either the current plot or you. Please wait for it to finish", "Errors"), + TILE_ENTITY_CAP_REACHED("$2The total number of tile entities in this chunk may not exceed $1%s", "Errors"), // DEBUG_REPORT_CREATED("$1Uploaded a full debug to: $1%url%", "Paste"), PURGE_SUCCESS("$4Successfully purged %s plots", "Purge"), diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 0967b137c..108bff9de 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -484,6 +484,8 @@ public class Settings extends Config { public static boolean SPAWNER_SPAWN = true; @Comment("Cancel entity spawns from tick spawn rates before they happen (performance buff)") public static boolean CREATURE_SPAWN = true; + @Comment("Check the tile entity limit on block placement") + public static boolean TILE_ENTITY_CHECK = false; } From 435d877262a3244f4352f8e6e783bbc6d62f0830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 13 May 2020 12:25:48 +0200 Subject: [PATCH 2/8] Make the tile entity check respect the chunk processor status --- .../java/com/plotsquared/bukkit/listener/PaperListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java index 870747c1a..6c7e4c9eb 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java @@ -257,7 +257,7 @@ public class PaperListener implements Listener { } @EventHandler(priority = EventPriority.HIGHEST) public void onBlockPlace(BlockPlaceEvent event) { - if (!Settings.Paper_Components.TILE_ENTITY_CHECK) { + if (!Settings.Paper_Components.TILE_ENTITY_CHECK || !Settings.Enabled_Components.CHUNK_PROCESSOR) { return; } if (!(event.getBlock().getState(false) instanceof TileState)) { From e6878d780436ba2f0d23a2ffab64e59678cdebf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 13 May 2020 12:47:52 +0200 Subject: [PATCH 3/8] clean up ProcessedWEExtent --- .../core/listener/ProcessedWEExtent.java | 116 +++++------------- 1 file changed, 29 insertions(+), 87 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java b/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java index a67e743c8..5e3f0af8e 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java +++ b/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java @@ -89,95 +89,37 @@ public class ProcessedWEExtent extends AbstractDelegateExtent { @Override public > boolean setBlock(BlockVector3 location, T block) throws WorldEditException { - String id = block.getBlockType().getId(); - switch (id) { - case "54": - case "130": - case "142": - case "27": - case "137": - case "52": - case "154": - case "84": - case "25": - case "144": - case "138": - case "176": - case "177": - case "63": - case "68": - case "323": - case "117": - case "116": - case "28": - case "66": - case "157": - case "61": - case "62": - case "140": - case "146": - case "149": - case "150": - case "158": - case "23": - case "123": - case "124": - case "29": - case "33": - case "151": - case "178": - if (this.BSblocked) { - return false; - } - this.BScount++; - if (this.BScount > Settings.Chunk_Processor.MAX_TILES) { - this.BSblocked = true; - PlotSquared.debug( - Captions.PREFIX + "&cDetected unsafe WorldEdit: " + location.getX() + "," - + location.getZ()); - } - if (WEManager - .maskContains(this.mask, location.getX(), location.getY(), location.getZ())) { - if (this.count++ > this.max) { - if (this.parent != null) { - try { - Field field = - AbstractDelegateExtent.class.getDeclaredField("extent"); - field.setAccessible(true); - field.set(this.parent, new NullExtent()); - } catch (Exception e) { - e.printStackTrace(); - } - this.parent = null; - } - return false; - } - return super.setBlock(location, block); - } - break; - default: - if (WEManager - .maskContains(this.mask, location.getX(), location.getY(), location.getZ())) { - if (this.count++ > this.max) { - if (this.parent != null) { - try { - Field field = - AbstractDelegateExtent.class.getDeclaredField("extent"); - field.setAccessible(true); - field.set(this.parent, new NullExtent()); - } catch (Exception e) { - e.printStackTrace(); - } - this.parent = null; - } - return false; - } - super.setBlock(location, block); - } - return true; + final boolean isTile = block.toBaseBlock().getNbtData() != null; + if (isTile) { + if (this.BSblocked) { + return false; + } + if (++this.BScount > Settings.Chunk_Processor.MAX_TILES) { + this.BSblocked = true; + PlotSquared.debug(Captions.PREFIX + "&cDetected unsafe WorldEdit: " + location.getX() + "," + + location.getZ()); + } } - return false; + if (WEManager.maskContains(this.mask, location.getX(), location.getY(), location.getZ())) { + if (this.count++ > this.max) { + if (this.parent != null) { + try { + Field field = + AbstractDelegateExtent.class.getDeclaredField("extent"); + field.setAccessible(true); + field.set(this.parent, new NullExtent()); + } catch (Exception e) { + e.printStackTrace(); + } + this.parent = null; + } + return false; + } + return super.setBlock(location, block); + } + + return !isTile; } @Override public Entity createEntity(Location location, BaseEntity entity) { From 19fe2efb6e4974dd52c1d4d6760d6ffa0e60d73c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 13 May 2020 14:11:17 +0200 Subject: [PATCH 4/8] Fix the WE extent and add our own tile entity list --- .../plotsquared/bukkit/util/BukkitUtil.java | 31 +++++++++++++++++++ .../com/plotsquared/core/command/Set.java | 3 +- .../core/listener/ProcessedWEExtent.java | 5 +-- .../com/plotsquared/core/util/WorldUtil.java | 4 +++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index 2371fe799..b1ec78382 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -44,7 +44,10 @@ import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BlockCategories; import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; import io.papermc.lib.PaperLib; import lombok.NonNull; import org.bukkit.Bukkit; @@ -95,10 +98,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.function.Consumer; import java.util.function.IntConsumer; +import java.util.stream.Stream; @SuppressWarnings({"unused", "WeakerAccess"}) public class BukkitUtil extends WorldUtil { @@ -638,6 +643,32 @@ public class BukkitUtil extends WorldUtil { return types; } + private final Collection tileEntityTypes = new HashSet<>(); + @Override public Collection getTileEntityTypes() { + if (this.tileEntityTypes.isEmpty()) { + // Categories + tileEntityTypes.addAll(BlockCategories.BANNERS.getAll()); + tileEntityTypes.addAll(BlockCategories.SIGNS.getAll()); + tileEntityTypes.addAll(BlockCategories.BEDS.getAll()); + tileEntityTypes.addAll(BlockCategories.FLOWER_POTS.getAll()); + // Individual Types + // Add these from strings + Stream.of("barrel", "beacon", "beehive", "bell", "blast_furnace", + "brewing_stand", "campfire", "chest", "ender_chest", "trapped_chest", + "command_block", "end_gateway", "hopper", "jigsaw", "jubekox", + "lectern", "note_block", "black_shulker_box", "blue_shulker_box", + "brown_shulker_box", "cyan_shulker_box", "gray_shulker_box", "green_shulker_box", + "light_blue_shulker_box", "light_gray_shulker_box", "lime_shulker_box", + "magenta_shulker_box", "orange_shulker_box", "pink_shulker_box", + "purple_shulker_box", "red_shulker_box", "shulker_box", "white_shulker_box", + "yellow_shulker_box", "smoker", "structure") + .map(BlockTypes::get) + .filter(Objects::nonNull) + .forEach(tileEntityTypes::add); + } + return this.tileEntityTypes; + } + private static void ensureLoaded(final String world, final int x, final int z, final Consumer chunkConsumer) { PaperLib.getChunkAtAsync(getWorld(world), x >> 4, z >> 4, true) diff --git a/Core/src/main/java/com/plotsquared/core/command/Set.java b/Core/src/main/java/com/plotsquared/core/command/Set.java index c6c2b67f3..54befdec9 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Set.java +++ b/Core/src/main/java/com/plotsquared/core/command/Set.java @@ -96,7 +96,8 @@ public class Set extends SubCommand { if (blockType.startsWith("##")) { try { - final BlockCategory category = BlockCategory.REGISTRY.get(blockType.substring(2).toLowerCase(Locale.ENGLISH)); + final BlockCategory category = BlockCategory.REGISTRY.get(blockType.substring(2) + .replaceAll("[*^|]+", "").toLowerCase(Locale.ENGLISH)); if (category == null || !category.contains(BlockTypes.get(forbiddenType))) { continue; } diff --git a/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java b/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java index 5e3f0af8e..ca7eb60e5 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java +++ b/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java @@ -29,6 +29,7 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.util.WEManager; +import com.plotsquared.core.util.WorldUtil; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; @@ -90,12 +91,12 @@ public class ProcessedWEExtent extends AbstractDelegateExtent { public > boolean setBlock(BlockVector3 location, T block) throws WorldEditException { - final boolean isTile = block.toBaseBlock().getNbtData() != null; + final boolean isTile = WorldUtil.IMP.getTileEntityTypes().contains(block.getBlockType()); if (isTile) { if (this.BSblocked) { return false; } - if (++this.BScount > Settings.Chunk_Processor.MAX_TILES) { + if (++this.BScount >= Settings.Chunk_Processor.MAX_TILES) { this.BSblocked = true; PlotSquared.debug(Captions.PREFIX + "&cDetected unsafe WorldEdit: " + location.getX() + "," + location.getZ()); diff --git a/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java b/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java index 9c7730703..940e908eb 100644 --- a/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java @@ -39,6 +39,7 @@ import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.entity.EntityType; import org.jetbrains.annotations.NotNull; @@ -48,6 +49,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.net.URL; +import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -216,4 +218,6 @@ public abstract class WorldUtil { public abstract Set getTypesInCategory(final String category); + public abstract Collection getTileEntityTypes(); + } From ec347f8738323561bf685b8c98341e13d08905ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 13 May 2020 14:24:04 +0200 Subject: [PATCH 5/8] Add missing blocks and block tile entities from `/plot set` if the chunk processor is enabled --- .../java/com/plotsquared/bukkit/util/BukkitUtil.java | 4 ++-- .../main/java/com/plotsquared/core/command/Set.java | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index b1ec78382..96e8ddad1 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -653,7 +653,7 @@ public class BukkitUtil extends WorldUtil { tileEntityTypes.addAll(BlockCategories.FLOWER_POTS.getAll()); // Individual Types // Add these from strings - Stream.of("barrel", "beacon", "beehive", "bell", "blast_furnace", + Stream.of("barrel", "beacon", "beehive", "bee_nest", "bell", "blast_furnace", "brewing_stand", "campfire", "chest", "ender_chest", "trapped_chest", "command_block", "end_gateway", "hopper", "jigsaw", "jubekox", "lectern", "note_block", "black_shulker_box", "blue_shulker_box", @@ -661,7 +661,7 @@ public class BukkitUtil extends WorldUtil { "light_blue_shulker_box", "light_gray_shulker_box", "lime_shulker_box", "magenta_shulker_box", "orange_shulker_box", "pink_shulker_box", "purple_shulker_box", "red_shulker_box", "shulker_box", "white_shulker_box", - "yellow_shulker_box", "smoker", "structure") + "yellow_shulker_box", "smoker", "structure_block", "structure_void") .map(BlockTypes::get) .filter(Objects::nonNull) .forEach(tileEntityTypes::add); diff --git a/Core/src/main/java/com/plotsquared/core/command/Set.java b/Core/src/main/java/com/plotsquared/core/command/Set.java index 54befdec9..3530cc5e4 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Set.java +++ b/Core/src/main/java/com/plotsquared/core/command/Set.java @@ -37,8 +37,10 @@ import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.PatternUtil; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.StringMan; +import com.plotsquared.core.util.WorldUtil; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.world.block.BlockCategory; +import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import java.util.ArrayList; @@ -80,7 +82,13 @@ public class Set extends SubCommand { String material = StringMan.join(Arrays.copyOfRange(args, 1, args.length), ",").trim(); - final List forbiddenTypes = Settings.General.INVALID_BLOCKS; + final List forbiddenTypes = new ArrayList<>(Settings.General.INVALID_BLOCKS); + + if (Settings.Enabled_Components.CHUNK_PROCESSOR) { + forbiddenTypes.addAll(WorldUtil.IMP.getTileEntityTypes().stream().map( + BlockType::getName).collect(Collectors.toList())); + } + if (!Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_ALLOW_UNSAFE) && !forbiddenTypes.isEmpty()) { for (String forbiddenType : forbiddenTypes) { From 8c0f7b207e0a581287e37a8a24bf3c42c5fc82f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 13 May 2020 14:39:58 +0200 Subject: [PATCH 6/8] Make the chunk listener NOT delete all tile entities in the chunk --- .../bukkit/listener/ChunkListener.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java index 2f84732a7..1cfc897d4 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/ChunkListener.java @@ -266,7 +266,7 @@ public class ChunkListener implements Listener { long start = System.currentTimeMillis(); int i = 0; while (System.currentTimeMillis() - start < 250) { - if (i >= tiles.length) { + if (i >= tiles.length - Settings.Chunk_Processor.MAX_TILES) { Bukkit.getScheduler().cancelTask(TaskManager.tasks.get(currentIndex)); TaskManager.tasks.remove(currentIndex); PlotSquared.debug("Successfully processed and unloaded chunk!"); @@ -287,11 +287,16 @@ public class ChunkListener implements Listener { Entity[] entities = chunk.getEntities(); BlockState[] tiles = chunk.getTileEntities(); if (entities.length > Settings.Chunk_Processor.MAX_ENTITIES) { - for (Entity ent : entities) { - if (!(ent instanceof Player)) { - ent.remove(); + int toRemove = entities.length - Settings.Chunk_Processor.MAX_ENTITIES; + int index = 0; + while (toRemove > 0 && index < entities.length) { + final Entity entity = entities[index++]; + if (!(entity instanceof Player)) { + entity.remove(); + toRemove--; } } + PlotSquared.debug( "PlotSquared detected unsafe chunk and processed: " + (chunk.getX() << 4) + "," + ( chunk.getX() << 4)); @@ -304,8 +309,9 @@ public class ChunkListener implements Listener { cleanChunk(chunk); return true; } - for (BlockState tile : tiles) { - tile.getBlock().setType(Material.AIR, false); + + for (int i = 0 ; i < (tiles.length - Settings.Chunk_Processor.MAX_TILES); i++) { + tiles[i].getBlock().setType(Material.AIR, false); } } return false; From e6a9daf31ae366f37dc7ab6fa94e6541b226c96f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 13 May 2020 14:54:54 +0200 Subject: [PATCH 7/8] Make the tile entity limit in ProcessedWEExtent apply per chunk rather than per edit --- .../plotsquared/bukkit/util/BukkitUtil.java | 7 ++++++ .../core/listener/ProcessedWEExtent.java | 23 +++++++++++++------ .../com/plotsquared/core/util/WorldUtil.java | 2 ++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index 96e8ddad1..23fd8937b 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -42,6 +42,7 @@ import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockCategories; @@ -669,6 +670,12 @@ public class BukkitUtil extends WorldUtil { return this.tileEntityTypes; } + @Override + public int getTileEntityCount(String world, BlockVector2 chunk) { + return Bukkit.getWorld(world).getChunkAt(chunk.getBlockX(), chunk.getBlockZ()) + .getTileEntities().length; + } + private static void ensureLoaded(final String world, final int x, final int z, final Consumer chunkConsumer) { PaperLib.getChunkAtAsync(getWorld(world), x >> 4, z >> 4, true) diff --git a/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java b/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java index ca7eb60e5..0df6c3a3c 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java +++ b/Core/src/main/java/com/plotsquared/core/listener/ProcessedWEExtent.java @@ -46,6 +46,8 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; import java.util.Set; public class ProcessedWEExtent extends AbstractDelegateExtent { @@ -53,12 +55,11 @@ public class ProcessedWEExtent extends AbstractDelegateExtent { private final Set mask; private final String world; private final int max; - int BScount = 0; int Ecount = 0; - boolean BSblocked = false; boolean Eblocked = false; private int count; private Extent parent; + private Map tileEntityCount = new HashMap<>(); public ProcessedWEExtent(String world, Set mask, int max, Extent child, Extent parent) { @@ -93,13 +94,15 @@ public class ProcessedWEExtent extends AbstractDelegateExtent { final boolean isTile = WorldUtil.IMP.getTileEntityTypes().contains(block.getBlockType()); if (isTile) { - if (this.BSblocked) { + final Integer[] tileEntityCount = this.tileEntityCount.computeIfAbsent(getChunkKey(location), + key -> new Integer[] {WorldUtil.IMP.getTileEntityCount(world, + BlockVector2.at(location.getBlockX() >> 4, location.getBlockZ() >> 4))}); + if (tileEntityCount[0] >= Settings.Chunk_Processor.MAX_TILES) { return false; - } - if (++this.BScount >= Settings.Chunk_Processor.MAX_TILES) { - this.BSblocked = true; + } else { + tileEntityCount[0]++; PlotSquared.debug(Captions.PREFIX + "&cDetected unsafe WorldEdit: " + location.getX() + "," - + location.getZ()); + + location.getZ()); } } if (WEManager.maskContains(this.mask, location.getX(), location.getY(), location.getZ())) { @@ -145,4 +148,10 @@ public class ProcessedWEExtent extends AbstractDelegateExtent { return WEManager.maskContains(this.mask, position.getX(), position.getZ()) && super .setBiome(position, biome); } + + + private static long getChunkKey(final BlockVector3 location) { + return (long) (location.getBlockX() >> 4) & 4294967295L | ((long) (location.getBlockZ() >> 4) & 4294967295L) << 32; + } + } diff --git a/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java b/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java index 940e908eb..683f59db1 100644 --- a/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/WorldUtil.java @@ -220,4 +220,6 @@ public abstract class WorldUtil { public abstract Collection getTileEntityTypes(); + public abstract int getTileEntityCount(String world, BlockVector2 chunk); + } From 86a996b2ff4bc6a09172b0fa1e2bd1759bac692c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 13 May 2020 15:09:00 +0200 Subject: [PATCH 8/8] Make the tile entity check true by default, as it only applies when the chunk processor is enabled (and it's disabled by default) --- .../main/java/com/plotsquared/core/configuration/Settings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 108bff9de..c99fd0268 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -485,7 +485,7 @@ public class Settings extends Config { @Comment("Cancel entity spawns from tick spawn rates before they happen (performance buff)") public static boolean CREATURE_SPAWN = true; @Comment("Check the tile entity limit on block placement") - public static boolean TILE_ENTITY_CHECK = false; + public static boolean TILE_ENTITY_CHECK = true; }