From 41f9dc9bb456883704e43cac171bc45c1f2fa637 Mon Sep 17 00:00:00 2001 From: jmp Date: Wed, 18 Nov 2020 20:52:25 -0800 Subject: [PATCH] PaperPR - Projectile load/save limit per chunk Adds a config option to limit the number of projectiles saved and loaded to a chunk. Limits are counted per entity type, i.e. a limit of 5 means that 5 arrows, 5 snowballs, 5 tridents, etc. will be allowed to be saved/loaded per chunk. The default value of -1 disables the limit. diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index ae5ed3bd0b663092a4658b24cbd69d37b4e141cb..2452f54d96cab2d93140c64e25d9b799cbc94caa 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -709,4 +709,9 @@ public class PaperWorldConfig { private void fixCuringExploit() { fixCuringZombieVillagerDiscountExploit = getBoolean("game-mechanics.fix-curing-zombie-villager-discount-exploit", fixCuringZombieVillagerDiscountExploit); } + + public int projectileSaveLimit = -1; + private void projectileSaveLimit() { + projectileSaveLimit = getInt("projectile-load-save-per-chunk-limit", projectileSaveLimit); + } } diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java index 64dd95292fb4d058f6200bfcadaedfbd62b2461d..3628b04fc4f4f4663b3780eadac6ff9e430e4900 100644 --- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java +++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java @@ -525,11 +525,21 @@ public class ChunkRegionLoader { chunk.d(false); + // Paper start + final Map, Integer> savedProjectileCounts = 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(); + if (worldserver.paperConfig.projectileSaveLimit > -1 && (entity instanceof IProjectile || entity instanceof EntityEnderSignal)) { + final EntityTypes projectileType = entity.getEntityType(); + if (savedProjectileCounts.getOrDefault(projectileType, 0) >= worldserver.paperConfig.projectileSaveLimit) { + continue; + } + savedProjectileCounts.merge(projectileType, 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) { @@ -660,10 +670,20 @@ public class ChunkRegionLoader { NBTTagList nbttaglist = nbttagcompound.getList("Entities", 10); World world = chunk.getWorld(); + // Paper start + final Map, Integer> loadedProjectileCounts = Maps.newHashMap(); for (int i = 0; i < nbttaglist.size(); ++i) { NBTTagCompound nbttagcompound1 = nbttaglist.getCompound(i); EntityTypes.a(nbttagcompound1, world, (entity) -> { + if (world.paperConfig.projectileSaveLimit > -1 && (entity instanceof IProjectile || entity instanceof EntityEnderSignal)) { + final EntityTypes projectileType = entity.getEntityType(); + if (loadedProjectileCounts.getOrDefault(projectileType, 0) >= world.paperConfig.projectileSaveLimit) { + return entity; + } + loadedProjectileCounts.merge(projectileType, 1, Integer::sum); + } + // Paper end chunk.a(entity); return entity; });