Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ index 5c8a603e5800e1cc282d899e2a3d6b556295e13c..2dca1ceb886537ff96d0834844429e1c
}
// Paper end - Optional per player mob spawns
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 908cd08e33fed1c4cd4bd34c3e63cbbe84ffead4..f5b58c181726536bedabd4b6f64769e312ef4257 100644
index 3a6c894178829cec8daa08ea9f0294f7f39a8efe..0e90863dbb3cf918f0091c1a64b3d02f566fef35 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -70,11 +70,11 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
Expand Down Expand Up @@ -82,7 +82,7 @@ index 908cd08e33fed1c4cd4bd34c3e63cbbe84ffead4..f5b58c181726536bedabd4b6f64769e3
// Paper start - per player mob spawning backoff
for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
player.mobCounts[ii] = 0;
@@ -525,34 +542,27 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -525,34 +542,21 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
player.mobBackoffCounts[ii] = newBackoff;
}
// Paper end - per player mob spawning backoff
Expand All @@ -92,7 +92,8 @@ index 908cd08e33fed1c4cd4bd34c3e63cbbe84ffead4..f5b58c181726536bedabd4b6f64769e3
firstRunSpawnCounts = false;
_pufferfish_spawnCountsReady.set(true);
}
if (_pufferfish_spawnCountsReady.getAndSet(false)) {
- if (_pufferfish_spawnCountsReady.getAndSet(false)) {
+ if (_pufferfish_spawnCountsReady.getAndSet(false) && level.paperConfig().entities.spawning.perPlayerMobSpawns) {
+ final int mapped = distanceManager.getNaturalSpawnChunkCount();
+ final Iterable<Entity> entities = this.level.getAllEntities();
net.minecraft.server.MinecraftServer.getServer().mobSpawnExecutor.submit(() -> {
Expand All @@ -117,30 +118,24 @@ index 908cd08e33fed1c4cd4bd34c3e63cbbe84ffead4..f5b58c181726536bedabd4b6f64769e3
- } finally {
- objectiterator.finishedIterating();
- }
+ // Fix: Use proper mob cap calculator based on configuration
+ LocalMobCapCalculator mobCapCalculator = !level.paperConfig().entities.spawning.perPlayerMobSpawns ?
+ new LocalMobCapCalculator(chunkMap) : null;
+
+ // This ensures the caps are properly enforced by using the correct calculator
+ lastSpawnState = NaturalSpawner.createState1( // Leaf - optimize mob spawning
+ lastSpawnState = NaturalSpawner.createStateAsync( // Leaf - optimize mob spawning
+ mapped,
+ entities,
+ this.level, // Leaf - optimize mob spawning
+ mobCapCalculator, // This is the key fix - was previously null
+ level.paperConfig().entities.spawning.perPlayerMobSpawns
+ this.level
+ );
_pufferfish_spawnCountsReady.set(true);
});
}
@@ -611,6 +621,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -611,6 +615,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
chunkRange = Math.min(chunkRange, 8);
entityPlayer.playerNaturallySpawnedEvent = new com.destroystokyo.paper.event.entity.PlayerNaturallySpawnCreaturesEvent(entityPlayer.getBukkitEntity(), (byte) chunkRange);
entityPlayer.playerNaturallySpawnedEvent.callEvent();
+ this.level.natureSpawnChunkMap.addPlayer(entityPlayer); // Leaf - optimize mob spawning
}
// Paper end - PlayerNaturallySpawnCreaturesEvent
boolean flag = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
@@ -622,16 +633,34 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -622,16 +627,34 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
List<LevelChunk> list = this.spawningChunks;

try {
Expand Down Expand Up @@ -178,7 +173,7 @@ index 908cd08e33fed1c4cd4bd34c3e63cbbe84ffead4..f5b58c181726536bedabd4b6f64769e3
list.clear();
}

@@ -649,7 +678,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -649,7 +672,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
}

if (!spawnCategories.isEmpty()) {
Expand All @@ -200,7 +195,7 @@ index bec2b39c1975da51302f6a395aa03269773e3007..eac2b9eb713d8a0a0b1682986745ae72
final net.minecraft.world.level.levelgen.BitRandomSource simpleRandom = this.simpleRandom; // Paper - optimise random ticking // Leaf - Faster random generator - upcasting
ChunkPos pos = chunk.getPos();
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index bb655318f49242858e2c25d5469705c0c314ed85..a015f0bbff3bb58fd4d28c59620f75dbb125f869 100644
index bb655318f49242858e2c25d5469705c0c314ed85..ea120c7737ba82586c46ad091a4bf0ceeb2e81e3 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -68,6 +68,7 @@ public final class NaturalSpawner {
Expand All @@ -211,17 +206,13 @@ index bb655318f49242858e2c25d5469705c0c314ed85..a015f0bbff3bb58fd4d28c59620f75db
public static NaturalSpawner.SpawnState createState(
int spawnableChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkGetter, LocalMobCapCalculator calculator, final boolean countMobs
) {
@@ -108,9 +109,71 @@ public final class NaturalSpawner {
}
}

- return new NaturalSpawner.SpawnState(spawnableChunkCount, map, potentialCalculator, calculator);
+ return new NaturalSpawner.SpawnState(spawnableChunkCount, map, potentialCalculator, calculator, new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>()); // Leaf - optimize mob spawning
@@ -111,6 +112,46 @@ public final class NaturalSpawner {
return new NaturalSpawner.SpawnState(spawnableChunkCount, map, potentialCalculator, calculator);
}

+ // Leaf start - optimize mob spawning
+ public static NaturalSpawner.SpawnState createState1(
+ int spawnableChunkCount, Iterable<Entity> entities, ServerLevel level, LocalMobCapCalculator calculator, final boolean countMobs
+ public static NaturalSpawner.SpawnState createStateAsync(
+ int spawnableChunkCount, Iterable<Entity> entities, ServerLevel level
+ ) {
+ // Paper end - Optional per player mob spawns
+ PotentialCalculator potentialCalculator = new PotentialCalculator();
Expand All @@ -247,44 +238,22 @@ index bb655318f49242858e2c25d5469705c0c314ed85..a015f0bbff3bb58fd4d28c59620f75db
+ potentialCalculator.addCharge(entity.blockPosition(), mobSpawnCost.charge());
+ }
+
+ if (calculator != null && entity instanceof Mob) { // Paper - Optional per player mob spawns
+ calculator.addMob(chunk.getPos(), category);
+ }
+
+ map.addTo(category, 1);
+ // Paper start - Optional per player mob spawns
+ if (countMobs) {
+ final int index = entity.getType().getCategory().ordinal();
+ ++chunkCap.computeIfAbsent(chunk.getPos().longKey, k -> new int[net.minecraft.server.level.ServerPlayer.MOBCATEGORY_TOTAL_ENUMS])[index];
+ /*
+ final int index = entity.getType().getCategory().ordinal();
+ final var inRange = level.moonrise$getNearbyPlayers().getPlayers(entity.chunkPosition(), NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
+ if (inRange == null) {
+ continue;
+ }
+
+ final net.minecraft.server.level.ServerPlayer[] backingSet = inRange.getRawDataUnchecked();
+ for (int i = 0, len = inRange.size(); i < len; i++) {
+ final net.minecraft.server.level.ServerPlayer player = backingSet[i];
+ if (player == null) continue;
+ ++playerCap.computeIfAbsent(player, k -> new int[net.minecraft.server.level.ServerPlayer.MOBCATEGORY_TOTAL_ENUMS])[index];
+ }
+ */
+ }
+ // Paper end - Optional per player mob spawns
+ ++chunkCap.computeIfAbsent(chunk.coordinateKey, k -> new int[net.minecraft.server.level.ServerPlayer.MOBCATEGORY_TOTAL_ENUMS])[index];
+ }
+ }
+ }
+ }
+
+ return new NaturalSpawner.SpawnState(spawnableChunkCount, map, potentialCalculator, calculator, chunkCap);
+ return new NaturalSpawner.SpawnState(spawnableChunkCount, map, potentialCalculator, null, chunkCap);
+ }
+ // Leaf end - optimize mob spawning
+
static Biome getRoughBiome(BlockPos pos, ChunkAccess chunk) {
return chunk.getNoiseBiome(QuartPos.fromBlock(pos.getX()), QuartPos.fromBlock(pos.getY()), QuartPos.fromBlock(pos.getZ())).value();
}
@@ -265,28 +328,68 @@ public final class NaturalSpawner {
@@ -265,28 +306,68 @@ public final class NaturalSpawner {
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 PR end - throttle failed spawn attempts
) {
Expand Down Expand Up @@ -360,7 +329,7 @@ index bb655318f49242858e2c25d5469705c0c314ed85..a015f0bbff3bb58fd4d28c59620f75db
mutableBlockPos.set(x, y, z);
double d = x + 0.5;
double d1 = z + 0.5;
@@ -295,8 +398,8 @@ public final class NaturalSpawner {
@@ -295,8 +376,8 @@ public final class NaturalSpawner {
double d2 = nearestPlayer.distanceToSqr(d, y, d1);
if (level.isLoadedAndInBounds(mutableBlockPos) && isRightDistanceToPlayerAndSpawnPoint(level, chunk, mutableBlockPos, d2)) { // Paper - don't load chunks for mob spawn
if (spawnerData == null) {
Expand All @@ -371,7 +340,7 @@ index bb655318f49242858e2c25d5469705c0c314ed85..a015f0bbff3bb58fd4d28c59620f75db
);
if (randomSpawnMobAt.isEmpty()) {
break;
@@ -307,7 +410,7 @@ public final class NaturalSpawner {
@@ -307,7 +388,7 @@ public final class NaturalSpawner {
}

// Paper start - PreCreatureSpawnEvent
Expand All @@ -380,7 +349,7 @@ index bb655318f49242858e2c25d5469705c0c314ed85..a015f0bbff3bb58fd4d28c59620f75db
// Paper start - per player mob count backoff
if (doSpawning == PreSpawnStatus.ABORT || doSpawning == PreSpawnStatus.CANCELLED) {
level.getChunkSource().chunkMap.updateFailurePlayerMobTypeMap(mutableBlockPos.getX() >> 4, mutableBlockPos.getZ() >> 4, category);
@@ -414,6 +517,44 @@ public final class NaturalSpawner {
@@ -414,6 +495,44 @@ public final class NaturalSpawner {
&& level.noCollision(entityType.getSpawnAABB(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5));
return success ? PreSpawnStatus.SUCCESS : PreSpawnStatus.FAIL; // Paper - PreCreatureSpawnEvent
}
Expand Down Expand Up @@ -425,7 +394,7 @@ index bb655318f49242858e2c25d5469705c0c314ed85..a015f0bbff3bb58fd4d28c59620f75db

@Nullable
private static Mob getMobForSpawn(ServerLevel level, EntityType<?> entityType) {
@@ -449,6 +590,17 @@ public final class NaturalSpawner {
@@ -449,6 +568,17 @@ public final class NaturalSpawner {
: mobsAt(level, structureManager, generator, category, pos, biome).getRandom(random);
}

Expand All @@ -443,7 +412,7 @@ index bb655318f49242858e2c25d5469705c0c314ed85..a015f0bbff3bb58fd4d28c59620f75db
private static boolean canSpawnMobAt(
ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, MobSpawnSettings.SpawnerData data, BlockPos pos
) {
@@ -463,8 +615,22 @@ public final class NaturalSpawner {
@@ -463,8 +593,22 @@ public final class NaturalSpawner {
: generator.getMobsAt(biome != null ? biome : (org.dreeam.leaf.config.modules.opt.OptimizeBiome.mobSpawn ? level.getBiomeCached(null, pos) : level.getBiome(pos)), structureManager, cetagory, pos); // Leaf - cache getBiome
}

Expand All @@ -467,7 +436,7 @@ index bb655318f49242858e2c25d5469705c0c314ed85..a015f0bbff3bb58fd4d28c59620f75db
Structure structure = structureManager.registryAccess().lookupOrThrow(Registries.STRUCTURE).getValue(BuiltinStructures.FORTRESS);
return structure != null && structureManager.getStructureAt(pos, structure).isValid();
} else {
@@ -472,6 +638,19 @@ public final class NaturalSpawner {
@@ -472,6 +616,19 @@ public final class NaturalSpawner {
}
}

Expand All @@ -487,30 +456,42 @@ index bb655318f49242858e2c25d5469705c0c314ed85..a015f0bbff3bb58fd4d28c59620f75db
private static BlockPos getRandomPosWithin(Level level, LevelChunk chunk) {
ChunkPos pos = chunk.getPos();
int i = pos.getMinBlockX() + level.random.nextInt(16);
@@ -612,18 +791,21 @@ public final class NaturalSpawner {
@@ -612,6 +769,7 @@ public final class NaturalSpawner {
@Nullable
private EntityType<?> lastCheckedType;
private double lastCharge;
+ public final it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<int[]> chunkCap; // Leaf - optimize mob spawning

SpawnState(
int spawnableChunkCount,
Object2IntOpenHashMap<MobCategory> mobCategoryCounts,
PotentialCalculator spawnPotential,
- LocalMobCapCalculator localMobCapCalculator
+ LocalMobCapCalculator localMobCapCalculator,
+ it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<int[]> playerCap // Leaf - optimize mob spawning
) {
this.spawnableChunkCount = spawnableChunkCount;
this.mobCategoryCounts = mobCategoryCounts;
@@ -624,8 +782,26 @@ public final class NaturalSpawner {
this.spawnPotential = spawnPotential;
this.localMobCapCalculator = localMobCapCalculator;
this.unmodifiableMobCategoryCounts = Object2IntMaps.unmodifiable(mobCategoryCounts);
+ this.chunkCap = playerCap; // Leaf - optimize mob spawning
+ this.chunkCap = new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>(); // Leaf - optimize mob spawning
}

+ // Leaf start - optimize mob spawning
+ SpawnState(
+ int spawnableChunkCount,
+ Object2IntOpenHashMap<MobCategory> mobCategoryCounts,
+ PotentialCalculator spawnPotential,
+ LocalMobCapCalculator localMobCapCalculator,
+ it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<int[]> playerCap
+ ) {
+ this.spawnableChunkCount = spawnableChunkCount;
+ this.mobCategoryCounts = mobCategoryCounts;
+ this.spawnPotential = spawnPotential;
+ this.localMobCapCalculator = localMobCapCalculator;
+ this.unmodifiableMobCategoryCounts = Object2IntMaps.unmodifiable(mobCategoryCounts);
+ this.chunkCap = playerCap;
+ }
+ // Leaf end - optimize mob spawning
+
private boolean canSpawn(EntityType<?> entityType, BlockPos pos, ChunkAccess chunk) {
@@ -680,5 +862,32 @@ public final class NaturalSpawner {
this.lastCheckedPos = pos;
this.lastCheckedType = entityType;
@@ -680,5 +856,32 @@ public final class NaturalSpawner {
boolean canSpawnForCategoryLocal(MobCategory category, ChunkPos chunkPos) {
return this.localMobCapCalculator.canSpawn(category, chunkPos);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ Subject: [PATCH] throttle mob spawning


diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index a015f0bbff3bb58fd4d28c59620f75dbb125f869..388a22d4ce37f1471fb906118d9e2135d7789834 100644
index ea120c7737ba82586c46ad091a4bf0ceeb2e81e3..6c6d768d4aa5a8c90bff2433489d777c5e66069b 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -217,6 +217,17 @@ public final class NaturalSpawner {
@@ -195,6 +195,17 @@ public final class NaturalSpawner {
// Paper start - Optional per player mob spawns
final boolean canSpawn;
int maxSpawns = Integer.MAX_VALUE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ Subject: [PATCH] optimize random tick


diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index f5b58c181726536bedabd4b6f64769e312ef4257..2847aa24cca82b1c66b69600ddcb5dbdadec5b9d 100644
index 0e90863dbb3cf918f0091c1a64b3d02f566fef35..357aaaa848dd6e47793e75225f690d2770a6cd4a 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -664,7 +664,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -658,7 +658,13 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
list.clear();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ index 4535858701b2bb232b9d2feb2af6551526232ddc..e65c62dbe4c1560ae153e4c4344e9194
- // Paper end - detailed watchdog information
}
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 2847aa24cca82b1c66b69600ddcb5dbdadec5b9d..bd4c98e9ec41a2bd608e2e2245c503be3171ceee 100644
index 357aaaa848dd6e47793e75225f690d2770a6cd4a..cc7f3f8487db241b235e5f49d8bab3eb635f6a37 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -638,8 +638,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@@ -632,8 +632,10 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
this.level.natureSpawnChunkMap.build();
this.level.natureSpawnChunkMap.collectSpawningChunks(this.level.moonrise$getPlayerTickingChunks(), list);
// Paper start - chunk tick iteration optimisation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ Subject: [PATCH] Skip PreCreatureSpawnEvent if no listeners


diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 388a22d4ce37f1471fb906118d9e2135d7789834..12731a0026531e33f28ce4b3ba1e690e2fc0b119 100644
index 6c6d768d4aa5a8c90bff2433489d777c5e66069b..ec2f630b8eeed85e81b730e3a3d339b3419f39e8 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -541,17 +541,35 @@ public final class NaturalSpawner {
@@ -519,17 +519,35 @@ public final class NaturalSpawner {
LevelChunk chunk
) {
EntityType<?> entityType = data.type();
Expand Down