From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Martijn Muijsers Date: Wed, 23 Nov 2022 16:45:45 +0100 Subject: [PATCH] Optimize random calls in chunk ticking License: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) Gale - https://galemc.org This patch is based on the following patch: "Optimize random calls in chunk ticking" By: Paul Sauve As part of: Airplane (https://github.com/TECHNOVE/Airplane) Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) The patch also received the following subsequent modification: By: Kevin Raneri As part of: Pufferfish (https://github.com/pufferfish-gg/Pufferfish) Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html) * Airplane description * Especially at over 30,000 chunks these random calls are fairly heavy. We use a different method here for checking lightning, and for checking ice. Lightning: Each chunk now keeps an int of how many ticks until the lightning should strike. This int is a random number from 0 to 100000 * 2, the multiplication is required to keep the probability the same. Ice and snow: We just generate a single random number 0-16 and increment it, while checking if it's 0 for the current chunk. Depending on configuration for things that tick in a chunk, this is a 5-10% improvement. * Airplane copyright * Airplane Copyright (C) 2020 Technove LLC This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java index 19625d104b19e02101ee7685a1df5bfd0c905296..643143fa45c7c480e4bbd3d03e1b7cc19e2969e2 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -603,6 +603,7 @@ public class ServerChunkCache extends ChunkSource { player.playerNaturallySpawnedEvent = event; } // Paper end - optimise chunk tick iteration + this.level.resetIceAndSnowTick(); // Gale - Airplane - optimize random calls in chunk ticking - reset ice & snow tick random int l = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.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 e38cd60ba31129ed53c8c3839fedd6f77440f4b1..be1dbe955461823de7b3dbf032d399837be62ea9 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -958,6 +958,8 @@ public class ServerLevel extends Level implements WorldGenLevel { private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos(); // Paper end + private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Gale - Airplane - optimize random calls in chunk ticking + public void tickChunk(LevelChunk chunk, int randomTickSpeed) { ChunkPos chunkcoordintpair = chunk.getPos(); boolean flag = this.isRaining(); @@ -965,7 +967,7 @@ public class ServerLevel extends Level implements WorldGenLevel { int k = chunkcoordintpair.getMinBlockZ(); 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 && /*this.random.nextInt(this.spigotConfig.thunderChance) == 0 &&*/ chunk.shouldDoLightning(this.random)) { // Spigot // Paper - disable thunder // Gale - Airplane - optimize random calls in chunk ticking - replace random with shouldDoLightning blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper if (this.isRainingAt(blockposition)) { @@ -993,7 +995,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } } - if (!this.paperConfig().environment.disableIceAndSnow) { // Paper + if (!this.paperConfig().environment.disableIceAndSnow && (this.currentIceAndSnowTick++ & 15) == 0) { // Paper // Gale - Airplane - optimize random calls in chunk ticking - optimize further random ticking for (int l = 0; l < randomTickSpeed; ++l) { if (this.random.nextInt(48) == 0) { // Paper start 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 c5ab3058f66a54dba397aa4b562ec95e4fd25686..cd375184c63453829be96449c4df88372f905d9e 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -85,6 +85,18 @@ public class LevelChunk extends ChunkAccess { private final LevelChunkTicks fluidTicks; public volatile FullChunkStatus chunkStatus = FullChunkStatus.INACCESSIBLE; // Paper - rewrite chunk system + // Gale start - Airplane - optimize random calls in chunk ticking - 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; + } + // Gale end - Airplane - optimize random calls in chunk ticking - 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); } @@ -108,6 +120,7 @@ public class LevelChunk extends ChunkAccess { this.postLoad = entityLoader; this.blockTicks = blockTickScheduler; this.fluidTicks = fluidTickScheduler; + this.lightningTick = this.level.randomTickRandom.nextInt(100000) << 1; // Gale - Airplane - optimize random calls in chunk ticking - initialize lightning tick } // CraftBukkit start