9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-28 19:39:17 +00:00
Files
Leaf/leaf-server/minecraft-patches/features/0185-optimise-NaturalSpawner-spawnForChunk.patch
hayanesuru 8e48e51e76 add config
2025-06-03 22:38:15 +09:00

127 lines
7.3 KiB
Diff

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
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index c0d941af10ffe8c158dab9db40c7c5767b6cfd6e..450f17badaa3f6c8f1cdb9e6dc76828b70afe6fc 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -238,10 +238,13 @@ public final class NaturalSpawner {
// Paper end - throttle failed spawn attempts
) {
// Paper end - Optional per player mob spawns
- BlockPos randomPosWithin = getRandomPosWithin(level, chunk);
- if (randomPosWithin.getY() >= level.getMinY() + 1) {
- return spawnCategoryForPosition(category, level, chunk, randomPosWithin, filter, callback, maxSpawns, trackEntity, false); // Paper - Optional per player mob spawns // Paper - throttle failed spawn attempts
+ // 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
}
+ // Leaf end
return 0; // Paper - throttle failed spawn attempts
}
@@ -275,31 +278,60 @@ 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
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
//int i = 0; // Paper - throttle failed spawn attempts - move up
+ // Leaf start
+ long rand = level.random.nextLong();
+ int bits = 0;
for (int i1 = 0; i1 < 3; i1++) {
- int x = pos.getX();
- int z = pos.getZ();
- int i2 = 6;
+ int x = posX;
+ int z = posZ;
MobSpawnSettings.SpawnerData spawnerData = null;
SpawnGroupData spawnGroupData = null;
- int ceil = Mth.ceil(level.random.nextFloat() * 4.0F);
+ int ceil = (int) ((rand & 0x3L) + 1L);
+ bits += 2;
int i3 = 0;
for (int i4 = 0; i4 < ceil; i4++) {
- x += level.random.nextInt(6) - level.random.nextInt(6);
- z += level.random.nextInt(6) - level.random.nextInt(6);
+ int rand1=0,rand2=0,rand3=0,rand4=0,valuesNeeded=4;
+ while (valuesNeeded > 0) {
+ if (bits > 61) {
+ rand = level.random.nextLong();
+ bits = 0;
+ }
+ int threeBits = (int) ((rand >>> bits) & 0x7L);
+ bits += 3;
+ if (threeBits != 7 && threeBits != 6) {
+ switch (valuesNeeded) {
+ case 1 -> rand4 = threeBits;
+ case 2 -> rand3 = threeBits;
+ case 3 -> rand2 = threeBits;
+ case 4 -> rand1 = threeBits;
+ }
+ valuesNeeded--;
+ }
+ }
+ x += rand1 - rand2;
+ z += rand3 - rand4;
+ // Leaf end
mutableBlockPos.set(x, y, z);
double d = x + 0.5;
double d1 = z + 0.5;
Player nearestPlayer = level.getNearestPlayer(d, y, d1, -1.0, level.purpurConfig.mobSpawningIgnoreCreativePlayers); // Purpur - mob spawning option to ignore creative players
if (nearestPlayer != null) {
double d2 = nearestPlayer.distanceToSqr(d, y, d1);
- if (level.isLoadedAndInBounds(mutableBlockPos) && isRightDistanceToPlayerAndSpawnPoint(level, chunk, mutableBlockPos, d2)) { // Paper - don't load chunks for mob spawn
+ if (level.getWorldBorder().isWithinBounds(mutableBlockPos) && (chunk.getPos().longKey == ChunkPos.asLong(mutableBlockPos) || level.getChunkIfLoadedImmediately(mutableBlockPos.getX() >> 4, mutableBlockPos.getZ() >> 4) != null) && isRightDistanceToPlayerAndSpawnPoint(level, chunk, mutableBlockPos, d2)) { // Paper - don't load chunks for mob spawn // Leaf
if (spawnerData == null) {
Optional<MobSpawnSettings.SpawnerData> randomSpawnMobAt = getRandomSpawnMobAt(
level, structureManager, generator, category, level.random, mutableBlockPos
@@ -368,8 +400,8 @@ public final class NaturalSpawner {
private static boolean isRightDistanceToPlayerAndSpawnPoint(ServerLevel level, ChunkAccess chunk, BlockPos.MutableBlockPos pos, double distance) {
return !(distance <= 576.0)
- && !level.getSharedSpawnPos().closerToCenterThan(new Vec3(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5), 24.0)
- && (Objects.equals(new ChunkPos(pos), chunk.getPos()) || level.isNaturalSpawningAllowed(pos));
+ && !(level.getSharedSpawnPos().distToCenterSqr(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5) < 576.0) // Leaf
+ && (ChunkPos.asLong(pos) == chunk.getPos().longKey || level.isNaturalSpawningAllowed(pos)); // Leaf
}
// Paper start - PreCreatureSpawnEvent
@@ -474,6 +506,17 @@ public final class NaturalSpawner {
}
}
+ // Leaf start
+ private static void mutableRandomPosWithin(BlockPos.MutableBlockPos pos1, Level level, LevelChunk chunk) {
+ ChunkPos pos = chunk.getPos();
+ int i = pos.getMinBlockX() + level.random.nextInt(16);
+ int i1 = pos.getMinBlockZ() + level.random.nextInt(16);
+ int i2 = chunk.getHeight(Heightmap.Types.WORLD_SURFACE, i, i1) + 1;
+ int i3 = Mth.randomBetweenInclusive(level.random, level.getMinY(), i2);
+ pos1.set(i, i3, i1);
+ }
+ // Leaf end
+
private static BlockPos getRandomPosWithin(Level level, LevelChunk chunk) {
ChunkPos pos = chunk.getPos();
int i = pos.getMinBlockX() + level.random.nextInt(16);