From aa295c78bc0181027c97528fd8ebbe46e340a7f6 Mon Sep 17 00:00:00 2001
From: MrPowerGamerBR
Date: Mon, 23 Oct 2023 00:33:25 -0300
Subject: [PATCH] Update upstream, add new cherry-picked patches from other
forks
---
BORKED_PATCHES.md | 16 +++
README.md | 11 +-
gradle.properties | 2 +-
...ve-iterators-from-inventory-contains.patch | 38 +++++++
...reams-and-iterators-from-range-check.patch | 49 +++++++++
...-an-iterator-in-getEffectiveRange-if.patch | 20 ----
...pelessRecipes-comparison-for-Vanilla.patch | 84 +++++++++++++++
...check-for-spooky-season-once-an-hour.patch | 49 +++++++++
...ve-ThreadUnsafeRandom-Initialization.patch | 35 ++++++
...hread-unsafe-random-for-mob-spawning.patch | 40 +++++++
...timize-random-calls-in-chunk-ticking.patch | 101 ++++++++++++++++++
.../0010-Reduce-chunk-loading-lookups.patch | 45 ++++++++
...turn-optimization-for-target-finding.patch | 31 ++++++
.../0012-Optimize-entity-coordinate-key.patch | 38 +++++++
...013-Remove-lambda-from-ticking-guard.patch | 52 +++++++++
.../0014-Reduce-entity-allocations.patch | 36 +++++++
...-Land-moisture-tick-rate-when-the-b.patch} | 0
...ring-once-per-world-instead-for-eve.patch} | 8 +-
18 files changed, 629 insertions(+), 26 deletions(-)
create mode 100644 BORKED_PATCHES.md
create mode 100644 patches/server/0003-Remove-iterators-from-inventory-contains.patch
create mode 100644 patches/server/0004-Remove-streams-and-iterators-from-range-check.patch
delete mode 100644 patches/server/0005-Avoid-allocating-an-iterator-in-getEffectiveRange-if.patch
create mode 100644 patches/server/0005-Simpler-ShapelessRecipes-comparison-for-Vanilla.patch
create mode 100644 patches/server/0006-Only-check-for-spooky-season-once-an-hour.patch
create mode 100644 patches/server/0007-Move-ThreadUnsafeRandom-Initialization.patch
create mode 100644 patches/server/0008-Use-thread-unsafe-random-for-mob-spawning.patch
create mode 100644 patches/server/0009-Optimize-random-calls-in-chunk-ticking.patch
create mode 100644 patches/server/0010-Reduce-chunk-loading-lookups.patch
create mode 100644 patches/server/0011-Early-return-optimization-for-target-finding.patch
create mode 100644 patches/server/0012-Optimize-entity-coordinate-key.patch
create mode 100644 patches/server/0013-Remove-lambda-from-ticking-guard.patch
create mode 100644 patches/server/0014-Reduce-entity-allocations.patch
rename patches/server/{0003-Configurable-Farm-Land-moisture-tick-rate-when-the-b.patch => 0015-Configurable-Farm-Land-moisture-tick-rate-when-the-b.patch} (100%)
rename patches/server/{0004-Only-check-thundering-once-per-world-instead-for-eve.patch => 0016-Only-check-thundering-once-per-world-instead-for-eve.patch} (88%)
diff --git a/BORKED_PATCHES.md b/BORKED_PATCHES.md
new file mode 100644
index 0000000..7cb947f
--- /dev/null
+++ b/BORKED_PATCHES.md
@@ -0,0 +1,16 @@
+# Borked Patches
+
+List of *maybe* borked and *maybe* useless patches that I found in other fork's that may be borked or not do anything useful, so I annoted them here to remember about why I didn't cherry-pick them to SparklyPaper.
+
+Keep in mind that I'm very naive when it comes to Minecraft Server internals, so I may be wrong!
+
+## (Pufferfish) `Reduce-entity-allocations`
+
+While not useless, the patch adds a `cachedBlockPos` variable that is never used by any other patch. Heck, not even in Airplane it was used!
+## (Pufferfish) `Skip-cloning-loot-parameters`
+
+Unnnecessarily wraps `parameters` and `dynamicDrops` into a unmodifiable map, causing unnecessary allocations.
+
+This was useful back in 1.17 days, where the patch DID bring a meaningful benefit, since vanilla used `ImmutableMap.copyOf` instead.
+
+As a reference, here's Airplane's original patch: https://github.com/TECHNOVE/Airplane/blob/af3563c98bdd8b27123e3a656de261ed96652b3e/patches/server/0030-Skip-cloning-loot-parameters.patch#L21
\ No newline at end of file
diff --git a/README.md b/README.md
index 0f23a70..b762812 100644
--- a/README.md
+++ b/README.md
@@ -6,4 +6,13 @@
✨ SparklyPaper ✨
-SparklyPower's Paper fork, with a mix of weird & crazy patches from other forks!
\ No newline at end of file
+SparklyPower's Paper fork, with a mix of weird & crazy patches from other forks!
+
+While our fork is mostly cherry-picked patches from other forks, we do have some handmade patches too to add and optimize some of the things that we have in our server!
+
+* Configurable Farm Land moisture tick rate when the block is already moisturised
+ * The isNearWater check is costly, especially if you have a lot of farm lands. If the block is already moistured, we can change the tick rate of it to avoid these expensive isNearWater checks.
+* Only check thundering once per world instead for every chunk
+ * For some reason the isThundering check is consuming ~3% of CPU time when profiled so, instead of checking the thunder every chunk, we can cache the result and reuse on the same chunk tick.
+
+We don't cherry-pick *everything* from other forks, only patches that I can see and think "yeah, I can see how this would improve performance" or patches that target specific performance/feature pain points in our server are cherry-picked! In fact, some patches that are used in other forks [may be actually borked](BORKED_PATCHES.md)...
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 16203b0..95dce08 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -2,7 +2,7 @@ group=net.sparklypower.sparklypaper
version=1.20.2-R0.1-SNAPSHOT
mcVersion=1.20.2
-paperRef=3a5c6f8cee7e1379fff1908e87af9fd5448eda0e
+paperRef=90fe0d58a5945c31f2c1b138799f64f2fe3475d8
org.gradle.caching=true
org.gradle.parallel=true
diff --git a/patches/server/0003-Remove-iterators-from-inventory-contains.patch b/patches/server/0003-Remove-iterators-from-inventory-contains.patch
new file mode 100644
index 0000000..549002f
--- /dev/null
+++ b/patches/server/0003-Remove-iterators-from-inventory-contains.patch
@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paul Sauve
+Date: Sat, 13 Mar 2021 12:24:41 -0600
+Subject: [PATCH] Remove iterators from inventory contains
+
+
+diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java
+index 96d664c28738d6090f7067761c2978dd1aa0fd0e..b1c24a02b87aca7b180a6efbce177f2300db49c1 100644
+--- a/src/main/java/net/minecraft/world/entity/player/Inventory.java
++++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java
+@@ -687,6 +687,8 @@ public class Inventory implements Container, Nameable {
+ }
+
+ public boolean contains(ItemStack stack) {
++ // Pufferfish start - don't allocate iterators
++ /*
+ Iterator iterator = this.compartments.iterator();
+
+ while (iterator.hasNext()) {
+@@ -701,6 +703,18 @@ public class Inventory implements Container, Nameable {
+ }
+ }
+ }
++ */
++ for (int i = 0; i < this.compartments.size(); i++) {
++ List list = this.compartments.get(i);
++ for (int j = 0; j < list.size(); j++) {
++ ItemStack itemstack1 = list.get(j);
++
++ if (!itemstack1.isEmpty() && ItemStack.isSameItemSameTags(itemstack1, stack)) {
++ return true;
++ }
++ }
++ }
++ // Pufferfish end
+
+ return false;
+ }
diff --git a/patches/server/0004-Remove-streams-and-iterators-from-range-check.patch b/patches/server/0004-Remove-streams-and-iterators-from-range-check.patch
new file mode 100644
index 0000000..daa3120
--- /dev/null
+++ b/patches/server/0004-Remove-streams-and-iterators-from-range-check.patch
@@ -0,0 +1,49 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paul Sauve
+Date: Tue, 22 Jun 2021 15:08:21 -0500
+Subject: [PATCH] Remove streams and iterators from range check
+
+
+diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
+index 28c6ec04750daca3d77a0cee2b9f17f2508662cc..219393390fcef956b0694ff597436249901b3e17 100644
+--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
+@@ -1330,8 +1330,28 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+ return ChunkMap.this.level.getServer().getScaledTrackingDistance(initialDistance);
+ }
+
++ private static int getHighestRange(Entity parent, int highest) {
++ List passengers = parent.getPassengers();
++
++ for (int i = 0, size = passengers.size(); i < size; i++) {
++ Entity entity = passengers.get(i);
++ int range = entity.getType().clientTrackingRange() * 16;
++ range = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, range); // Paper
++
++ if (range > highest) { // Paper - we need the lowest range thanks to the fact that our tracker doesn't account for passenger logic // Tuinity - not anymore!
++ highest = range;
++ }
++
++ highest = getHighestRange(entity, highest);
++ }
++
++ return highest;
++ }
++
+ private int getEffectiveRange() {
+ int i = this.range;
++ // Pufferfish start - remove iterators and streams
++ /*
+ Iterator iterator = this.entity.getIndirectPassengers().iterator();
+
+ while (iterator.hasNext()) {
+@@ -1343,6 +1363,9 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+ i = j;
+ }
+ }
++ */
++ i = getHighestRange(this.entity, i);
++ // Pufferfish end
+
+ return this.scaledRange(i);
+ }
diff --git a/patches/server/0005-Avoid-allocating-an-iterator-in-getEffectiveRange-if.patch b/patches/server/0005-Avoid-allocating-an-iterator-in-getEffectiveRange-if.patch
deleted file mode 100644
index f07fb3f..0000000
--- a/patches/server/0005-Avoid-allocating-an-iterator-in-getEffectiveRange-if.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: MrPowerGamerBR
-Date: Sun, 22 Oct 2023 12:47:38 -0300
-Subject: [PATCH] Avoid allocating an iterator in getEffectiveRange if the
- entity does not have any passengers
-
-
-diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
-index 28c6ec04750daca3d77a0cee2b9f17f2508662cc..841e2458548aa7ba3e29e693161f31f17344dfbe 100644
---- a/src/main/java/net/minecraft/server/level/ChunkMap.java
-+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
-@@ -1332,6 +1332,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
-
- private int getEffectiveRange() {
- int i = this.range;
-+ if (this.entity.passengers.isEmpty()) return this.scaledRange(i); // SparklyPaper - Avoid allocating an iterator if the entity does not have any passengers
-+
- Iterator iterator = this.entity.getIndirectPassengers().iterator();
-
- while (iterator.hasNext()) {
diff --git a/patches/server/0005-Simpler-ShapelessRecipes-comparison-for-Vanilla.patch b/patches/server/0005-Simpler-ShapelessRecipes-comparison-for-Vanilla.patch
new file mode 100644
index 0000000..e37786b
--- /dev/null
+++ b/patches/server/0005-Simpler-ShapelessRecipes-comparison-for-Vanilla.patch
@@ -0,0 +1,84 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paul Sauve
+Date: Sat, 31 Oct 2020 18:51:38 -0500
+Subject: [PATCH] Simpler ShapelessRecipes comparison for Vanilla
+
+Paper added a fancy sorting comparison due to Bukkit recipes breaking
+the vanilla one, however this is far more advanced than what you need
+for all the vanilla recipes.
+
+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/world/item/crafting/ShapelessRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
+index 38f7d1ece27ec1a3deda21fb6a6f0e788c8ed718..252fc22844682c0f67dc02a87478e01e49b6430d 100644
+--- a/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
++++ b/src/main/java/net/minecraft/world/item/crafting/ShapelessRecipe.java
+@@ -26,8 +26,13 @@ public class ShapelessRecipe extends io.papermc.paper.inventory.recipe.RecipeBoo
+ final CraftingBookCategory category;
+ final ItemStack result;
+ final NonNullList ingredients;
++ private final boolean isBukkit; // Pufferfish
+
++ // Pufferfish start
+ public ShapelessRecipe(String group, CraftingBookCategory category, ItemStack result, NonNullList ingredients) {
++ this(group, category, result, ingredients, false);
++ }
++ public ShapelessRecipe(String group, CraftingBookCategory category, ItemStack result, NonNullList ingredients, boolean isBukkit) { this.isBukkit = isBukkit; // Pufferfish end
+ this.group = group;
+ this.category = category;
+ this.result = result;
+@@ -77,6 +82,28 @@ public class ShapelessRecipe extends io.papermc.paper.inventory.recipe.RecipeBoo
+ }
+
+ public boolean matches(CraftingContainer inventory, Level world) {
++ // Pufferfish start
++ if (!this.isBukkit) {
++ java.util.List ingredients = com.google.common.collect.Lists.newArrayList(this.ingredients.toArray(new Ingredient[0]));
++
++ inventory: for (int index = 0; index < inventory.getContainerSize(); index++) {
++ ItemStack itemStack = inventory.getItem(index);
++
++ if (!itemStack.isEmpty()) {
++ for (int i = 0; i < ingredients.size(); i++) {
++ if (ingredients.get(i).test(itemStack)) {
++ ingredients.remove(i);
++ continue inventory;
++ }
++ }
++ return false;
++ }
++ }
++
++ return ingredients.isEmpty();
++ }
++ // Pufferfish end
++
+ StackedContents autorecipestackmanager = new StackedContents();
+ autorecipestackmanager.initialize(this); // Paper - better exact choice recipes
+ int i = 0;
+diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
+index acfe2676b840d4edc70507aa139f7db212ed90b7..ef89684b5e8ab20744ba02a71fe0465d197f627d 100644
+--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
++++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftShapelessRecipe.java
+@@ -45,6 +45,6 @@ public class CraftShapelessRecipe extends ShapelessRecipe implements CraftRecipe
+ data.set(i, toNMS(ingred.get(i), true));
+ }
+
+- MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.ShapelessRecipe(this.getGroup(), CraftRecipe.getCategory(this.getCategory()), CraftItemStack.asNMSCopy(this.getResult()), data)));
++ MinecraftServer.getServer().getRecipeManager().addRecipe(new RecipeHolder<>(CraftNamespacedKey.toMinecraft(this.getKey()), new net.minecraft.world.item.crafting.ShapelessRecipe(this.getGroup(), CraftRecipe.getCategory(this.getCategory()), CraftItemStack.asNMSCopy(this.getResult()), data, true))); // Pufferfish
+ }
+ }
diff --git a/patches/server/0006-Only-check-for-spooky-season-once-an-hour.patch b/patches/server/0006-Only-check-for-spooky-season-once-an-hour.patch
new file mode 100644
index 0000000..3b59c7a
--- /dev/null
+++ b/patches/server/0006-Only-check-for-spooky-season-once-an-hour.patch
@@ -0,0 +1,49 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paul Sauve
+Date: Sun, 13 Dec 2020 17:53:08 -0600
+Subject: [PATCH] Only check for spooky season once an hour
+
+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/world/entity/ambient/Bat.java b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
+index 5beaa849a250ea005733250ad3edfa8382224667..2c91fe46355c9a201507de5577f693ed4f5fb974 100644
+--- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java
++++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java
+@@ -237,13 +237,22 @@ public class Bat extends AmbientCreature {
+ }
+ }
+
++ // Pufferfish start - only check for spooky season once an hour
++ private static boolean isSpookySeason = false;
++ private static final int ONE_HOUR = 20 * 60 * 60;
++ private static int lastSpookyCheck = -ONE_HOUR;
+ private static boolean isHalloween() {
++ if (net.minecraft.server.MinecraftServer.currentTick - lastSpookyCheck > ONE_HOUR) {
+ LocalDate localdate = LocalDate.now();
+ int i = localdate.get(ChronoField.DAY_OF_MONTH);
+ int j = localdate.get(ChronoField.MONTH_OF_YEAR);
+
+- return j == 10 && i >= 20 || j == 11 && i <= 3;
++ isSpookySeason = j == 10 && i >= 20 || j == 11 && i <= 3;
++ lastSpookyCheck = net.minecraft.server.MinecraftServer.currentTick;
++ }
++ return isSpookySeason;
+ }
++ // Pufferfish end
+
+ @Override
+ protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) {
diff --git a/patches/server/0007-Move-ThreadUnsafeRandom-Initialization.patch b/patches/server/0007-Move-ThreadUnsafeRandom-Initialization.patch
new file mode 100644
index 0000000..f661252
--- /dev/null
+++ b/patches/server/0007-Move-ThreadUnsafeRandom-Initialization.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Kevin Raneri
+Date: Sun, 12 Jun 2022 22:19:37 -0500
+Subject: [PATCH] Move ThreadUnsafeRandom Initialization
+
+ThreadUnsafeRandom is initialized too late and some of our patches
+require it to be initialized earlier. By moving it to the superclass, we
+initialize it earlier, ensuring that it is available sooner.
+
+diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
+index 17610196db7a1c6feb2cf74a02479a8691aa323f..715a622a11b295badb0821376fec721f9c6ecaed 100644
+--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
+@@ -962,7 +962,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ }
+ // Paper start - optimise random block ticking
+ private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos();
+- private final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(this.random.nextLong());
++ // private final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(); // Pufferfish - moved to super
+ // Paper end
+
+ public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
+diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
+index aa9c56fb95d5e438e85aced984631493b84c8556..33b81d637bb5fe2a864f4313ad8796e42a5d2ad8 100644
+--- a/src/main/java/net/minecraft/world/level/Level.java
++++ b/src/main/java/net/minecraft/world/level/Level.java
+@@ -211,6 +211,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+
+ public abstract ResourceKey getTypeKey();
+
++ protected final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(java.util.concurrent.ThreadLocalRandom.current().nextLong()); // Pufferfish - move thread unsafe random initialization
++
+ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor
+ this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
+ this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper
diff --git a/patches/server/0008-Use-thread-unsafe-random-for-mob-spawning.patch b/patches/server/0008-Use-thread-unsafe-random-for-mob-spawning.patch
new file mode 100644
index 0000000..f956509
--- /dev/null
+++ b/patches/server/0008-Use-thread-unsafe-random-for-mob-spawning.patch
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paul Sauve
+Date: Tue, 22 Jun 2021 15:04:37 -0500
+Subject: [PATCH] Use thread unsafe random for mob spawning
+
+
+diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
+index 33b81d637bb5fe2a864f4313ad8796e42a5d2ad8..e357223bcaa27a668e7e95cf54e183fed13920aa 100644
+--- a/src/main/java/net/minecraft/world/level/Level.java
++++ b/src/main/java/net/minecraft/world/level/Level.java
+@@ -211,7 +211,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+
+ public abstract ResourceKey getTypeKey();
+
+- protected final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(java.util.concurrent.ThreadLocalRandom.current().nextLong()); // Pufferfish - move thread unsafe random initialization
++ protected final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(java.util.concurrent.ThreadLocalRandom.current().nextLong()); public net.minecraft.util.RandomSource getThreadUnsafeRandom() { return this.randomTickRandom; } // Pufferfish - move thread unsafe random initialization // Pufferfish - getter
+
+ protected Level(WritableLevelData worlddatamutable, ResourceKey resourcekey, RegistryAccess iregistrycustom, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, java.util.concurrent.Executor executor) { // Paper - Async-Anti-Xray - Pass executor
+ this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
+diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+index 3cdddda9c0618e95288b81b975d499c8dd30c05f..9c2d62feff1816f5729060c6192269a5b2d34153 100644
+--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+@@ -429,12 +429,12 @@ public final class NaturalSpawner {
+ }
+ }
+
+- private static BlockPos getRandomPosWithin(Level world, LevelChunk chunk) {
++ private static BlockPos getRandomPosWithin(ServerLevel world, LevelChunk chunk) { // Pufferfish - accept serverlevel
+ ChunkPos chunkcoordintpair = chunk.getPos();
+- int i = chunkcoordintpair.getMinBlockX() + world.random.nextInt(16);
+- int j = chunkcoordintpair.getMinBlockZ() + world.random.nextInt(16);
++ int i = chunkcoordintpair.getMinBlockX() + world.getThreadUnsafeRandom().nextInt(16); // Pufferfish - use thread unsafe random
++ int j = chunkcoordintpair.getMinBlockZ() + world.getThreadUnsafeRandom().nextInt(16); // Pufferfish
+ int k = chunk.getHeight(Heightmap.Types.WORLD_SURFACE, i, j) + 1;
+- int l = Mth.randomBetweenInclusive(world.random, world.getMinBuildHeight(), k);
++ int l = Mth.randomBetweenInclusive(world.getThreadUnsafeRandom(), world.getMinBuildHeight(), k); // Pufferfish
+
+ return new BlockPos(i, l, j);
+ }
diff --git a/patches/server/0009-Optimize-random-calls-in-chunk-ticking.patch b/patches/server/0009-Optimize-random-calls-in-chunk-ticking.patch
new file mode 100644
index 0000000..155c557
--- /dev/null
+++ b/patches/server/0009-Optimize-random-calls-in-chunk-ticking.patch
@@ -0,0 +1,101 @@
+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 17b6925b46f8386dcfc561483693de516465ec12..c02ffd419236980cd063741612e99d739d97ec94 100644
+--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+@@ -521,6 +521,7 @@ public class ServerChunkCache extends ChunkSource {
+ ProfilerFiller gameprofilerfiller = this.level.getProfiler();
+
+ gameprofilerfiller.push("pollingChunks");
++ this.level.resetIceAndSnowTick(); // Pufferfish - 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 715a622a11b295badb0821376fec721f9c6ecaed..2192db61ced4434c2c643599b5d2dcc11fcfb45c 100644
+--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
+@@ -965,6 +965,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ // private final io.papermc.paper.util.math.ThreadUnsafeRandom randomTickRandom = new io.papermc.paper.util.math.ThreadUnsafeRandom(); // Pufferfish - moved to super
+ // Paper end
+
++ private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Pufferfish
++
+ public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
+ ChunkPos chunkcoordintpair = chunk.getPos();
+ boolean flag = this.isRaining();
+@@ -975,7 +977,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 && /*this.random.nextInt(this.spigotConfig.thunderChance) == 0 &&*/ chunk.shouldDoLightning(this.random)) { // Spigot // Paper - disable thunder // Pufferfish - replace random with shouldDoLightning
+ blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper
+
+ if (this.isRainingAt(blockposition)) {
+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 3e9758fa40bf93fe3d315cc66389193bd57bc393..b78476223637722efe12520d3c2e301603abd8a1 100644
+--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+@@ -86,6 +86,18 @@ public class LevelChunk extends ChunkAccess {
+ private final LevelChunkTicks fluidTicks;
+ public volatile FullChunkStatus chunkStatus = FullChunkStatus.INACCESSIBLE; // Paper - rewrite chunk system
+
++ // Pufferfish 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;
++ }
++ // Pufferfish end
++
+ public LevelChunk(Level world, ChunkPos pos) {
+ this(world, pos, UpgradeData.EMPTY, new LevelChunkTicks<>(), new LevelChunkTicks<>(), 0L, (LevelChunkSection[]) null, (LevelChunk.PostLoadProcessor) null, (BlendingData) null);
+ }
+@@ -109,6 +121,8 @@ public class LevelChunk extends ChunkAccess {
+ this.postLoad = entityLoader;
+ this.blockTicks = blockTickScheduler;
+ this.fluidTicks = fluidTickScheduler;
++
++ this.lightningTick = this.level.getThreadUnsafeRandom().nextInt(100000) << 1; // Pufferfish - initialize lightning tick
+ }
+
+ // CraftBukkit start
diff --git a/patches/server/0010-Reduce-chunk-loading-lookups.patch b/patches/server/0010-Reduce-chunk-loading-lookups.patch
new file mode 100644
index 0000000..7c29aad
--- /dev/null
+++ b/patches/server/0010-Reduce-chunk-loading-lookups.patch
@@ -0,0 +1,45 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paul Sauve
+Date: Thu, 4 Feb 2021 23:33:52 -0600
+Subject: [PATCH] Reduce chunk loading & lookups
+
+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/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
+index b0a97679157a18a3c623ce3b2ae315789772c254..9fc3db543a0c9df502df5fb85012c6aa590e887d 100644
+--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java
+@@ -333,11 +333,17 @@ public class EnderMan extends Monster implements NeutralMob {
+ private boolean teleport(double x, double y, double z) {
+ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(x, y, z);
+
+- while (blockposition_mutableblockposition.getY() > this.level().getMinBuildHeight() && !this.level().getBlockState(blockposition_mutableblockposition).blocksMotion()) {
++ // Pufferfish start - single chunk lookup
++ net.minecraft.world.level.chunk.LevelChunk chunk = this.level().getChunkIfLoaded(blockposition_mutableblockposition);
++ if (chunk == null) {
++ return false;
++ }
++ // Pufferfish end
++ while (blockposition_mutableblockposition.getY() > this.level().getMinBuildHeight() && !chunk.getBlockState(blockposition_mutableblockposition).blocksMotion()) { // Pufferfish
+ blockposition_mutableblockposition.move(Direction.DOWN);
+ }
+
+- BlockState iblockdata = this.level().getBlockState(blockposition_mutableblockposition);
++ BlockState iblockdata = chunk.getBlockState(blockposition_mutableblockposition); // Pufferfish
+ boolean flag = iblockdata.blocksMotion();
+ boolean flag1 = iblockdata.getFluidState().is(FluidTags.WATER);
+
diff --git a/patches/server/0011-Early-return-optimization-for-target-finding.patch b/patches/server/0011-Early-return-optimization-for-target-finding.patch
new file mode 100644
index 0000000..548d806
--- /dev/null
+++ b/patches/server/0011-Early-return-optimization-for-target-finding.patch
@@ -0,0 +1,31 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paul Sauve
+Date: Sat, 13 Mar 2021 15:05:28 -0600
+Subject: [PATCH] Early return optimization for target finding
+
+
+diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
+index c157309ac78e7af084d3acb6e8b2bcd469a39d5e..ac5e5676b194a2a99e5cf53eb89c1152cac963b8 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
++++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java
+@@ -75,9 +75,18 @@ public class TargetingConditions {
+ }
+
+ if (this.range > 0.0D) {
+- double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D;
+- double e = Math.max((this.useFollowRange ? this.getFollowRange(baseEntity) : this.range) * d, 2.0D); // Paper
++ // Pufferfish start - check range before getting visibility
++ // d = invisibility percent, e = follow range adjusted for invisibility, f = distance
+ double f = baseEntity.distanceToSqr(targetEntity.getX(), targetEntity.getY(), targetEntity.getZ());
++ double followRangeRaw = this.useFollowRange ? this.getFollowRange(baseEntity) : this.range;
++
++ if (f > followRangeRaw * followRangeRaw) { // the actual follow range will always be this value or smaller, so if the distance is larger then it never will return true after getting invis
++ return false;
++ }
++
++ double d = this.testInvisible ? targetEntity.getVisibilityPercent(baseEntity) : 1.0D;
++ double e = Math.max((followRangeRaw) * d, 2.0D); // Paper
++ // Pufferfish end
+ if (f > e * e) {
+ return false;
+ }
diff --git a/patches/server/0012-Optimize-entity-coordinate-key.patch b/patches/server/0012-Optimize-entity-coordinate-key.patch
new file mode 100644
index 0000000..6c90688
--- /dev/null
+++ b/patches/server/0012-Optimize-entity-coordinate-key.patch
@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Kevin Raneri
+Date: Tue, 9 Nov 2021 14:33:16 -0500
+Subject: [PATCH] Optimize entity coordinate key
+
+When executing getCoordinateKey for entities (a hotpath), the JVM is
+required to repeatedly cast doubles to longs. The performance impact of
+this depends on the CPU architecture, but generally switching between
+FPU and ALU incurs a significant performance hit. The casted/rounded
+data is already available in the blockPosition struct, so we use that
+instead of re-doing the casting.
+
+diff --git a/src/main/java/io/papermc/paper/util/MCUtil.java b/src/main/java/io/papermc/paper/util/MCUtil.java
+index d02546b18cb689724887b4e85e8d32a18828a4ad..91eaff58bb422ba188e6cfaa9c20b45bec211edd 100644
+--- a/src/main/java/io/papermc/paper/util/MCUtil.java
++++ b/src/main/java/io/papermc/paper/util/MCUtil.java
+@@ -213,7 +213,7 @@ public final class MCUtil {
+ }
+
+ public static long getCoordinateKey(final Entity entity) {
+- return ((long)(MCUtil.fastFloor(entity.getZ()) >> 4) << 32) | ((MCUtil.fastFloor(entity.getX()) >> 4) & 0xFFFFFFFFL);
++ return ((long)(entity.blockPosition.getZ() >> 4) << 32) | ((entity.blockPosition.getX() >> 4) & 0xFFFFFFFFL); // Pufferfish - eliminate double->long cast in hotpath
+ }
+
+ public static long getCoordinateKey(final ChunkPos pair) {
+diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
+index f20ae9153b7098980ce6c0e75fcbbb4da652661b..4b551df667bb1aeca7ba78a063f7f0e0f1e11c5e 100644
+--- a/src/main/java/net/minecraft/world/entity/Entity.java
++++ b/src/main/java/net/minecraft/world/entity/Entity.java
+@@ -305,7 +305,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+ public double yo;
+ public double zo;
+ private Vec3 position;
+- private BlockPos blockPosition;
++ public BlockPos blockPosition; // Pufferfish - private->public
+ private ChunkPos chunkPosition;
+ private Vec3 deltaMovement;
+ private float yRot;
diff --git a/patches/server/0013-Remove-lambda-from-ticking-guard.patch b/patches/server/0013-Remove-lambda-from-ticking-guard.patch
new file mode 100644
index 0000000..e5caa30
--- /dev/null
+++ b/patches/server/0013-Remove-lambda-from-ticking-guard.patch
@@ -0,0 +1,52 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paul
+Date: Fri, 2 Jul 2021 18:27:12 -0500
+Subject: [PATCH] Remove lambda from ticking guard
+
+
+diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
+index 2192db61ced4434c2c643599b5d2dcc11fcfb45c..008a4cd92932024af8ced4e33100570d2ded3552 100644
+--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
+@@ -897,7 +897,20 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ }
+
+ gameprofilerfiller.push("tick");
+- this.guardEntityTick(this::tickNonPassenger, entity);
++ // Pufferfish start - copied from this.guardEntityTick
++ try {
++ this.tickNonPassenger(entity); // Pufferfish - changed
++ MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick
++ } catch (Throwable throwable) {
++ if (throwable instanceof ThreadDeath) throw throwable; // Paper
++ // Paper start - Prevent tile entity and entity crashes
++ final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ());
++ MinecraftServer.LOGGER.error(msg, throwable);
++ getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable)));
++ entity.discard();
++ // Paper end
++ }
++ // Pufferfish end
+ gameprofilerfiller.pop();
+ }
+ }
+diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
+index e357223bcaa27a668e7e95cf54e183fed13920aa..9388dd9b34bb8148ce8b5f7e24122fa4bd1bafa8 100644
+--- a/src/main/java/net/minecraft/world/level/Level.java
++++ b/src/main/java/net/minecraft/world/level/Level.java
+@@ -1312,13 +1312,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+ try {
+ tickConsumer.accept(entity);
+ MinecraftServer.getServer().executeMidTickTasks(); // Paper - execute chunk tasks mid tick
+- } catch (Throwable throwable) {
++ } catch (Throwable throwable) { // Pufferfish - diff on change ServerLevel.tick
+ if (throwable instanceof ThreadDeath) throw throwable; // Paper
+ // Paper start - Prevent tile entity and entity crashes
+ final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ());
+ MinecraftServer.LOGGER.error(msg, throwable);
+ getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable)));
+- entity.discard();
++ entity.discard(); // Pufferfish - diff on change ServerLevel.tick
+ // Paper end
+ }
+ }
diff --git a/patches/server/0014-Reduce-entity-allocations.patch b/patches/server/0014-Reduce-entity-allocations.patch
new file mode 100644
index 0000000..4108ecd
--- /dev/null
+++ b/patches/server/0014-Reduce-entity-allocations.patch
@@ -0,0 +1,36 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Paul
+Date: Fri, 2 Jul 2021 18:25:18 -0500
+Subject: [PATCH] Reduce entity allocations
+
+
+diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
+index 7204b973c3ad9239e82355513f6d538107102e48..3087f8359b098682a345399c85395de8a15b6eed 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
++++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
+@@ -23,9 +23,11 @@ public class AttributeMap {
+ private final Map attributes = Maps.newHashMap();
+ private final Set dirtyAttributes = Sets.newHashSet();
+ private final AttributeSupplier supplier;
++ private final java.util.function.Function createInstance; // Pufferfish
+
+ public AttributeMap(AttributeSupplier defaultAttributes) {
+ this.supplier = defaultAttributes;
++ this.createInstance = attribute -> this.supplier.createInstance(this::onAttributeModified, attribute); // Pufferfish
+ }
+
+ private void onAttributeModified(AttributeInstance instance) {
+@@ -45,11 +47,10 @@ public class AttributeMap {
+ }).collect(Collectors.toList());
+ }
+
++
+ @Nullable
+ public AttributeInstance getInstance(Attribute attribute) {
+- return this.attributes.computeIfAbsent(attribute, (attributex) -> {
+- return this.supplier.createInstance(this::onAttributeModified, attributex);
+- });
++ return this.attributes.computeIfAbsent(attribute, this.createInstance); // Pufferfish - cache lambda, as for some reason java allocates it anyways
+ }
+
+ @Nullable
diff --git a/patches/server/0003-Configurable-Farm-Land-moisture-tick-rate-when-the-b.patch b/patches/server/0015-Configurable-Farm-Land-moisture-tick-rate-when-the-b.patch
similarity index 100%
rename from patches/server/0003-Configurable-Farm-Land-moisture-tick-rate-when-the-b.patch
rename to patches/server/0015-Configurable-Farm-Land-moisture-tick-rate-when-the-b.patch
diff --git a/patches/server/0004-Only-check-thundering-once-per-world-instead-for-eve.patch b/patches/server/0016-Only-check-thundering-once-per-world-instead-for-eve.patch
similarity index 88%
rename from patches/server/0004-Only-check-thundering-once-per-world-instead-for-eve.patch
rename to patches/server/0016-Only-check-thundering-once-per-world-instead-for-eve.patch
index 9e5edb6..de6fada 100644
--- a/patches/server/0004-Only-check-thundering-once-per-world-instead-for-eve.patch
+++ b/patches/server/0016-Only-check-thundering-once-per-world-instead-for-eve.patch
@@ -6,10 +6,10 @@ Subject: [PATCH] Only check thundering once per world instead for every chunk
For some reason the isThundering check is consuming ~3% of CPU time when profiled so, instead of checking the thunder every chunk, we can cache the result and reuse on the same chunk tick
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-index 17b6925b46f8386dcfc561483693de516465ec12..8f57bf4fffae352b1f81220b94def01c81af7f5e 100644
+index c02ffd419236980cd063741612e99d739d97ec94..daa5948cc7b86a719a313ea595f135cd00b6a3cc 100644
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
-@@ -598,6 +598,7 @@ public class ServerChunkCache extends ChunkSource {
+@@ -599,6 +599,7 @@ public class ServerChunkCache extends ChunkSource {
}
// Paper end - optimise chunk tick iteration
@@ -18,7 +18,7 @@ index 17b6925b46f8386dcfc561483693de516465ec12..8f57bf4fffae352b1f81220b94def01c
// Paper start - optimise chunk tick iteration
io.papermc.paper.util.player.NearbyPlayers nearbyPlayers = this.chunkMap.getNearbyPlayers(); // Paper - optimise chunk tick iteration
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
-index aa9c56fb95d5e438e85aced984631493b84c8556..10adb0b41b4140c1361572f868b2595b0511590d 100644
+index 9388dd9b34bb8148ce8b5f7e24122fa4bd1bafa8..0210226d2185803a18c0020d7985c1fccb798953 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -184,6 +184,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
@@ -29,7 +29,7 @@ index aa9c56fb95d5e438e85aced984631493b84c8556..10adb0b41b4140c1361572f868b2595b
// Paper start - fix and optimise world upgrading
// copied from below
-@@ -1612,7 +1613,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+@@ -1614,7 +1615,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
this.rainLevel = f1;
}