aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--patches/server/1054-Optional-per-player-mob-spawns.patch (renamed from patches/later/0991-Optional-per-player-mob-spawns.patch)181
1 files changed, 76 insertions, 105 deletions
diff --git a/patches/later/0991-Optional-per-player-mob-spawns.patch b/patches/server/1054-Optional-per-player-mob-spawns.patch
index fee5589666..e08da27a04 100644
--- a/patches/later/0991-Optional-per-player-mob-spawns.patch
+++ b/patches/server/1054-Optional-per-player-mob-spawns.patch
@@ -5,10 +5,10 @@ Subject: [PATCH] Optional per player mob spawns
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
-index 48b8fa3dea0244f9a0f4e0b8850b17a6d23b639c..56f7a63e65cce587512b77aafdb4ced18b43d024 100644
+index bf43bdb43c5301c0e0954729bc531fb6a5045075..97a24cb410cf7d22a1a8edf8a5622d03a3d5a9c7 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
-@@ -223,8 +223,26 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+@@ -231,8 +231,26 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
// Paper start
@@ -37,43 +37,44 @@ index 48b8fa3dea0244f9a0f4e0b8850b17a6d23b639c..56f7a63e65cce587512b77aafdb4ced1
// Paper end
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-index 9ccb3ffc375298fda4dca97803e65e39df8493eb..e18c3e08f9fbfe17c797c1f96dce1b86fa41fab6 100644
+index 4b5985c284faac7b06c0f99d53065f5060ecff4a..ba989879c43cb7d614198444fd2ead85ea71eae9 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-@@ -450,14 +450,26 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
- gameprofilerfiller.popPush("naturalSpawnCount");
- this.level.timings.countNaturalMobs.startTiming(); // Paper - timings
- int k = this.distanceManager.getNaturalSpawnChunkCount();
-- NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(k, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap));
-+ // Paper start - Optional per player mob spawns
-+ int naturalSpawnChunkCount = k;
-+ NaturalSpawner.SpawnState spawnercreature_d; // moved down
-+ if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
-+ // re-set mob counts
-+ for (ServerPlayer player : this.level.players) {
-+ Arrays.fill(player.mobCounts, 0);
-+ }
-+ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
-+ } else {
-+ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
-+ }
-+ // Paper end - Optional per player mob spawns
- this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
-
- this.lastSpawnState = spawnercreature_d;
- gameprofilerfiller.popPush("spawnAndTick");
- boolean flag = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
+@@ -503,7 +503,7 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
+ gameprofilerfiller.popPush("shuffleChunks");
+ // Paper start - chunk tick iteration optimisation
+ this.shuffleRandom.setSeed(this.level.random.nextLong());
+- Util.shuffle(list, this.shuffleRandom);
++ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.shuffleRandom); // Paper - Optional per player mob spawns; do not need this when per-player is enabled
+ // Paper end - chunk tick iteration optimisation
+ this.tickChunks(gameprofilerfiller, j, list);
+ gameprofilerfiller.pop();
+@@ -563,7 +563,19 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
+ profiler.popPush("naturalSpawnCount");
+ this.level.timings.countNaturalMobs.startTiming(); // Paper - timings
+ int j = this.distanceManager.getNaturalSpawnChunkCount();
+- NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(j, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap));
++ // Paper start - Optional per player mob spawns
++ final int naturalSpawnChunkCount = j;
++ NaturalSpawner.SpawnState spawnercreature_d; // moved down
++ if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled
++ // re-set mob counts
++ for (ServerPlayer player : this.level.players) {
++ Arrays.fill(player.mobCounts, 0);
++ }
++ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
++ } else {
++ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false);
++ }
++ // Paper end - Optional per player mob spawns
+ this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
-- Util.shuffle(list, this.level.random);
-+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) Util.shuffle(list, this.level.random); // Paper - per player mob spawns - do not need this when per-player is enabled
- // Paper start - PlayerNaturallySpawnCreaturesEvent
- int chunkRange = level.spigotConfig.mobSpawnRange;
- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange;
+ this.lastSpawnState = spawnercreature_d;
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-index 30f53916a9e49165bcfef2bea2c0b50a26f5a8a3..cb961d9051416626f499c1ca87107f1114433c94 100644
+index 8c9148426f23cbbdfaf7ae66657d1a620f8bd853..8cc02ee9b1a710e35eb65a5a095681cc7dc542bb 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
-@@ -276,6 +276,10 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple
+@@ -303,6 +303,10 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple
public boolean queueHealthUpdatePacket;
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
// Paper end - cancellable death event
@@ -85,10 +86,10 @@ index 30f53916a9e49165bcfef2bea2c0b50a26f5a8a3..cb961d9051416626f499c1ca87107f11
// CraftBukkit start
public CraftPlayer.TransferCookieConnection transferCookieConnection;
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
-index ea6533c1ac218aa075da3401807a06fcb7892321..364510c0d0667e67aa3b25099a021f5f856fc113 100644
+index 6eb69ebe688c1c52d5a5986dfc63cdd42e66687e..f3b52e61ddde25a60c1d178a7607b220ca01f770 100644
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
-@@ -67,6 +67,12 @@ public final class NaturalSpawner {
+@@ -71,6 +71,12 @@ public final class NaturalSpawner {
private NaturalSpawner() {}
public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkSource, LocalMobCapCalculator densityCapper) {
@@ -101,7 +102,7 @@ index ea6533c1ac218aa075da3401807a06fcb7892321..364510c0d0667e67aa3b25099a021f5f
PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator();
Object2IntOpenHashMap<MobCategory> object2intopenhashmap = new Object2IntOpenHashMap();
Iterator iterator = entities.iterator();
-@@ -99,11 +105,16 @@ public final class NaturalSpawner {
+@@ -103,11 +109,16 @@ public final class NaturalSpawner {
spawnercreatureprobabilities.addCharge(entity.blockPosition(), biomesettingsmobs_b.charge());
}
@@ -119,17 +120,32 @@ index ea6533c1ac218aa075da3401807a06fcb7892321..364510c0d0667e67aa3b25099a021f5f
});
}
}
-@@ -138,13 +149,35 @@ public final class NaturalSpawner {
+@@ -142,7 +153,7 @@ public final class NaturalSpawner {
continue;
}
-- if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (rareSpawn || !enumcreaturetype.isPersistent()) && info.canSpawnForCategory(enumcreaturetype, chunk.getPos(), limit)) {
-+ // Paper start - Optional per player mob spawns; only allow spawns upto the limit per chunk and update count afterwards
-+ int currEntityCount = info.mobCategoryCounts.getInt(enumcreaturetype);
-+ int k1 = limit * info.getSpawnableChunkCount() / NaturalSpawner.MAGIC_NUMBER;
-+ int difference = k1 - currEntityCount;
-+
+- if ((flag || !enumcreaturetype.isFriendly()) && (flag1 || enumcreaturetype.isFriendly()) && (flag2 || !enumcreaturetype.isPersistent()) && spawnercreature_d.canSpawnForCategoryGlobal(enumcreaturetype, limit)) {
++ if ((flag || !enumcreaturetype.isFriendly()) && (flag1 || enumcreaturetype.isFriendly()) && (flag2 || !enumcreaturetype.isPersistent()) && (!worldserver.paperConfig().entities.spawning.perPlayerMobSpawns || spawnercreature_d.canSpawnForCategoryGlobal(enumcreaturetype, limit))) { // Paper - Optional per player mob spawns; remove global check, check later during the local one
+ // CraftBukkit end
+ list.add(enumcreaturetype);
+ }
+@@ -161,12 +172,43 @@ public final class NaturalSpawner {
+ while (iterator.hasNext()) {
+ MobCategory enumcreaturetype = (MobCategory) iterator.next();
+
+- if (info.canSpawnForCategoryLocal(enumcreaturetype, chunk.getPos())) {
++ // Paper start - Optional per player mob spawns
++ final boolean canSpawn;
++ int maxSpawns = Integer.MAX_VALUE;
+ if (world.paperConfig().entities.spawning.perPlayerMobSpawns) {
++ // Copied from getFilteredSpawningCategories
++ int limit = enumcreaturetype.getMaxInstancesPerChunk();
++ SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(enumcreaturetype);
++ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
++ limit = world.getWorld().getSpawnLimit(spawnCategory);
++ }
++
++ // Apply per-player limit
+ int minDiff = Integer.MAX_VALUE;
+ final ca.spottedleaf.moonrise.common.list.ReferenceList<net.minecraft.server.level.ServerPlayer> inRange =
+ world.moonrise$getNearbyPlayers().getPlayers(chunk.getPos(), ca.spottedleaf.moonrise.common.misc.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
@@ -139,44 +155,44 @@ index ea6533c1ac218aa075da3401807a06fcb7892321..364510c0d0667e67aa3b25099a021f5f
+ minDiff = Math.min(limit - world.getChunkSource().chunkMap.getMobCountNear(backingSet[k], enumcreaturetype), minDiff);
+ }
+ }
-+ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
++
++ maxSpawns = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
++ canSpawn = maxSpawns > 0;
++ } else {
++ canSpawn = info.canSpawnForCategoryLocal(enumcreaturetype, chunk.getPos());
+ }
-+ if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (rareSpawn || !enumcreaturetype.isPersistent()) && difference > 0) {
++ if (canSpawn) {
+ // Paper end - Optional per player mob spawns
- // CraftBukkit end
Objects.requireNonNull(info);
NaturalSpawner.SpawnPredicate spawnercreature_c = info::canSpawn;
Objects.requireNonNull(info);
- NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn);
+ // Paper start - Optional per player mob spawns
-+ int spawnCount = NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn,
-+ difference, world.paperConfig().entities.spawning.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null);
-+ info.mobCategoryCounts.mergeInt(enumcreaturetype, spawnCount, Integer::sum);
++ NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn,
++ maxSpawns, world.paperConfig().entities.spawning.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null);
+ // Paper end - Optional per player mob spawns
}
}
-@@ -163,11 +196,17 @@ public final class NaturalSpawner {
+@@ -185,10 +227,15 @@ public final class NaturalSpawner {
// Paper end - Add mobcaps commands
public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) {
+ // Paper start - Optional per player mob spawns
+ spawnCategoryForChunk(group, world, chunk, checker, runner, Integer.MAX_VALUE, null);
+ }
-+ public static int spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer<Entity> trackEntity) {
++ public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer<Entity> trackEntity) {
+ // Paper end - Optional per player mob spawns
BlockPos blockposition = NaturalSpawner.getRandomPosWithin(world, chunk);
- if (blockposition.getY() >= world.getMinBuildHeight() + 1) {
+ if (blockposition.getY() >= world.getMinY() + 1) {
- NaturalSpawner.spawnCategoryForPosition(group, world, chunk, blockposition, checker, runner);
-+ return NaturalSpawner.spawnCategoryForPosition(group, world, chunk, blockposition, checker, runner, maxSpawns, trackEntity); // Paper - Optional per player mob spawns
++ NaturalSpawner.spawnCategoryForPosition(group, world, chunk, blockposition, checker, runner, maxSpawns, trackEntity); // Paper - Optional per player mob spawns
}
-+ return 0; // Paper - Optional per player mob spawns
}
- @VisibleForDebug
-@@ -178,15 +217,21 @@ public final class NaturalSpawner {
+@@ -200,7 +247,12 @@ public final class NaturalSpawner {
});
}
@@ -184,39 +200,12 @@ index ea6533c1ac218aa075da3401807a06fcb7892321..364510c0d0667e67aa3b25099a021f5f
public static void spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) {
+ spawnCategoryForPosition(group, world,chunk, pos, checker, runner, Integer.MAX_VALUE, null);
+ }
-+ public static int spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer<Entity> trackEntity) {
++ public static void spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer<Entity> trackEntity) {
+ // Paper end - Optional per player mob spawns
StructureManager structuremanager = world.structureManager();
ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator();
int i = pos.getY();
- BlockState iblockdata = world.getBlockStateIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn
-+ int j = 0; // Paper - Optional per player mob spawns; moved up
-
- if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn
- BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
-- int j = 0;
-+ //int j = 0; // Paper - Optional per player mob spawns; moved up
- int k = 0;
-
- while (k < 3) {
-@@ -228,14 +273,14 @@ public final class NaturalSpawner {
- // Paper start - PreCreatureSpawnEvent
- PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
- if (doSpawning == PreSpawnStatus.ABORT) {
-- return;
-+ return j; // Paper - Optional per player mob spawns
- }
- if (doSpawning == PreSpawnStatus.SUCCESS && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) {
- // Paper end - PreCreatureSpawnEvent
- Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type);
-
- if (entityinsentient == null) {
-- return;
-+ return j; // Paper - Optional per player mob spawns
- }
-
- entityinsentient.moveTo(d0, (double) i, d1, world.random.nextFloat() * 360.0F, 0.0F);
-@@ -248,10 +293,15 @@ public final class NaturalSpawner {
+@@ -270,9 +322,14 @@ public final class NaturalSpawner {
++j;
++k1;
runner.run(entityinsentient, chunk);
@@ -228,21 +217,11 @@ index ea6533c1ac218aa075da3401807a06fcb7892321..364510c0d0667e67aa3b25099a021f5f
}
// CraftBukkit end
- if (j >= entityinsentient.getMaxSpawnClusterSize()) {
-- return;
+ if (j >= entityinsentient.getMaxSpawnClusterSize() || j >= maxSpawns) { // Paper - Optional per player mob spawns
-+ return j; // Paper - Optional per player mob spawns
+ return;
}
- if (entityinsentient.isMaxGroupSizeReached(k1)) {
-@@ -273,6 +323,7 @@ public final class NaturalSpawner {
- }
-
- }
-+ return j; // Paper - Optional per player mob spawns
- }
-
- private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) {
-@@ -523,7 +574,7 @@ public final class NaturalSpawner {
+@@ -545,7 +602,7 @@ public final class NaturalSpawner {
MobCategory enumcreaturetype = entitytypes.getCategory();
this.mobCategoryCounts.addTo(enumcreaturetype, 1);
@@ -251,11 +230,3 @@ index ea6533c1ac218aa075da3401807a06fcb7892321..364510c0d0667e67aa3b25099a021f5f
}
public int getSpawnableChunkCount() {
-@@ -539,6 +590,7 @@ public final class NaturalSpawner {
- int i = limit * this.spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER;
- // CraftBukkit end
-
-+ if (this.localMobCapCalculator == null) return this.mobCategoryCounts.getInt(enumcreaturetype) < i; // Paper - Optional per player mob spawns
- return this.mobCategoryCounts.getInt(enumcreaturetype) >= i ? false : this.localMobCapCalculator.canSpawn(enumcreaturetype, chunkcoordintpair);
- }
- }