9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-21 16:09:19 +00:00
Files
Leaf/patches/server/0117-Paper-PR-Throttle-failed-spawn-attempts.patch
Kobe ⑧ 848fb2dc4d Smart sorting & Remove streams & Throttle hopper (#157)
* =-=

* Reuse comparator

* Cleanup DAB patch
2024-11-10 09:25:58 -05:00

141 lines
8.9 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: froobynooby <froobynooby@froobworld.com>
Date: Wed, 17 Jul 2024 18:46:11 +0930
Subject: [PATCH] Paper PR: Throttle failed spawn attempts
Original license: GPLv3
Original project: https://github.com/PaperMC/Paper
Paper pull request: https://github.com/PaperMC/Paper/pull/11099
For example config in paper-world-defaults.yml
```
spawning-throttle:
failed-attempts-threshold: 1200
throttled-ticks-per-spawn:
ambient: 10 # default value in bukkit.yml tickers-per * 10
axolotls: 10
creature: 4000
monster: 10
underground_water_creature: 10
water_ambient: 10
water_creature: 10
```
This patch adds the option to use longer ticks-per-spawn for a given
mob type in chunks where spawn attempts are consecutively failing.
This behaviour is particularly useful on servers where players build
mob farms. Mob farm designs often require making surrounding chunks
spawnproof, which causes the server to waste CPU cycles trying to spawn mobs in
vain. Throttling spawn attempts in suspected spawnproof chunks improves
performance without noticeably advantaging or disadvantaging the mob farm.
diff --git a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
index c867796f625813797f167610ad443c4be5a7561e..04d13abd8d98f4e72732afbdbb9719d835389793 100644
--- a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
+++ b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
@@ -190,6 +190,15 @@ public class WorldConfiguration extends ConfigurationPart {
@MergeMap
public Reference2IntMap<MobCategory> ticksPerSpawn = Util.make(new Reference2IntOpenHashMap<>(NaturalSpawner.SPAWNING_CATEGORIES.length), map -> Arrays.stream(NaturalSpawner.SPAWNING_CATEGORIES).forEach(mobCategory -> map.put(mobCategory, -1)));
+ public SpawningThrottle spawningThrottle;
+
+ public class SpawningThrottle extends ConfigurationPart {
+ public IntOr.Disabled failedAttemptsThreshold = IntOr.Disabled.DISABLED;
+
+ @MergeMap
+ public Reference2IntMap<MobCategory> throttledTicksPerSpawn = Util.make(new Reference2IntOpenHashMap<>(NaturalSpawner.SPAWNING_CATEGORIES.length), map -> Arrays.stream(NaturalSpawner.SPAWNING_CATEGORIES).forEach(mobCategory -> map.put(mobCategory, -1)));
+ }
+
@ConfigSerializable
public record DespawnRangePair(@Required DespawnRange hard, @Required DespawnRange soft) {
public static DespawnRangePair createDefault() {
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
index 95a000dbf1a05cfd8182f15c0e0bbf7023578974..455c7e66fc1ff28c4f720a01ff11aa408446b42e 100644
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
@@ -138,8 +138,14 @@ public final class NaturalSpawner {
boolean spawnThisTick = true;
int limit = enumcreaturetype.getMaxInstancesPerChunk();
SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(enumcreaturetype);
+ // Paper start - throttle failed spawn attempts
+ long ticksPerSpawn = world.ticksPerSpawnCategory.getLong(spawnCategory);
+ if (world.paperConfig().entities.spawning.spawningThrottle.failedAttemptsThreshold.test(threshold -> chunk.failedSpawnAttempts[enumcreaturetype.ordinal()] > threshold)) {
+ ticksPerSpawn = Math.max(ticksPerSpawn, world.paperConfig().entities.spawning.spawningThrottle.throttledTicksPerSpawn.getOrDefault(enumcreaturetype, -1));
+ }
+ // Paper end - throttle failed spawn attempts
if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
- spawnThisTick = world.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % world.ticksPerSpawnCategory.getLong(spawnCategory) == 0;
+ spawnThisTick = world.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % ticksPerSpawn == 0; // Paper - throttle failed spawn attempts
limit = world.getWorld().getSpawnLimit(spawnCategory);
}
@@ -172,8 +178,13 @@ public final class NaturalSpawner {
Objects.requireNonNull(info);
// Paper start - Optional per player mob spawns
- NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn,
- difference, world.paperConfig().entities.spawning.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null);
+ // Paper start - throttle failed spawn attempts
+ if (NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn, difference, world.paperConfig().entities.spawning.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null) == 0) {
+ chunk.failedSpawnAttempts[enumcreaturetype.ordinal()]++;
+ } else {
+ chunk.failedSpawnAttempts[enumcreaturetype.ordinal()] = 0;
+ }
+ // Paper end - throttle failed spawn attempts
// Paper end - Optional per player mob spawns
}
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
index 5bb8fe022f580a626a99324f53515890a99b798d..5cee82d3d17739858e47f24ec5340233f09d0713 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -84,6 +84,7 @@ public abstract class ChunkAccess implements BlockGetter, BiomeManager.NoiseBiom
public final Map<BlockPos, BlockEntity> blockEntities = new Object2ObjectOpenHashMap();
protected final LevelHeightAccessor levelHeightAccessor;
protected final LevelChunkSection[] sections;
+ public final long[] failedSpawnAttempts = new long[net.minecraft.world.entity.MobCategory.values().length]; // Paper - throttle failed spawn attempts
// Leaf start - Matter - Feature Secure Seed
private boolean slimeChunk;
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
index 4bd048387651250135f963303c78c17f8473cfee..8257177404b23e131143017f3a7d835ad447f9fb 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
@@ -302,6 +302,16 @@ public class ChunkSerializer {
((ChunkAccess) object1).addPackedPostProcess(nbttaglist2.getShort(i1), j1);
}
}
+ // Paper start - throttle failed spawn attempts
+ if (nbt.contains("Paper.FailedSpawnAttempts", Tag.TAG_COMPOUND)) {
+ CompoundTag failedSpawnAttemptsTag = nbt.getCompound("Paper.FailedSpawnAttempts");
+ for (net.minecraft.world.entity.MobCategory mobCategory : net.minecraft.world.level.NaturalSpawner.SPAWNING_CATEGORIES) {
+ if (failedSpawnAttemptsTag.contains(mobCategory.getSerializedName(), Tag.TAG_LONG)) {
+ ((ChunkAccess) object1).failedSpawnAttempts[mobCategory.ordinal()] = failedSpawnAttemptsTag.getLong(mobCategory.getSerializedName());
+ }
+ }
+ }
+ // Paper end - throttle failed spawn attempts
ca.spottedleaf.moonrise.patches.starlight.util.SaveUtil.loadLightHook(world, chunkPos, nbt, (ChunkAccess)object1); // Paper - rewrite chunk system - note: it's ok to pass the raw value instead of wrapped
@@ -545,6 +555,18 @@ public class ChunkSerializer {
nbttagcompound.put("ChunkBukkitValues", chunk.persistentDataContainer.toTagCompound());
}
// CraftBukkit end
+ // Paper start - throttle failed spawn attempts
+ CompoundTag failedSpawnAttemptsTag = new CompoundTag();
+ for (net.minecraft.world.entity.MobCategory mobCategory : net.minecraft.world.entity.MobCategory.values()) {
+ long failedSpawnAttempts = chunk.failedSpawnAttempts[mobCategory.ordinal()];
+ if (failedSpawnAttempts > 0) {
+ failedSpawnAttemptsTag.putLong(mobCategory.getSerializedName(), failedSpawnAttempts);
+ }
+ }
+ if (!failedSpawnAttemptsTag.isEmpty()) {
+ nbttagcompound.put("Paper.FailedSpawnAttempts", failedSpawnAttemptsTag);
+ }
+ // Paper end - throttle failed spawn attempts
ca.spottedleaf.moonrise.patches.starlight.util.SaveUtil.saveLightHook(world, chunk, nbttagcompound); // Paper - rewrite chunk system
return nbttagcompound;
}