diff --git a/leaf-server/minecraft-patches/features/0184-optimise-getBiome.patch b/leaf-server/minecraft-patches/features/0184-optimise-getBiome.patch index fca33074..4eaf4697 100644 --- a/leaf-server/minecraft-patches/features/0184-optimise-getBiome.patch +++ b/leaf-server/minecraft-patches/features/0184-optimise-getBiome.patch @@ -57,26 +57,42 @@ index ce2621a87dec1befb016b3437ceb2d02ed6d0b75..c0d941af10ffe8c158dab9db40c7c576 public static boolean isInNetherFortressBounds(BlockPos pos, ServerLevel level, MobCategory category, StructureManager structureManager) { diff --git a/net/minecraft/world/level/biome/BiomeManager.java b/net/minecraft/world/level/biome/BiomeManager.java -index a48175a7ebb1788ace46395621ed78d910178a53..4c0c74b73651cdbc98f0c8f101832e4c23fd0f8d 100644 +index a48175a7ebb1788ace46395621ed78d910178a53..cb6b99dd4504681bdf2f7dbd7e3d2218304f891a 100644 --- a/net/minecraft/world/level/biome/BiomeManager.java +++ b/net/minecraft/world/level/biome/BiomeManager.java -@@ -15,6 +15,10 @@ public class BiomeManager { +@@ -15,10 +15,23 @@ public class BiomeManager { private final BiomeManager.NoiseBiomeSource noiseBiomeSource; private final long biomeZoomSeed; private static final double maxOffset = 0.4500000001D; // Leaf - Carpet-Fixes - Optimized getBiome method + // Leaf start - cache getBiome -+ private final Holder[] biomeCache = new Holder[65536]; -+ private final long[] biomeCachePos = new long[65536]; ++ private final Holder[] biomeCache; ++ private final long[] biomeCachePos; + // Leaf end - cache getBiome public BiomeManager(BiomeManager.NoiseBiomeSource noiseBiomeSource, long biomeZoomSeed) { this.noiseBiomeSource = noiseBiomeSource; -@@ -29,6 +33,37 @@ public class BiomeManager { + this.biomeZoomSeed = biomeZoomSeed; ++ // Leaf start - cache getBiome ++ if (org.dreeam.leaf.config.modules.opt.OptimizeBiome.enabled) { ++ biomeCache = new Holder[65536]; ++ biomeCachePos = new long[65536]; ++ } else { ++ biomeCache = null; ++ biomeCachePos = null; ++ } ++ // Leaf end - cache getBiome + } + + public static long obfuscateSeed(long seed) { +@@ -29,6 +42,40 @@ public class BiomeManager { return new BiomeManager(newSource, this.biomeZoomSeed); } + // Leaf start - cache getBiome + public Holder getBiomeCached(BlockPos pos) { ++ if (biomeCache == null) { ++ return getBiome(pos); ++ } + int xMinus2 = pos.getX() - 2; + int yMinus2 = pos.getY() - 2; + int zMinus2 = pos.getZ() - 2; @@ -109,7 +125,7 @@ index a48175a7ebb1788ace46395621ed78d910178a53..4c0c74b73651cdbc98f0c8f101832e4c public Holder getBiome(BlockPos pos) { // Leaf start - Carpet-Fixes - Optimized getBiome method int xMinus2 = pos.getX() - 2; -@@ -126,9 +161,18 @@ public class BiomeManager { +@@ -126,9 +173,18 @@ public class BiomeManager { return Mth.square(zNoise + fiddle2) + Mth.square(yNoise + fiddle1) + Mth.square(xNoise + fiddle); } diff --git a/leaf-server/minecraft-patches/features/0185-optimise-NaturalSpawner-spawnForChunk.patch b/leaf-server/minecraft-patches/features/0185-optimise-NaturalSpawner-spawnForChunk.patch index a97d2de1..6601e40d 100644 --- a/leaf-server/minecraft-patches/features/0185-optimise-NaturalSpawner-spawnForChunk.patch +++ b/leaf-server/minecraft-patches/features/0185-optimise-NaturalSpawner-spawnForChunk.patch @@ -5,45 +5,27 @@ Subject: [PATCH] optimise NaturalSpawner#spawnForChunk diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java -index c0d941af10ffe8c158dab9db40c7c5767b6cfd6e..878eb750f2d2bddae81d9fbfb772d13077b37d51 100644 +index c0d941af10ffe8c158dab9db40c7c5767b6cfd6e..450f17badaa3f6c8f1cdb9e6dc76828b70afe6fc 100644 --- a/net/minecraft/world/level/NaturalSpawner.java +++ b/net/minecraft/world/level/NaturalSpawner.java -@@ -156,8 +156,15 @@ public final class NaturalSpawner { - } +@@ -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 - public static void spawnForChunk(ServerLevel level, LevelChunk chunk, NaturalSpawner.SpawnState spawnState, List categories) { -+ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); // Leaf - for (MobCategory mobCategory : categories) { - // Paper start - Optional per player mob spawns -+ // Leaf start - reduce 3/4 while failed 16 canSpawn attempts -+ if (chunk.failedSpawnAttempts[mobCategory.ordinal()] >= 16 && (level.random.nextInt(4)) != 0) { -+ continue; -+ } -+ // Leaf end - reduce 3/4 while failed 16 canSpawn attempts -+ // Paper start - Optional per player mob attempts - final boolean canSpawn; - int maxSpawns = Integer.MAX_VALUE; - if (level.paperConfig().entities.spawning.perPlayerMobSpawns) { -@@ -197,9 +204,16 @@ public final class NaturalSpawner { - canSpawn = spawnState.canSpawnForCategoryLocal(mobCategory, chunk.getPos()); - } - if (canSpawn) { -+ // Leaf start - // Paper start - throttle failed spawn attempts -- int spawnCount = spawnCategoryForChunk(mobCategory, level, chunk, spawnState::canSpawn, spawnState::afterSpawn, -- maxSpawns, level.paperConfig().entities.spawning.perPlayerMobSpawns ? level.getChunkSource().chunkMap::updatePlayerMobTypeMap : null, false); -+ int spawnCount = 0; -+ final Consumer trackEntity = level.paperConfig().entities.spawning.perPlayerMobSpawns ? level.getChunkSource().chunkMap::updatePlayerMobTypeMap : null; -+ // Paper end - Optional per player mob spawns -+ mutableRandomPosWithin(pos, level, chunk); -+ if (pos.getY() >= level.getMinY() + 1) { -+ spawnCount = spawnCategoryForPosition(mobCategory, level, chunk, pos, spawnState::canSpawn, spawnState::afterSpawn, maxSpawns, trackEntity, false);// Paper - Optional per player mob spawns // Paper - throttle failed spawn attempts -+ } // Paper - throttle failed spawn attempts -+ // Leaf end - if (spawnCount == 0) { - chunk.failedSpawnAttempts[mobCategory.ordinal()]++; - } else { -@@ -275,31 +289,60 @@ public final class NaturalSpawner { + 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(); @@ -113,7 +95,7 @@ index c0d941af10ffe8c158dab9db40c7c5767b6cfd6e..878eb750f2d2bddae81d9fbfb772d130 if (spawnerData == null) { Optional randomSpawnMobAt = getRandomSpawnMobAt( level, structureManager, generator, category, level.random, mutableBlockPos -@@ -368,8 +411,8 @@ public final class NaturalSpawner { +@@ -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) @@ -124,7 +106,7 @@ index c0d941af10ffe8c158dab9db40c7c5767b6cfd6e..878eb750f2d2bddae81d9fbfb772d130 } // Paper start - PreCreatureSpawnEvent -@@ -474,6 +517,17 @@ public final class NaturalSpawner { +@@ -474,6 +506,17 @@ public final class NaturalSpawner { } } diff --git a/leaf-server/minecraft-patches/features/0186-optimize-structure-map.patch b/leaf-server/minecraft-patches/features/0186-optimize-structure-map.patch index 19712045..34592250 100644 --- a/leaf-server/minecraft-patches/features/0186-optimize-structure-map.patch +++ b/leaf-server/minecraft-patches/features/0186-optimize-structure-map.patch @@ -5,7 +5,7 @@ Subject: [PATCH] optimize structure map diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java -index 50a9903367f49ece2a267d10944b1515c7b93859..db6828ec94682c16b5b7ec6fc6262df256781f01 100644 +index 50a9903367f49ece2a267d10944b1515c7b93859..ceabb277bef2633de8f55e16431dbb4d0869817b 100644 --- a/net/minecraft/world/level/chunk/ChunkAccess.java +++ b/net/minecraft/world/level/chunk/ChunkAccess.java @@ -76,8 +76,8 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh @@ -24,7 +24,7 @@ index 50a9903367f49ece2a267d10944b1515c7b93859..db6828ec94682c16b5b7ec6fc6262df2 public Map getAllStarts() { - return Collections.unmodifiableMap(this.structureStarts); -+ return it.unimi.dsi.fastutil.objects.Object2ObjectMaps.unmodifiable((it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap) this.structureStarts); // Leaf ++ return this.structureStarts; // Leaf } public void setAllStarts(Map structureStarts) { @@ -40,7 +40,7 @@ index 50a9903367f49ece2a267d10944b1515c7b93859..db6828ec94682c16b5b7ec6fc6262df2 @Override public Map getAllReferences() { - return Collections.unmodifiableMap(this.structuresRefences); -+ return it.unimi.dsi.fastutil.objects.Object2ObjectMaps.unmodifiable((it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap) this.structuresRefences); // Leaf ++ return this.structuresRefences; // Leaf } @Override diff --git a/leaf-server/minecraft-patches/features/0187-throttle-mob-spawning.patch b/leaf-server/minecraft-patches/features/0187-throttle-mob-spawning.patch new file mode 100644 index 00000000..c2e3ab5a --- /dev/null +++ b/leaf-server/minecraft-patches/features/0187-throttle-mob-spawning.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: hayanesuru +Date: Tue, 3 Jun 2025 21:34:25 +0900 +Subject: [PATCH] throttle mob spawning + + +diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java +index 450f17badaa3f6c8f1cdb9e6dc76828b70afe6fc..8db4fd335e661111c52721be2f5ffc65a2c843d2 100644 +--- a/net/minecraft/world/level/NaturalSpawner.java ++++ b/net/minecraft/world/level/NaturalSpawner.java +@@ -160,6 +160,18 @@ 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 (failedAttempt >= 0L ++ && spawnChance >= 0 ++ && chunk.failedSpawnAttempts[mobCategory.ordinal()] >= failedAttempt ++ && (level.random.nextInt() & 1023) > spawnChance) { ++ continue; ++ } ++ } ++ // Leaf end + if (level.paperConfig().entities.spawning.perPlayerMobSpawns) { + // Copied from getFilteredSpawningCategories + int limit = mobCategory.getMaxInstancesPerChunk(); diff --git a/leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizeBiome.java b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizeBiome.java new file mode 100644 index 00000000..3287f98c --- /dev/null +++ b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/OptimizeBiome.java @@ -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 OptimizeBiome extends ConfigModules { + public String getBasePath() { + return EnumConfigCategory.PERF.getBaseKeyName() + ".cache-mob-spawning-biome"; + } + + public static boolean enabled = false; + + @Override + public void onLoaded() { + enabled = config().getBoolean(getBasePath(), enabled); + } +} diff --git a/leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/ThrottleNaturalSpawnMob.java b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/ThrottleNaturalSpawnMob.java new file mode 100644 index 00000000..2be54108 --- /dev/null +++ b/leaf-server/src/main/java/org/dreeam/leaf/config/modules/opt/ThrottleNaturalSpawnMob.java @@ -0,0 +1,28 @@ +package org.dreeam.leaf.config.modules.opt; + +import net.minecraft.world.entity.MobCategory; +import org.dreeam.leaf.config.ConfigModules; +import org.dreeam.leaf.config.EnumConfigCategory; + +public class ThrottleNaturalSpawnMob extends ConfigModules { + public String getBasePath() { + return EnumConfigCategory.PERF.getBaseKeyName() + ".throttled-mob-spawning"; + } + + public static boolean enabled = false; + public static long[] failedAttempts; + public static int[] spawnChance; + + @Override + public void onLoaded() { + enabled = config.getBoolean(getBasePath() + ".enabled", enabled); + MobCategory[] categories = MobCategory.values(); + failedAttempts = new long[categories.length]; + spawnChance = new int[categories.length]; + for (int i = 0; i < categories.length; i++) { + String category = getBasePath() + "." + categories[i].getSerializedName(); + failedAttempts[i] = config.getLong(category + ".failed-attempts", -1); + spawnChance[i] = (int) Math.round(config.getDouble(category + ".spawn-chance", 100.0) * 10.24); + } + } +}