Paper/Spigot-Server-Patches/0649-Entity-load-save-limit-per-chunk.patch
Riley Park 4e958e229f
We're going on an Adventure! (#4842)
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
Co-authored-by: zml <zml@stellardrift.ca>
Co-authored-by: Mariell Hoversholm <proximyst@proximyst.com>
2021-02-21 20:45:33 +01:00

91 lines
4.8 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: jmp <jasonpenilla2@me.com>
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<EntityTypes<?>, 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..f51bf71c8d6eef3c054ac64765709794fcfad5ee 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<EntityTypes<?>, 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<EntityTypes<?>, 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 null;
+ }
+ loadedEntityCounts.merge(entityType, 1, Integer::sum);
+ }
+ // Paper end
chunk.a(entity);
return entity;
});