Archiviert
13
0
Dieses Repository wurde am 2024-12-25 archiviert. Du kannst Dateien ansehen und es klonen, aber nicht pushen oder Issues/Pull-Requests öffnen.
Paper-Old/patches/server/0332-Optional-per-player-mob-spawns.patch

256 Zeilen
16 KiB
Diff

2021-06-11 14:02:28 +02:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: kickash32 <kickash32@gmail.com>
Date: Mon, 19 Aug 2019 01:27:58 +0500
Subject: [PATCH] Optional per player mob spawns
2021-06-14 04:41:44 +02:00
2021-06-11 14:02:28 +02:00
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 279cb641b795b6f4ced545c3a09b61fde69c47d6..19f1432ae1405eee0ee56dec151e7d602816a943 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
Updated Upstream (Bukkit/CraftBukkit/Spigot) Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: cc9aa21a SPIGOT-6399, SPIGOT-7344: Clarify collidable behavior for player entities f23325b6 Add API for per-world simulation distances 26e1774e Add API for per-world view distances 0b541e60 Add PlayerLoginEvent#getRealAddress 5f027d2d PR-949: Add Vector#fromJOML() overloads for read-only vector types CraftBukkit Changes: bcf56171a PR-1321: Clean up some stuff which got missed during previous PRs 7f833a2d1 SPIGOT-7462: Players no longer drop XP after dying near a Sculk Catalyst 752aac669 Implement APIs for per world view and simulation distances 57d7ef433 Preserve empty enchantment tags for glow effect 465ec3fb4 Remove connected check on setScoreboard f90ce621e Use one PermissibleBase for all command blocks 5876cca44 SPIGOT-7550: Fix creation of Arrow instances f03fc3aa3 SPIGOT-7549: ServerTickManager#setTickRate incorrect Precondition 9d7f49b01 SPIGOT-7548: Fix wrong spawn location for experience orb and dropped item Spigot Changes: ed9ba9a4 Drop no longer required patch ignoring -o option 86b5dd6a SPIGOT-7546: Fix hardcoded check for outdated client message aa7cde7a Remove obsolete APIs for per world view and simulation distances 6dff577e Remove obsolete patch preserving empty `ench` tags a3bf95b8 Remove obsolete PlayerLoginEvent#getRealAddress 1b02f5d6 Remove obsolete connected check on setScoreboard patch acf717eb Remove obsolete command block PermissibleBase patch 053fa2a9 Remove redundant patch dealing with null tile entities
2023-12-25 23:51:56 +01:00
@@ -288,6 +288,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
Rewrite chunk system (#8177) Patch documentation to come Issues with the old system that are fixed now: - World generation does not scale with cpu cores effectively. - Relies on the main thread for scheduling and maintaining chunk state, dropping chunk load/generate rates at lower tps. - Unreliable prioritisation of chunk gen/load calls that block the main thread. - Shutdown logic is utterly unreliable, as it has to wait for all chunks to unload - is it guaranteed that the chunk system is in a state on shutdown that it can reliably do this? Watchdog shutdown also typically failed due to thread checks, which is now resolved. - Saving of data is not unified (i.e can save chunk data without saving entity data, poses problems for desync if shutdown is really abnormal. - Entities are not loaded with chunks. This caused quite a bit of headache for Chunk#getEntities API, but now the new chunk system loads entities with chunks so that they are ready whenever the chunk loads in. Effectively brings the behavior back to 1.16 era, but still storing entities in their own separate regionfiles. The above list is not complete. The patch documentation will complete it. New chunk system hard relies on starlight and dataconverter, and most importantly the new concurrent utilities in ConcurrentUtil. Some of the old async chunk i/o interface (i.e the old file io thread reroutes _some_ calls to the new file io thread) is kept for plugin compat reasons. It will be removed in the next major version of minecraft. The old legacy chunk system patches have been moved to the removed folder in case we need them again.
2022-09-26 10:02:51 +02:00
});
}
Rewrite chunk system (#8177) Patch documentation to come Issues with the old system that are fixed now: - World generation does not scale with cpu cores effectively. - Relies on the main thread for scheduling and maintaining chunk state, dropping chunk load/generate rates at lower tps. - Unreliable prioritisation of chunk gen/load calls that block the main thread. - Shutdown logic is utterly unreliable, as it has to wait for all chunks to unload - is it guaranteed that the chunk system is in a state on shutdown that it can reliably do this? Watchdog shutdown also typically failed due to thread checks, which is now resolved. - Saving of data is not unified (i.e can save chunk data without saving entity data, poses problems for desync if shutdown is really abnormal. - Entities are not loaded with chunks. This caused quite a bit of headache for Chunk#getEntities API, but now the new chunk system loads entities with chunks so that they are ready whenever the chunk loads in. Effectively brings the behavior back to 1.16 era, but still storing entities in their own separate regionfiles. The above list is not complete. The patch documentation will complete it. New chunk system hard relies on starlight and dataconverter, and most importantly the new concurrent utilities in ConcurrentUtil. Some of the old async chunk i/o interface (i.e the old file io thread reroutes _some_ calls to the new file io thread) is kept for plugin compat reasons. It will be removed in the next major version of minecraft. The old legacy chunk system patches have been moved to the removed folder in case we need them again.
2022-09-26 10:02:51 +02:00
+ // Paper start - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
+ public void updatePlayerMobTypeMap(Entity entity) {
+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
2021-06-11 14:02:28 +02:00
+ return;
+ }
2021-06-14 04:41:44 +02:00
+ int index = entity.getType().getCategory().ordinal();
2021-06-11 14:02:28 +02:00
+
+ final com.destroystokyo.paper.util.maplist.ReferenceList<ServerPlayer> inRange =
+ this.getNearbyPlayers().getPlayers(entity.chunkPosition(), io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
+ if (inRange == null) {
+ return;
+ }
+ final Object[] backingSet = inRange.getRawData();
+ for (int i = 0, len = inRange.size(); i < len; i++) {
+ ++((ServerPlayer)backingSet[i]).mobCounts[index];
2021-06-11 14:02:28 +02:00
+ }
+ }
+
+ public int getMobCountNear(ServerPlayer entityPlayer, net.minecraft.world.entity.MobCategory mobCategory) {
+ return entityPlayer.mobCounts[mobCategory.ordinal()];
2021-06-14 04:41:44 +02:00
+ }
+ // Paper end - Optional per player mob spawns
Rewrite chunk system (#8177) Patch documentation to come Issues with the old system that are fixed now: - World generation does not scale with cpu cores effectively. - Relies on the main thread for scheduling and maintaining chunk state, dropping chunk load/generate rates at lower tps. - Unreliable prioritisation of chunk gen/load calls that block the main thread. - Shutdown logic is utterly unreliable, as it has to wait for all chunks to unload - is it guaranteed that the chunk system is in a state on shutdown that it can reliably do this? Watchdog shutdown also typically failed due to thread checks, which is now resolved. - Saving of data is not unified (i.e can save chunk data without saving entity data, poses problems for desync if shutdown is really abnormal. - Entities are not loaded with chunks. This caused quite a bit of headache for Chunk#getEntities API, but now the new chunk system loads entities with chunks so that they are ready whenever the chunk loads in. Effectively brings the behavior back to 1.16 era, but still storing entities in their own separate regionfiles. The above list is not complete. The patch documentation will complete it. New chunk system hard relies on starlight and dataconverter, and most importantly the new concurrent utilities in ConcurrentUtil. Some of the old async chunk i/o interface (i.e the old file io thread reroutes _some_ calls to the new file io thread) is kept for plugin compat reasons. It will be removed in the next major version of minecraft. The old legacy chunk system patches have been moved to the removed folder in case we need them again.
2022-09-26 10:02:51 +02:00
+
2021-06-11 14:02:28 +02:00
private static double euclideanDistanceSquared(ChunkPos pos, Entity entity) {
2021-06-14 04:41:44 +02:00
double d0 = (double) SectionPos.sectionToBlockCoord(pos.x, 8);
Rewrite chunk system (#8177) Patch documentation to come Issues with the old system that are fixed now: - World generation does not scale with cpu cores effectively. - Relies on the main thread for scheduling and maintaining chunk state, dropping chunk load/generate rates at lower tps. - Unreliable prioritisation of chunk gen/load calls that block the main thread. - Shutdown logic is utterly unreliable, as it has to wait for all chunks to unload - is it guaranteed that the chunk system is in a state on shutdown that it can reliably do this? Watchdog shutdown also typically failed due to thread checks, which is now resolved. - Saving of data is not unified (i.e can save chunk data without saving entity data, poses problems for desync if shutdown is really abnormal. - Entities are not loaded with chunks. This caused quite a bit of headache for Chunk#getEntities API, but now the new chunk system loads entities with chunks so that they are ready whenever the chunk loads in. Effectively brings the behavior back to 1.16 era, but still storing entities in their own separate regionfiles. The above list is not complete. The patch documentation will complete it. New chunk system hard relies on starlight and dataconverter, and most importantly the new concurrent utilities in ConcurrentUtil. Some of the old async chunk i/o interface (i.e the old file io thread reroutes _some_ calls to the new file io thread) is kept for plugin compat reasons. It will be removed in the next major version of minecraft. The old legacy chunk system patches have been moved to the removed folder in case we need them again.
2022-09-26 10:02:51 +02:00
double d1 = (double) SectionPos.sectionToBlockCoord(pos.z, 8);
2021-06-11 14:02:28 +02:00
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index 16028723b36c1ca3a3c5d1bf2a7c82d2b42a0be4..488f7e2f1ab0312673983d9079b4d7d99eebe611 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
2023-12-05 23:32:41 +01:00
@@ -549,7 +549,19 @@ public class ServerChunkCache extends ChunkSource {
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
2023-12-05 23:32:41 +01:00
+ 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);
2021-06-11 14:02:28 +02:00
+ }
+ // Paper end - Optional per player mob spawns
2023-12-05 23:32:41 +01:00
this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
2021-06-11 14:02:28 +02:00
2023-12-05 23:32:41 +01:00
this.lastSpawnState = spawnercreature_d;
2021-06-11 14:02:28 +02:00
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index af75f20fff15f95aed238e3f6ae57182f4076d46..f9f994f74ff2fc9024c51104eb9af536beb24943 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
2023-12-05 23:32:41 +01:00
@@ -253,6 +253,10 @@ public class ServerPlayer extends Player {
2021-06-11 14:02:28 +02:00
public boolean queueHealthUpdatePacket = false;
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
// Paper end
+ // Paper start - Optional per player mob spawns
+ public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
+ public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper
+ // Paper end - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
// CraftBukkit start
public String displayName;
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
index a19c0e30ebcea8feff035a451ded567dfa86dfff..db22e35d19597488a08ba3cd710ced7da77f8b5e 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
2022-12-07 20:22:28 +01:00
@@ -70,6 +70,12 @@ public final class NaturalSpawner {
2021-06-14 04:41:44 +02:00
private NaturalSpawner() {}
2022-11-12 21:57:41 +01:00
public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkSource, LocalMobCapCalculator densityCapper) {
+ // Paper start - Optional per player mob spawns
2022-11-12 21:57:41 +01:00
+ return createState(spawningChunkCount, entities, chunkSource, densityCapper, false);
2021-06-11 14:02:28 +02:00
+ }
+
2022-11-12 21:57:41 +01:00
+ public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkSource, LocalMobCapCalculator densityCapper, boolean countMobs) {
+ // Paper end - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator();
Object2IntOpenHashMap<MobCategory> object2intopenhashmap = new Object2IntOpenHashMap();
2021-06-14 04:41:44 +02:00
Iterator iterator = entities.iterator();
2022-12-07 20:22:28 +01:00
@@ -104,11 +110,16 @@ public final class NaturalSpawner {
2023-03-14 20:54:57 +01:00
spawnercreatureprobabilities.addCharge(entity.blockPosition(), biomesettingsmobs_b.charge());
}
- if (entity instanceof Mob) {
+ if (densityCapper != null && entity instanceof Mob) { // Paper - Optional per player mob spawns
2022-11-12 21:57:41 +01:00
densityCapper.addMob(chunk.getPos(), enumcreaturetype);
2021-06-11 14:02:28 +02:00
}
object2intopenhashmap.addTo(enumcreaturetype, 1);
+ // Paper start - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
+ if (countMobs) {
2021-06-14 04:41:44 +02:00
+ chunk.level.getChunkSource().chunkMap.updatePlayerMobTypeMap(entity);
2021-06-11 14:02:28 +02:00
+ }
+ // Paper end - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
});
}
}
@@ -143,13 +154,35 @@ public final class NaturalSpawner {
2021-06-11 14:02:28 +02:00
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
2021-06-14 06:29:25 +02:00
+ int currEntityCount = info.mobCategoryCounts.getInt(enumcreaturetype);
2021-06-14 04:41:44 +02:00
+ int k1 = limit * info.getSpawnableChunkCount() / NaturalSpawner.MAGIC_NUMBER;
2021-06-11 14:02:28 +02:00
+ int difference = k1 - currEntityCount;
+
+ if (world.paperConfig().entities.spawning.perPlayerMobSpawns) {
2021-06-11 14:02:28 +02:00
+ int minDiff = Integer.MAX_VALUE;
+ final com.destroystokyo.paper.util.maplist.ReferenceList<net.minecraft.server.level.ServerPlayer> inRange =
+ world.chunkSource.chunkMap.getNearbyPlayers().getPlayers(chunk.getPos(), io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
+ if (inRange != null) {
+ final Object[] backingSet = inRange.getRawData();
+ for (int k = 0, len = inRange.size(); k < len; k++) {
+ minDiff = Math.min(limit - world.getChunkSource().chunkMap.getMobCountNear((net.minecraft.server.level.ServerPlayer)backingSet[k], enumcreaturetype), minDiff);
+ }
2021-06-11 14:02:28 +02:00
+ }
+ difference = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
+ }
+ if ((spawnAnimals || !enumcreaturetype.isFriendly()) && (spawnMonsters || enumcreaturetype.isFriendly()) && (rareSpawn || !enumcreaturetype.isPersistent()) && difference > 0) {
+ // Paper end - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
// CraftBukkit end
2021-06-14 04:41:44 +02:00
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
2021-06-14 04:41:44 +02:00
+ int spawnCount = NaturalSpawner.spawnCategoryForChunk(enumcreaturetype, world, chunk, spawnercreature_c, info::afterSpawn,
+ difference, world.paperConfig().entities.spawning.perPlayerMobSpawns ? world.getChunkSource().chunkMap::updatePlayerMobTypeMap : null);
2021-06-14 06:29:25 +02:00
+ info.mobCategoryCounts.mergeInt(enumcreaturetype, spawnCount, Integer::sum);
+ // Paper end - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
}
}
@@ -158,11 +191,17 @@ public final class NaturalSpawner {
2021-06-11 14:02:28 +02:00
}
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);
2021-06-11 14:02:28 +02:00
+ }
2021-06-14 04:41:44 +02:00
+ public static int 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
2021-06-14 04:41:44 +02:00
BlockPos blockposition = NaturalSpawner.getRandomPosWithin(world, chunk);
2021-06-11 14:02:28 +02:00
2021-06-14 04:41:44 +02:00
if (blockposition.getY() >= world.getMinBuildHeight() + 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
2021-06-11 14:02:28 +02:00
}
+ return 0; // Paper - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
}
2021-06-14 04:41:44 +02:00
@VisibleForDebug
@@ -173,15 +212,21 @@ public final class NaturalSpawner {
2021-06-14 04:41:44 +02:00
});
}
+ // Paper start - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
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);
2021-06-11 14:02:28 +02:00
+ }
2021-06-14 04:41:44 +02:00
+ public static int 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
2022-06-08 06:06:41 +02:00
StructureManager structuremanager = world.structureManager();
2021-06-14 04:41:44 +02:00
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
2021-06-14 04:41:44 +02:00
if (iblockdata != null && !iblockdata.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn
2021-06-11 14:02:28 +02:00
BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
- int j = 0;
+ //int j = 0; // Paper - Optional per player mob spawns; moved up
2021-06-11 14:02:28 +02:00
int k = 0;
while (k < 3) {
@@ -223,14 +268,14 @@ public final class NaturalSpawner {
2021-06-14 08:45:29 +02:00
// Paper start
PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2);
if (doSpawning == PreSpawnStatus.ABORT) {
2021-06-14 08:45:29 +02:00
- return;
+ return j; // Paper - Optional per player mob spawns
2021-06-14 08:45:29 +02:00
}
if (doSpawning == PreSpawnStatus.SUCCESS && checker.test(biomesettingsmobs_c.type, blockposition_mutableblockposition, chunk)) {
2021-06-14 08:45:29 +02:00
// Paper end
2021-06-14 04:41:44 +02:00
Mob entityinsentient = NaturalSpawner.getMobForSpawn(world, biomesettingsmobs_c.type);
2021-06-11 14:02:28 +02:00
if (entityinsentient == null) {
- return;
+ return j; // Paper - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
}
2021-06-14 04:41:44 +02:00
entityinsentient.moveTo(d0, (double) i, d1, world.random.nextFloat() * 360.0F, 0.0F);
@@ -243,10 +288,15 @@ public final class NaturalSpawner {
2021-06-14 04:41:44 +02:00
++j;
2021-06-11 14:02:28 +02:00
++k1;
2021-06-14 04:41:44 +02:00
runner.run(entityinsentient, chunk);
+ // Paper start - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
+ if (trackEntity != null) {
+ trackEntity.accept(entityinsentient);
+ }
+ // Paper end - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
}
// 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
2021-06-11 14:02:28 +02:00
}
if (entityinsentient.isMaxGroupSizeReached(k1)) {
@@ -268,6 +318,7 @@ public final class NaturalSpawner {
2021-06-11 14:02:28 +02:00
}
}
+ return j; // Paper - Optional per player mob spawns
2021-06-11 14:02:28 +02:00
}
private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel world, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double squaredDistance) {
@@ -567,7 +618,7 @@ public final class NaturalSpawner {
MobCategory enumcreaturetype = entitytypes.getCategory();
this.mobCategoryCounts.addTo(enumcreaturetype, 1);
- this.localMobCapCalculator.addMob(new ChunkPos(blockposition), enumcreaturetype);
+ if (this.localMobCapCalculator != null) this.localMobCapCalculator.addMob(new ChunkPos(blockposition), enumcreaturetype); // Paper - Optional per player mob spawns
}
public int getSpawnableChunkCount() {
@@ -583,6 +634,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);
}
}