9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-23 17:09:29 +00:00

preload mob spawning position

This commit is contained in:
hayanesuru
2025-06-04 21:34:07 +09:00
parent e32cdae1bf
commit 9d6e3ae5ff
8 changed files with 238 additions and 112 deletions

View File

@@ -5,7 +5,7 @@ Subject: [PATCH] optimise getBiome
diff --git a/net/minecraft/advancements/critereon/LocationPredicate.java b/net/minecraft/advancements/critereon/LocationPredicate.java
index a26a5311f87873e0d4d26fda9cb8956a32ee81e8..9405f1f211db3fa2d313429866de454ede64d95b 100644
index a26a5311f87873e0d4d26fda9cb8956a32ee81e8..65e4315cce35814c60b21bbd5baea2ffac82162c 100644
--- a/net/minecraft/advancements/critereon/LocationPredicate.java
+++ b/net/minecraft/advancements/critereon/LocationPredicate.java
@@ -49,7 +49,7 @@ public record LocationPredicate(
@@ -13,7 +13,7 @@ index a26a5311f87873e0d4d26fda9cb8956a32ee81e8..9405f1f211db3fa2d313429866de454e
BlockPos blockPos = BlockPos.containing(x, y, z);
boolean isLoaded = level.isLoaded(blockPos);
- return (!this.biomes.isPresent() || isLoaded && this.biomes.get().contains(level.getBiome(blockPos)))
+ return (!this.biomes.isPresent() || isLoaded && this.biomes.get().contains(level.getBiomeCached(blockPos))) // Leaf - cache getBiome
+ return (!this.biomes.isPresent() || isLoaded && this.biomes.get().contains(org.dreeam.leaf.config.modules.opt.OptimizeBiome.advancement ? level.getBiomeCached(blockPos) : level.getBiome(blockPos))) // Leaf - cache getBiome
&& (!this.structures.isPresent() || isLoaded && level.structureManager().getStructureWithPieceAt(blockPos, this.structures.get()).isValid())
&& (!this.smokey.isPresent() || isLoaded && this.smokey.get() == CampfireBlock.isSmokeyPos(level, blockPos))
&& (!this.light.isPresent() || this.light.get().matches(level, blockPos))
@@ -35,7 +35,7 @@ index 26c8c1e5598daf3550aef05b12218c47bda6618b..91b2fc5b2da6566b05fef1111665b895
int floor = Mth.floor(aabb.minX);
int floor1 = Mth.floor(aabb.maxX);
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index ce2621a87dec1befb016b3437ceb2d02ed6d0b75..c0d941af10ffe8c158dab9db40c7c5767b6cfd6e 100644
index ce2621a87dec1befb016b3437ceb2d02ed6d0b75..9b37b763c6555705f3e256010f508b5a0c2cdb66 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -445,7 +445,7 @@ public final class NaturalSpawner {
@@ -43,7 +43,7 @@ index ce2621a87dec1befb016b3437ceb2d02ed6d0b75..c0d941af10ffe8c158dab9db40c7c576
ServerLevel level, StructureManager structureManager, ChunkGenerator generator, MobCategory category, RandomSource random, BlockPos pos
) {
- Holder<Biome> biome = level.getBiome(pos);
+ Holder<Biome> biome = level.getBiomeCached(pos); // Leaf - cache getBiome
+ Holder<Biome> biome = org.dreeam.leaf.config.modules.opt.OptimizeBiome.mobSpawn ? level.getBiomeCached(pos) : level.getBiome(pos); // Leaf - cache getBiome
return category == MobCategory.WATER_AMBIENT && biome.is(BiomeTags.REDUCED_WATER_AMBIENT_SPAWNS) && random.nextFloat() < 0.98F
? Optional.empty()
: mobsAt(level, structureManager, generator, category, pos, biome).getRandom(random);
@@ -52,7 +52,7 @@ index ce2621a87dec1befb016b3437ceb2d02ed6d0b75..c0d941af10ffe8c158dab9db40c7c576
return isInNetherFortressBounds(pos, level, category, structureManager)
? NetherFortressStructure.FORTRESS_ENEMIES
- : generator.getMobsAt(biome != null ? biome : level.getBiome(pos), structureManager, category, pos);
+ : generator.getMobsAt(biome != null ? biome : level.getBiomeCached(pos), structureManager, category, pos); // Leaf - cache getBiome
+ : generator.getMobsAt(biome != null ? biome : (org.dreeam.leaf.config.modules.opt.OptimizeBiome.mobSpawn ? level.getBiomeCached(pos) : level.getBiome(pos)), structureManager, category, pos); // Leaf - cache getBiome
}
public static boolean isInNetherFortressBounds(BlockPos pos, ServerLevel level, MobCategory category, StructureManager structureManager) {

View File

@@ -1,14 +1,95 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: hayanesuru <hayanesuru@outlook.jp>
Date: Tue, 3 Jun 2025 15:20:59 +0900
Subject: [PATCH] optimise NaturalSpawner#spawnForChunk
Subject: [PATCH] optimize mob spawning
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index d61da0fbe7f6c181e4084ce60bfe7dab86f361ad..1ce1b21a77cd727b52bd937b65ce97517fed9c68 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -70,7 +70,9 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
private final Set<ChunkHolder> chunkHoldersToBroadcast = new ReferenceOpenHashSet<>();
@Nullable
@VisibleForDebug
- private NaturalSpawner.SpawnState lastSpawnState;
+ private volatile NaturalSpawner.SpawnState lastSpawnState; // Leaf
+ private long delayTimeInhabited = 0L; // Leaf
+ private long delaySpawn = -1L; // Leaf
// Paper start
private final ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<net.minecraft.world.level.chunk.LevelChunk> fullChunks = new ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<>();
public int getFullChunksCount() {
@@ -656,13 +658,37 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
filteredSpawningCategories = List.of();
}
- for (LevelChunk levelChunk : chunks) {
- ChunkPos pos = levelChunk.getPos();
- levelChunk.incrementInhabitedTime(timeInhabited);
- if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && lastSpawnState != null && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get()) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot // Pufferfish // Leaf - Don't spawn if lastSpawnState is null
- NaturalSpawner.spawnForChunk(this.level, levelChunk, lastSpawnState, filteredSpawningCategories); // Pufferfish
+ // Leaf start
+ var lastSpawnState1 = this.lastSpawnState;
+ if (lastSpawnState1 != null && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get())) {
+ long sumTimeInhabited = timeInhabited + delayTimeInhabited;
+ long time = level.getGameTime();
+ for (LevelChunk levelChunk : chunks) {
+ ChunkPos pos = levelChunk.getPos();
+ levelChunk.incrementInhabitedTime(sumTimeInhabited);
+ if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot
+ NaturalSpawner.spawnForChunk(this.level, levelChunk, lastSpawnState1, filteredSpawningCategories, time); // Pufferfish
+ }
+ }
+ if (delaySpawn != -1L) {
+ time = delaySpawn;
+ for (LevelChunk levelChunk : chunks) {
+ ChunkPos pos = levelChunk.getPos();
+ if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot
+ NaturalSpawner.spawnForChunk(this.level, levelChunk, lastSpawnState1, filteredSpawningCategories, time); // Pufferfish
+ }
+ }
}
+ delaySpawn = -1L;
+ delayTimeInhabited = 0L;
+ } else {
+ // unlikely
+ delayTimeInhabited += timeInhabited;
+ delaySpawn = level.getGameTime();
+ }
+ // Leaf end
+ for (LevelChunk levelChunk : chunks) { // Leaf - split to 2 loop
if (true) { // Paper - rewrite chunk system
this.level.tickChunk(levelChunk, _int);
}
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index c0d941af10ffe8c158dab9db40c7c5767b6cfd6e..450f17badaa3f6c8f1cdb9e6dc76828b70afe6fc 100644
index 9b37b763c6555705f3e256010f508b5a0c2cdb66..7bfc636fb442036f742903c4e69a8a9fcd0e6fc2 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -238,10 +238,13 @@ public final class NaturalSpawner {
@@ -155,7 +155,13 @@ public final class NaturalSpawner {
return list;
}
+ @Deprecated(forRemoval = true) // Leaf
public static void spawnForChunk(ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnState spawnState, List<MobCategory> categories) {
+ // Leaf start
+ spawnForChunk(level, chunk, spawnState, categories, level.getGameTime());
+ }
+ public static void spawnForChunk(ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnState spawnState, List<MobCategory> categories, long gameTime) {
+ // Leaf end
for (MobCategory mobCategory : categories) {
// Paper start - Optional per player mob spawns
final boolean canSpawn;
@@ -174,7 +180,7 @@ public final class NaturalSpawner {
}
// Paper end - throttle failed spawn attempts
if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
- spawnThisTick = ticksPerSpawnTmp != 0 && level.getGameTime() % ticksPerSpawn == 0; // Paper - throttle failed spawn attempts
+ spawnThisTick = ticksPerSpawnTmp != 0 && gameTime % ticksPerSpawn == 0; // Paper - throttle failed spawn attempts // Leaf
limit = level.getWorld().getSpawnLimit(spawnCategory);
}
@@ -238,12 +244,14 @@ public final class NaturalSpawner {
// Paper end - throttle failed spawn attempts
) {
// Paper end - Optional per player mob spawns
@@ -18,27 +99,24 @@ index c0d941af10ffe8c158dab9db40c7c5767b6cfd6e..450f17badaa3f6c8f1cdb9e6dc76828b
+ // Leaf start
+ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
+ mutableRandomPosWithin(pos, level, chunk);
+ if (pos.getY() >= level.getMinY() + 1) {
+ if (pos.getY() < level.getMinY() + 1) {
+ return 0;
}
-
- return 0; // Paper - throttle failed spawn attempts
+ return spawnCategoryForPosition(category, level, chunk, pos, filter, callback, maxSpawns, trackEntity, false); // Paper - Optional per player mob spawns // Paper - throttle failed spawn attempts
}
+ // Leaf end
return 0; // Paper - throttle failed spawn attempts
}
@@ -275,31 +278,60 @@ public final class NaturalSpawner {
@VisibleForDebug
@@ -275,31 +283,55 @@ public final class NaturalSpawner {
StructureManager structureManager = level.structureManager();
ChunkGenerator generator = level.getChunkSource().getGenerator();
int y = pos.getY();
+ int posX = pos.getX(); // Leaf
+ int posZ = pos.getZ(); // Leaf
int i = 0; // Paper - throttle failed spawn attempts
- BlockState blockState = level.getBlockStateIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn
+ // Leaf start
+ if (!level.getWorldBorder().isWithinBounds(pos) || level.isOutsideBuildHeight(pos)) {
+ return i;
+ }
+ BlockState blockState = chunk.getPos().longKey == ChunkPos.asLong(pos) ? chunk.getBlockState(posX, y, posZ) : level.getBlockStateIfLoaded(pos);
+ // Leaf end
BlockState blockState = level.getBlockStateIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn
if (blockState != null && !blockState.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn
- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
+ BlockPos.MutableBlockPos mutableBlockPos = pos instanceof BlockPos.MutableBlockPos pos2 ? pos2 : new BlockPos.MutableBlockPos(); // Leaf

View File

@@ -1,21 +1,21 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: hayanesuru <hayanesuru@outlook.jp>
Date: Tue, 3 Jun 2025 21:34:25 +0900
Date: Wed, 4 Jun 2025 20:54:03 +0900
Subject: [PATCH] throttle mob spawning
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 450f17badaa3f6c8f1cdb9e6dc76828b70afe6fc..2f709cca7180e2f4874a7f80ed32498aba6dcac0 100644
index 7bfc636fb442036f742903c4e69a8a9fcd0e6fc2..762bdf1fe19546f89d34b9efdad66b00dab80006 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -160,6 +160,17 @@ public final class NaturalSpawner {
@@ -166,6 +166,17 @@ public final class NaturalSpawner {
// Paper start - Optional per player mob spawns
final boolean canSpawn;
int maxSpawns = Integer.MAX_VALUE;
+ // Leaf start
+ if (org.dreeam.leaf.config.modules.opt.ThrottleNaturalSpawnMob.enabled) {
+ int spawnChance = org.dreeam.leaf.config.modules.opt.ThrottleNaturalSpawnMob.spawnChance[mobCategory.ordinal()];
+ long failedAttempt = org.dreeam.leaf.config.modules.opt.ThrottleNaturalSpawnMob.failedAttempts[mobCategory.ordinal()];
+ if (org.dreeam.leaf.config.modules.opt.ThrottleNaturalMobSpawning.enabled) {
+ int spawnChance = org.dreeam.leaf.config.modules.opt.ThrottleNaturalMobSpawning.spawnChance[mobCategory.ordinal()];
+ long failedAttempt = org.dreeam.leaf.config.modules.opt.ThrottleNaturalMobSpawning.failedAttempts[mobCategory.ordinal()];
+ if (failedAttempt >= 0L
+ && chunk.failedSpawnAttempts[mobCategory.ordinal()] >= failedAttempt
+ && (level.random.nextInt() & 1023) > spawnChance) {

View File

@@ -1,81 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: hayanesuru <hayanesuru@outlook.jp>
Date: Wed, 4 Jun 2025 00:31:39 +0900
Subject: [PATCH] delay to next tick when mob spawning not ready
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index d61da0fbe7f6c181e4084ce60bfe7dab86f361ad..d9f74ac79e67ed7b9619041cce763b60a8f9a929 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -70,7 +70,8 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
private final Set<ChunkHolder> chunkHoldersToBroadcast = new ReferenceOpenHashSet<>();
@Nullable
@VisibleForDebug
- private NaturalSpawner.SpawnState lastSpawnState;
+ private volatile NaturalSpawner.SpawnState lastSpawnState; // Leaf
+ private final it.unimi.dsi.fastutil.longs.LongArrayList delaySpawn = new it.unimi.dsi.fastutil.longs.LongArrayList(); // Leaf
// Paper start
private final ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<net.minecraft.world.level.chunk.LevelChunk> fullChunks = new ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<>();
public int getFullChunksCount() {
@@ -656,13 +657,30 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
filteredSpawningCategories = List.of();
}
- for (LevelChunk levelChunk : chunks) {
- ChunkPos pos = levelChunk.getPos();
- levelChunk.incrementInhabitedTime(timeInhabited);
- if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && lastSpawnState != null && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get()) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot // Pufferfish // Leaf - Don't spawn if lastSpawnState is null
- NaturalSpawner.spawnForChunk(this.level, levelChunk, lastSpawnState, filteredSpawningCategories); // Pufferfish
+ // Leaf start
+ var lastSpawnState1 = this.lastSpawnState;
+ if (lastSpawnState1 != null && (!org.dreeam.leaf.config.modules.async.AsyncMobSpawning.enabled || _pufferfish_spawnCountsReady.get())) {
+ int delaySpawnSize = delaySpawn.size();
+ for (LevelChunk levelChunk : chunks) {
+ ChunkPos pos = levelChunk.getPos();
+ levelChunk.incrementInhabitedTime(timeInhabited);
+ if (!filteredSpawningCategories.isEmpty() && this.level.getWorldBorder().isWithinBounds(pos) && this.chunkMap.anyPlayerCloseEnoughForSpawning(pos, true)) { // Spigot
+ for (int i = 0; i < delaySpawnSize; i++) {
+ NaturalSpawner.spawnForChunk(this.level, levelChunk, lastSpawnState1, filteredSpawningCategories, delaySpawn.getLong(i));
+ }
+ NaturalSpawner.spawnForChunk(this.level, levelChunk, lastSpawnState1, filteredSpawningCategories); // Pufferfish
+ }
}
+ delaySpawn.clear();
+ } else {
+ for (LevelChunk levelChunk : chunks) {
+ levelChunk.incrementInhabitedTime(timeInhabited);
+ }
+ delaySpawn.add(level.getGameTime());
+ }
+ // Leaf end
+ for (LevelChunk levelChunk : chunks) { // Leaf
if (true) { // Paper - rewrite chunk system
this.level.tickChunk(levelChunk, _int);
}
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 2f709cca7180e2f4874a7f80ed32498aba6dcac0..32c9106b70ef7ab85077d6ec4bd7d7b84d9f8c00 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -156,6 +156,11 @@ public final class NaturalSpawner {
}
public static void spawnForChunk(ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnState spawnState, List<MobCategory> categories) {
+ // Leaf start
+ spawnForChunk(level, chunk, spawnState, categories, level.getGameTime());
+ }
+ public static void spawnForChunk(ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnState spawnState, List<MobCategory> categories, long gameTime) {
+ // Leaf end
for (MobCategory mobCategory : categories) {
// Paper start - Optional per player mob spawns
final boolean canSpawn;
@@ -185,7 +190,7 @@ public final class NaturalSpawner {
}
// Paper end - throttle failed spawn attempts
if (CraftSpawnCategory.isValidForLimits(spawnCategory)) {
- spawnThisTick = ticksPerSpawnTmp != 0 && level.getGameTime() % ticksPerSpawn == 0; // Paper - throttle failed spawn attempts
+ spawnThisTick = ticksPerSpawnTmp != 0 && gameTime % ticksPerSpawn == 0; // Paper - throttle failed spawn attempts // Leaf
limit = level.getWorld().getSpawnLimit(spawnCategory);
}

View File

@@ -0,0 +1,108 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: hayanesuru <hayanesuru@outlook.jp>
Date: Wed, 4 Jun 2025 20:54:32 +0900
Subject: [PATCH] preload mob spawning position
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 762bdf1fe19546f89d34b9efdad66b00dab80006..0443df34de4f940f64e563ea76453493cadf200b 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -257,9 +257,56 @@ public final class NaturalSpawner {
// Paper end - Optional per player mob spawns
// Leaf start
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
- mutableRandomPosWithin(pos, level, chunk);
- if (pos.getY() < level.getMinY() + 1) {
- return 0;
+ // Leaf start
+ if (org.dreeam.leaf.config.modules.opt.PreloadNaturalMobSpawning.enabled) {
+ if (chunk.cacheSpawnPosIndex == 16 || chunk.cacheSpawnPosIndex == -1) {
+ if (chunk.cacheSpawnPos == null) {
+ chunk.cacheSpawnPos = new long[16];
+ }
+ // cache friendly
+ for (int i = 0; i < 16; i++) {
+ mutableRandomPosWithin(pos, level, chunk);
+ if (pos.getY() >= level.getMinY() + 1
+ && level.getWorldBorder().isWithinBounds(pos)
+ && !level.isOutsideBuildHeight(pos)) {
+ LevelChunk chunk1 = chunk.getPos().longKey == ChunkPos.asLong(pos)
+ ? chunk
+ : level.chunkSource.getChunkAtIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4);
+ if (chunk1 != null) {
+ BlockState bs = chunk1.getBlockStateFinal(pos.getX(), pos.getY(), pos.getZ());
+ if (bs != null && !bs.isRedstoneConductor(level, pos)) {
+ chunk.cacheSpawnPos[i] = BlockPos.asLong(pos.getX(), pos.getY(), pos.getZ());
+ continue;
+ }
+ }
+ }
+ chunk.cacheSpawnPos[i] = -1;
+ }
+ chunk.cacheSpawnPosIndex = 0;
+ }
+ long cachePos = chunk.cacheSpawnPos[chunk.cacheSpawnPosIndex];
+ chunk.cacheSpawnPosIndex++;
+ if (cachePos == -1) {
+ return 0;
+ }
+ pos.set(cachePos);
+ } else {
+ mutableRandomPosWithin(pos, level, chunk);
+ if (pos.getY() < level.getMinY() + 1
+ || !level.getWorldBorder().isWithinBounds(pos)
+ || level.isOutsideBuildHeight(pos)) {
+ return 0;
+ }
+ LevelChunk chunk1 = chunk.getPos().longKey == ChunkPos.asLong(pos)
+ ? chunk
+ : level.chunkSource.getChunkAtIfLoadedImmediately(pos.getX() >> 4, pos.getZ() >> 4);
+ if (chunk1 == null) {
+ return 0;
+ }
+ BlockState bs = chunk1.getBlockStateFinal(pos.getX(), pos.getY(), pos.getZ());
+ if (bs == null || bs.isRedstoneConductor(level, pos)) {
+ return 0;
+ }
}
return spawnCategoryForPosition(category, level, chunk, pos, filter, callback, maxSpawns, trackEntity, false); // Paper - Optional per player mob spawns // Paper - throttle failed spawn attempts
// Leaf end
@@ -284,7 +331,12 @@ public final class NaturalSpawner {
MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final @Nullable Consumer<Entity> trackEntity
// Paper start - throttle failed spawn attempts
) {
- spawnCategoryForPosition(category, level, chunk, pos, filter, callback, maxSpawns, trackEntity, false);
+ // Leaf start
+ BlockState blockState = level.getBlockStateIfLoadedAndInBounds(pos);
+ if (blockState != null && !blockState.isRedstoneConductor(chunk, pos)) {
+ spawnCategoryForPosition(category, level, chunk, pos, filter, callback, maxSpawns, trackEntity, false);
+ }
+ // Leaf end
}
public static int spawnCategoryForPosition(
MobCategory category, ServerLevel level, ChunkAccess chunk, BlockPos pos, NaturalSpawner.SpawnPredicate filter, NaturalSpawner.AfterSpawnCallback callback, final int maxSpawns, final @Nullable Consumer<Entity> trackEntity, final boolean nothing
@@ -297,8 +349,8 @@ public final class NaturalSpawner {
int posX = pos.getX(); // Leaf
int posZ = pos.getZ(); // Leaf
int i = 0; // Paper - throttle failed spawn attempts
- BlockState blockState = level.getBlockStateIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn
- if (blockState != null && !blockState.isRedstoneConductor(chunk, pos)) { // Paper - don't load chunks for mob spawn
+ // BlockState blockState = level.getBlockStateIfLoadedAndInBounds(pos); // Paper - don't load chunks for mob spawn // Leaf
+ if (true /*blockState != null && !blockState.isRedstoneConductor(chunk, pos)*/) { // Paper - don't load chunks for mob spawn // Leaf
BlockPos.MutableBlockPos mutableBlockPos = pos instanceof BlockPos.MutableBlockPos pos2 ? pos2 : new BlockPos.MutableBlockPos(); // Leaf
//int i = 0; // Paper - throttle failed spawn attempts - move up
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index e6eab6929b08503c49debbbd25497ffedad438e1..624a177695580510c0a49d4503dee72da7fd7114 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -106,6 +106,8 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
// Paper start - rewrite chunk system
private boolean postProcessingDone;
private net.minecraft.server.level.ServerChunkCache.ChunkAndHolder chunkAndHolder;
+ public long[] cacheSpawnPos = null; // Leaf
+ public int cacheSpawnPosIndex = -1; // Leaf
@Override
public final boolean moonrise$isPostProcessingDone() {

View File

@@ -5,13 +5,17 @@ import org.dreeam.leaf.config.EnumConfigCategory;
public class OptimizeBiome extends ConfigModules {
public String getBasePath() {
return EnumConfigCategory.PERF.getBaseKeyName() + ".cache-mob-spawning-biome";
return EnumConfigCategory.PERF.getBaseKeyName() + ".cache-biome";
}
public static boolean enabled = false;
public static boolean mobSpawn = false;
public static boolean advancement = false;
@Override
public void onLoaded() {
enabled = config().getBoolean(getBasePath(), enabled);
enabled = config().getBoolean(getBasePath() + ".enabled", enabled);
mobSpawn = config.getBoolean(getBasePath() + ".mob-spawning", false);
advancement = config.getBoolean(getBasePath() + ".advancements", false);
}
}

View File

@@ -0,0 +1,17 @@
package org.dreeam.leaf.config.modules.opt;
import org.dreeam.leaf.config.ConfigModules;
import org.dreeam.leaf.config.EnumConfigCategory;
public class PreloadNaturalMobSpawning extends ConfigModules {
public String getBasePath() {
return EnumConfigCategory.PERF.getBaseKeyName() + ".preload-mob-spawning-position";
}
public static boolean enabled = false;
@Override
public void onLoaded() {
enabled = config.getBoolean(getBasePath() + ".enabled", enabled);
}
}

View File

@@ -4,9 +4,9 @@ import net.minecraft.world.entity.MobCategory;
import org.dreeam.leaf.config.ConfigModules;
import org.dreeam.leaf.config.EnumConfigCategory;
public class ThrottleNaturalSpawnMob extends ConfigModules {
public class ThrottleNaturalMobSpawning extends ConfigModules {
public String getBasePath() {
return EnumConfigCategory.PERF.getBaseKeyName() + ".throttled-mob-spawning";
return EnumConfigCategory.PERF.getBaseKeyName() + ".throttle-mob-spawning";
}
public static boolean enabled = false;
@@ -21,7 +21,7 @@ public class ThrottleNaturalSpawnMob extends ConfigModules {
spawnChance = new int[categories.length];
for (int i = 0; i < categories.length; i++) {
String category = getBasePath() + "." + categories[i].getSerializedName();
long attempts = config.getLong(category + ".min-failed-attempts", 8);
long attempts = config.getLong(category + ".min-failed", 8);
double chance = config.getDouble(category + ".spawn-chance", 25.0);
failedAttempts[i] = Math.max(-1, attempts);