From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Sun, 14 Aug 2022 11:01:17 +0800 Subject: [PATCH] Optimize random calls in chunk ticking This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java index 6a2adfe51b5ea6b3290349781f41ed7818f15fe5..928139e8d0f7b65e2376d3c89d7bea294e3ed3a2 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -708,6 +708,11 @@ public class ServerChunkCache extends ChunkSource { ProfilerFiller gameprofilerfiller = this.level.getProfiler(); gameprofilerfiller.push("pollingChunks"); + // Leaves start - reset ice & snow tick random + if (top.leavesmc.leaves.LeavesConfig.optimizeChunkTicking) { + this.level.resetIceAndSnowTick(); + } + // Leaves end - reset ice & snow tick random 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 diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index b1950cd42cb7890309c1fb591110b6b9e4d37e51..03a4e114a3383ce779a6fc48747834b33b480f66 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -796,6 +796,13 @@ public class ServerLevel extends Level implements WorldGenLevel { // private final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(this.random.nextLong()); // Leaves - moved to super // Paper end + // Leaves start - reset ice & snow tick random + private int currentIceAndSnowTick = 0; + protected void resetIceAndSnowTick() { + this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); + } + // Leaves end - reset ice & snow tick random + public void tickChunk(LevelChunk chunk, int randomTickSpeed) { ChunkPos chunkcoordintpair = chunk.getPos(); boolean flag = this.isRaining(); @@ -806,7 +813,7 @@ public class ServerLevel extends Level implements WorldGenLevel { gameprofilerfiller.push("thunder"); final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change - if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && this.random.nextInt(this.spigotConfig.thunderChance) == 0) { // Spigot // Paper - disable thunder + if (!this.paperConfig().environment.disableThunder && flag && this.isThundering() && this.spigotConfig.thunderChance > 0 && (top.leavesmc.leaves.LeavesConfig.optimizeChunkTicking ? chunk.shouldDoLightning(this.random) : this.random.nextInt(this.spigotConfig.thunderChance) == 0)) { // Spigot // Paper - disable thunder // Leaves - replace random with shouldDoLightning blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper if (this.isRainingAt(blockposition)) { DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); @@ -836,7 +843,7 @@ public class ServerLevel extends Level implements WorldGenLevel { gameprofilerfiller.popPush("iceandsnow"); int l; - if (!this.paperConfig().environment.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow + if (!this.paperConfig().environment.disableIceAndSnow && (top.leavesmc.leaves.LeavesConfig.optimizeChunkTicking ? (this.currentIceAndSnowTick++ & 15) == 0 : this.random.nextInt(16) == 0)) { // Paper - Disable ice and snow // Paper - optimise random ticking // Leaves - optimize further random ticking // Paper start - optimise chunk ticking this.getRandomBlockPosition(j, 0, k, 15, blockposition); int normalY = chunk.getHeight(Heightmap.Types.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15) + 1; diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java index 28e4b302284f955a73e75d0f4276d55fb51826f5..1bf1af06fbd6501e98def7997c487c425d6a1623 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -88,6 +88,18 @@ public class LevelChunk extends ChunkAccess { private final LevelChunkTicks blockTicks; private final LevelChunkTicks fluidTicks; + // Leaves start - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively + private int lightningTick; + // shouldDoLightning compiles down to 29 bytes, which with the default of 35 byte inlining should guarantee an inline + public final boolean shouldDoLightning(net.minecraft.util.RandomSource random) { + if (this.lightningTick-- <= 0) { + this.lightningTick = random.nextInt(this.level.spigotConfig.thunderChance) << 1; + return true; + } + return false; + } + // Leaves end - instead of using a random every time the chunk is ticked, define when lightning strikes preemptively + public LevelChunk(Level world, ChunkPos pos) { this(world, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, (LevelChunkSection[]) null, (LevelChunk.PostLoadProcessor) null, (BlendingData) null); } @@ -118,6 +130,11 @@ public class LevelChunk extends ChunkAccess { this.fluidTicks = fluidTickScheduler; // CraftBukkit start this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); + // Leaves start - initialize lightning tick + if (top.leavesmc.leaves.LeavesConfig.optimizeChunkTicking) { + this.lightningTick = this.level.getThreadUnsafeRandom().nextInt(100000) << 1; + } + // Leaves end - initialize lightning tick } public org.bukkit.Chunk bukkitChunk; diff --git a/src/main/java/top/leavesmc/leaves/LeavesConfig.java b/src/main/java/top/leavesmc/leaves/LeavesConfig.java index 240fe801ba2670f5986faa58b77c7902f0465fc6..64215f03789db0555422c4b0aec32c8a4504cb4d 100644 --- a/src/main/java/top/leavesmc/leaves/LeavesConfig.java +++ b/src/main/java/top/leavesmc/leaves/LeavesConfig.java @@ -280,6 +280,15 @@ public final class LeavesConfig { checkSpookySeasonOnceAnHour = getBoolean("settings.performance.check-spooky-season-once-an-hour", checkSpookySeasonOnceAnHour); } + public static boolean optimizeChunkTicking = true; + private static boolean optimizeChunkTickingLock = false; + private static void optimizeChunkTicking() { + if (!optimizeChunkTickingLock) { + optimizeChunkTicking = getBoolean("settings.performance.optimize-chunk-ticking", optimizeChunkTicking); + optimizeChunkTickingLock = true; + } + } + public static final class WorldConfig { public final String worldName;