Update more feature patches

The incremental chunk saving patch has exactly one line that it expects to come from the moonrise patch, I just left the output as is
This commit is contained in:
Nassim Jahnke
2024-12-19 12:03:16 +01:00
parent 0eb8f95dec
commit 5f9265cc31
4 changed files with 232 additions and 228 deletions

View File

@@ -4,23 +4,23 @@ Date: Sun, 9 Jun 2019 03:53:22 +0100
Subject: [PATCH] Incremental chunk and player saving Subject: [PATCH] Incremental chunk and player saving
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index f4fba4e2d12c7ab4b4eb9858cd738a9678a2d203..a0a75c84379432ccc525ab22d476c358c77f663b 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java --- a/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -862,7 +862,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
boolean var4;
try { try {
this.isSaving = true; this.isSaving = true;
- this.getPlayerList().saveAll(); - this.getPlayerList().saveAll();
+ this.getPlayerList().saveAll(); // Paper - Incremental chunk and player saving; diff on change + this.getPlayerList().saveAll(); // Paper - Incremental chunk and player saving; diff on change
flag3 = this.saveAllChunks(suppressLogs, flush, force); var4 = this.saveAllChunks(suppressLog, flush, forced);
} finally { } finally {
this.isSaving = false; this.isSaving = false;
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1409,9 +1409,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} }
--this.ticksUntilAutosave; this.ticksUntilAutosave--;
- if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) { // CraftBukkit - if (this.autosavePeriod > 0 && this.ticksUntilAutosave <= 0) { // CraftBukkit
- this.autoSave(); - this.autoSave();
+ // Paper start - Incremental chunk and player saving + // Paper start - Incremental chunk and player saving
@@ -47,22 +47,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ profiler.pop(); + profiler.pop();
+ // Paper end - Incremental chunk and player saving + // Paper end - Incremental chunk and player saving
ProfilerFiller gameprofilerfiller = Profiler.get(); ProfilerFiller profilerFiller = Profiler.get();
this.runAllTasks(); // Paper - move runAllTasks() into full server tick (previously for timings)
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index c38eda42b33cfa4792625f40ebde6f30e591119b..c8129f0d8218daff9123f1ad2d8ca321a02e1c7e 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java --- a/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java
@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe @@ -1007,6 +1007,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos); return !this.server.isUnderSpawnProtection(this, pos, player) && this.getWorldBorder().isWithinBounds(pos);
} }
+ // Paper start - Incremental chunk and player saving + // Paper start - Incremental chunk and player saving
+ public void saveIncrementally(boolean doFull) { + public void saveIncrementally(boolean doFull) {
+ ServerChunkCache chunkproviderserver = this.getChunkSource();
+
+ if (doFull) { + if (doFull) {
+ org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); + org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(this.getWorld()));
+ } + }
+ +
+ if (doFull) { + if (doFull) {
@@ -72,8 +70,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ // Copied from save() + // Copied from save()
+ // CraftBukkit start - moved from MinecraftServer.saveChunks + // CraftBukkit start - moved from MinecraftServer.saveChunks
+ if (doFull) { // Paper + if (doFull) { // Paper
+ ServerLevel worldserver1 = this; + ServerLevel serverLevel1 = this;
+ this.serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); + this.serverLevelData.setWorldBorder(serverLevel1.getWorldBorder().createSettings());
+ this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save(this.registryAccess())); + this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save(this.registryAccess()));
+ this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); + this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData());
+ } + }
@@ -81,34 +79,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end - Incremental chunk and player saving + // Paper end - Incremental chunk and player saving
+ +
public void save(@Nullable ProgressListener progressListener, boolean flush, boolean savingDisabled) { public void save(@Nullable ProgressListener progress, boolean flush, boolean skipSave) {
// Paper start - add close param ServerChunkCache chunkSource = this.getChunkSource();
this.save(progressListener, flush, savingDisabled, false); if (!skipSave) {
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 92bd46cca1956f327fb0b407e988d68782f441a4..0f00db82e85c9e510c2e4fe4065291971c408dad 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java --- a/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java
@@ -0,0 +0,0 @@ import org.bukkit.inventory.MainHand; @@ -180,6 +180,7 @@ import org.slf4j.Logger;
public class ServerPlayer extends net.minecraft.world.entity.player.Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system
public class ServerPlayer extends Player {
private static final Logger LOGGER = LogUtils.getLogger(); private static final Logger LOGGER = LogUtils.getLogger();
+ public long lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving + public long lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32; private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10; private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
private static final int FLY_STAT_RECORDING_SPEED = 25; private static final int FLY_STAT_RECORDING_SPEED = 25;
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index bafeeab3edbc73f6f86474e18ab4a3d96ce17157..aaa6b8eee7b34fe6efa76f1fe997dcece827d5dd 100644
--- a/src/main/java/net/minecraft/server/players/PlayerList.java --- a/net/minecraft/server/players/PlayerList.java
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java
@@ -0,0 +0,0 @@ public abstract class PlayerList { @@ -483,6 +483,7 @@ public abstract class PlayerList {
protected void save(ServerPlayer player) { protected void save(ServerPlayer player) {
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
+ player.lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving + player.lastSave = MinecraftServer.currentTick; // Paper - Incremental chunk and player saving
this.playerIo.save(player); this.playerIo.save(player);
ServerStatsCounter serverstatisticmanager = (ServerStatsCounter) player.getStats(); // CraftBukkit ServerStatsCounter serverStatsCounter = player.getStats(); // CraftBukkit
if (serverStatsCounter != null) {
@@ -0,0 +0,0 @@ public abstract class PlayerList { @@ -1070,9 +1071,23 @@ public abstract class PlayerList {
} }
public void saveAll() { public void saveAll() {
@@ -116,18 +114,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ this.saveAll(-1); + this.saveAll(-1);
+ } + }
+ +
+ public void saveAll(int interval) { + public void saveAll(final int interval) {
io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main
+ int numSaved = 0; + int numSaved = 0;
+ long now = MinecraftServer.currentTick; + final long now = MinecraftServer.currentTick;
for (int i = 0; i < this.players.size(); ++i) { for (int i = 0; i < this.players.size(); i++) {
- this.save((ServerPlayer) this.players.get(i)); - this.save(this.players.get(i));
+ final ServerPlayer player = this.players.get(i); + final ServerPlayer player = this.players.get(i);
+ if (interval == -1 || now - player.lastSave >= interval) { + if (interval == -1 || now - player.lastSave >= interval) {
+ this.save(player); + this.save(player);
+ if (interval != -1 && ++numSaved >= io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick()) { break; } + if (interval != -1 && ++numSaved >= io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick()) {
+ break;
+ }
+ } + }
+ // Paper end - Incremental chunk and player saving + // Paper end - Incremental chunk and player saving
} }
return null; }); // Paper - ensure main return null; }); // Paper - ensure main
}

View File

@@ -4,229 +4,233 @@ Date: Mon, 19 Aug 2019 01:27:58 +0500
Subject: [PATCH] Optional per player mob spawns 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 diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 809f3fe1285e347f18709c2368923fcc8f953ded..6c5b2eb411fb60babbb0c74d5c075696ef70b38d 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java --- a/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -237,11 +237,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.chunksToEagerlySave.add(chunkPos.toLong());
} }
// Paper start - // Paper start
- public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) {
- return -1;
+ // Paper start - Optional per player mob spawns + // Paper start - Optional per player mob spawns
+ public void updatePlayerMobTypeMap(final Entity entity) { + public void updatePlayerMobTypeMap(final Entity entity) {
+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { + if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
+ return; + return;
+ } + }
+ final int index = entity.getType().getCategory().ordinal();
+ +
+ final int index = entity.getType().getCategory().ordinal();
+ final ca.spottedleaf.moonrise.common.list.ReferenceList<ServerPlayer> inRange = + final ca.spottedleaf.moonrise.common.list.ReferenceList<ServerPlayer> inRange =
+ this.level.moonrise$getNearbyPlayers().getPlayers(entity.chunkPosition(), ca.spottedleaf.moonrise.common.misc.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE); + this.level.moonrise$getNearbyPlayers().getPlayers(entity.chunkPosition(), ca.spottedleaf.moonrise.common.misc.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
+ if (inRange == null) { + if (inRange == null) {
+ return; + return;
+ } + }
+
+ final ServerPlayer[] backingSet = inRange.getRawDataUnchecked(); + final ServerPlayer[] backingSet = inRange.getRawDataUnchecked();
+ for (int i = 0, len = inRange.size(); i < len; i++) { + for (int i = 0, len = inRange.size(); i < len; i++) {
+ ++(backingSet[i].mobCounts[index]); + ++(backingSet[i].mobCounts[index]);
+ } + }
+ }
public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) {
- return -1;
+ return player.mobCounts[mobCategory.ordinal()];
+ // Paper end - Optional per player mob spawns
} }
// Paper end - // Paper end
+
+ public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) {
+ return player.mobCounts[mobCategory.ordinal()];
+ }
+ // Paper end - Optional per player mob spawns
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java protected ChunkGenerator generator() {
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 return this.worldGenContext.generator();
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java index 2f49dbc919f7f5eea9abce6106723c72f5ae45fb..078f208e104a652ce48458150389d19ede6808ef 100644
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon --- a/net/minecraft/server/level/ServerChunkCache.java
gameprofilerfiller.popPush("shuffleChunks"); +++ b/net/minecraft/server/level/ServerChunkCache.java
// Paper start - chunk tick iteration optimisation @@ -435,7 +435,7 @@ public class ServerChunkCache extends ChunkSource {
this.shuffleRandom.setSeed(this.level.random.nextLong()); profilerFiller.push("filteringTickingChunks");
- Util.shuffle(list, this.shuffleRandom); this.collectTickingChunks(list);
profilerFiller.popPush("shuffleChunks");
- Util.shuffle(list, this.level.random);
+ 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 + 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(profilerFiller, l, list);
this.tickChunks(gameprofilerfiller, j, list); profilerFiller.pop();
gameprofilerfiller.pop(); } finally {
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -474,9 +474,18 @@ public class ServerChunkCache extends ChunkSource {
private void tickChunks(ProfilerFiller profiler, long timeDelta, List<LevelChunk> chunks) { private void tickChunks(ProfilerFiller profiler, long timeInhabited, List<LevelChunk> chunks) {
profiler.popPush("naturalSpawnCount"); profiler.popPush("naturalSpawnCount");
int j = this.distanceManager.getNaturalSpawnChunkCount(); int naturalSpawnChunkCount = this.distanceManager.getNaturalSpawnChunkCount();
- NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(j, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)); - NaturalSpawner.SpawnState spawnState = NaturalSpawner.createState(
- naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)
- );
+ // Paper start - Optional per player mob spawns + // Paper start - Optional per player mob spawns
+ final int naturalSpawnChunkCount = j; + NaturalSpawner.SpawnState spawnState;
+ 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 + 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 + // re-set mob counts
+ for (ServerPlayer player : this.level.players) { + for (ServerPlayer player : this.level.players) {
+ Arrays.fill(player.mobCounts, 0); + Arrays.fill(player.mobCounts, 0);
+ } + }
+ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); + spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
+ } else { + } else {
+ spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); + spawnState = 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 + // Paper end - Optional per player mob spawns
this.lastSpawnState = spawnState;
this.lastSpawnState = spawnercreature_d;
profiler.popPush("spawnAndTick"); profiler.popPush("spawnAndTick");
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java index 0f00db82e85c9e510c2e4fe4065291971c408dad..dab58457ed02d3f8153c07de101262b1a0182d71 100644
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java --- a/net/minecraft/server/level/ServerPlayer.java
@@ -0,0 +0,0 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple +++ b/net/minecraft/server/level/ServerPlayer.java
@@ -368,6 +368,10 @@ public class ServerPlayer extends Player {
public boolean queueHealthUpdatePacket; public boolean queueHealthUpdatePacket;
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket; public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
// Paper end - cancellable death event // Paper end - cancellable death event
+ // Paper start - Optional per player mob spawns + // Paper start - Optional per player mob spawns
+ public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length; + public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
+ public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper + public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS];
+ // Paper end - Optional per player mob spawns + // Paper end - Optional per player mob spawns
// CraftBukkit start // CraftBukkit start
public CraftPlayer.TransferCookieConnection transferCookieConnection; public org.bukkit.craftbukkit.entity.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 public String displayName;
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java index 6e6e028621ccc4597b2c24f54f53cb7f3de603e2..14e99450a8522b79e4c3805bd91439a950bc8f99 100644
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java --- a/net/minecraft/world/level/NaturalSpawner.java
@@ -0,0 +0,0 @@ public final class NaturalSpawner { +++ b/net/minecraft/world/level/NaturalSpawner.java
private NaturalSpawner() {} @@ -72,6 +72,14 @@ public final class NaturalSpawner {
public static NaturalSpawner.SpawnState createState(
public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkSource, LocalMobCapCalculator densityCapper) { int spawnableChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkGetter, LocalMobCapCalculator calculator
) {
+ // Paper start - Optional per player mob spawns + // Paper start - Optional per player mob spawns
+ return createState(spawningChunkCount, entities, chunkSource, densityCapper, false); + return createState(spawnableChunkCount, entities, chunkGetter, calculator, false);
+ } + }
+ +
+ public static NaturalSpawner.SpawnState createState(int spawningChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkSource, LocalMobCapCalculator densityCapper, boolean countMobs) { + public static NaturalSpawner.SpawnState createState(
+ int spawnableChunkCount, Iterable<Entity> entities, NaturalSpawner.ChunkGetter chunkGetter, LocalMobCapCalculator calculator, final boolean countMobs
+ ) {
+ // Paper end - Optional per player mob spawns + // Paper end - Optional per player mob spawns
PotentialCalculator spawnercreatureprobabilities = new PotentialCalculator(); PotentialCalculator potentialCalculator = new PotentialCalculator();
Object2IntOpenHashMap<MobCategory> object2intopenhashmap = new Object2IntOpenHashMap(); Object2IntOpenHashMap<MobCategory> map = new Object2IntOpenHashMap<>();
Iterator iterator = entities.iterator();
@@ -0,0 +0,0 @@ public final class NaturalSpawner {
spawnercreatureprobabilities.addCharge(entity.blockPosition(), biomesettingsmobs_b.charge());
}
- if (entity instanceof Mob) { @@ -93,11 +101,16 @@ public final class NaturalSpawner {
+ if (densityCapper != null && entity instanceof Mob) { // Paper - Optional per player mob spawns potentialCalculator.addCharge(entity.blockPosition(), mobSpawnCost.charge());
densityCapper.addMob(chunk.getPos(), enumcreaturetype); }
}
object2intopenhashmap.addTo(enumcreaturetype, 1); - if (entity instanceof Mob) {
+ // Paper start - Optional per player mob spawns + if (calculator != null && entity instanceof Mob) { // Paper - Optional per player mob spawns
+ if (countMobs) { calculator.addMob(chunk.getPos(), category);
+ chunk.level.getChunkSource().chunkMap.updatePlayerMobTypeMap(entity); }
+ }
+ // Paper end - Optional per player mob spawns map.addTo(category, 1);
}); + // Paper start - Optional per player mob spawns
+ if (countMobs) {
+ chunk.level.getChunkSource().chunkMap.updatePlayerMobTypeMap(entity);
+ }
+ // Paper end - Optional per player mob spawns
});
}
} }
} @@ -135,7 +148,7 @@ public final class NaturalSpawner {
@@ -0,0 +0,0 @@ public final class NaturalSpawner { if ((spawnFriendlies || !mobCategory.isFriendly())
continue; && (spawnEnemies || mobCategory.isFriendly())
} && (spawnPassives || !mobCategory.isPersistent())
- && spawnState.canSpawnForCategoryGlobal(mobCategory, limit)) { // Paper - Optional per player mob spawns; remove global check, check later during the local one
- if ((flag || !enumcreaturetype.isFriendly()) && (flag1 || enumcreaturetype.isFriendly()) && (flag2 || !enumcreaturetype.isPersistent()) && spawnercreature_d.canSpawnForCategoryGlobal(enumcreaturetype, limit)) { + && (level.paperConfig().entities.spawning.perPlayerMobSpawns || spawnState.canSpawnForCategoryGlobal(mobCategory, limit))) { // Paper - Optional per player mob spawns; remove global check, check later during the local one
+ 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 list.add(mobCategory);
// CraftBukkit end // CraftBukkit end
list.add(enumcreaturetype);
} }
@@ -0,0 +0,0 @@ public final class NaturalSpawner { @@ -149,8 +162,37 @@ public final class NaturalSpawner {
while (iterator.hasNext()) { profilerFiller.push("spawner");
MobCategory enumcreaturetype = (MobCategory) iterator.next();
- if (info.canSpawnForCategoryLocal(enumcreaturetype, chunk.getPos())) { for (MobCategory mobCategory : categories) {
- if (spawnState.canSpawnForCategoryLocal(mobCategory, chunk.getPos())) {
- spawnCategoryForChunk(mobCategory, level, chunk, spawnState::canSpawn, spawnState::afterSpawn);
+ // Paper start - Optional per player mob spawns + // Paper start - Optional per player mob spawns
+ final boolean canSpawn; + final boolean canSpawn;
+ int maxSpawns = Integer.MAX_VALUE; + int maxSpawns = Integer.MAX_VALUE;
+ if (world.paperConfig().entities.spawning.perPlayerMobSpawns) { + if (level.paperConfig().entities.spawning.perPlayerMobSpawns) {
+ // Copied from getFilteredSpawningCategories + // Copied from getFilteredSpawningCategories
+ int limit = enumcreaturetype.getMaxInstancesPerChunk(); + int limit = mobCategory.getMaxInstancesPerChunk();
+ SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(enumcreaturetype); + SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(mobCategory);
+ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { + if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
+ limit = world.getWorld().getSpawnLimit(spawnCategory); + limit = level.getWorld().getSpawnLimit(spawnCategory);
+ } + }
+ +
+ // Apply per-player limit + // Apply per-player limit
+ int minDiff = Integer.MAX_VALUE; + int minDiff = Integer.MAX_VALUE;
+ final ca.spottedleaf.moonrise.common.list.ReferenceList<net.minecraft.server.level.ServerPlayer> inRange = + 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); + level.moonrise$getNearbyPlayers().getPlayers(chunk.getPos(), ca.spottedleaf.moonrise.common.misc.NearbyPlayers.NearbyMapType.TICK_VIEW_DISTANCE);
+ if (inRange != null) { + if (inRange != null) {
+ final net.minecraft.server.level.ServerPlayer[] backingSet = inRange.getRawDataUnchecked(); + final net.minecraft.server.level.ServerPlayer[] backingSet = inRange.getRawDataUnchecked();
+ for (int k = 0, len = inRange.size(); k < len; k++) { + for (int k = 0, len = inRange.size(); k < len; k++) {
+ minDiff = Math.min(limit - world.getChunkSource().chunkMap.getMobCountNear(backingSet[k], enumcreaturetype), minDiff); + minDiff = Math.min(limit - level.getChunkSource().chunkMap.getMobCountNear(backingSet[k], mobCategory), minDiff);
+ } + }
+ } + }
+ +
+ maxSpawns = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff; + maxSpawns = (minDiff == Integer.MAX_VALUE) ? 0 : minDiff;
+ canSpawn = maxSpawns > 0; + canSpawn = maxSpawns > 0;
+ } else { + } else {
+ canSpawn = info.canSpawnForCategoryLocal(enumcreaturetype, chunk.getPos()); + canSpawn = spawnState.canSpawnForCategoryLocal(mobCategory, chunk.getPos());
+ } + }
+ if (canSpawn) { + if (canSpawn) {
+ // Paper end - Optional per player mob spawns + spawnCategoryForChunk(mobCategory, level, chunk, spawnState::canSpawn, spawnState::afterSpawn,
Objects.requireNonNull(info); + maxSpawns, level.paperConfig().entities.spawning.perPlayerMobSpawns ? level.getChunkSource().chunkMap::updatePlayerMobTypeMap : null);
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
+ 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 + // Paper end - Optional per player mob spawns
} }
} }
@@ -0,0 +0,0 @@ public final class NaturalSpawner { @@ -170,9 +212,16 @@ public final class NaturalSpawner {
// Paper end - Add mobcaps commands public static void spawnCategoryForChunk(
MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback
public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) { ) {
+ // Paper start - Optional per player mob spawns + // Paper start - Optional per player mob spawns
+ spawnCategoryForChunk(group, world, chunk, checker, runner, Integer.MAX_VALUE, null); + spawnCategoryForChunk(category, level, chunk, filter, callback, Integer.MAX_VALUE, null);
+ } + }
+ public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer<Entity> trackEntity) { + public static void spawnCategoryForChunk(
+ MobCategory category, ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final Consumer<Entity> trackEntity
+ ) {
+ // Paper end - Optional per player mob spawns + // Paper end - Optional per player mob spawns
BlockPos blockposition = NaturalSpawner.getRandomPosWithin(world, chunk); BlockPos randomPosWithin = getRandomPosWithin(level, chunk);
if (randomPosWithin.getY() >= level.getMinY() + 1) {
if (blockposition.getY() >= world.getMinY() + 1) { - spawnCategoryForPosition(category, level, chunk, randomPosWithin, filter, callback);
- NaturalSpawner.spawnCategoryForPosition(group, world, chunk, blockposition, checker, runner); + spawnCategoryForPosition(category, level, chunk, randomPosWithin, filter, callback, maxSpawns, trackEntity); // Paper - Optional per player mob spawns
+ NaturalSpawner.spawnCategoryForPosition(group, world, chunk, blockposition, checker, runner, maxSpawns, trackEntity); // Paper - Optional per player mob spawns
} }
} }
@@ -0,0 +0,0 @@ public final class NaturalSpawner { @@ -189,6 +238,12 @@ public final class NaturalSpawner {
}); NaturalSpawner.SpawnPredicate filter,
} NaturalSpawner.AfterSpawnCallback callback
) {
+ // Paper start - Optional per player mob spawns + spawnCategoryForPosition(category, level, chunk, pos, filter, callback, Integer.MAX_VALUE, null);
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 void spawnCategoryForPosition(MobCategory group, ServerLevel world, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner, int maxSpawns, Consumer<Entity> trackEntity) { + public static void spawnCategoryForPosition(
+ // Paper end - Optional per player mob spawns + MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final @Nullable Consumer<Entity> trackEntity
StructureManager structuremanager = world.structureManager(); + ) {
ChunkGenerator chunkgenerator = world.getChunkSource().getGenerator(); + // Paper end - Optional per player mob spawns
int i = pos.getY(); StructureManager structureManager = level.structureManager();
@@ -0,0 +0,0 @@ public final class NaturalSpawner { ChunkGenerator generator = level.getChunkSource().getGenerator();
++j; int y = pos.getY();
++k1; @@ -252,9 +307,14 @@ public final class NaturalSpawner {
runner.run(entityinsentient, chunk); ++i;
+ // Paper start - Optional per player mob spawns ++i3;
+ if (trackEntity != null) { callback.run(mobForSpawn, chunk);
+ trackEntity.accept(entityinsentient); + // Paper start - Optional per player mob spawns
+ } + if (trackEntity != null) {
+ // Paper end - Optional per player mob spawns + trackEntity.accept(mobForSpawn);
} + }
// CraftBukkit end + // Paper end - Optional per player mob spawns
- if (j >= entityinsentient.getMaxSpawnClusterSize()) { }
+ if (j >= entityinsentient.getMaxSpawnClusterSize() || j >= maxSpawns) { // Paper - Optional per player mob spawns // CraftBukkit end
return; - if (i >= mobForSpawn.getMaxSpawnClusterSize()) {
} + if (i >= mobForSpawn.getMaxSpawnClusterSize() || i >= maxSpawns) { // Paper - Optional per player mob spawns
return;
}
@@ -0,0 +0,0 @@ public final class NaturalSpawner { @@ -565,7 +625,7 @@ public final class NaturalSpawner {
MobCategory enumcreaturetype = entitytypes.getCategory(); this.spawnPotential.addCharge(blockPos, d);
MobCategory category = type.getCategory();
this.mobCategoryCounts.addTo(enumcreaturetype, 1); this.mobCategoryCounts.addTo(category, 1);
- this.localMobCapCalculator.addMob(new ChunkPos(blockposition), enumcreaturetype); - this.localMobCapCalculator.addMob(new ChunkPos(blockPos), category);
+ if (this.localMobCapCalculator != null) this.localMobCapCalculator.addMob(new ChunkPos(blockposition), enumcreaturetype); // Paper - Optional per player mob spawns + if (this.localMobCapCalculator != null) this.localMobCapCalculator.addMob(new ChunkPos(blockPos), category); // Paper - Optional per player mob spawns
} }
public int getSpawnableChunkCount() { public int getSpawnableChunkCount() {

View File

@@ -5,14 +5,14 @@ Subject: [PATCH] Improve cancelling PreCreatureSpawnEvent with per player mob
spawns spawns
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 6c5b2eb411fb60babbb0c74d5c075696ef70b38d..cf439285e4ba9babda228c36aa81dfc49db2c22a 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java --- a/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java
@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -256,8 +256,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
++(backingSet[i].mobCounts[index]);
} }
} }
+ // Paper start - per player mob count backoff + // Paper start - per player mob count backoff
+ public void updateFailurePlayerMobTypeMap(int chunkX, int chunkZ, net.minecraft.world.entity.MobCategory mobCategory) { + public void updateFailurePlayerMobTypeMap(int chunkX, int chunkZ, net.minecraft.world.entity.MobCategory mobCategory) {
+ if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { + if (!this.level.paperConfig().entities.spawning.perPlayerMobSpawns) {
@@ -33,14 +33,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) { public int getMobCountNear(final ServerPlayer player, final net.minecraft.world.entity.MobCategory mobCategory) {
- return player.mobCounts[mobCategory.ordinal()]; - return player.mobCounts[mobCategory.ordinal()];
+ return player.mobCounts[mobCategory.ordinal()] + player.mobBackoffCounts[mobCategory.ordinal()]; // Paper - per player mob count backoff + return player.mobCounts[mobCategory.ordinal()] + player.mobBackoffCounts[mobCategory.ordinal()]; // Paper - per player mob count backoff
// Paper end - Optional per player mob spawns }
} // Paper end - Optional per player mob spawns
// Paper end
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 078f208e104a652ce48458150389d19ede6808ef..aa141c00a41d49daee8e4ab7be70ce4e4767b105 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java --- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon @@ -479,7 +479,17 @@ public class ServerChunkCache extends ChunkSource {
if ((this.spawnFriendlies || this.spawnEnemies) && this.level.paperConfig().entities.spawning.perPlayerMobSpawns) { // don't count mobs when animals and monsters are disabled 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 // re-set mob counts
for (ServerPlayer player : this.level.players) { for (ServerPlayer player : this.level.players) {
@@ -57,33 +57,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end - per player mob spawning backoff + // Paper end - per player mob spawning backoff
} }
spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true); spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
} else { } else {
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index dab58457ed02d3f8153c07de101262b1a0182d71..2d20f42fbcfb67845323d994843d7b977aa867e0 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java --- a/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java
@@ -0,0 +0,0 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple @@ -372,6 +372,7 @@ public class ServerPlayer extends Player {
public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length; public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS];
// Paper end - Optional per player mob spawns // Paper end - Optional per player mob spawns
+ public final int[] mobBackoffCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper - per player mob count backoff + public final int[] mobBackoffCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper - per player mob count backoff
// CraftBukkit start // CraftBukkit start
public CraftPlayer.TransferCookieConnection transferCookieConnection; public org.bukkit.craftbukkit.entity.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 public String displayName;
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java index 5e82a8fdaec5a6750040ebb687aa35bba4dcc2ba..23f7fb22906e49babc7784f4b3d1f8ea8e187b1d 100644
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java --- a/net/minecraft/world/level/NaturalSpawner.java
@@ -0,0 +0,0 @@ public final class NaturalSpawner { +++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -285,6 +285,11 @@ public final class NaturalSpawner {
// Paper start - PreCreatureSpawnEvent // Paper start - PreCreatureSpawnEvent
PreSpawnStatus doSpawning = isValidSpawnPostitionForType(world, group, structuremanager, chunkgenerator, biomesettingsmobs_c, blockposition_mutableblockposition, d2); PreSpawnStatus doSpawning = isValidSpawnPostitionForType(level, category, structureManager, generator, spawnerData, mutableBlockPos, d2);
+ // Paper start - per player mob count backoff + // Paper start - per player mob count backoff
+ if (doSpawning == PreSpawnStatus.ABORT || doSpawning == PreSpawnStatus.CANCELLED) { + if (doSpawning == PreSpawnStatus.ABORT || doSpawning == PreSpawnStatus.CANCELLED) {
+ world.getChunkSource().chunkMap.updateFailurePlayerMobTypeMap(blockposition_mutableblockposition.getX() >> 4, blockposition_mutableblockposition.getZ() >> 4, group); + level.getChunkSource().chunkMap.updateFailurePlayerMobTypeMap(mutableBlockPos.getX() >> 4, mutableBlockPos.getZ() >> 4, category);
+ } + }
+ // Paper end - per player mob count backoff + // Paper end - per player mob count backoff
if (doSpawning == PreSpawnStatus.ABORT) { if (doSpawning == PreSpawnStatus.ABORT) {
return; return;
} }

View File

@@ -35,9 +35,9 @@
+ // CraftBukkit start - add server + // CraftBukkit start - add server
public static List<MobCategory> getFilteredSpawningCategories( public static List<MobCategory> getFilteredSpawningCategories(
- NaturalSpawner.SpawnState spawnState, boolean spawnFriendlies, boolean spawnEnemies, boolean spawnPassives - NaturalSpawner.SpawnState spawnState, boolean spawnFriendlies, boolean spawnEnemies, boolean spawnPassives
+ NaturalSpawner.SpawnState spawnState, boolean spawnFriendlies, boolean spawnEnemies, boolean spawnPassives, ServerLevel worldserver + NaturalSpawner.SpawnState spawnState, boolean spawnFriendlies, boolean spawnEnemies, boolean spawnPassives, ServerLevel level
) { ) {
+ LevelData worlddata = worldserver.getLevelData(); // CraftBukkit - Other mob type spawn tick rate + LevelData worlddata = level.getLevelData(); // CraftBukkit - Other mob type spawn tick rate
+ // CraftBukkit end + // CraftBukkit end
List<MobCategory> list = new ArrayList<>(SPAWNING_CATEGORIES.length); List<MobCategory> list = new ArrayList<>(SPAWNING_CATEGORIES.length);
@@ -47,8 +47,8 @@
+ int limit = mobCategory.getMaxInstancesPerChunk(); + int limit = mobCategory.getMaxInstancesPerChunk();
+ SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(mobCategory); + SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(mobCategory);
+ if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { + if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
+ spawnThisTick = worldserver.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % worldserver.ticksPerSpawnCategory.getLong(spawnCategory) == 0; + spawnThisTick = level.ticksPerSpawnCategory.getLong(spawnCategory) != 0 && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(spawnCategory) == 0;
+ limit = worldserver.getWorld().getSpawnLimit(spawnCategory); + limit = level.getWorld().getSpawnLimit(spawnCategory);
+ } + }
+ +
+ if (!spawnThisTick || limit == 0) { + if (!spawnThisTick || limit == 0) {