9
0
mirror of https://github.com/LeavesMC/Leaves.git synced 2025-12-19 14:59:32 +00:00
Files
LeavesMC/patches/server/0107-Skip-unnecessary-mob-spawning-computations.patch
2023-08-29 14:22:45 +08:00

138 lines
9.6 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Fri, 21 Jul 2023 11:32:47 +0800
Subject: [PATCH] Skip unnecessary mob spawning computations
This patch is Powered by Gale(https://github.com/GaleMC/Gale)
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
index 5942626173e68d80a2e93d7221f2f470f07f022b..82234b5a0288438cc1a0b8ca59c9a8e4e1a845b4 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
@@ -566,50 +566,57 @@ public class ServerChunkCache extends ChunkSource {
int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING);
boolean flag1 = level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && worlddata.getGameTime() % level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit
- gameprofilerfiller.push("naturalSpawnCount");
- this.level.timings.countNaturalMobs.startTiming(); // Paper - timings
- int l = this.distanceManager.getNaturalSpawnChunkCount();
- // Paper start - per player mob spawning
+ // Leaves start - skip unnecessary mob spawning computations
NaturalSpawner.SpawnState spawnercreature_d; // moved down
- if ((this.spawnFriendlies || this.spawnEnemies) && this.chunkMap.playerMobDistanceMap != null) { // don't count mobs when animals and monsters are disabled
- // Leaves start - optimize mob spawning
- if (!top.leavesmc.leaves.LeavesConfig.asyncMobSpawning) {
- // re-set mob counts
- for (ServerPlayer player : this.level.players) {
- // Paper start - per player mob spawning backoff
- for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
- player.mobCounts[ii] = 0;
-
- int newBackoff = player.mobBackoffCounts[ii] - 1; // TODO make configurable bleed // TODO use nonlinear algorithm?
- if (newBackoff < 0) {
- newBackoff = 0;
+ boolean flag2 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
+ boolean flag2AndHasNaturalSpawn = flag2 && this.anySpawnCategoryIsSpawnedThisTick();
+ if (!top.leavesmc.leaves.LeavesConfig.skipUnnecessaryMobSpawningComputations || flag2AndHasNaturalSpawn) {
+ gameprofilerfiller.push("naturalSpawnCount");
+ this.level.timings.countNaturalMobs.startTiming(); // Paper - timings
+ int l = this.distanceManager.getNaturalSpawnChunkCount();
+ // Paper start - per player mob spawning
+ if ((this.spawnFriendlies || this.spawnEnemies) && this.chunkMap.playerMobDistanceMap != null) { // don't count mobs when animals and monsters are disabled
+ // Leaves start - optimize mob spawning
+ if (!top.leavesmc.leaves.LeavesConfig.asyncMobSpawning) {
+ //re-set mob counts
+ for (ServerPlayer player : this.level.players) {
+ // Paper start - per player mob spawning backoff
+ for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
+ player.mobCounts[ii] = 0;
+
+ int newBackoff = player.mobBackoffCounts[ii] - 1; // TODO make configurable bleed // TODO use nonlinear algorithm?
+ if (newBackoff < 0) {
+ newBackoff = 0;
+ }
+ player.mobBackoffCounts[ii] = newBackoff;
}
- player.mobBackoffCounts[ii] = newBackoff;
- }
- // Paper end - per player mob spawning backoff
+ // Paper end - per player mob spawning backoff
+ }
+ lastSpawnState = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, null, true);
}
- lastSpawnState = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, null, true);
+ // Leaves end - optimize mob spawning
+ } else {
+ // Leaves start - optimize mob spawning
+ lastSpawnState = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, this.chunkMap.playerMobDistanceMap == null ? new LocalMobCapCalculator(this.chunkMap) : null, false);
+ spawnCountsReady.set(true);
+ // Leaves end - optimize mob spawning
}
- // Leaves end - optimize mob spawning
+ // Paper end
+ this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
+
+ // this.lastSpawnState = spawnercreature_d; // Leaves - optimize mob spawning
+ gameprofilerfiller.popPush("filteringLoadedChunks");
} else {
- // Leaves start - optimize mob spawning
- lastSpawnState = NaturalSpawner.createState(l, this.level.getAllEntities(), this::getFullChunk, this.chunkMap.playerMobDistanceMap == null ? new LocalMobCapCalculator(this.chunkMap) : null, false);
- spawnCountsReady.set(true);
- // Leaves end - optimize mob spawning
+ spawnercreature_d = null;
}
- // Paper end
- this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings
-
- // this.lastSpawnState = spawnercreature_d; // Leaves - optimize mob spawning
- gameprofilerfiller.popPush("filteringLoadedChunks");
// Paper - moved down
this.level.timings.chunkTicks.startTiming(); // Paper
// Paper - moved down
gameprofilerfiller.popPush("spawnAndTick");
- boolean flag2 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
+ // Leaves start - skip unnecessary mob spawning computations
// Paper - only shuffle if per-player mob spawning is disabled
// Paper - moved natural spawn event up
@@ -641,7 +648,7 @@ public class ServerChunkCache extends ChunkSource {
if ((true || this.level.isNaturalSpawningAllowed(chunkcoordintpair)) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning // Paper - the chunk is known ticking
chunk1.incrementInhabitedTime(j);
// Leaves start - optimize mob spawning
- if (flag2 && (!top.leavesmc.leaves.LeavesConfig.asyncMobSpawning || spawnCountsReady.get()) && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning & optimise chunk tick iteration
+ if ((top.leavesmc.leaves.LeavesConfig.skipUnnecessaryMobSpawningComputations ? flag2AndHasNaturalSpawn : flag2) && (!top.leavesmc.leaves.LeavesConfig.asyncMobSpawning || spawnCountsReady.get()) && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning & optimise chunk tick iteration // Leaves -skip unnecessary mob spawning computations
NaturalSpawner.spawnForChunk(this.level, chunk1, lastSpawnState, this.spawnFriendlies, this.spawnEnemies, flag1);
}
// Leaves end - optimize mob spawning
@@ -706,7 +713,7 @@ public class ServerChunkCache extends ChunkSource {
// Paper end - controlled flush for entity tracker packets
// Leaves start - optimize mob spawning
- if (top.leavesmc.leaves.LeavesConfig.asyncMobSpawning) {
+ if (top.leavesmc.leaves.LeavesConfig.asyncMobSpawning && (!top.leavesmc.leaves.LeavesConfig.skipUnnecessaryMobSpawningComputations || flag2AndHasNaturalSpawn)) {
for (ServerPlayer player : this.level.players) {
for (int ii = 0; ii < ServerPlayer.MOBCATEGORY_TOTAL_ENUMS; ii++) {
player.mobCounts[ii] = 0;
@@ -739,6 +746,18 @@ public class ServerChunkCache extends ChunkSource {
}
}
+ // Leaves start - skip unnecessary mob spawning computations
+ public boolean anySpawnCategoryIsSpawnedThisTick() {
+ long gameTime = this.level.getLevelData().getGameTime();
+ for (long ticksForSpawnCategory : this.level.ticksPerSpawnCategory.values()) {
+ if (ticksForSpawnCategory != 0L && gameTime % ticksForSpawnCategory == 0L) {
+ return true;
+ }
+ }
+ return false;
+ }
+ // Leaves stop - skip unnecessary mob spawning computations
+
private void getFullChunk(long pos, Consumer<LevelChunk> chunkConsumer) {
ChunkHolder playerchunk = this.getVisibleChunkIfPresent(pos);