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:
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
+ return spawnCategoryForPosition(category, level, chunk, pos, filter, callback, maxSpawns, trackEntity, false); // Paper - Optional per player mob spawns // Paper - throttle failed spawn attempts
|
||||
+ 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
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
Reference in New Issue
Block a user