From bd9ace578b65e71b4f72a2cb9f7fb0dcebf4682f Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 13 Jan 2021 16:04:51 -0800 Subject: [PATCH] Add a config option to limit the number of entities of each type to load/save in a chunk (#4792) --- ...649-Entity-load-save-limit-per-chunk.patch | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 Spigot-Server-Patches/0649-Entity-load-save-limit-per-chunk.patch diff --git a/Spigot-Server-Patches/0649-Entity-load-save-limit-per-chunk.patch b/Spigot-Server-Patches/0649-Entity-load-save-limit-per-chunk.patch new file mode 100644 index 000000000..63edb0445 --- /dev/null +++ b/Spigot-Server-Patches/0649-Entity-load-save-limit-per-chunk.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: jmp +Date: Wed, 18 Nov 2020 20:52:25 -0800 +Subject: [PATCH] Entity load/save limit per chunk + +Adds a config option to limit the number of entities saved and loaded +to a chunk. The default values of -1 disable the limit. Although +defaults are only included for certain entites, this allows setting +limits for any entity type. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c5495e02c3fe271b26f62ea2ec64e07957edf37e..234d2daecc5d0bf6a99c0a5f4a87f947a15029d9 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -11,6 +11,7 @@ import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.Engin + import net.minecraft.server.EntityVindicator; + import net.minecraft.server.EntityZombie; + import net.minecraft.server.EnumDifficulty; ++import net.minecraft.server.EntityTypes; + import org.bukkit.Bukkit; + import org.bukkit.Material; + import org.bukkit.configuration.ConfigurationSection; +@@ -761,4 +762,18 @@ public class PaperWorldConfig { + EnumDifficulty.class + ); + } ++ ++ public Map, Integer> entityPerChunkSaveLimits = new HashMap<>(); ++ private void entityPerChunkSaveLimits() { ++ getInt("entity-per-chunk-save-limit.experience_orb", -1); ++ getInt("entity-per-chunk-save-limit.snowball", -1); ++ getInt("entity-per-chunk-save-limit.ender_pearl", -1); ++ getInt("entity-per-chunk-save-limit.arrow", -1); ++ EntityTypes.getEntityNameList().forEach(name -> { ++ final EntityTypes type = EntityTypes.getByName(name.getKey()).orElseThrow(() -> new IllegalStateException("Unknown Entity Type: " + name.toString())); ++ final String path = ".entity-per-chunk-save-limit." + name.getKey(); ++ final int value = config.getInt("world-settings." + worldName + path, config.getInt("world-settings.default" + path, -1)); // get without setting defaults ++ if (value != -1) entityPerChunkSaveLimits.put(type, value); ++ }); ++ } + } +diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +index 8e7da2c5f3852920ec5fbcdd2bff4d299e6aa499..060ef42bc8f22688071fa375bd4dbab8dd2c1e9e 100644 +--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java ++++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java +@@ -495,11 +495,22 @@ public class ChunkRegionLoader { + + chunk.d(false); + ++ // Paper start ++ final Map, Integer> savedEntityCounts = Maps.newHashMap(); + for (int j = 0; j < chunk.getEntitySlices().length; ++j) { + Iterator iterator1 = chunk.getEntitySlices()[j].iterator(); + + while (iterator1.hasNext()) { + Entity entity = (Entity) iterator1.next(); ++ final EntityTypes entityType = entity.getEntityType(); ++ final int saveLimit = worldserver.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ continue; ++ } ++ savedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end + NBTTagCompound nbttagcompound4 = new NBTTagCompound(); + // Paper start + if (asyncsavedata == null && !entity.dead && (int) Math.floor(entity.locX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.locZ()) >> 4 != chunk.getPos().z) { +@@ -630,10 +641,21 @@ public class ChunkRegionLoader { + NBTTagList nbttaglist = nbttagcompound.getList("Entities", 10); + World world = chunk.getWorld(); + ++ // Paper start ++ final Map, Integer> loadedEntityCounts = Maps.newHashMap(); + for (int i = 0; i < nbttaglist.size(); ++i) { + NBTTagCompound nbttagcompound1 = nbttaglist.getCompound(i); + + EntityTypes.a(nbttagcompound1, world, (entity) -> { ++ final EntityTypes entityType = entity.getEntityType(); ++ final int saveLimit = world.paperConfig.entityPerChunkSaveLimits.getOrDefault(entityType, -1); ++ if (saveLimit > -1) { ++ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) { ++ return entity; ++ } ++ loadedEntityCounts.merge(entityType, 1, Integer::sum); ++ } ++ // Paper end + chunk.a(entity); + return entity; + });