9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-29 03:49:21 +00:00
Files
Leaf/leaf-server/minecraft-patches/features/0220-Paper-PR-Throttle-failed-spawn-attempts.patch
Dreeam 66887e3367 Update Leaf 1.21.6 (#385)
* Init 1.21.6

* Finish API patches

* Apply purpur patches & all paper server patches

* Apply some

* Apply all

* Updated Upstream (Paper/Purpur)

Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@6aafe29e 1.21.6 dev
PaperMC/Paper@ae7c74ec tweak mob goal keys, generate missing api
PaperMC/Paper@9ea1460b Revert "fix sponge-absorb deleting chest content (#12647)"

Purpur Changes:
PurpurMC/Purpur@eb0ba67d Updated Upstream (Paper)
PurpurMC/Purpur@7c6502dc Updated Upstream (Paper)
PurpurMC/Purpur@aa289e2c Updated Upstream (Paper)
PurpurMC/Purpur@b1d412fb Updated Upstream (Paper)
PurpurMC/Purpur@293e28a0 use empty registryaccess where context is not needed, closes #1676
PurpurMC/Purpur@452bb319 port PaperMC/Paper#12654, closes #1665
PurpurMC/Purpur@849bc79c register test subcommands used for debugging, closes #1675

* Fix build & diff

* Update vanilla attribute size

* [ci/skip] Forget to remove this

* Updated Upstream (Paper/Purpur)

Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@a24f9b20 1.21.6 dev
PaperMC/Paper@457a0a69 Bump version string and protocol version to 1.21.6 release
PaperMC/Paper@245b5473 Update base to 1.21.6
PaperMC/Paper@b28d77b3 Update Moonrise to 1.21.6
PaperMC/Paper@8318dcb7 Update DataConverter to 1.21.6-rc1

Purpur Changes:
PurpurMC/Purpur@b228e316 Updated Upstream (Paper)
PurpurMC/Purpur@d6562a57 make happy ghast takes-damage-from-water and always-drop-exp options work
PurpurMC/Purpur@08d989b6 inline import
PurpurMC/Purpur@61d7f559 Updated Upstream (Paper)
PurpurMC/Purpur@469a4de5 Merge branch 'ver/1.21.5' into ver/1.21.6

* Updated Upstream (Paper)

Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@d2b1158e Set correct world access on BSL snapshots

* Updated Upstream (Paper)

Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@023e6c29 Ensure waypoints are per world
PaperMC/Paper@40d5d31c Fix recursively converting JSON Text Components

* Update spigot mapping to remap reobf mapping to mojamp for plugins

* Updated Upstream (Paper/Purpur)

Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@1fcc4162 Implement FeatureHooks#isChunkSent for Moonrise chunk system
PaperMC/Paper@e4d7178a Implement WaypointTransmitter#isChunkVisible
PaperMC/Paper@8980ead7 Directly walk text component after converting from JSON
PaperMC/Paper@5613ed6d Provide env environment variable and copy spigots sys prop for overriding default repository
PaperMC/Paper@62b7f86d Avoid and discourage use of Maven Central as a CDN (#12689)
PaperMC/Paper@f5534cb7 [ci/skip] Run generators (#12691)
PaperMC/Paper@4781d28b Re-add Log4j Javadocs (#12693)
PaperMC/Paper@74fbcce5 Check type of Material in get/set stats (#12607)
PaperMC/Paper@4b3f967e Improve Fix MC-44654 (#12703)
PaperMC/Paper@a7dd2635 Enable spigot obfuscation support (#12695)
PaperMC/Paper@6a51c44e Cleanup Primed TNT Fix (#12704)
PaperMC/Paper@839c6a18 Fix #11169 (#12706)
PaperMC/Paper@c77d5f99 Fix MC-297591
PaperMC/Paper@219f86ee Implement chunk unload delay config option
PaperMC/Paper@e4eb69b8 Do not allow ticket level decreases to be processed asynchronously
PaperMC/Paper@71b0c768 Adds support for vanilla negative explosions (#12705)
PaperMC/Paper@3750927a [ci/skip] Fix PermissionManager#clearPermissions() docs bad wording (#12657)
PaperMC/Paper@d61a51e8 Add ItemType#getBurnDuration() (#12604)
PaperMC/Paper@29fc8532 Allow empty paths in namespaced keys (#12687)
PaperMC/Paper@4419afb9 fix: Safely handle nanosecond overflow in ClickCallback (#12686)
PaperMC/Paper@56528821 Add `isProxyEnabled` method to ServerConfiguration (#12664)
PaperMC/Paper@c0dda0ea Add `isForceDefaultGameMode` method (#12673)
PaperMC/Paper@e714de63 Fix excess slot updates
PaperMC/Paper@6d0821d2 [ci/skip] Fix docs for Spawner class and cleanup (#12710)
PaperMC/Paper@cceffe3d Release ItemType and BlockType (#12708)
PaperMC/Paper@186e9e33 Relocate CommandMap#registerServerAliases() call to after lifecycle events have been run (#12601)
PaperMC/Paper@5edcf6dd Cleanup/command dispatching (#12713)

Purpur Changes:
PurpurMC/Purpur@baa196f5 Updated Upstream (Paper)
PurpurMC/Purpur@fdd1e980 Updated Upstream (Paper)
PurpurMC/Purpur@439f15db Updated Upstream (Paper)
PurpurMC/Purpur@46a28b93 [ci/skip] update version in README
PurpurMC/Purpur@162bd288 Updated Upstream (Paper)
PurpurMC/Purpur@afcdf9bb Updated Upstream (Paper)

* fix random tick order

Signed-off-by: hayanesuru <hayanesuru@outlook.jp>

* update optimize random tick

* fix mob spawning over limit

* optimize mob spawning

* fix FastBitRadixSort memory leak

* optimize brain collections

* [ci/skip] update comments

* Revert "fix FastBitRadixSort memory leak"

This reverts commit bdea683525.

* optimize brain collections

* fix async mob spawning data race

* [ci/skip] cleanup

* remove hash lookup in optimize random tick

* Updated Upstream (Paper/Purpur)

Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@803baf0b Support hidden entities in Waypoints (#12715)
PaperMC/Paper@1814d8b4 build: publish to fill (#12717)
PaperMC/Paper@e454fef4 Add support for private constructors in plugin main classes (#12652)
PaperMC/Paper@d0e808f4 Move player to correct position in vehicle move packet handler
PaperMC/Paper@46b4b0b8 Improve keepalive ping system
PaperMC/Paper@38c1ddb5 Add and use FeatureHooks.getAllEntities
PaperMC/Paper@2f083acb Ensure player entity schedulers are ticked when they are dead
PaperMC/Paper@7c90c7c4 Optimise EntityScheduler ticking
PaperMC/Paper@aa6ee44a Re-add global region scheduler tick erroneously removed in last commit
PaperMC/Paper@d7510efc Fix #12722 (#12726)
PaperMC/Paper@0caf75f8 Fix #12721 (#12725)
PaperMC/Paper@bee28792 Adventure 4.23.0 (#12690)
PaperMC/Paper@692e93a9 Fix MC-299110
PaperMC/Paper@ea10fa4a Don't mutate the position of Items for MC-4 Fix (#12702)
PaperMC/Paper@aa6cd74c Remove unnecesary item check for ServerboundPlayerActionPacket RELEASE_USE_ITEM (#12668)
PaperMC/Paper@c9e89f49 Expose arrow velocity in EntityShootBowEvent for mobs (#12688)
PaperMC/Paper@7ec3174a Jump out of experimental phase
PaperMC/Paper@4e1a2555 Update try catch for command handling
PaperMC/Paper@e382e687 Fix 0 yield on explosion events
PaperMC/Paper@35b2c6ec Use dropped item for stats info (#12747)
PaperMC/Paper@bd79e20c [ci/skip] PluginManager#getPlugin and PluginManager#isPluginEnabled are case-insensitive (#12723)

Purpur Changes:
PurpurMC/Purpur@4a5974cf Updated Upstream (Paper)
PurpurMC/Purpur@3893bba0 this is important...
PurpurMC/Purpur@47e758fb Updated Upstream (Paper)

* Update PWT patch

* cleanup

* fix playermobcaps command

* fix Didn't fill chunk buffer in async chunk sending

* cleanup

* fix HurtByTargetGoal npe

* optimize collectSpawningChunks (#382)

* optimize collectSpawningChunks

* add bit set

* cleanup

* cleanup

* cleanup

* cleanup

* Updated Upstream (Paper/Purpur)

Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@57c202e0 Allow adventure nbt codec to parse all tags

Purpur Changes:
PurpurMC/Purpur@a4776d7b Updated Upstream (Paper)
PurpurMC/Purpur@dfd8a7ad Fix phantom going at high speed when ridden (#1680)

* Fix diff

---------

Signed-off-by: hayanesuru <hayanesuru@outlook.jp>
Co-authored-by: hayanesuru <hayanesuru@outlook.jp>
2025-06-30 05:17:33 +08:00

322 lines
18 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/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 345d4b80bd4383e0fb66d744d87bc8ef4100fd32..a2da4fce50f31d56036d04041c4f80ed90c18b27 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -158,10 +158,21 @@ public final class NaturalSpawner {
// Copied from getFilteredSpawningCategories
int limit = mobCategory.getMaxInstancesPerChunk();
org.bukkit.entity.SpawnCategory spawnCategory = org.bukkit.craftbukkit.util.CraftSpawnCategory.toBukkit(mobCategory);
+ // Paper start - throttle failed spawn attempts
+ boolean spawnThisTick = true;
+ long ticksPerSpawn = level.ticksPerSpawnCategory.getLong(spawnCategory);
+ long ticksPerSpawnTmp = ticksPerSpawn;
+ io.papermc.paper.configuration.WorldConfiguration.Entities.Spawning.SpawningThrottle spawningThrottle = level.paperConfig().entities.spawning.spawningThrottle;
+ if (spawningThrottle.failedAttemptsThreshold.test(threshold -> chunk.failedSpawnAttempts[mobCategory.ordinal()] > threshold)) {
+ ticksPerSpawn = Math.max(ticksPerSpawn, spawningThrottle.throttledTicksPerSpawn.getOrDefault(mobCategory, -1));
+ }
+ // Paper end - throttle failed spawn attempts
if (org.bukkit.craftbukkit.util.CraftSpawnCategory.isValidForLimits(spawnCategory)) {
+ spawnThisTick = ticksPerSpawnTmp != 0 && level.getGameTime() % ticksPerSpawn == 0; // Paper - throttle failed spawn attempts
limit = level.getWorld().getSpawnLimit(spawnCategory);
}
+ if (!spawningThrottle.failedAttemptsThreshold.enabled() || spawnThisTick) { // Paper - throttle failed spawn attempts
// Apply per-player limit
int minDiff = Integer.MAX_VALUE;
final ca.spottedleaf.moonrise.common.list.ReferenceList<net.minecraft.server.level.ServerPlayer> inRange =
@@ -175,12 +186,20 @@ public final class NaturalSpawner {
maxSpawns = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
canSpawn = maxSpawns > 0;
+ } else { canSpawn = false; } // Paper - throttle failed spawn attempts
} else {
canSpawn = spawnState.canSpawnForCategoryLocal(mobCategory, chunk.getPos());
}
if (canSpawn) {
- spawnCategoryForChunk(mobCategory, level, chunk, spawnState::canSpawn, spawnState::afterSpawn,
- maxSpawns, level.paperConfig().entities.spawning.perPlayerMobSpawns ? level.getChunkSource().chunkMap::updatePlayerMobTypeMap : null);
+ // Paper start - throttle failed spawn attempts
+ int spawnCount = spawnCategoryForChunk(mobCategory, level, chunk, spawnState::canSpawn, spawnState::afterSpawn,
+ maxSpawns, level.paperConfig().entities.spawning.perPlayerMobSpawns ? level.getChunkSource().chunkMap::updatePlayerMobTypeMap : null, false);
+ if (spawnCount == 0) {
+ chunk.failedSpawnAttempts[mobCategory.ordinal()]++;
+ } else {
+ chunk.failedSpawnAttempts[mobCategory.ordinal()] = 0;
+ }
+ // Paper end - throttle failed spawn attempts
// Paper end - Optional per player mob spawns
}
}
@@ -204,12 +223,21 @@ public final class NaturalSpawner {
}
public static void spawnCategoryForChunk(
MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final Consumer<Entity> trackEntity
+ // Paper start - throttle failed spawn attempts
+ ) {
+ spawnCategoryForChunk(category, level, chunk, filter, callback, maxSpawns, trackEntity, false);
+ }
+ public static int spawnCategoryForChunk(
+ MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final Consumer<Entity> trackEntity, final boolean nothing
+ // Paper end - throttle failed spawn attempts
) {
// Paper end - Optional per player mob spawns
BlockPos randomPosWithin = getRandomPosWithin(level, chunk);
if (randomPosWithin.getY() >= level.getMinY() + 1) {
- spawnCategoryForPosition(category, level, chunk, randomPosWithin, filter, callback, maxSpawns, trackEntity); // Paper - Optional per player mob spawns
+ return spawnCategoryForPosition(category, level, chunk, randomPosWithin, filter, callback, maxSpawns, trackEntity, false); // Paper - Optional per player mob spawns // Paper - throttle failed spawn attempts
}
+
+ return 0; // Paper - throttle failed spawn attempts
}
@VisibleForDebug
@@ -229,15 +257,23 @@ public final class NaturalSpawner {
}
public static void spawnCategoryForPosition(
MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final @Nullable Consumer<Entity> trackEntity
+ // Paper start - throttle failed spawn attempts
+ ) {
+ spawnCategoryForPosition(category, level, chunk, pos, filter, callback, maxSpawns, trackEntity, false);
+ }
+ public static int spawnCategoryForPosition(
+ MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final @Nullable Consumer<Entity> trackEntity, final boolean nothing
+ // Paper end - throttle failed spawn attempts
) {
// Paper end - Optional per player mob spawns
StructureManager structureManager = level.structureManager();
ChunkGenerator generator = level.getChunkSource().getGenerator();
int y = pos.getY();
+ int i = 0; // Paper - throttle failed spawn attempts
BlockState blockState = level.getBlockStateIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn
if (blockState != null && !blockState.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
- int i = 0;
+ //int i = 0; // Paper - throttle failed spawn attempts - move up
for (int i1 = 0; i1 < 3; i1++) {
int x = pos.getX();
@@ -278,14 +314,14 @@ public final class NaturalSpawner {
}
// Paper end - per player mob count backoff
if (doSpawning == PreSpawnStatus.ABORT) {
- return;
+ return i; // Paper - throttle failed spawn attempts
}
if (doSpawning == PreSpawnStatus.SUCCESS
// Paper end - PreCreatureSpawnEvent
&& filter.test(spawnerData.type(), mutableBlockPos, chunk)) {
Mob mobForSpawn = getMobForSpawn(level, spawnerData.type());
if (mobForSpawn == null) {
- return;
+ return i; // Paper - throttle failed spawn attempts
}
mobForSpawn.snapTo(d, y, d1, level.random.nextFloat() * 360.0F, 0.0F);
@@ -308,7 +344,7 @@ public final class NaturalSpawner {
}
// CraftBukkit end
if (i >= mobForSpawn.getMaxSpawnClusterSize() || i >= maxSpawns) { // Paper - Optional per player mob spawns
- return;
+ return i; // Paper - throttle failed spawn attempts
}
if (mobForSpawn.isMaxGroupSizeReached(i3)) {
@@ -321,6 +357,8 @@ public final class NaturalSpawner {
}
}
}
+
+ return i; // Paper - throttle failed spawn attempts
}
private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel level, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double distance) {
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
index 686c031ec73acc80683aaa39a78fe9221f0215a6..d7dbe7d24a6697be6b5db729f940b16b74838d11 100644
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -92,6 +92,7 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
private boolean slimeChunk;
private boolean hasComputedSlimeChunk;
// Leaf end - Matter - Secure Seed
+ public final long[] failedSpawnAttempts = new long[net.minecraft.world.entity.MobCategory.values().length]; // Paper - throttle failed spawn attempts
// Paper start - rewrite chunk system
private volatile ca.spottedleaf.moonrise.patches.starlight.light.SWMRNibbleArray[] blockNibbles;
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index e04d3479383cd480cf35ed7ac3c82e7f6fb69e28..ab1fc7ca0639f9e71933f623258bb8d123988262 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -94,6 +94,7 @@ public record SerializableChunkData(
List<CompoundTag> blockEntities,
CompoundTag structureData
, @Nullable net.minecraft.nbt.Tag persistentDataContainer // CraftBukkit - persistentDataContainer
+ , @Nullable long[] failedSpawnAttempts // Paper - throttle failed spawn attempts
) {
public static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(
Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), null // Paper - Anti-Xray
@@ -190,6 +191,19 @@ public record SerializableChunkData(
lists[i] = list2;
}
+ // Paper start - throttle failed spawn attempts
+ long[] failedSpawnAttemptsData = null;
+ if (tag.contains("Paper.FailedSpawnAttempts")) {
+ failedSpawnAttemptsData = new long[net.minecraft.world.entity.MobCategory.values().length];
+ CompoundTag failedSpawnAttemptsTag = tag.getCompoundOrEmpty("Paper.FailedSpawnAttempts");
+ for (net.minecraft.world.entity.MobCategory mobCategory : net.minecraft.world.level.NaturalSpawner.SPAWNING_CATEGORIES) {
+ if (failedSpawnAttemptsTag.contains(mobCategory.getSerializedName())) {
+ failedSpawnAttemptsData[mobCategory.ordinal()] = failedSpawnAttemptsTag.getLongOr(mobCategory.getSerializedName(), 0);
+ }
+ }
+ }
+ // Paper end - throttle failed spawn attempts
+
List<CompoundTag> list3 = tag.getList("entities").stream().flatMap(ListTag::compoundStream).toList();
List<CompoundTag> list4 = tag.getList("block_entities").stream().flatMap(ListTag::compoundStream).toList();
CompoundTag compoundOrEmpty = tag.getCompoundOrEmpty("structures");
@@ -270,6 +284,7 @@ public record SerializableChunkData(
list4,
compoundOrEmpty
, tag.get("ChunkBukkitValues") // CraftBukkit - ChunkBukkitValues
+ , failedSpawnAttemptsData // Paper - throttle failed spawn attempts
);
}
}
@@ -426,6 +441,15 @@ public record SerializableChunkData(
chunkAccess.addPackedPostProcess(this.postProcessingSections[i], i);
}
+ // Paper start - throttle failed spawn attempts
+ long[] failedSpawnAttemptsData = this.failedSpawnAttempts;
+ if (failedSpawnAttemptsData != null) {
+ for (net.minecraft.world.entity.MobCategory mobCategory : net.minecraft.world.entity.MobCategory.values()) {
+ System.arraycopy(failedSpawnAttemptsData, 0, chunkAccess.failedSpawnAttempts, 0, failedSpawnAttemptsData.length);
+ }
+ }
+ // Paper end - throttle failed spawn attempts
+
if (chunkType == ChunkType.LEVELCHUNK) {
return this.loadStarlightLightData(level, new ImposterProtoChunk((LevelChunk)chunkAccess, false)); // Paper - starlight
} else {
@@ -556,6 +580,7 @@ public record SerializableChunkData(
persistentDataContainer = chunk.persistentDataContainer.toTagCompound();
}
// CraftBukkit end
+ final long[] failedSpawnAttemptsData = chunk.failedSpawnAttempts; // Paper - throttle failed spawn attempts
return new SerializableChunkData(
level.registryAccess().lookupOrThrow(Registries.BIOME),
pos,
@@ -576,6 +601,7 @@ public record SerializableChunkData(
list1,
compoundTag
, persistentDataContainer // CraftBukkit - persistentDataContainer
+ , failedSpawnAttemptsData // Paper - throttle failed spawn attempts
);
}
}
@@ -660,6 +686,21 @@ public record SerializableChunkData(
compoundTag.put("ChunkBukkitValues", this.persistentDataContainer);
}
// CraftBukkit end
+ // Paper start - throttle failed spawn attempts
+ CompoundTag failedSpawnAttemptsTag = new CompoundTag();
+ long[] failedSpawnAttemptsData = this.failedSpawnAttempts;
+ if (failedSpawnAttemptsData != null) {
+ for (net.minecraft.world.entity.MobCategory mobCategory : net.minecraft.world.entity.MobCategory.values()) {
+ long failedAttempts = failedSpawnAttemptsData[mobCategory.ordinal()];
+ if (failedAttempts > 0) {
+ failedSpawnAttemptsTag.putLong(mobCategory.getSerializedName(), failedAttempts);
+ }
+ }
+ }
+ if (!failedSpawnAttemptsTag.isEmpty()) {
+ compoundTag.put("Paper.FailedSpawnAttempts", failedSpawnAttemptsTag);
+ }
+ // Paper end - throttle failed spawn attempts
// Paper start - starlight
if (this.lightCorrect && !this.chunkStatus.isBefore(net.minecraft.world.level.chunk.status.ChunkStatus.LIGHT)) {
// clobber vanilla value to force vanilla to relight
@@ -875,4 +916,50 @@ public record SerializableChunkData(
}
// Paper end - starlight - convert from record
}
+
+ // Paper start - throttle failed spawn attempts
+ // For plugin compatibility
+ public SerializableChunkData(
+ Registry<Biome> biomeRegistry,
+ ChunkPos chunkPos,
+ int minSectionY,
+ long lastUpdateTime,
+ long inhabitedTime,
+ ChunkStatus chunkStatus,
+ @Nullable BlendingData.Packed blendingData,
+ @Nullable BelowZeroRetrogen belowZeroRetrogen,
+ UpgradeData upgradeData,
+ @Nullable long[] carvingMask,
+ Map<Heightmap.Types, long[]> heightmaps,
+ ChunkAccess.PackedTicks packedTicks,
+ ShortList[] postProcessingSections,
+ boolean lightCorrect,
+ List<net.minecraft.world.level.chunk.storage.SerializableChunkData.SectionData> sectionData,
+ List<CompoundTag> entities,
+ List<CompoundTag> blockEntities,
+ CompoundTag structureData,
+ @Nullable net.minecraft.nbt.Tag persistentDataContainer // CraftBukkit - persistentDataContainer
+ ) {
+ this(biomeRegistry,
+ chunkPos,
+ minSectionY,
+ lastUpdateTime,
+ inhabitedTime,
+ chunkStatus,
+ blendingData,
+ belowZeroRetrogen,
+ upgradeData,
+ carvingMask,
+ heightmaps,
+ packedTicks,
+ postProcessingSections,
+ lightCorrect,
+ sectionData,
+ entities,
+ blockEntities,
+ structureData,
+ persistentDataContainer,
+ null);
+ }
+ // Paper end - throttle failed spawn attempts
}