1.21.3-update #16
@ -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,16 +37,25 @@ 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");
|
||||
@@ -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 k = this.distanceManager.getNaturalSpawnChunkCount();
|
||||
- NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(k, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap));
|
||||
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
|
||||
+ int naturalSpawnChunkCount = k;
|
||||
+ 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
|
||||
@ -61,19 +70,11 @@ index 9ccb3ffc375298fda4dca97803e65e39df8493eb..e18c3e08f9fbfe17c797c1f96dce1b86
|
||||
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
|
||||
|
||||
- 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;
|
||||
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);
|
||||
}
|
||||
}
|
In neuem Issue referenzieren
Einen Benutzer sperren