From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Paul Sauve Date: Thu, 7 Jan 2021 11:49:36 -0600 Subject: [PATCH] Optimize random calls in chunk ticking 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 (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 3f0168a9edfa67f99e6fe9ce161878034e57c3f4..59b5d658c6dee34c819101a507ba4e7ecb5b80e0 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -987,6 +987,7 @@ public class ServerChunkCache extends ChunkSource { } // Paper end - optimize isOutisdeRange this.level.getProfiler().push("pollingChunks"); + this.level.resetIceAndSnowTick(); // Airplane - reset ice & snow tick random int k = this.level.getGameRules().getInt(GameRules.RULE_RANDOMTICKING); boolean flag2 = level.ticksPerAnimalSpawns != 0L && worlddata.getGameTime() % level.ticksPerAnimalSpawns == 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 f9ed48f5bbde84fd1804e482f2777b516cc3a1ef..ad02d30bcad577dbe38b6c16657899636f891007 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -838,6 +838,8 @@ public class ServerLevel extends Level implements WorldGenLevel { private final com.tuinity.tuinity.util.math.ThreadUnsafeRandom randomTickRandom = new com.tuinity.tuinity.util.math.ThreadUnsafeRandom(); // Paper end + private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Airplane + public void tickChunk(LevelChunk chunk, int randomTickSpeed) { ChunkPos chunkcoordintpair = chunk.getPos(); boolean flag = this.isRaining(); @@ -848,7 +850,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.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder + if (!this.paperConfig.disableThunder && flag && this.isThundering() && chunk.shouldDoLightning(this.random)) { // Paper - Disable thunder // Airplane - replace random with shouldDoLightning blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper if (this.isRainingAt(blockposition)) { DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition); @@ -872,7 +874,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } gameprofilerfiller.popPush("iceandsnow"); - if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking + if (!this.paperConfig.disableIceAndSnow && (this.currentIceAndSnowTick++ & 15) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking // Airplane - 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 4f6a356e3a27915f1d95132a0a5fddb163735cf6..3a8d1c79e85386efa39de5fac085bbdee0c076c1 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -172,6 +172,18 @@ public class LevelChunk implements ChunkAccess { } // Tuinity end - rewrite light engine + // Airplane 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(java.util.Random random) { + if (this.lightningTick-- <= 0) { + this.lightningTick = random.nextInt(100000) << 1; + return true; + } + return false; + } + // Airplane end + public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes) { this(world, pos, biomes, UpgradeData.EMPTY, EmptyTickList.empty(), EmptyTickList.empty(), 0L, (LevelChunkSection[]) null, (Consumer) null); } @@ -220,6 +232,7 @@ public class LevelChunk implements ChunkAccess { this.postProcessing = new ShortList[world.getSectionsCount()]; // CraftBukkit start this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this); + this.lightningTick = this.level.random.nextInt(100000) << 1; // Airplane - initialize lightning tick } public org.bukkit.Chunk bukkitChunk;