diff --git a/gradle.properties b/gradle.properties index accb24a..73be0e1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ group=net.sparklypower.sparklypaper version=1.20.4-R0.1-SNAPSHOT mcVersion=1.20.4 -paperRef=351923d17e3b5f2a2a3ed848c171d7d2b077a55a +paperRef=4939f8711884901ddf1c56337f606de71cdae78d org.gradle.caching=true org.gradle.parallel=true diff --git a/patches/paper-api-generator/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch b/patches/paper-api-generator/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch index 3af0ce7..4835cb2 100644 --- a/patches/paper-api-generator/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch +++ b/patches/paper-api-generator/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch @@ -5,7 +5,7 @@ Subject: [PATCH] new fork who dis - Rebrand to SparklyPaper and Build Changes diff --git a/build.gradle.kts b/build.gradle.kts -index 50cc3c1e5968d95a21133e4d554a93e181aba0f6..3f0c449c373c015c1cf10165ff402e29e82ac5de 100644 +index 3b86451bdc939aec0ec6b4bf82a789cab38345b4..32fa3dbf6975b1435bbfc7bbd1094687b7e882f7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,7 +20,7 @@ minecraft { @@ -14,6 +14,6 @@ index 50cc3c1e5968d95a21133e4d554a93e181aba0f6..3f0c449c373c015c1cf10165ff402e29 implementation("com.squareup:javapoet:1.13.0") - implementation(project(":paper-api")) + implementation(project(":sparklypaper-api")) // SparklyPaper + implementation("io.github.classgraph:classgraph:4.8.47") } - group = "io.papermc.paper" diff --git a/patches/server/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch b/patches/server/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch index bc6b338..eb29a77 100644 --- a/patches/server/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch +++ b/patches/server/0001-new-fork-who-dis-Rebrand-to-SparklyPaper-and-Build-C.patch @@ -3,7 +3,6 @@ From: MrPowerGamerBR Date: Sat, 12 Jun 2021 16:40:34 +0200 Subject: [PATCH] new fork who dis - Rebrand to SparklyPaper and Build Changes - diff --git a/build.gradle.kts b/build.gradle.kts index 58da26ad2f128ba0b66f86820f60853f4be352f0..f2c2d7af8d3647879702c27e8a0ee62e76afd6e7 100644 --- a/build.gradle.kts @@ -16,10 +15,10 @@ index 58da26ad2f128ba0b66f86820f60853f4be352f0..f2c2d7af8d3647879702c27e8a0ee62e + kotlin("plugin.serialization") version "1.9.10" id("com.github.johnrengelman.shadow") } - + @@ -13,8 +15,15 @@ configurations.named(log4jPlugins.compileClasspathConfigurationName) { val alsoShade: Configuration by configurations.creating - + dependencies { - implementation(project(":paper-api")) - implementation(project(":paper-mojangapi")) @@ -66,23 +65,23 @@ index 58da26ad2f128ba0b66f86820f60853f4be352f0..f2c2d7af8d3647879702c27e8a0ee62e standardInput = System.`in` workingDir = rootProject.layout.projectDirectory diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 34f19ac897a30c0c4e3ab406013fcca1c8b7db93..f1c65967b74e79452870438eea0942cc700fe0e9 100644 +index d06185566b447c432d4dc2e3ba04d121bcdbc71b..8f250966ab5e4576e3a57beba2e417d53713e84e 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1866,7 +1866,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop // Spigot - Spigot > // CraftBukkit - cb > vanilla! -+ return "SparklyPaper"; // SparklyPaper - SparklyPaper > // Paper - Paper > // Spigot - Spigot > // CraftBukkit - cb > vanilla! +- return "Paper"; // Paper ++ return "SparklyPaper"; // SparklyPaper // "Paper"; // Paper } public SystemReport fillSystemReport(SystemReport details) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index e011cfcdda2e0a609d4158b0454bdf046b04c9d9..3b28e079dcfba5ca3de2aad903f95c142e73e6a3 100644 +index 9f7ed337463cc9bb370a5541d9de5cd8f9c1a78a..404e5715a43068fb3338e7bcef52f8967e1e4bb4 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -264,7 +264,7 @@ import javax.annotation.Nullable; // Paper +@@ -266,7 +266,7 @@ import javax.annotation.Nullable; // Paper import javax.annotation.Nonnull; // Paper public final class CraftServer implements Server { @@ -105,7 +104,7 @@ index 774556a62eb240da42e84db4502e2ed43495be17..22e504565de83f976c8b2996f0b2207b if (stream != null) { diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 40dcdf6885e99b26283a9ea2bd4d4bf6ec358e71..d502b0d45bc950a586049dd5cd242319da5ba721 100644 +index 9e638f72f180ff5ef63ec3dd6cf548c53f7bd4a5..7de20ceb7ba52178b1939deb01dbe3d51a52dfb0 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java @@ -155,14 +155,14 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa @@ -126,12 +125,12 @@ index 40dcdf6885e99b26283a9ea2bd4d4bf6ec358e71..d502b0d45bc950a586049dd5cd242319 // if ( net.minecraft.world.level.Level.lastPhysicsProblem != null ) { -@@ -190,7 +190,7 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa +@@ -189,7 +189,7 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa } // Paper end - Different message for short timeout log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to SparklyPaper!):" ); // SparklyPaper - branding changes // Paper - io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(isLongTimeout); // Paper // Paper - rewrite chunk system + io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(isLongTimeout); // Paper - rewrite chunk system this.dumpTickingInfo(); // Paper - log detailed tick information WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); diff --git a/patches/server/0002-SparklyPaper-config-files.patch b/patches/server/0002-SparklyPaper-config-files.patch index 03ddc3d..6cdcc44 100644 --- a/patches/server/0002-SparklyPaper-config-files.patch +++ b/patches/server/0002-SparklyPaper-config-files.patch @@ -5,13 +5,13 @@ Subject: [PATCH] SparklyPaper config files diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 58536aabf607015939a1326f80207c0a06eed8ff..b69860955a6c1efb68b17e1fc9b0c42771f40e15 100644 +index 68d268b6fff126e8645b6deec3fb549ea2286b77..d61cf0d713dcdef5a7081142838ee6960593fe95 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -218,6 +218,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - thread.start(); // Paper - start console thread after MinecraftServer.console & PaperConfig are initialized - io.papermc.paper.command.PaperCommands.registerCommands(this); - com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); +@@ -219,6 +219,15 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + thread.start(); // Paper - Enhance console tab completions for brigadier commands; start console thread after MinecraftServer.console & PaperConfig are initialized + io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command + com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics + // SparklyPaper start + try { + net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.init((java.io.File) options.valueOf("sparklypaper-settings")); @@ -21,25 +21,25 @@ index 58536aabf607015939a1326f80207c0a06eed8ff..b69860955a6c1efb68b17e1fc9b0c427 + } + net.sparklypower.sparklypaper.SparklyPaperCommands.INSTANCE.registerCommands(this); + // SparklyPaper end - com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now - io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider - // Paper end + com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now + io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // Paper - init PaperBrigadierProvider + diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 0b56e5f7f18fc4286992af22d402205b771165a3..f5e3c87581cbdc762806ad4412b68d3c84612b88 100644 +index 19f23a6c8fb5c02843c27fb8a242ec9d0d1b538b..e199c852f4c493dbe6ab776d18b91a53e5a36f7c 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -179,6 +179,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - // Paper end +@@ -173,6 +173,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Paper end - add paper world config public final com.destroystokyo.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray + public net.sparklypower.sparklypaper.configs.SparklyPaperWorldConfig sparklyPaperConfig; // SparklyPaper public final co.aikar.timings.WorldTimingsHandler timings; // Paper public static BlockPos lastPhysicsProblem; // Spigot private org.spigotmc.TickLimiter entityLimiter; -@@ -216,6 +217,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - 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 +@@ -210,6 +211,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + 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 - create paper world config; 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 + this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config + this.sparklyPaperConfig = net.sparklypower.sparklypaper.configs.SparklyPaperConfigUtils.INSTANCE.getWorldSettings(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // SparklyPaper this.generator = gen; this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env); @@ -116,7 +116,7 @@ index 0000000000000000000000000000000000000000..bc0ec96f91f7c9ab9f9a865a50f69707 + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 3b28e079dcfba5ca3de2aad903f95c142e73e6a3..64044cb5888c72797c369b5d015297677b20419a 100644 +index 404e5715a43068fb3338e7bcef52f8967e1e4bb4..3754360b3be729e7fa03697543e219506a5499b4 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -112,6 +112,7 @@ import net.minecraft.world.level.storage.PrimaryLevelData; @@ -127,7 +127,7 @@ index 3b28e079dcfba5ca3de2aad903f95c142e73e6a3..64044cb5888c72797c369b5d01529767 import org.bukkit.BanList; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -@@ -1037,6 +1038,7 @@ public final class CraftServer implements Server { +@@ -1054,6 +1055,7 @@ public final class CraftServer implements Server { org.spigotmc.SpigotConfig.init((File) this.console.options.valueOf("spigot-settings")); // Spigot this.console.paperConfigurations.reloadConfigs(this.console); @@ -135,7 +135,7 @@ index 3b28e079dcfba5ca3de2aad903f95c142e73e6a3..64044cb5888c72797c369b5d01529767 for (ServerLevel world : this.console.getAllLevels()) { // world.serverLevelData.setDifficulty(config.difficulty); // Paper - per level difficulty world.setSpawnSettings(world.serverLevelData.getDifficulty() != Difficulty.PEACEFUL && config.spawnMonsters, config.spawnAnimals); // Paper - per level difficulty (from MinecraftServer#setDifficulty(ServerLevel, Difficulty, boolean)) -@@ -1052,6 +1054,7 @@ public final class CraftServer implements Server { +@@ -1069,6 +1071,7 @@ public final class CraftServer implements Server { } } world.spigotConfig.init(); // Spigot @@ -143,7 +143,7 @@ index 3b28e079dcfba5ca3de2aad903f95c142e73e6a3..64044cb5888c72797c369b5d01529767 } Plugin[] pluginClone = pluginManager.getPlugins().clone(); // Paper -@@ -1067,6 +1070,7 @@ public final class CraftServer implements Server { +@@ -1084,6 +1087,7 @@ public final class CraftServer implements Server { this.reloadData(); org.spigotmc.SpigotConfig.registerCommands(); // Spigot io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper @@ -152,7 +152,7 @@ index 3b28e079dcfba5ca3de2aad903f95c142e73e6a3..64044cb5888c72797c369b5d01529767 this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java -index a74a8a027c99eef199c1a6a54232ac2c8ffb9d08..73a358912fccd70b350d75e857a2affc5480473a 100644 +index ce341f42b3a5e17fb6d1f7de8057e73137ae2a6e..8851fd0dbca2d788b16dec92a121ad00f209459a 100644 --- a/src/main/java/org/bukkit/craftbukkit/Main.java +++ b/src/main/java/org/bukkit/craftbukkit/Main.java @@ -174,6 +174,14 @@ public class Main { diff --git a/patches/server/0003-Optimize-entity-coordinate-key.patch b/patches/server/0003-Optimize-entity-coordinate-key.patch index b248d09..b362e85 100644 --- a/patches/server/0003-Optimize-entity-coordinate-key.patch +++ b/patches/server/0003-Optimize-entity-coordinate-key.patch @@ -11,7 +11,7 @@ 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 200ed770b57e1a9240abf0473968d4b85cbefe3c..0acc7cfc0fb0264dd76a58f7582e79d83fa040eb 100644 +index 850f75172e9efa72cabb8e5bd124b96a0b1a945f..3db1de70c76e1427e257d988d1a7f26e986b5617 100644 --- a/src/main/java/io/papermc/paper/util/MCUtil.java +++ b/src/main/java/io/papermc/paper/util/MCUtil.java @@ -212,7 +212,7 @@ public final class MCUtil { @@ -24,10 +24,10 @@ index 200ed770b57e1a9240abf0473968d4b85cbefe3c..0acc7cfc0fb0264dd76a58f7582e79d8 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 0c46a4aeafd03fbbfd590b0362d41bf2b1d5ca74..aa6045039450c4cce8d9481aa7f56867dd15c0fa 100644 +index 906eded9a2ab61737a30cfe89292a71237ce4eb7..b0b9e07da81ca0c2a0e915afbcd1a50a39e3bf20 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -307,7 +307,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -308,7 +308,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S public double yo; public double zo; private Vec3 position; diff --git a/patches/server/0004-Rewrite-framed-map-tracker-ticking.patch b/patches/server/0004-Rewrite-framed-map-tracker-ticking.patch index bac861f..e36483a 100644 --- a/patches/server/0004-Rewrite-framed-map-tracker-ticking.patch +++ b/patches/server/0004-Rewrite-framed-map-tracker-ticking.patch @@ -11,15 +11,15 @@ now is just updating dirty map/decoration data. When no bukkit renderers are added to the map, we also re-use the same packet for all players who are tracking it which avoids a lot of work. diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index 35674f92a67f93382103c2766df4b678ba5c862f..bfdd0ce9acfae75a403d3689b391dd8fff7416a0 100644 +index 529ab44baaf573b97cf7e89560c548642733188f..7ee0335b02741f6b06d0c697a19faf479db2ae4b 100644 --- a/src/main/java/net/minecraft/server/level/ServerEntity.java +++ b/src/main/java/net/minecraft/server/level/ServerEntity.java @@ -111,29 +111,42 @@ public class ServerEntity { Entity entity = this.entity; -- if (!this.trackedPlayers.isEmpty() && entity instanceof ItemFrame) { // Paper - Only tick item frames if players can see it -+ if (!this.trackedPlayers.isEmpty() && entity instanceof ItemFrame frame && frame.cachedMapId != null) { // Paper - Only tick item frames if players can see it // Paper +- if (!this.trackedPlayers.isEmpty() && entity instanceof ItemFrame) { // Paper - Perf: Only tick item frames if players can see it ++ if (!this.trackedPlayers.isEmpty() && entity instanceof ItemFrame frame && frame.cachedMapId != null) { // Paper - Perf: Only tick item frames if players can see it // Paper ItemFrame entityitemframe = (ItemFrame) entity; if (true || this.tickCount % 10 == 0) { // CraftBukkit - Moved below, should always enter this block @@ -28,7 +28,7 @@ index 35674f92a67f93382103c2766df4b678ba5c862f..bfdd0ce9acfae75a403d3689b391dd8f - if (this.level.paperConfig().maps.itemFrameCursorUpdateInterval > 0 && this.tickCount % this.level.paperConfig().maps.itemFrameCursorUpdateInterval == 0 && itemstack.getItem() instanceof MapItem) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks // Paper - Make item frame map cursor update interval configurable + if (this.level.paperConfig().maps.itemFrameCursorUpdateInterval > 0 && this.tickCount % this.level.paperConfig().maps.itemFrameCursorUpdateInterval == 0 /*&& itemstack.getItem() instanceof MapItem*/) { // CraftBukkit - Moved this.tickCounter % 10 logic here so item frames do not enter the other blocks // Paper - Make item frame map cursor update interval configurable // Paper - skip redundant getItem - Integer integer = entityitemframe.cachedMapId; // Paper + Integer integer = entityitemframe.cachedMapId; // Paper - Perf: Cache map ids on item frames MapItemSavedData worldmap = MapItem.getSavedData(integer, this.level); if (worldmap != null) { @@ -62,7 +62,7 @@ index 35674f92a67f93382103c2766df4b678ba5c862f..bfdd0ce9acfae75a403d3689b391dd8f } } -@@ -366,6 +379,19 @@ public class ServerEntity { +@@ -372,6 +385,19 @@ public class ServerEntity { } } @@ -83,13 +83,13 @@ index 35674f92a67f93382103c2766df4b678ba5c862f..bfdd0ce9acfae75a403d3689b391dd8f private void sendDirtyEntityData() { diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java -index 69912c5b300b67394dce3876d2d96872033cf156..bde22dcbc67211a62c2280b0c6cf5b85aa3b96eb 100644 +index 80303f9466b8c7097151be313afc9a383693d18a..4ddcda7783750e485e283a7f7df3f52c9bed5c45 100644 --- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java +++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java @@ -483,6 +483,16 @@ public class ItemFrame extends HangingEntity { } this.setItem(ItemStack.fromBukkitCopy(event.getItemStack())); - // Paper end + // Paper end - Add PlayerItemFrameChangeEvent + // Paper start - add decoration and mark everything dirty for other players who are already tracking this frame + final ItemStack item = this.getItem(); + if (item.is(Items.FILLED_MAP)) { @@ -104,7 +104,7 @@ index 69912c5b300b67394dce3876d2d96872033cf156..bde22dcbc67211a62c2280b0c6cf5b85 if (!player.getAbilities().instabuild) { itemstack.shrink(1); diff --git a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java -index e4c4948e076cd64686dfd16ae0568fafc1437140..fec7d474df8cfc8c36f5a69faac7ad03ad648d45 100644 +index 45269115e63cfc3bd7dc740a5694e2cc7c35bcb1..ad0c4660dd15a7dc6cf3639223dda5d704f96a4c 100644 --- a/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java +++ b/src/main/java/net/minecraft/world/level/saveddata/maps/MapItemSavedData.java @@ -67,6 +67,16 @@ public class MapItemSavedData extends SavedData { diff --git a/patches/server/0005-Skip-distanceToSqr-call-in-ServerEntity-sendChanges-.patch b/patches/server/0005-Skip-distanceToSqr-call-in-ServerEntity-sendChanges-.patch index a076f77..ce4da52 100644 --- a/patches/server/0005-Skip-distanceToSqr-call-in-ServerEntity-sendChanges-.patch +++ b/patches/server/0005-Skip-distanceToSqr-call-in-ServerEntity-sendChanges-.patch @@ -9,10 +9,10 @@ The "distanceToSqr" call is a bit expensive, so avoiding it is pretty nice, arou We could also check if the x,y,z coordinates are equal, but for now, let's just keep the identity check, which also helps us since Minecraft's code does reuse the original delta movement Vec3 object diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java -index bfdd0ce9acfae75a403d3689b391dd8fff7416a0..71d6f63feb8548181882c481f53c810baf8c1e07 100644 +index 7ee0335b02741f6b06d0c697a19faf479db2ae4b..056b3dd172a7b8d1bf5ac76d88d373fae0b85a8f 100644 --- a/src/main/java/net/minecraft/server/level/ServerEntity.java +++ b/src/main/java/net/minecraft/server/level/ServerEntity.java -@@ -215,12 +215,14 @@ public class ServerEntity { +@@ -221,12 +221,14 @@ public class ServerEntity { if ((this.trackDelta || this.entity.hasImpulse || this.entity instanceof LivingEntity && ((LivingEntity) this.entity).isFallFlying()) && this.tickCount > 0) { Vec3 vec3d1 = this.entity.getDeltaMovement(); diff --git a/patches/server/0008-Skip-dirty-stats-copy-when-requesting-player-stats.patch b/patches/server/0008-Skip-dirty-stats-copy-when-requesting-player-stats.patch index d9a7589..2a42196 100644 --- a/patches/server/0008-Skip-dirty-stats-copy-when-requesting-player-stats.patch +++ b/patches/server/0008-Skip-dirty-stats-copy-when-requesting-player-stats.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Skip dirty stats copy when requesting player stats There's literally only one getDirty call. Because the map was only retrieved once, we don't actually need to create a copy of the map just to iterate it, we can just access it directly and clear it manually after use. diff --git a/src/main/java/net/minecraft/stats/ServerStatsCounter.java b/src/main/java/net/minecraft/stats/ServerStatsCounter.java -index 9bb8d4d7be6a937980aa653db82be084d066a563..e93722fd8b7a97037914beddbace9a0de5dca8b4 100644 +index f890738d3bb9fb5e70a9d323c6cec97f9948f9cf..8685cb5bbfa26b0d77c6fdde8cf2dc8bebc06585 100644 --- a/src/main/java/net/minecraft/stats/ServerStatsCounter.java +++ b/src/main/java/net/minecraft/stats/ServerStatsCounter.java -@@ -85,12 +85,16 @@ public class ServerStatsCounter extends StatsCounter { +@@ -90,12 +90,16 @@ public class ServerStatsCounter extends StatsCounter { this.dirty.add(stat); } @@ -26,7 +26,7 @@ index 9bb8d4d7be6a937980aa653db82be084d066a563..e93722fd8b7a97037914beddbace9a0d public void parseLocal(DataFixer dataFixer, String json) { try { -@@ -238,7 +242,7 @@ public class ServerStatsCounter extends StatsCounter { +@@ -243,7 +247,7 @@ public class ServerStatsCounter extends StatsCounter { public void sendStats(ServerPlayer player) { Object2IntMap> object2intmap = new Object2IntOpenHashMap(); @@ -35,7 +35,7 @@ index 9bb8d4d7be6a937980aa653db82be084d066a563..e93722fd8b7a97037914beddbace9a0d while (iterator.hasNext()) { Stat statistic = (Stat) iterator.next(); -@@ -246,6 +250,8 @@ public class ServerStatsCounter extends StatsCounter { +@@ -251,6 +255,8 @@ public class ServerStatsCounter extends StatsCounter { object2intmap.put(statistic, this.getValue(statistic)); } diff --git a/patches/server/0009-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch b/patches/server/0009-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch index ccc1232..8771b42 100644 --- a/patches/server/0009-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch +++ b/patches/server/0009-Skip-EntityScheduler-s-executeTick-checks-if-there-i.patch @@ -73,18 +73,20 @@ index 62484ebf4550b05182f693a3180bbac5d5fd906d..67800e426445060a8343e27a7452b8d7 throw new IllegalStateException("Ticking retired scheduler"); } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f1c65967b74e79452870438eea0942cc700fe0e9..4820e5ae050966d89a0d0b587c83537d4a1e1393 100644 +index 8f250966ab5e4576e3a57beba2e417d53713e84e..3aab37ae2ef5a359b09c885f0988aa7be84b0159 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -314,6 +314,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run (concurrent because plugins may schedule tasks async) - ++ public static S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); -@@ -1640,6 +1641,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { // Paper - rewrite chunk system +@@ -1637,6 +1638,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { - for (final Entity entity : level.getEntityLookup().getAllCopy()) { + for (final Entity entity : level.getEntityLookup().getAllCopy()) { // Paper - rewrite chunk system if (entity.isRemoved()) { -@@ -1651,6 +1664,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run (concurrent because plugins may schedule tasks async) +- ++ + public static S spin(Function serverFactory) { + AtomicReference atomicreference = new AtomicReference(); + Thread thread = new io.papermc.paper.util.TickThread(() -> { // Paper - rewrite chunk system diff --git a/src/main/java/net/minecraft/world/level/block/CropBlock.java b/src/main/java/net/minecraft/world/level/block/CropBlock.java -index 9550ce8588c6aa3ba4cbbbb86912eae2b452eb01..622413a5f9a472a759e9cc869ee7cdb223880188 100644 +index 5b96d1ae4bd8546311e986bc312b1f85883a67f4..ec20b138642b080c9d0050cbdb8c6d593264ecd5 100644 --- a/src/main/java/net/minecraft/world/level/block/CropBlock.java +++ b/src/main/java/net/minecraft/world/level/block/CropBlock.java @@ -81,6 +81,57 @@ public class CropBlock extends BushBlock implements BonemealableBlock { @@ -76,7 +89,7 @@ index 9550ce8588c6aa3ba4cbbbb86912eae2b452eb01..622413a5f9a472a759e9cc869ee7cdb2 } diff --git a/src/main/java/net/minecraft/world/level/block/FarmBlock.java b/src/main/java/net/minecraft/world/level/block/FarmBlock.java -index 59bbdead2ebd8965d222540c7243dde051bbcc4b..e7cc73fe8f7aaa1f66c598c9018983319db4213f 100644 +index 6e4c852c93f2418ea69e485ed3a10cbe3a6e3bd2..fc2703fcf1639a85518330e4ffcd0c23fd6e118f 100644 --- a/src/main/java/net/minecraft/world/level/block/FarmBlock.java +++ b/src/main/java/net/minecraft/world/level/block/FarmBlock.java @@ -92,6 +92,19 @@ public class FarmBlock extends Block { @@ -96,8 +109,8 @@ index 59bbdead2ebd8965d222540c7243dde051bbcc4b..e7cc73fe8f7aaa1f66c598c901898331 + return; + } + // SparklyPaper end - if (i > 0 && world.paperConfig().tickRates.wetFarmland != 1 && (world.paperConfig().tickRates.wetFarmland < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.wetFarmland != 0)) { return; } // Paper - if (i == 0 && world.paperConfig().tickRates.dryFarmland != 1 && (world.paperConfig().tickRates.dryFarmland < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.dryFarmland != 0)) { return; } // Paper + if (i > 0 && world.paperConfig().tickRates.wetFarmland != 1 && (world.paperConfig().tickRates.wetFarmland < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.wetFarmland != 0)) { return; } // Paper - Configurable random tick rates for blocks + if (i == 0 && world.paperConfig().tickRates.dryFarmland != 1 && (world.paperConfig().tickRates.dryFarmland < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.dryFarmland != 0)) { return; } // Paper - Configurable random tick rates for blocks @@ -150,7 +163,7 @@ public class FarmBlock extends Block { return world.getBlockState(pos.above()).is(BlockTags.MAINTAINS_FARMLAND); @@ -105,7 +118,7 @@ index 59bbdead2ebd8965d222540c7243dde051bbcc4b..e7cc73fe8f7aaa1f66c598c901898331 - private static boolean isNearWater(LevelReader world, BlockPos pos) { + public static boolean isNearWater(LevelReader world, BlockPos pos) { // SparklyPaper - make public for the Blazingly simple farm checks - // Paper start - remove abstract block iteration + // Paper start - Perf: remove abstract block iteration int xOff = pos.getX(); int yOff = pos.getY(); diff --git a/src/main/java/net/minecraft/world/level/block/StemBlock.java b/src/main/java/net/minecraft/world/level/block/StemBlock.java diff --git a/patches/server/0011-Spooky-month-optimizations.patch b/patches/server/0011-Spooky-month-optimizations.patch index 1fd6cf4..308e30c 100644 --- a/patches/server/0011-Spooky-month-optimizations.patch +++ b/patches/server/0011-Spooky-month-optimizations.patch @@ -10,22 +10,22 @@ Caches when Bat's spooky season starts and ends, and when Skeleton and Zombies h Avoids unnecessary date checks, even tho that this shouldn't really improve performance that much... unless you have a lot of bats/zombies/skeletons spawning. diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 4820e5ae050966d89a0d0b587c83537d4a1e1393..f43060555bf02f13268b284606045fce2b3e911a 100644 +index ccf79aef050e2ef1ece1631e5bb165ef7fe3bca6..f2edb992729325140d4b2f6f347c3bd8c6394a77 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -315,6 +315,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run (concurrent because plugins may schedule tasks async) + public net.sparklypower.sparklypaper.HalloweenManager halloweenManager = new net.sparklypower.sparklypaper.HalloweenManager(); // SparklyPaper - Spooky month optimizations public static S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index b69860955a6c1efb68b17e1fc9b0c42771f40e15..734fd1ced38a16649177bb941e76d9ca66dceac5 100644 +index d61cf0d713dcdef5a7081142838ee6960593fe95..4c549a2656183e4e4bbaf3f7d5169f3d258e81ce 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -227,6 +227,10 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -228,6 +228,10 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } net.sparklypower.sparklypaper.SparklyPaperCommands.INSTANCE.registerCommands(this); // SparklyPaper end @@ -33,11 +33,11 @@ index b69860955a6c1efb68b17e1fc9b0c42771f40e15..734fd1ced38a16649177bb941e76d9ca + halloweenManager.startHalloweenEpochTask(); + halloweenManager.waitUntilEpochHasBeenUpdated(); + // SparklyPaper end - com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now - io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // init PaperBrigadierProvider - // Paper end + com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now + io.papermc.paper.brigadier.PaperBrigadierProviderImpl.INSTANCE.getClass(); // Paper - init PaperBrigadierProvider + 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 6b614818b14ecfc8fc82b523eeb7e21fdf9bf1ba..2588e7eb1f55d3f01f4f8d794a59f3ba16f5985a 100644 +index 44fa2d4f90389f5526746bd94a2450c03340bd0b..ed4e7673bfcc02d077b61cab5898f4199ada4d03 100644 --- a/src/main/java/net/minecraft/world/entity/ambient/Bat.java +++ b/src/main/java/net/minecraft/world/entity/ambient/Bat.java @@ -231,7 +231,7 @@ public class Bat extends AmbientCreature { @@ -67,11 +67,11 @@ index 6b614818b14ecfc8fc82b523eeb7e21fdf9bf1ba..2588e7eb1f55d3f01f4f8d794a59f3ba @Override protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { diff --git a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java -index b319021b22c5dceba6199ed27814b2dcf47b8d50..4e7f19215bafc8ff6b06abc08076a154df5307aa 100644 +index 586e3e92ccc275446df6dbbff9bf010a37a9aa8f..aaab68a2e5f28b4da0cb5bb7bca42ac08fa9d7bb 100644 --- a/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java +++ b/src/main/java/net/minecraft/world/entity/monster/AbstractSkeleton.java @@ -162,10 +162,12 @@ public abstract class AbstractSkeleton extends Monster implements RangedAttackMo - this.setCanPickUpLoot(this.level().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.skeletons || randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper + this.setCanPickUpLoot(this.level().paperConfig().entities.behavior.mobsCanAlwaysPickUpLoot.skeletons || randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); // Paper - Add world settings for mobs picking up loot if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { LocalDate localdate = LocalDate.now(); - int i = localdate.get(ChronoField.DAY_OF_MONTH); @@ -87,7 +87,7 @@ index b319021b22c5dceba6199ed27814b2dcf47b8d50..4e7f19215bafc8ff6b06abc08076a154 this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F; } diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java -index 753defa8f8b48d004a2a53b2fc322fd9c083d95e..cc7073efaa9984c95b125878df94556b1e865c7a 100644 +index 5c40e994007dbf46ebc12c1e6a6ca90379471b74..5a7919f05f0f4785d3ac98df067a53c53a7d4f73 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java +++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java @@ -553,10 +553,11 @@ public class Zombie extends Monster { diff --git a/patches/server/0012-Cache-coordinate-key-used-for-nearby-players-when-ti.patch b/patches/server/0012-Cache-coordinate-key-used-for-nearby-players-when-ti.patch index 6ce4172..198d40f 100644 --- a/patches/server/0012-Cache-coordinate-key-used-for-nearby-players-when-ti.patch +++ b/patches/server/0012-Cache-coordinate-key-used-for-nearby-players-when-ti.patch @@ -11,7 +11,7 @@ So instead of paying the price on each tick, we pay the price when the chunk is Which, if you think about it, is actually better, since we tick chunks more than we load chunks diff --git a/src/main/java/io/papermc/paper/util/player/NearbyPlayers.java b/src/main/java/io/papermc/paper/util/player/NearbyPlayers.java -index 17ba07cbd4792f63d88ce29d00da280f30c4abff..8e8aad958c96fa1df3d906ec120a89adecae38c4 100644 +index f164256d59b761264876ca0c85f812d101bfd5de..10465a33d90a1e43b9dbd7764c895dd39ef11b1a 100644 --- a/src/main/java/io/papermc/paper/util/player/NearbyPlayers.java +++ b/src/main/java/io/papermc/paper/util/player/NearbyPlayers.java @@ -106,6 +106,14 @@ public final class NearbyPlayers { @@ -30,10 +30,10 @@ index 17ba07cbd4792f63d88ce29d00da280f30c4abff..8e8aad958c96fa1df3d906ec120a89ad final TrackedChunk chunk = this.byChunk.get(CoordinateUtils.getChunkKey(chunkX, chunkZ)); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 44ada45d9bf2d9b48e5de1c3cb1a855902f3884b..22213a52c5d546145d8b8de929af61e49d40375d 100644 +index 366c0c9b45a819f7f94ebe3e49b8ab7f9edf9ce7..53bce70f5cc14672d41618747d3919429896001f 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -617,7 +617,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -609,7 +609,7 @@ public class ServerChunkCache extends ChunkSource { // Paper start - optimise chunk tick iteration com.destroystokyo.paper.util.maplist.ReferenceList playersNearby diff --git a/patches/server/0013-Optimize-canSee-checks.patch b/patches/server/0013-Optimize-canSee-checks.patch index 0058297..cdb9b39 100644 --- a/patches/server/0013-Optimize-canSee-checks.patch +++ b/patches/server/0013-Optimize-canSee-checks.patch @@ -14,11 +14,11 @@ This seems stupid, but it does seem that it improves the performance a bit, and We also create a "canSee" method tailored for "ChunkMap#updatePlayer()", a method without the equals check (the "updatePlayer()" already checks if the entity is the same entity) because the CraftPlayer's `equals()` check is a *bit* expensive compared to only checking the object's identity, and because the identity has already been check, we don't need to check it twice. diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index d9cd497bc1b654030ff1a597f038b6a881df9f6b..5c70baf0113004e5c5cbc2fd6a6d34c75cf65217 100644 +index 5a7278b093e37b95fb005ad5cc3cac90ac36f8fb..6f886a44c4320df46c86f62ce2d6f070a9ca877f 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -1435,7 +1435,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - // Paper end - check Y +@@ -1425,7 +1425,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider + // Paper end - Configurable entity tracking range by Y // CraftBukkit start - respect vanish API - if (flag && !player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper - only consider hits @@ -27,19 +27,19 @@ index d9cd497bc1b654030ff1a597f038b6a881df9f6b..5c70baf0113004e5c5cbc2fd6a6d34c7 } // CraftBukkit end diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index da63b4050be25dcb91d04df8c2fcc643cbb0751d..bd4ca61dd2bb238bb05a64724e9926ede7063eef 100644 +index 206520f6f20b2e48b1eefdd4edb26510b88e4c92..715d9811a58a9224c72a923e4a74c76bd2b1e5f0 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -181,7 +181,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -187,7 +187,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player { private boolean hasPlayedBefore = false; private final ConversationTracker conversationTracker = new ConversationTracker(); private final Set channels = new HashSet(); - private final Map>> invertedVisibilityEntities = new HashMap<>(); + private final Map>> invertedVisibilityEntities = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(); // SparklyPaper - optimize canSee checks - private final Set unlistedEntities = new HashSet<>(); // Paper + private final Set unlistedEntities = new HashSet<>(); // Paper - Add Listing API for Player private static final WeakHashMap> pluginWeakReferences = new WeakHashMap<>(); private int hash = 0; -@@ -2138,9 +2138,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { +@@ -2141,9 +2141,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { @Override public boolean canSee(org.bukkit.entity.Entity entity) { diff --git a/patches/server/0014-Revert-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/patches/server/0014-Revert-Fix-MC-117075-Block-entity-unload-lag-spike.patch similarity index 66% rename from patches/server/0014-Revert-Fix-MC-117075-TE-Unload-Lag-Spike.patch rename to patches/server/0014-Revert-Fix-MC-117075-Block-entity-unload-lag-spike.patch index e8af745..22add33 100644 --- a/patches/server/0014-Revert-Fix-MC-117075-TE-Unload-Lag-Spike.patch +++ b/patches/server/0014-Revert-Fix-MC-117075-Block-entity-unload-lag-spike.patch @@ -1,37 +1,37 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MrPowerGamerBR -Date: Tue, 26 Dec 2023 16:45:54 -0300 -Subject: [PATCH] Revert "Fix MC-117075: TE Unload Lag Spike" +Date: Sun, 18 Feb 2024 14:22:37 -0300 +Subject: [PATCH] Revert "Fix MC-117075: Block entity unload lag spike" -This reverts commit f5e3e154a00754c18d557401cfb8d4aad5bc45e9. +This reverts commit f3453b204569ea865cc1d1302edb6d125e7f0cb3. diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index fdb86e3bcd48c9a27ca91e105bcd035de5781923..ed736827a7741a54e3a712cf5fcd19195aebaee5 100644 +index e199c852f4c493dbe6ab776d18b91a53e5a36f7c..06fe87cf8bd0e48885ae5f1773bcd603b4335b5e 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1281,8 +1281,6 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1276,8 +1276,6 @@ public abstract class Level implements LevelAccessor, AutoCloseable { boolean flag = this.tickRateManager().runsNormally(); int tilesThisCycle = 0; -- var toRemove = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet(); // Paper - use removeAll -- toRemove.add(null); +- var toRemove = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet(); // Paper - Fix MC-117075; use removeAll +- toRemove.add(null); // Paper - Fix MC-117075 for (tileTickPosition = 0; tileTickPosition < this.blockEntityTickers.size(); tileTickPosition++) { // Paper - Disable tick limiters this.tileTickPosition = (this.tileTickPosition < this.blockEntityTickers.size()) ? this.tileTickPosition : 0; TickingBlockEntity tickingblockentity = (TickingBlockEntity) this.blockEntityTickers.get(this.tileTickPosition); -@@ -1291,7 +1289,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1286,7 +1284,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { if (tickingblockentity.isRemoved()) { // Spigot start tilesThisCycle--; -- toRemove.add(tickingblockentity); // Paper - use removeAll +- toRemove.add(tickingblockentity); // Paper - Fix MC-117075; use removeAll + this.blockEntityTickers.remove(this.tileTickPosition--); // Spigot end } else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) { tickingblockentity.tick(); -@@ -1302,7 +1300,6 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1297,7 +1295,6 @@ public abstract class Level implements LevelAccessor, AutoCloseable { // Paper end - execute chunk tasks during tick } } -- this.blockEntityTickers.removeAll(toRemove); +- this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 this.timings.tileEntityTick.stopTiming(); // Spigot this.tickingBlockEntities = false; diff --git a/patches/server/0015-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/patches/server/0015-Fix-MC-117075-TE-Unload-Lag-Spike.patch index 5c8e51c..7b197ae 100644 --- a/patches/server/0015-Fix-MC-117075-TE-Unload-Lag-Spike.patch +++ b/patches/server/0015-Fix-MC-117075-TE-Unload-Lag-Spike.patch @@ -8,19 +8,19 @@ We replaced the `blockEntityTickers` list with a custom list based on fastutil's This is WAY FASTER than using `removeAll` with a list of entries to be removed, because we don't need to calculate the identity of each block entity to be removed, and we can jump directly to where the search should begin, giving a performance boost for small removals (because we don't need to loop thru the entire list to find what element should be removed) and a performance boost for big removals (no need to calculate the identity of each block entity). diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index ed736827a7741a54e3a712cf5fcd19195aebaee5..7681bce91247c13c8211ed6fd2a2998b815604f0 100644 +index 06fe87cf8bd0e48885ae5f1773bcd603b4335b5e..3558e39fe8bde6bb4133cfef211a5bf9251db0de 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -120,7 +120,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -115,7 +115,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public static final int TICKS_PER_DAY = 24000; public static final int MAX_ENTITY_SPAWN_Y = 20000000; public static final int MIN_ENTITY_SPAWN_Y = -20000000; -- protected final List blockEntityTickers = Lists.newArrayList(); public final int getTotalTileEntityTickers() { return this.blockEntityTickers.size(); } // Paper -+ protected final net.sparklypower.sparklypaper.BlockEntityTickersList blockEntityTickers = new net.sparklypower.sparklypaper.BlockEntityTickersList(); public final int getTotalTileEntityTickers() { return this.blockEntityTickers.size(); } // Paper // SparklyPaper - optimize block entity removals +- public final List blockEntityTickers = Lists.newArrayList(); // Paper - public ++ public final net.sparklypower.sparklypaper.BlockEntityTickersList blockEntityTickers = new net.sparklypower.sparklypaper.BlockEntityTickersList(); // Paper - public // SparklyPaper - optimize block entity removals protected final NeighborUpdater neighborUpdater; private final List pendingBlockEntityTickers = Lists.newArrayList(); private boolean tickingBlockEntities; -@@ -1289,7 +1289,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1284,7 +1284,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { if (tickingblockentity.isRemoved()) { // Spigot start tilesThisCycle--; @@ -29,7 +29,7 @@ index ed736827a7741a54e3a712cf5fcd19195aebaee5..7681bce91247c13c8211ed6fd2a2998b // Spigot end } else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) { tickingblockentity.tick(); -@@ -1300,7 +1300,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1295,7 +1295,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { // Paper end - execute chunk tasks during tick } } @@ -144,109 +144,3 @@ index 0000000000000000000000000000000000000000..7affec7e343c39a83390ae13ce23f3bf + size = j; + } +} -diff --git a/src/main/kotlin/net/sparklypower/sparklypaper/BlockEntityTickersList.java b/src/main/kotlin/net/sparklypower/sparklypaper/BlockEntityTickersList.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7affec7e343c39a83390ae13ce23f3bfa0db1eb6 ---- /dev/null -+++ b/src/main/kotlin/net/sparklypower/sparklypaper/BlockEntityTickersList.java -@@ -0,0 +1,100 @@ -+package net.sparklypower.sparklypaper; -+ -+import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -+import it.unimi.dsi.fastutil.objects.ObjectArrayList; -+import net.minecraft.world.level.block.entity.TickingBlockEntity; -+ -+import java.util.Arrays; -+import java.util.Collection; -+import java.util.HashSet; -+import java.util.Set; -+ -+/** -+ * A list for ServerLevel's blockEntityTickers -+ * -+ * This list is behaves identically to ObjectArrayList, but it has an additional method, `removeAllByIndex`, that allows a list of integers to be passed indicating what -+ * indexes should be deleted from the list -+ * -+ * This is faster than using removeAll, since we don't need to compare the identity of each block entity, and faster than looping thru each index manually and deleting with remove, -+ * since we don't need to resize the array every single remove. -+ */ -+public final class BlockEntityTickersList extends ObjectArrayList { -+ private final IntOpenHashSet toRemove = new IntOpenHashSet(); -+ private int startSearchFromIndex = -1; -+ -+ /** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity. */ -+ public BlockEntityTickersList() { -+ super(); -+ } -+ -+ /** -+ * Creates a new array list and fills it with a given collection. -+ * -+ * @param c a collection that will be used to fill the array list. -+ */ -+ public BlockEntityTickersList(final Collection c) { -+ super(c); -+ } -+ -+ /** -+ * Marks an entry as removed -+ * -+ * @param index the index of the item on the list to be marked as removed -+ */ -+ public void markAsRemoved(final int index) { -+ // The block entities list always loop starting from 0, so we only need to check if the startSearchFromIndex is -1 and that's it -+ if (this.startSearchFromIndex == -1) -+ this.startSearchFromIndex = index; -+ this.toRemove.add(index); -+ } -+ -+ /** -+ * Removes elements that have been marked as removed. -+ */ -+ public void removeMarkedEntries() { -+ if (this.startSearchFromIndex == -1) // No entries in the list, skip -+ return; -+ -+ removeAllByIndex(startSearchFromIndex, toRemove); -+ toRemove.clear(); -+ this.startSearchFromIndex = -1; // Reset the start search index -+ } -+ -+ /** -+ * Removes elements by their index. -+ */ -+ private void removeAllByIndex(final int startSearchFromIndex, final IntOpenHashSet c) { // can't use Set because we want to avoid autoboxing when using contains -+ final int requiredMatches = c.size(); -+ if (requiredMatches == 0) -+ return; // exit early, we don't need to do anything -+ -+ final Object[] a = this.a; -+ int j = startSearchFromIndex; -+ int matches = 0; -+ for (int i = startSearchFromIndex; i < size; i++) { // If the user knows the first index to be removed, we can skip a lot of unnecessary comparsions -+ if (!c.contains(i)) { -+ // TODO: It can be possible to optimize this loop by tracking the start/finish and then using arraycopy to "skip" the elements, -+ // this would optimize cases where the index to be removed are far apart, HOWEVER it does have a big performance impact if you are doing -+ // "arraycopy" for each element -+ a[j++] = a[i]; -+ } else { -+ matches++; -+ } -+ -+ if (matches == requiredMatches) { // Exit the loop if we already removed everything, we don't need to check anything else -+ // We need to update the final size here, because we know that we already found everything! -+ // Because we know that the size must be currentSize - requiredMatches (because we have matched everything), let's update the value -+ // However, we need to copy the rest of the stuff over -+ if (i != (size - 1)) { // If it isn't the last index... -+ // i + 1 because we want to copy the *next* element over -+ // and the size - i - 1 is because we want to get the current size, minus the current index (which is i), and then - 1 because we want to copy -1 ahead (remember, we are adding +1 to copy the *next* element) -+ System.arraycopy(a, i + 1, a, j, size - i - 1); -+ } -+ j = size - requiredMatches; -+ break; -+ } -+ } -+ Arrays.fill(a, j, size, null); -+ size = j; -+ } -+} diff --git a/patches/server/0016-Optimize-tickBlockEntities.patch b/patches/server/0016-Optimize-tickBlockEntities.patch index 13071fa..06c8e37 100644 --- a/patches/server/0016-Optimize-tickBlockEntities.patch +++ b/patches/server/0016-Optimize-tickBlockEntities.patch @@ -12,10 +12,10 @@ But here's the thing: We don't care if we have a small performance penalty if th And finally, we also cache the chunk's coordinate key when creating the block entity, which is actually "free" because we just reuse the already cached chunk coordinate key from the chunk! diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 7681bce91247c13c8211ed6fd2a2998b815604f0..608259c6092f5353e818b5fbeb0e1a5249ed136b 100644 +index 3558e39fe8bde6bb4133cfef211a5bf9251db0de..1008f136ec24efc588b41fe8bf313c926ca000ed 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -1281,6 +1281,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1276,6 +1276,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable { boolean flag = this.tickRateManager().runsNormally(); int tilesThisCycle = 0; @@ -26,7 +26,7 @@ index 7681bce91247c13c8211ed6fd2a2998b815604f0..608259c6092f5353e818b5fbeb0e1a52 for (tileTickPosition = 0; tileTickPosition < this.blockEntityTickers.size(); tileTickPosition++) { // Paper - Disable tick limiters this.tileTickPosition = (this.tileTickPosition < this.blockEntityTickers.size()) ? this.tileTickPosition : 0; TickingBlockEntity tickingblockentity = (TickingBlockEntity) this.blockEntityTickers.get(this.tileTickPosition); -@@ -1291,13 +1295,25 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1286,13 +1290,25 @@ public abstract class Level implements LevelAccessor, AutoCloseable { tilesThisCycle--; this.blockEntityTickers.markAsRemoved(this.tileTickPosition); // this.blockEntityTickers.remove(this.tileTickPosition--); // SparklyPaper - optimize block entity removals // Spigot end @@ -65,7 +65,7 @@ index 28e3b73507b988f7234cbf29c4024c88180d0aef..427cf73383155c52bca8fb4b32f43029 + long getChunkCoordinateKey(); // SparklyPaper - optimize tickBlockEntities } 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 fa170cc1ce7011d201295b89718292d696c7fc24..1338f91a85f5db6ce78705a0c48bec8a449a6220 100644 +index 6ec3fc801453fd54c25b642e6fa71c19b463311d..91b538f047428b8836f7ad3b62a0586fb7beb9ec 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -73,6 +73,13 @@ public class LevelChunk extends ChunkAccess { @@ -82,7 +82,7 @@ index fa170cc1ce7011d201295b89718292d696c7fc24..1338f91a85f5db6ce78705a0c48bec8a }; private final Map tickersInLevel; public boolean loaded; -@@ -1090,7 +1097,7 @@ public class LevelChunk extends ChunkAccess { +@@ -1089,7 +1096,7 @@ public class LevelChunk extends ChunkAccess { } private TickingBlockEntity createTicker(T blockEntity, BlockEntityTicker blockEntityTicker) { @@ -91,7 +91,7 @@ index fa170cc1ce7011d201295b89718292d696c7fc24..1338f91a85f5db6ce78705a0c48bec8a } @FunctionalInterface -@@ -1141,6 +1148,13 @@ public class LevelChunk extends ChunkAccess { +@@ -1140,6 +1147,13 @@ public class LevelChunk extends ChunkAccess { public String toString() { return this.ticker + " "; } @@ -105,7 +105,7 @@ index fa170cc1ce7011d201295b89718292d696c7fc24..1338f91a85f5db6ce78705a0c48bec8a } private class BoundTickingBlockEntity implements TickingBlockEntity { -@@ -1148,10 +1162,12 @@ public class LevelChunk extends ChunkAccess { +@@ -1147,10 +1161,12 @@ public class LevelChunk extends ChunkAccess { private final T blockEntity; private final BlockEntityTicker ticker; private boolean loggedInvalidBlockState; @@ -119,7 +119,7 @@ index fa170cc1ce7011d201295b89718292d696c7fc24..1338f91a85f5db6ce78705a0c48bec8a } @Override -@@ -1214,5 +1230,12 @@ public class LevelChunk extends ChunkAccess { +@@ -1213,5 +1229,12 @@ public class LevelChunk extends ChunkAccess { return "Level ticker for " + s + "@" + this.getPos(); } diff --git a/patches/server/0017-Track-how-much-MSPT-each-world-used.patch b/patches/server/0017-Track-how-much-MSPT-each-world-used.patch index 0d947f8..2b1ed84 100644 --- a/patches/server/0017-Track-how-much-MSPT-each-world-used.patch +++ b/patches/server/0017-Track-how-much-MSPT-each-world-used.patch @@ -56,10 +56,10 @@ index 8b5293b0c696ef21d0101493ffa41b60bf0bc86b..601198a33adb29316b0617d5390d1620 } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f43060555bf02f13268b284606045fce2b3e911a..f34a9d3a255ee72e2c467376bd1f7bc2a1309443 100644 +index f2edb992729325140d4b2f6f347c3bd8c6394a77..2de67af8952f5299476c1eaa979fdcb3fe7d3203 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -1730,7 +1730,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { @@ -494,7 +494,7 @@ index bf1c5834717758991c1520afd4b2a5c3fa68a558..c1387cd2726083b52f2ba51297072de3 Location location = CraftLocation.toBukkit(blockposition, worldserver.getWorld()); List blocks = new java.util.ArrayList<>(worldserver.capturedBlockStates.values()); worldserver.capturedBlockStates.clear(); -@@ -890,7 +890,7 @@ public interface DispenseItemBehavior { +@@ -899,7 +899,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseEvent event = new BlockDispenseEvent(block, craftItem.clone(), new org.bukkit.util.Vector((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D)); @@ -503,7 +503,7 @@ index bf1c5834717758991c1520afd4b2a5c3fa68a558..c1387cd2726083b52f2ba51297072de3 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -947,7 +947,7 @@ public interface DispenseItemBehavior { +@@ -956,7 +956,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); @@ -512,7 +512,7 @@ index bf1c5834717758991c1520afd4b2a5c3fa68a558..c1387cd2726083b52f2ba51297072de3 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -996,7 +996,7 @@ public interface DispenseItemBehavior { +@@ -1005,7 +1005,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - single item in event BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); @@ -521,7 +521,7 @@ index bf1c5834717758991c1520afd4b2a5c3fa68a558..c1387cd2726083b52f2ba51297072de3 worldserver.getCraftServer().getPluginManager().callEvent(event); } -@@ -1069,7 +1069,7 @@ public interface DispenseItemBehavior { +@@ -1078,7 +1078,7 @@ public interface DispenseItemBehavior { CraftItemStack craftItem = CraftItemStack.asCraftMirror(stack.copyWithCount(1)); // Paper - only single item in event BlockDispenseEvent event = new BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(blockposition.getX(), blockposition.getY(), blockposition.getZ())); @@ -531,7 +531,7 @@ index bf1c5834717758991c1520afd4b2a5c3fa68a558..c1387cd2726083b52f2ba51297072de3 } diff --git a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java -index 887e75c940ab5089f4e42e4553ab95adf172df46..c477e31142be8ee20f1dbba7ad1f5b7baad7437d 100644 +index 8d65cdb013706a932c2c73231108b2810b99e1c7..77741616d3b208c55d84a2246dbaf6cc16180187 100644 --- a/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/ShearsDispenseItemBehavior.java @@ -40,7 +40,7 @@ public class ShearsDispenseItemBehavior extends OptionalDispenseItemBehavior { @@ -544,7 +544,7 @@ index 887e75c940ab5089f4e42e4553ab95adf172df46..c477e31142be8ee20f1dbba7ad1f5b7b } diff --git a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java -index 6f2adf2334e35e8a617a4ced0c1af2abf32bbd8d..a5ea9df0a021ed820c0c1ccb612caebd582878e2 100644 +index cb308808906a8cdb127df8284e106e00553473ca..323d41e2bed5e83a26dfe4c88dfce7ed87cdfb4c 100644 --- a/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java +++ b/src/main/java/net/minecraft/core/dispenser/ShulkerBoxDispenseBehavior.java @@ -37,7 +37,7 @@ public class ShulkerBoxDispenseBehavior extends OptionalDispenseItemBehavior { @@ -557,19 +557,11 @@ index 6f2adf2334e35e8a617a4ced0c1af2abf32bbd8d..a5ea9df0a021ed820c0c1ccb612caebd } diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index f34a9d3a255ee72e2c467376bd1f7bc2a1309443..cbb830d36c5ad753a650667f7fd178fca83d49fb 100644 +index 2de67af8952f5299476c1eaa979fdcb3fe7d3203..749bd41a6913cbc6a99e994d2adfa5d9d0c1d7c9 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -152,6 +152,7 @@ import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; - import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; - import net.minecraft.world.level.storage.WorldData; - import net.minecraft.world.level.storage.loot.LootDataManager; -+import org.bukkit.craftbukkit.event.CraftEventFactory; - import org.slf4j.Logger; - - // CraftBukkit start -@@ -316,6 +317,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop entitiesWithScheduledTasks = java.util.concurrent.ConcurrentHashMap.newKeySet(); // SparklyPaper - skip EntityScheduler's executeTick checks if there isn't any tasks to be run (concurrent because plugins may schedule tasks async) public net.sparklypower.sparklypaper.HalloweenManager halloweenManager = new net.sparklypower.sparklypaper.HalloweenManager(); // SparklyPaper - Spooky month optimizations + // SparklyPaper - parallel world ticking @@ -578,35 +570,46 @@ index f34a9d3a255ee72e2c467376bd1f7bc2a1309443..cbb830d36c5ad753a650667f7fd178fc public static S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); -@@ -1708,63 +1712,124 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper - BlockPhysicsEvent +- worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent +- net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers - worldserver.updateLagCompensationTick(); // Paper - lag compensation -- worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper -- net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper -- worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper +- +- this.profiler.push(() -> { +- return worldserver + " " + worldserver.dimension().location(); +- }); +- /* Drop global time updates +- if (this.tickCount % 20 == 0) { +- this.profiler.push("timeSync"); +- this.synchronizeTime(worldserver); +- this.profiler.pop(); +- } +- // CraftBukkit end */ + // SparklyPaper start - parallel world ticking + java.util.ArrayDeque> tasks = new java.util.ArrayDeque<>(); -+ // while (iterator.hasNext()) { // SparklyPaper - commented out to cause diff when upstream changes this code -+ // ServerLevel worldserver = (ServerLevel) iterator.next(); -+ // worldserver.updateLagCompensationTick(); // Paper - lag compensation -+ // worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper -+ // net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper -+ // worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper ++ // while (iterator.hasNext()) { ++ // ServerLevel worldserver = (ServerLevel) iterator.next(); ++ // worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent ++ // worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent ++ // net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers ++ // worldserver.updateLagCompensationTick(); // Paper - lag compensation + // -+ // this.profiler.push(() -> { -+ // return worldserver + " " + worldserver.dimension().location(); -+ // }); -+ // /* Drop global time updates -+ // if (this.tickCount % 20 == 0) { -+ // this.profiler.push("timeSync"); -+ // this.synchronizeTime(worldserver); -+ // this.profiler.pop(); -+ // } -+ // // CraftBukkit end */ ++ // this.profiler.push(() -> { ++ // return worldserver + " " + worldserver.dimension().location(); ++ // }); ++ // /* Drop global time updates ++ // if (this.tickCount % 20 == 0) { ++ // this.profiler.push("timeSync"); ++ // this.synchronizeTime(worldserver); ++ // this.profiler.pop(); ++ // } ++ // // CraftBukkit end */ + // + // this.profiler.push("tick"); + // @@ -615,7 +618,7 @@ index f34a9d3a255ee72e2c467376bd1f7bc2a1309443..cbb830d36c5ad753a650667f7fd178fc + // long i = Util.getNanos(); // SparklyPaper - track world's MSPT + // worldserver.tick(shouldKeepTicking); + // // SparklyPaper start - track world's MSPT -+ // long j = this.tickTimes[this.tickCount % 100] = Util.getNanos() - i; ++ // long j = Util.getNanos() - i; + // + // // These are from the "tickServer" function + // worldserver.tickTimes5s.add(this.tickCount, j); @@ -629,15 +632,7 @@ index f34a9d3a255ee72e2c467376bd1f7bc2a1309443..cbb830d36c5ad753a650667f7fd178fc + // // Paper end + // worldserver.timings.doTick.stopTiming(); // Spigot + // } catch (Throwable throwable) { -+ // // Spigot Start -+ // CrashReport crashreport; -+ // try { -+ // crashreport = CrashReport.forThrowable(throwable, "Exception ticking world"); -+ // } catch (Throwable t) { -+ // if (throwable instanceof ThreadDeath) { throw (ThreadDeath)throwable; } // Paper -+ // throw new RuntimeException("Error generating crash report", t); -+ // } -+ // // Spigot End ++ // CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception ticking world"); + // + // worldserver.fillReportDetails(crashreport); + // throw new ReportedException(crashreport); @@ -651,9 +646,9 @@ index f34a9d3a255ee72e2c467376bd1f7bc2a1309443..cbb830d36c5ad753a650667f7fd178fc + while (iterator.hasNext()) { + ServerLevel worldserver = (ServerLevel) iterator.next(); + worldserver.updateLagCompensationTick(); // Paper - lag compensation -+ worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper ++ worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper + net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper -+ worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper ++ worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper + + serverLevelTickingSemaphore.acquire(); + tasks.add( @@ -669,26 +664,10 @@ index f34a9d3a255ee72e2c467376bd1f7bc2a1309443..cbb830d36c5ad753a650667f7fd178fc + } + worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions -- this.profiler.push(() -> { -- return worldserver + " " + worldserver.dimension().location(); -- }); -- /* Drop global time updates -- if (this.tickCount % 20 == 0) { -- this.profiler.push("timeSync"); -- this.synchronizeTime(worldserver); -- this.profiler.pop(); -- } -- // CraftBukkit end */ +- this.profiler.push("tick"); + // SparklyPaper start - track world's MSPT + long j = Util.getNanos() - i; -- this.profiler.push("tick"); -+ // These are from the "tickServer" function -+ worldserver.tickTimes5s.add(this.tickCount, j); -+ worldserver.tickTimes10s.add(this.tickCount, j); -+ worldserver.tickTimes60s.add(this.tickCount, j); -+ // SparklyPaper end - - try { - worldserver.timings.doTick.startTiming(); // Spigot - long i = Util.getNanos(); // SparklyPaper - track world's MSPT @@ -708,15 +687,15 @@ index f34a9d3a255ee72e2c467376bd1f7bc2a1309443..cbb830d36c5ad753a650667f7fd178fc - // Paper end - worldserver.timings.doTick.stopTiming(); // Spigot - } catch (Throwable throwable) { -- // Spigot Start -- CrashReport crashreport; -- try { -- crashreport = CrashReport.forThrowable(throwable, "Exception ticking world"); -- } catch (Throwable t) { -- if (throwable instanceof ThreadDeath) { throw (ThreadDeath)throwable; } // Paper -- throw new RuntimeException("Error generating crash report", t); -- } -- // Spigot End +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception ticking world"); ++ // These are from the "tickServer" function ++ worldserver.tickTimes5s.add(this.tickCount, j); ++ worldserver.tickTimes10s.add(this.tickCount, j); ++ worldserver.tickTimes60s.add(this.tickCount, j); ++ // SparklyPaper end + +- worldserver.fillReportDetails(crashreport); +- throw new ReportedException(crashreport); + currentThread.currentlyTickingServerLevel = null; // Reset current ticking level + } catch (Throwable throwable) { + // Spigot Start @@ -724,13 +703,12 @@ index f34a9d3a255ee72e2c467376bd1f7bc2a1309443..cbb830d36c5ad753a650667f7fd178fc + try { + crashreport = CrashReport.forThrowable(throwable, "Exception ticking world"); + } catch (Throwable t) { -+ if (throwable instanceof ThreadDeath) { throw (ThreadDeath)throwable; } // Paper ++ if (throwable instanceof ThreadDeath) { ++ throw (ThreadDeath) throwable; ++ } // Paper + throw new RuntimeException("Error generating crash report", t); + } + // Spigot End - -- worldserver.fillReportDetails(crashreport); -- throw new ReportedException(crashreport); + worldserver.fillReportDetails(crashreport); + throw new ReportedException(crashreport); + } finally { @@ -739,7 +717,7 @@ index f34a9d3a255ee72e2c467376bd1f7bc2a1309443..cbb830d36c5ad753a650667f7fd178fc + }, worldserver) + ); } - +- - this.profiler.pop(); - this.profiler.pop(); - worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions @@ -750,11 +728,11 @@ index f34a9d3a255ee72e2c467376bd1f7bc2a1309443..cbb830d36c5ad753a650667f7fd178fc + throw new RuntimeException(e); // Propagate exception } + // SparklyPaper end - this.isIteratingOverLevels = false; // Paper + this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked this.profiler.popPush("connection"); diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 734fd1ced38a16649177bb941e76d9ca66dceac5..f1cc1083e6093d3813042f94c5229993d7b5df44 100644 +index 4c549a2656183e4e4bbaf3f7d5169f3d258e81ce..dd889a41412ce62bd362d82c44dea71eb490a05c 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -17,6 +17,7 @@ import java.util.Collections; @@ -773,7 +751,7 @@ index 734fd1ced38a16649177bb941e76d9ca66dceac5..f1cc1083e6093d3813042f94c5229993 import org.slf4j.Logger; // CraftBukkit start -@@ -226,6 +228,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -227,6 +229,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface return false; } net.sparklypower.sparklypaper.SparklyPaperCommands.INSTANCE.registerCommands(this); @@ -783,10 +761,10 @@ index 734fd1ced38a16649177bb941e76d9ca66dceac5..f1cc1083e6093d3813042f94c5229993 // SparklyPaper start - Spooky month optimizations halloweenManager.startHalloweenEpochTask(); diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 22213a52c5d546145d8b8de929af61e49d40375d..40878c28fa1e383e88c7ce2dfa142ab06582cf27 100644 +index 53bce70f5cc14672d41618747d3919429896001f..ec27e20d661ecde3992a4b4366cf19b2cb1ee2d5 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -236,7 +236,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -197,7 +197,7 @@ public class ServerChunkCache extends ChunkSource { public LevelChunk getChunkAtIfLoadedImmediately(int x, int z) { long k = ChunkPos.asLong(x, z); @@ -795,7 +773,7 @@ index 22213a52c5d546145d8b8de929af61e49d40375d..40878c28fa1e383e88c7ce2dfa142ab0 return this.getChunkAtIfLoadedMainThread(x, z); } -@@ -263,7 +263,16 @@ public class ServerChunkCache extends ChunkSource { +@@ -250,7 +250,16 @@ public class ServerChunkCache extends ChunkSource { @Override public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) { final int x1 = x; final int z1 = z; // Paper - conflict on variable change @@ -813,7 +791,7 @@ index 22213a52c5d546145d8b8de929af61e49d40375d..40878c28fa1e383e88c7ce2dfa142ab0 return (ChunkAccess) CompletableFuture.supplyAsync(() -> { return this.getChunk(x, z, leastStatus, create); }, this.mainThreadProcessor).join(); -@@ -315,7 +324,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -300,7 +309,7 @@ public class ServerChunkCache extends ChunkSource { @Nullable @Override public LevelChunk getChunkNow(int chunkX, int chunkZ) { @@ -821,8 +799,8 @@ index 22213a52c5d546145d8b8de929af61e49d40375d..40878c28fa1e383e88c7ce2dfa142ab0 + if (!io.papermc.paper.util.TickThread.isTickThreadFor(level, chunkX, chunkZ)) { // Paper - rewrite chunk system // SparklyPaper - parallel world ticking return null; } else { - return this.getChunkAtIfLoadedMainThread(chunkX, chunkZ); // Paper - optimise for loaded chunks -@@ -329,7 +338,7 @@ public class ServerChunkCache extends ChunkSource { + return this.getChunkAtIfLoadedMainThread(chunkX, chunkZ); // Paper - Perf: Optimise getChunkAt calls for loaded chunks +@@ -314,7 +323,7 @@ public class ServerChunkCache extends ChunkSource { } public CompletableFuture> getChunkFuture(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { @@ -831,7 +809,7 @@ index 22213a52c5d546145d8b8de929af61e49d40375d..40878c28fa1e383e88c7ce2dfa142ab0 CompletableFuture completablefuture; if (flag1) { -@@ -646,7 +655,7 @@ public class ServerChunkCache extends ChunkSource { +@@ -638,7 +647,7 @@ public class ServerChunkCache extends ChunkSource { if (true || this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { // Paper - optimise chunk tick iteration this.level.tickChunk(chunk1, l); @@ -841,10 +819,10 @@ index 22213a52c5d546145d8b8de929af61e49d40375d..40878c28fa1e383e88c7ce2dfa142ab0 } } diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 6999dde76bb98f9a1cb74a24fa518d705421e58e..f53b7230a49678824039bea94fc5bd1501b38bf4 100644 +index 9a1f5ce72dbe116c31d9f72a8ad2dfaedf962d7d..919f49c4dac25fe129cb0d7ddfd63932aff89c17 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -218,6 +218,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -217,6 +217,7 @@ public class ServerLevel extends Level implements WorldGenLevel { private final boolean tickTime; private final RandomSequences randomSequences; public long lastMidTickExecuteFailure; // Paper - execute chunk tasks mid tick @@ -852,7 +830,7 @@ index 6999dde76bb98f9a1cb74a24fa518d705421e58e..f53b7230a49678824039bea94fc5bd15 // CraftBukkit start public final LevelStorageSource.LevelStorageAccess convertable; -@@ -710,7 +711,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -704,7 +705,7 @@ public class ServerLevel extends Level implements WorldGenLevel { this.uuid = WorldUUID.getUUID(convertable_conversionsession.levelDirectory.path().toFile()); // CraftBukkit end this.players = Lists.newArrayList(); @@ -861,7 +839,7 @@ index 6999dde76bb98f9a1cb74a24fa518d705421e58e..f53b7230a49678824039bea94fc5bd15 this.blockTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); this.fluidTicks = new LevelTicks<>(this::isPositionTickingWithEntitiesLoaded, this.getProfilerSupplier()); this.navigatingMobs = new ObjectOpenHashSet(); -@@ -781,6 +782,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -775,6 +776,7 @@ public class ServerLevel extends Level implements WorldGenLevel { this.chunkTaskScheduler = new io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler(this, io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.workerThreads); // Paper - rewrite chunk system this.entityLookup = new io.papermc.paper.chunk.system.entity.EntityLookup(this, new EntityCallbacks()); // Paper - rewrite chunk system @@ -869,7 +847,7 @@ index 6999dde76bb98f9a1cb74a24fa518d705421e58e..f53b7230a49678824039bea94fc5bd15 } // Paper start -@@ -1358,7 +1360,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1352,7 +1354,7 @@ public class ServerLevel extends Level implements WorldGenLevel { if (fluid1.is(fluid)) { fluid1.tick(this, pos); } @@ -878,7 +856,7 @@ index 6999dde76bb98f9a1cb74a24fa518d705421e58e..f53b7230a49678824039bea94fc5bd15 } -@@ -1368,7 +1370,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1362,7 +1364,7 @@ public class ServerLevel extends Level implements WorldGenLevel { if (iblockdata.is(block)) { iblockdata.tick(this, pos, this.random); } @@ -887,7 +865,7 @@ index 6999dde76bb98f9a1cb74a24fa518d705421e58e..f53b7230a49678824039bea94fc5bd15 } -@@ -1386,7 +1388,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1380,7 +1382,7 @@ public class ServerLevel extends Level implements WorldGenLevel { public void tickNonPassenger(Entity entity) { // Paper start - log detailed entity tick information @@ -896,7 +874,7 @@ index 6999dde76bb98f9a1cb74a24fa518d705421e58e..f53b7230a49678824039bea94fc5bd15 try { if (currentlyTickingEntity.get() == null) { currentlyTickingEntity.lazySet(entity); -@@ -1674,6 +1676,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1668,6 +1670,7 @@ public class ServerLevel extends Level implements WorldGenLevel { } private void addPlayer(ServerPlayer player) { @@ -904,16 +882,16 @@ index 6999dde76bb98f9a1cb74a24fa518d705421e58e..f53b7230a49678824039bea94fc5bd15 Entity entity = (Entity) this.getEntities().get(player.getUUID()); if (entity != null) { -@@ -1687,7 +1690,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -1681,7 +1684,7 @@ public class ServerLevel extends Level implements WorldGenLevel { // CraftBukkit start private boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) { - org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot + io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot add entity off-main"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - // Paper start + entity.generation = false; // Paper - Don't fire sync event during generation; Reset flag if it was added during a ServerLevel generation process + // Paper start - extra debug info if (entity.valid) { - MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); -@@ -2672,6 +2675,7 @@ public class ServerLevel extends Level implements WorldGenLevel { +@@ -2652,6 +2655,7 @@ public class ServerLevel extends Level implements WorldGenLevel { @Override public void close() throws IOException { super.close(); @@ -922,40 +900,10 @@ index 6999dde76bb98f9a1cb74a24fa518d705421e58e..f53b7230a49678824039bea94fc5bd15 } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java -index be05a52be037042c6158100e2ce880b8ed415d53..0eda3d6699a35ffe320c7fc7b86e4573c9d4e6cd 100644 +index 58591bf2f63b9c5e97d9ce4188dff3366968a178..3debae03ef3d6e01699be2f49a43835f7ed83608 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java -@@ -17,6 +17,7 @@ import java.util.OptionalInt; - import java.util.Set; - import java.util.stream.Collectors; - import javax.annotation.Nullable; -+ - import net.minecraft.BlockUtil; - import net.minecraft.ChatFormatting; - import net.minecraft.CrashReport; -@@ -95,7 +96,6 @@ import net.minecraft.util.Mth; - import net.minecraft.util.RandomSource; - import net.minecraft.util.Unit; - import net.minecraft.world.damagesource.DamageSource; --import net.minecraft.world.damagesource.DamageSources; - import net.minecraft.world.effect.MobEffectInstance; - import net.minecraft.world.effect.MobEffects; - import net.minecraft.world.entity.Entity; -@@ -118,12 +118,7 @@ import net.minecraft.world.entity.projectile.AbstractArrow; - import net.minecraft.world.entity.vehicle.AbstractMinecart; - import net.minecraft.world.entity.vehicle.Boat; - import net.minecraft.world.food.FoodData; --import net.minecraft.world.inventory.AbstractContainerMenu; --import net.minecraft.world.inventory.ContainerListener; --import net.minecraft.world.inventory.ContainerSynchronizer; --import net.minecraft.world.inventory.HorseInventoryMenu; --import net.minecraft.world.inventory.ResultSlot; --import net.minecraft.world.inventory.Slot; -+import net.minecraft.world.inventory.*; - import net.minecraft.world.item.ComplexItem; - import net.minecraft.world.item.ItemCooldowns; - import net.minecraft.world.item.ItemStack; -@@ -328,6 +323,7 @@ public class ServerPlayer extends Player { +@@ -328,6 +328,7 @@ public class ServerPlayer extends Player { // Paper start - optimise chunk tick iteration public double lastEntitySpawnRadiusSquared = -1.0; // Paper end - optimise chunk tick iteration @@ -963,7 +911,7 @@ index be05a52be037042c6158100e2ce880b8ed415d53..0eda3d6699a35ffe320c7fc7b86e4573 public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) { super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); -@@ -717,6 +713,7 @@ public class ServerPlayer extends Player { +@@ -717,6 +718,7 @@ public class ServerPlayer extends Player { @Override public void tick() { @@ -971,15 +919,7 @@ index be05a52be037042c6158100e2ce880b8ed415d53..0eda3d6699a35ffe320c7fc7b86e4573 // CraftBukkit start if (this.joining) { this.joining = false; -@@ -735,6 +732,7 @@ public class ServerPlayer extends Player { - containerUpdateDelay = this.level().paperConfig().tickRates.containerUpdate; - } - // Paper end -+ // SparklyPaper - parallel world ticking (debugging) - if (!this.level().isClientSide && this.containerMenu != this.inventoryMenu && (this.isImmobile() || !this.containerMenu.stillValid(this))) { // Paper - auto close while frozen - this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - this.containerMenu = this.inventoryMenu; -@@ -1185,6 +1183,7 @@ public class ServerPlayer extends Player { +@@ -1185,6 +1187,7 @@ public class ServerPlayer extends Player { ResourceKey resourcekey = worldserver1.getTypeKey(); // CraftBukkit if (resourcekey == LevelStem.END && worldserver != null && worldserver.getTypeKey() == LevelStem.OVERWORLD) { // CraftBukkit @@ -987,7 +927,7 @@ index be05a52be037042c6158100e2ce880b8ed415d53..0eda3d6699a35ffe320c7fc7b86e4573 this.isChangingDimension = true; // CraftBukkit - Moved down from above this.unRide(); this.serverLevel().removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION); -@@ -1197,6 +1196,10 @@ public class ServerPlayer extends Player { +@@ -1197,6 +1200,10 @@ public class ServerPlayer extends Player { return this; } else { @@ -998,7 +938,7 @@ index be05a52be037042c6158100e2ce880b8ed415d53..0eda3d6699a35ffe320c7fc7b86e4573 // CraftBukkit start /* WorldData worlddata = worldserver.getLevelData(); -@@ -1605,6 +1608,12 @@ public class ServerPlayer extends Player { +@@ -1605,6 +1612,12 @@ public class ServerPlayer extends Player { return OptionalInt.empty(); } else { // CraftBukkit start @@ -1009,9 +949,9 @@ index be05a52be037042c6158100e2ce880b8ed415d53..0eda3d6699a35ffe320c7fc7b86e4573 + } + // SparklyPaper end this.containerMenu = container; - if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), Objects.requireNonNullElseGet(title, container::getTitle))); // Paper + if (!this.isImmobile()) this.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), Objects.requireNonNullElseGet(title, container::getTitle))); // Paper - Add titleOverride to InventoryOpenEvent // CraftBukkit end -@@ -1666,6 +1675,11 @@ public class ServerPlayer extends Player { +@@ -1666,6 +1679,11 @@ public class ServerPlayer extends Player { } @Override public void closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) { @@ -1021,29 +961,13 @@ index be05a52be037042c6158100e2ce880b8ed415d53..0eda3d6699a35ffe320c7fc7b86e4573 + } + // SparklyPaper end CraftEventFactory.handleInventoryCloseEvent(this, reason); // CraftBukkit - // Paper end + // Paper end - Inventory close reason this.connection.send(new ClientboundContainerClosePacket(this.containerMenu.containerId)); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index e98a455b6bca9d094d0da323bddd7b3f2c07bb23..7b82aae91fda6a73c2ca2e27a89a2ec34ba0fa3c 100644 +index 91feb12732564c90656da487664dbc12e55397fc..7dc3355c7a40081498b4a3c6a6dca7edd151e59b 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java +++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -109,7 +109,6 @@ import org.bukkit.Location; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; - import org.bukkit.craftbukkit.entity.CraftPlayer; --import org.bukkit.craftbukkit.util.CraftChatMessage; - import org.bukkit.craftbukkit.util.CraftLocation; - import org.bukkit.entity.Player; - import org.bukkit.event.player.PlayerChangedWorldEvent; -@@ -118,7 +117,6 @@ import org.bukkit.event.player.PlayerLoginEvent; - import org.bukkit.event.player.PlayerQuitEvent; - import org.bukkit.event.player.PlayerRespawnEvent; - import org.bukkit.event.player.PlayerRespawnEvent.RespawnReason; --import org.bukkit.event.player.PlayerSpawnChangeEvent; - // CraftBukkit end - - public abstract class PlayerList { -@@ -134,7 +132,7 @@ public abstract class PlayerList { +@@ -134,7 +134,7 @@ public abstract class PlayerList { private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); private final MinecraftServer server; public final List players = new java.util.concurrent.CopyOnWriteArrayList(); // CraftBukkit - ArrayList -> CopyOnWriteArrayList: Iterator safety @@ -1052,33 +976,33 @@ index e98a455b6bca9d094d0da323bddd7b3f2c07bb23..7b82aae91fda6a73c2ca2e27a89a2ec3 private final UserBanList bans; private final IpBanList ipBans; private final ServerOpList ops; -@@ -155,7 +153,7 @@ public abstract class PlayerList { +@@ -155,7 +155,7 @@ public abstract class PlayerList { // CraftBukkit start private CraftServer cserver; - private final Map playersByName = new java.util.HashMap<>(); + private final Map playersByName = new java.util.HashMap<>(); // SparklyPaper - parallel world ticking (we don't need to replace the original map because we never iterate on top of this map) - public @Nullable String collideRuleTeamName; // Paper - Team name used for collideRule + public @Nullable String collideRuleTeamName; // Paper - Configurable player collision public PlayerList(MinecraftServer server, LayeredRegistryAccess registryManager, PlayerDataStorage saveHandler, int maxPlayers) { -@@ -179,6 +177,7 @@ public abstract class PlayerList { - abstract public void loadAndSaveFiles(); // Paper - moved from DedicatedPlayerList constructor +@@ -179,6 +179,7 @@ public abstract class PlayerList { + abstract public void loadAndSaveFiles(); // Paper - fix converting txt to json file; moved from DedicatedPlayerList constructor public void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie clientData) { + io.papermc.paper.util.TickThread.ensureOnlyTickThread("Cannot place new player off-main"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) player.isRealPlayer = true; // Paper - player.loginTime = System.currentTimeMillis(); // Paper + player.loginTime = System.currentTimeMillis(); // Paper - Replace OfflinePlayer#getLastPlayed GameProfile gameprofile = player.getGameProfile(); -@@ -818,6 +817,8 @@ public abstract class PlayerList { +@@ -817,6 +818,8 @@ public abstract class PlayerList { } public ServerPlayer respawn(ServerPlayer entityplayer, ServerLevel worldserver, boolean flag, Location location, boolean avoidSuffocation, RespawnReason reason, org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag...respawnFlags) { + System.out.println("respawning player - current player container is " + entityplayer.containerMenu + " but their inventory is " + entityplayer.inventoryMenu); + io.papermc.paper.util.TickThread.ensureOnlyTickThread("Cannot respawn player off-main, from world " + entityplayer.serverLevel().getWorld().getName() + " to world " + worldserver.getWorld().getName()); // SparklyPaper - parallel world ticking (additional concurrency issues logs) - // Paper end + // Paper end - Expand PlayerRespawnEvent entityplayer.stopRiding(); // CraftBukkit this.players.remove(entityplayer); -@@ -842,6 +843,7 @@ public abstract class PlayerList { +@@ -841,6 +844,7 @@ public abstract class PlayerList { ServerPlayer entityplayer1 = entityplayer; org.bukkit.World fromWorld = entityplayer.getBukkitEntity().getWorld(); entityplayer.wonGame = false; @@ -1087,10 +1011,10 @@ index e98a455b6bca9d094d0da323bddd7b3f2c07bb23..7b82aae91fda6a73c2ca2e27a89a2ec3 entityplayer1.connection = entityplayer.connection; diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index aa6045039450c4cce8d9481aa7f56867dd15c0fa..807a11fa10b1aeb46c9e4e47b9477a5f15d86149 100644 +index b0b9e07da81ca0c2a0e915afbcd1a50a39e3bf20..f0db55f14388724d81640e6b4ead2429d11207c9 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -808,7 +808,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -813,7 +813,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S // CraftBukkit start public void postTick() { // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle @@ -1099,33 +1023,7 @@ index aa6045039450c4cce8d9481aa7f56867dd15c0fa..807a11fa10b1aeb46c9e4e47b9477a5f this.handleNetherPortal(); } } -@@ -938,11 +938,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S - // This will be called every single tick the entity is in lava, so don't throw an event - this.setSecondsOnFire(15, false); - } -- CraftEventFactory.blockDamage = (this.lastLavaContact) == null ? null : org.bukkit.craftbukkit.block.CraftBlock.at(this.level, this.lastLavaContact); -+ CraftEventFactory.blockDamageRT.set((this.lastLavaContact) == null ? null : org.bukkit.craftbukkit.block.CraftBlock.at(this.level, this.lastLavaContact)); // SparklyPaper - parallel world ticking - if (this.hurt(this.damageSources().lava(), 4.0F)) { - this.playSound(SoundEvents.GENERIC_BURN, 0.4F, 2.0F + this.random.nextFloat() * 0.4F); - } -- CraftEventFactory.blockDamage = null; -+ CraftEventFactory.blockDamageRT.set(null); // SparklyPaper - parallel world ticking - // CraftBukkit end - we also don't throw an event unless the object in lava is living, to save on some event calls - - } -@@ -3440,9 +3440,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S - if (this.fireImmune()) { - return; - } -- CraftEventFactory.entityDamage = lightning; -+ CraftEventFactory.entityDamageRT.set(lightning); // SparklyPaper - parallel world ticking - if (!this.hurt(this.damageSources().lightningBolt(), 5.0F)) { -- CraftEventFactory.entityDamage = null; -+ CraftEventFactory.entityDamageRT.set(null); // SparklyPaper - parallel world ticking - return; - } - // CraftBukkit end -@@ -3958,6 +3958,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S +@@ -3960,6 +3960,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S this.teleportPassengers(); this.setYHeadRot(yaw); } else { @@ -1133,100 +1031,8 @@ index aa6045039450c4cce8d9481aa7f56867dd15c0fa..807a11fa10b1aeb46c9e4e47b9477a5f this.unRide(); Entity entity = this.getType().create(world); -diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -index d8056421249c8e75e96a55ec07dce84d2bba9c5c..b7150ab57334ca4dcecb7ce5510cd19e5ca2e087 100644 ---- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java -+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java -@@ -336,9 +336,9 @@ public class Turtle extends Animal { - - @Override - public void thunderHit(ServerLevel world, LightningBolt lightning) { -- org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = lightning; // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamageRT.set(lightning); // CraftBukkit // SparklyPaper - parallel world ticking - this.hurt(this.damageSources().lightningBolt(), Float.MAX_VALUE); -- org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamageRT.set(null); // CraftBukkit // SparklyPaper - parallel world ticking - } - - @Override -diff --git a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -index 45c07733f03b5c11f6d8e820f65dc950c70d9a67..60b9219778472e489192ca3259b4649a254187eb 100644 ---- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java -@@ -295,9 +295,9 @@ public class FallingBlockEntity extends Entity { - float f2 = (float) Math.min(Mth.floor((float) i * this.fallDamagePerDistance), this.fallDamageMax); - - this.level().getEntities((Entity) this, this.getBoundingBox(), predicate).forEach((entity) -> { -- CraftEventFactory.entityDamage = this; // CraftBukkit -+ CraftEventFactory.entityDamageRT.set(this); // CraftBukkit // SparklyPaper - parallel world ticking - entity.hurt(damagesource2, f2); -- CraftEventFactory.entityDamage = null; // CraftBukkit -+ CraftEventFactory.entityDamageRT.set(null); // CraftBukkit // SparklyPaper - parallel world ticking - }); - boolean flag = this.blockState.is(BlockTags.ANVIL); - -diff --git a/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java b/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java -index bbdb82b319480b103df463cce3c1b8e3dd5857ec..46093cd5d70ad6a95b2407aa5d749a3790ccd92a 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/EvokerFangs.java -@@ -129,9 +129,9 @@ public class EvokerFangs extends Entity implements TraceableEntity { - - if (target.isAlive() && !target.isInvulnerable() && target != entityliving1) { - if (entityliving1 == null) { -- org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = this; // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamageRT.set(this); // CraftBukkit // SparklyPaper - parallel world ticking - target.hurt(this.damageSources().magic(), 6.0F); -- org.bukkit.craftbukkit.event.CraftEventFactory.entityDamage = null; // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.entityDamageRT.set(null); // CraftBukkit // SparklyPaper - parallel world ticking - } else { - if (entityliving1.isAlliedTo((Entity) target)) { - return; -diff --git a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -index b2f08889139dc447f7071f1c81456035bf8de31e..f816f197df8f36c83d5fe5b6d677da91bac2c16f 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/FireworkRocketEntity.java -@@ -240,9 +240,9 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { - - if (f > 0.0F) { - if (this.attachedToEntity != null) { -- CraftEventFactory.entityDamage = this; // CraftBukkit -+ CraftEventFactory.entityDamageRT.set(this); // CraftBukkit // SparklyPaper - parallel world ticking - this.attachedToEntity.hurt(this.damageSources().fireworks(this, this.getOwner()), 5.0F + (float) (nbttaglist.size() * 2)); -- CraftEventFactory.entityDamage = null; // CraftBukkit -+ CraftEventFactory.entityDamageRT.set(null); // CraftBukkit // SparklyPaper - parallel world ticking - } - - double d0 = 5.0D; -@@ -269,9 +269,9 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier { - if (flag) { - float f1 = f * (float) Math.sqrt((5.0D - (double) this.distanceTo(entityliving)) / 5.0D); - -- CraftEventFactory.entityDamage = this; // CraftBukkit -+ CraftEventFactory.entityDamageRT.set(this); // CraftBukkit // SparklyPaper - parallel world ticking - entityliving.hurt(this.damageSources().fireworks(this, this.getOwner()), f1); -- CraftEventFactory.entityDamage = null; // CraftBukkit -+ CraftEventFactory.entityDamageRT.set(null); // CraftBukkit // SparklyPaper - parallel world ticking - } - } - } -diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -index af4da25c9b13c114179fab3254aea5323210d7da..92347924a1ccea98daee9c0fe2bb403d6b3aad22 100644 ---- a/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownEnderpearl.java -@@ -85,9 +85,9 @@ public class ThrownEnderpearl extends ThrowableItemProjectile { - - entityplayer.connection.teleport(teleEvent.getTo()); - entity.resetFallDistance(); -- CraftEventFactory.entityDamage = this; -+ CraftEventFactory.entityDamageRT.set(this); // SparklyPaper - parallel world ticking - entity.hurt(this.damageSources().fall(), 5.0F); -- CraftEventFactory.entityDamage = null; -+ CraftEventFactory.entityDamageRT.set(null); // SparklyPaper - parallel world ticking - } - // CraftBukkit end - this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS); diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java -index 8fd82051bba33b4703e4d99fff886b63a319a5ba..ffdea352e973858931bdd4c3f7e81d179f9edfdf 100644 +index 48f634a7521d31c1e9dfd3cfc83139d428dbd37a..072dfc7355f0fade0b007c800fb633dd4739adb5 100644 --- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -102,8 +102,14 @@ public abstract class AbstractContainerMenu { @@ -1245,10 +1051,10 @@ index 8fd82051bba33b4703e4d99fff886b63a319a5ba..ffdea352e973858931bdd4c3f7e81d17 this.remoteSlots = NonNullList.create(); this.remoteDataSlots = new IntArrayList(); diff --git a/src/main/java/net/minecraft/world/item/ArmorItem.java b/src/main/java/net/minecraft/world/item/ArmorItem.java -index 42d87800a328f71c5127ce5599ca4c71cc9bb1cd..466526dfe8f81379bccf640f2c3a70640c353540 100644 +index 6b81be03f87967124b046708557e05d519aa79e4..f9a4e71f1bdd59256bceb7af92a53e435feea55e 100644 --- a/src/main/java/net/minecraft/world/item/ArmorItem.java +++ b/src/main/java/net/minecraft/world/item/ArmorItem.java -@@ -69,7 +69,7 @@ public class ArmorItem extends Item implements Equipable { +@@ -75,7 +75,7 @@ public class ArmorItem extends Item implements Equipable { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (org.bukkit.craftbukkit.entity.CraftLivingEntity) entityliving.getBukkitEntity()); @@ -1258,10 +1064,10 @@ index 42d87800a328f71c5127ce5599ca4c71cc9bb1cd..466526dfe8f81379bccf640f2c3a7064 } diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java -index de277d61b718fe07a87d75a2547bb1c7f8553aa1..d4499bc920ec8c8f59b39d0ed0ff58df5e6b089c 100644 +index 1ad126d992d95062a3db08374db7a927f23a0cac..a75fa6301d597b5f295ea8ba82ce011dda159d16 100644 --- a/src/main/java/net/minecraft/world/item/ItemStack.java +++ b/src/main/java/net/minecraft/world/item/ItemStack.java -@@ -399,8 +399,8 @@ public final class ItemStack { +@@ -400,8 +400,8 @@ public final class ItemStack { if (enuminteractionresult.consumesAction() && world.captureTreeGeneration && world.capturedBlockStates.size() > 0) { world.captureTreeGeneration = false; Location location = CraftLocation.toBukkit(blockposition, world.getWorld()); @@ -1285,33 +1091,11 @@ index 3aa73cd44aa8c86b78c35bc1788e4f83018c49ed..eac9b4148d0951f7c54ce4ad8ab4d97e worldserver.getCraftServer().getPluginManager().callEvent(event); } -diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java -index 9442f58dff89ec843c321533965fbee2727d02f8..ab30f345381e32a1751adbd2344d8f3c473553ae 100644 ---- a/src/main/java/net/minecraft/world/level/Explosion.java -+++ b/src/main/java/net/minecraft/world/level/Explosion.java -@@ -584,7 +584,7 @@ public class Explosion { - continue; - } - -- CraftEventFactory.entityDamage = this.source; -+ CraftEventFactory.entityDamageRT.set(this.source); // SparklyPaper - parallel world ticking - entity.lastDamageCancelled = false; - - if (entity instanceof EnderDragon) { -@@ -598,7 +598,7 @@ public class Explosion { - entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount(this, entity, getSeenFraction(vec3d, entity, blockCache, blockPos))); // Paper - actually optimise explosions - } - -- CraftEventFactory.entityDamage = null; -+ CraftEventFactory.entityDamageRT.set(null); // SparklyPaper - parallel world ticking - if (entity.lastDamageCancelled) { // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Skip entity if damage event was cancelled - continue; - } diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 6aae2e409258607df170165c959a1cc7448c7f62..c74c8950058084a9d2dcd44b3d4941d5bdde75a9 100644 +index 1008f136ec24efc588b41fe8bf313c926ca000ed..5d73bd30d6c48effd5977c7ae6a4d85d770541cc 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -15,6 +15,8 @@ import java.util.function.Consumer; +@@ -10,6 +10,8 @@ import java.util.function.Consumer; import java.util.function.Predicate; import java.util.function.Supplier; import javax.annotation.Nullable; @@ -1320,24 +1104,24 @@ index 6aae2e409258607df170165c959a1cc7448c7f62..c74c8950058084a9d2dcd44b3d4941d5 import net.minecraft.CrashReport; import net.minecraft.CrashReportCategory; import net.minecraft.ReportedException; -@@ -830,7 +832,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -820,7 +822,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline - // Paper start - make sure loaded chunks get the inlined variant of this function + // Paper start - Perf: make sure loaded chunks get the inlined variant of this function net.minecraft.server.level.ServerChunkCache cps = ((ServerLevel)this).getChunkSource(); - if (cps.mainThread == Thread.currentThread()) { + if (TickThread.isTickThreadFor((ServerLevel) this, chunkX, chunkZ)) { // SparklyPaper - parallel world ticking, let tick threads load chunks via the main thread LevelChunk ifLoaded = cps.getChunkAtIfLoadedMainThread(chunkX, chunkZ); if (ifLoaded != null) { return ifLoaded; -@@ -914,6 +916,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -904,6 +906,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Override public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { + io.papermc.paper.util.TickThread.ensureTickThread((ServerLevel)this, pos, "Updating block asynchronously"); // SparklyPaper - parallel world ticking (additional concurrency issues logs) // CraftBukkit start - tree generation if (this.captureTreeGeneration) { - // Paper start -@@ -1310,7 +1313,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Paper start - Protect Bedrock and End Portal/Frames from being destroyed +@@ -1305,7 +1308,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { tickingblockentity.tick(); // Paper start - execute chunk tasks during tick if ((this.tileTickPosition & 7) == 0) { @@ -1346,7 +1130,7 @@ index 6aae2e409258607df170165c959a1cc7448c7f62..c74c8950058084a9d2dcd44b3d4941d5 } // Paper end - execute chunk tasks during tick } // SparklyPaper end -@@ -1327,7 +1330,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1322,7 +1325,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public void guardEntityTick(Consumer tickConsumer, T entity) { try { tickConsumer.accept(entity); @@ -1354,18 +1138,18 @@ index 6aae2e409258607df170165c959a1cc7448c7f62..c74c8950058084a9d2dcd44b3d4941d5 + // MinecraftServer.getServer().executeMidTickTasks(); // SparklyPaper - parallel world ticking (only run mid-tick at the end of each tick / fixes concurrency bugs related to executeMidTickTasks) // Paper - execute chunk tasks mid tick } catch (Throwable throwable) { if (throwable instanceof ThreadDeath) throw throwable; // Paper - // Paper start - Prevent tile entity and entity crashes -@@ -1434,6 +1437,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + // Paper start - Prevent block entity and entity crashes +@@ -1429,6 +1432,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Nullable public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) { + io.papermc.paper.util.TickThread.ensureTickThreadOrAsyncThread((ServerLevel) this, "Cannot read world asynchronously"); // SparklyPaper start - parallel world ticking - // Paper start - Optimize capturedTileEntities lookup + // Paper start - Perf: Optimize capturedTileEntities lookup net.minecraft.world.level.block.entity.BlockEntity blockEntity; if (!this.capturedTileEntities.isEmpty() && (blockEntity = this.capturedTileEntities.get(blockposition)) != null) { -@@ -1441,10 +1445,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1436,10 +1440,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } - // Paper end + // Paper end - Perf: Optimize capturedTileEntities lookup // CraftBukkit end - return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && !io.papermc.paper.util.TickThread.isTickThread() ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE)); // Paper - rewrite chunk system + return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && !io.papermc.paper.util.TickThread.isTickThread() ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE)); // Paper - rewrite chunk system // SparklyPaper - parallel world ticking @@ -1376,7 +1160,7 @@ index 6aae2e409258607df170165c959a1cc7448c7f62..c74c8950058084a9d2dcd44b3d4941d5 BlockPos blockposition = blockEntity.getBlockPos(); if (!this.isOutsideBuildHeight(blockposition)) { -@@ -1530,6 +1535,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1525,6 +1530,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @Override public List getEntities(@Nullable Entity except, AABB box, Predicate predicate) { @@ -1384,7 +1168,7 @@ index 6aae2e409258607df170165c959a1cc7448c7f62..c74c8950058084a9d2dcd44b3d4941d5 this.getProfiler().incrementCounter("getEntities"); List list = Lists.newArrayList(); ((ServerLevel)this).getEntityLookup().getEntities(except, box, list, predicate); // Paper - optimise this call -@@ -1796,8 +1802,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { +@@ -1791,8 +1797,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { } public final BlockPos.MutableBlockPos getRandomBlockPosition(int x, int y, int z, int l, BlockPos.MutableBlockPos out) { // Paper end @@ -1394,40 +1178,8 @@ index 6aae2e409258607df170165c959a1cc7448c7f62..c74c8950058084a9d2dcd44b3d4941d5 out.set(x + (i1 & 15), y + (i1 >> 16 & l), z + (i1 >> 8 & 15)); // Paper - change to setValues call return out; // Paper -diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -index a9629a102c4fa4e5720e63fcf4590e9231426c62..c86f4eaf1d130a2eee820e4831f0b2dd23dd2ac3 100644 ---- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java -@@ -122,9 +122,9 @@ public class CactusBlock extends Block { - @Override - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { - if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper -- CraftEventFactory.blockDamage = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit -+ CraftEventFactory.blockDamageRT.set(world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); // CraftBukkit // SparklyPaper - parallel world ticking - entity.hurt(world.damageSources().cactus(), 1.0F); -- CraftEventFactory.blockDamage = null; // CraftBukkit -+ CraftEventFactory.blockDamageRT.set(null); // CraftBukkit // SparklyPaper - parallel world ticking - } - - @Override -diff --git a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java -index 7302d07c6ff69608e75ac52fdb19f2ec1d105129..64890b15dcec19732c45e1f3f485ccd67cb00142 100644 ---- a/src/main/java/net/minecraft/world/level/block/CampfireBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/CampfireBlock.java -@@ -110,9 +110,9 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB - public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) { - if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper - if ((Boolean) state.getValue(CampfireBlock.LIT) && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { -- org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = CraftBlock.at(world, pos); // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamageRT.set(CraftBlock.at(world, pos)); // CraftBukkit // SparklyPaper - parallel world ticking - entity.hurt(world.damageSources().inFire(), (float) this.fireDamage); -- org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamageRT.set(null); // CraftBukkit // SparklyPaper - parallel world ticking - } - - super.entityInside(state, world, pos, entity); diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java -index 52e92ffd6bf5d3d721807a0b3a8e2d301951f934..2b86f1ef01e5119ccf951c22f9b2da137d3f6735 100644 +index 644e64850479cea20a98b8a65503ccf3a34fd32a..9013711498a96d8d680e62ee2a3b7ac91c355ab8 100644 --- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java +++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java @@ -49,7 +49,8 @@ public class DispenserBlock extends BaseEntityBlock { @@ -1443,7 +1195,7 @@ index 52e92ffd6bf5d3d721807a0b3a8e2d301951f934..2b86f1ef01e5119ccf951c22f9b2da13 @@ -105,7 +106,7 @@ public class DispenserBlock extends BaseEntityBlock { if (idispensebehavior != DispenseItemBehavior.NOOP) { - if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(world, pos, itemstack, i)) return; // Paper - BlockPreDispenseEvent is called here + if (!org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockPreDispenseEvent(world, pos, itemstack, i)) return; // Paper - Add BlockPreDispenseEvent - DispenserBlock.eventFired = false; // CraftBukkit - reset event status + DispenserBlock.eventFired.set(Boolean.FALSE); // CraftBukkit - reset event status // SparklyPaper - parallel world ticking tileentitydispenser.setItem(i, idispensebehavior.dispense(sourceblock, itemstack)); @@ -1465,56 +1217,24 @@ index 50d7235cf2ef036451db708c45a063d037051ae9..ff9b3d7cbf4ffcc81b4837da0c4eb0d5 } // CraftBukkit end ((ConfiguredFeature) holder.value()).place(world, world.getChunkSource().getGenerator(), random, pos); -diff --git a/src/main/java/net/minecraft/world/level/block/MagmaBlock.java b/src/main/java/net/minecraft/world/level/block/MagmaBlock.java -index 10f5ffacc72a5e0116e2599ca83ee57a5b1ce0eb..9e52c7e4459318171163ffae5d1a6c3e66ed84b0 100644 ---- a/src/main/java/net/minecraft/world/level/block/MagmaBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/MagmaBlock.java -@@ -30,9 +30,9 @@ public class MagmaBlock extends Block { - @Override - public void stepOn(Level world, BlockPos pos, BlockState state, Entity entity) { - if (!entity.isSteppingCarefully() && entity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity) entity)) { -- org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()); // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamageRT.set(world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); // CraftBukkit // SparklyPaper - parallel world ticking - entity.hurt(world.damageSources().hotFloor(), 1.0F); -- org.bukkit.craftbukkit.event.CraftEventFactory.blockDamage = null; // CraftBukkit -+ org.bukkit.craftbukkit.event.CraftEventFactory.blockDamageRT.set(null); // CraftBukkit // SparklyPaper - parallel world ticking - } - - super.stepOn(world, pos, state, entity); diff --git a/src/main/java/net/minecraft/world/level/block/MushroomBlock.java b/src/main/java/net/minecraft/world/level/block/MushroomBlock.java -index 7368c76a01275223a7bd3df1d36e80a15f66edbb..46a266b5f0d347b095ea0d03b41c18ae25277b13 100644 +index 1f27ae8abd5891a0b8057b454f2210b088b4e95a..7549cdc77c7738d3aba753c51a11e5a6997bd1d8 100644 --- a/src/main/java/net/minecraft/world/level/block/MushroomBlock.java +++ b/src/main/java/net/minecraft/world/level/block/MushroomBlock.java @@ -105,7 +105,7 @@ public class MushroomBlock extends BushBlock implements BonemealableBlock { return false; } else { world.removeBlock(pos, false); -- SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? TreeType.BROWN_MUSHROOM : TreeType.RED_MUSHROOM; // CraftBukkit // Paper -+ SaplingBlock.treeTypeRT.set((this == Blocks.BROWN_MUSHROOM) ? TreeType.BROWN_MUSHROOM : TreeType.RED_MUSHROOM); // CraftBukkit // Paper // SparklyPaper - parallel world ticking +- SaplingBlock.treeType = (this == Blocks.BROWN_MUSHROOM) ? TreeType.BROWN_MUSHROOM : TreeType.RED_MUSHROOM; // CraftBukkit ++ SaplingBlock.treeTypeRT.set((this == Blocks.BROWN_MUSHROOM) ? TreeType.BROWN_MUSHROOM : TreeType.RED_MUSHROOM); // CraftBukkit // SparklyPaper - parallel world ticking if (((ConfiguredFeature) ((Holder) optional.get()).value()).place(world, world.getChunkSource().getGenerator(), random, pos)) { return true; } else { -diff --git a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java -index bd22d3fdecbc992b11073a74d854b7d1b43c3f6a..f6a76279119847af45c517fe481782a79f51761e 100644 ---- a/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/PointedDripstoneBlock.java -@@ -150,9 +150,9 @@ public class PointedDripstoneBlock extends Block implements Fallable, SimpleWate - @Override - public void fallOn(Level world, BlockState state, BlockPos pos, Entity entity, float fallDistance) { - if (state.getValue(PointedDripstoneBlock.TIP_DIRECTION) == Direction.UP && state.getValue(PointedDripstoneBlock.THICKNESS) == DripstoneThickness.TIP) { -- CraftEventFactory.blockDamage = CraftBlock.at(world, pos); // CraftBukkit -+ CraftEventFactory.blockDamageRT.set(CraftBlock.at(world, pos)); // CraftBukkit // SparklyPaper - parallel world ticking - entity.causeFallDamage(fallDistance + 2.0F, 2.0F, world.damageSources().stalagmite()); -- CraftEventFactory.blockDamage = null; // CraftBukkit -+ CraftEventFactory.blockDamageRT.set(null); // CraftBukkit // SparklyPaper - parallel world ticking - } else { - super.fallOn(world, state, pos, entity, fallDistance); - } diff --git a/src/main/java/net/minecraft/world/level/block/SaplingBlock.java b/src/main/java/net/minecraft/world/level/block/SaplingBlock.java -index 836c86104ed4f0d375330c9123af5d502efefa4d..8e88047053e18b2d1b56ae9e329659969b3dc08e 100644 +index 3ff0d08e4964aae82d8e51d3b8bf9aa002096f81..069f669a31b8ac5b90341c7ef066b3a32f75fc3c 100644 --- a/src/main/java/net/minecraft/world/level/block/SaplingBlock.java +++ b/src/main/java/net/minecraft/world/level/block/SaplingBlock.java -@@ -34,7 +34,7 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { +@@ -35,7 +35,7 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { protected static final float AABB_OFFSET = 6.0F; protected static final VoxelShape SHAPE = Block.box(2.0D, 0.0D, 2.0D, 14.0D, 12.0D, 14.0D); protected final TreeGrower treeGrower; @@ -1523,7 +1243,7 @@ index 836c86104ed4f0d375330c9123af5d502efefa4d..8e88047053e18b2d1b56ae9e32965996 @Override public MapCodec codec() { -@@ -72,8 +72,8 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { +@@ -73,8 +73,8 @@ public class SaplingBlock extends BushBlock implements BonemealableBlock { this.treeGrower.growTree(world, world.getChunkSource().getGenerator(), pos, state, random); world.captureTreeGeneration = false; if (world.capturedBlockStates.size() > 0) { @@ -1534,24 +1254,8 @@ index 836c86104ed4f0d375330c9123af5d502efefa4d..8e88047053e18b2d1b56ae9e32965996 Location location = CraftLocation.toBukkit(pos, world.getWorld()); java.util.List blocks = new java.util.ArrayList<>(world.capturedBlockStates.values()); world.capturedBlockStates.clear(); -diff --git a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java -index f474ae7b3121de701f371b7d88e80086ec07d03d..3b7a14d76b0e24aa7747e3b37560db4c8a7370db 100644 ---- a/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java -+++ b/src/main/java/net/minecraft/world/level/block/SweetBerryBushBlock.java -@@ -92,9 +92,9 @@ public class SweetBerryBushBlock extends BushBlock implements BonemealableBlock - double d1 = Math.abs(entity.getZ() - entity.zOld); - - if (d0 >= 0.003000000026077032D || d1 >= 0.003000000026077032D) { -- CraftEventFactory.blockDamage = CraftBlock.at(world, pos); // CraftBukkit -+ CraftEventFactory.blockDamageRT.set(CraftBlock.at(world, pos)); // CraftBukkit // SparklyPaper - parallel world ticking - entity.hurt(world.damageSources().sweetBerryBush(), 1.0F); -- CraftEventFactory.blockDamage = null; // CraftBukkit -+ CraftEventFactory.blockDamageRT.set(null); // CraftBukkit // SparklyPaper - parallel world ticking - } - } - diff --git a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java -index c134d089e55ea2ffb180f92aea020bd7647259c9..a7e1e05fdcb380de71b1bac5f7b5daca3dee2ac9 100644 +index b8b4d74076fa5ed6eb3b2045384db77e165931b2..331c156c915d47fae67003bd650738ea00492bd3 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BaseContainerBlockEntity.java @@ -78,6 +78,12 @@ public abstract class BaseContainerBlockEntity extends BlockEntity implements Co @@ -1567,30 +1271,12 @@ index c134d089e55ea2ffb180f92aea020bd7647259c9..a7e1e05fdcb380de71b1bac5f7b5daca if (player instanceof net.minecraft.server.level.ServerPlayer serverPlayer && blockEntity != null && blockEntity.getLevel() != null && blockEntity.getLevel().getBlockEntity(blockEntity.getBlockPos()) == blockEntity) { final org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(blockEntity.getLevel(), blockEntity.getBlockPos()); net.kyori.adventure.text.Component lockedMessage = net.kyori.adventure.text.Component.translatable("container.isLocked", io.papermc.paper.adventure.PaperAdventure.asAdventure(containerName)); -diff --git a/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java -index 963a596154091b79ca139af6274aa323518ad1ad..2817225e5efc97d24e54800689cdda0f53baa616 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/ConduitBlockEntity.java -@@ -235,11 +235,11 @@ public class ConduitBlockEntity extends BlockEntity { - - if (blockEntity.destroyTarget != null) { - // CraftBukkit start -- CraftEventFactory.blockDamage = CraftBlock.at(world, pos); -+ CraftEventFactory.blockDamageRT.set(CraftBlock.at(world, pos)); // SparklyPaper - parallel world ticking - if (blockEntity.destroyTarget.hurt(world.damageSources().magic(), 4.0F)) { - world.playSound((Player) null, blockEntity.destroyTarget.getX(), blockEntity.destroyTarget.getY(), blockEntity.destroyTarget.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F); - } -- CraftEventFactory.blockDamage = null; -+ CraftEventFactory.blockDamageRT.set(null); // SparklyPaper - parallel world ticking - // CraftBukkit end - } - diff --git a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java -index 65112ec3a6ea1c27f032477720ae74395523012b..41ed21bbb7762e52cd800846f546277c19ecd67e 100644 +index 83481539e058e5f428d9951e409fed62ef159e5c..c4165376eda073add2a267b737a676123e63a197 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/SculkCatalystBlockEntity.java @@ -43,9 +43,9 @@ public class SculkCatalystBlockEntity extends BlockEntity implements GameEventLi - // Paper end + // Paper end - Fix NPE in SculkBloomEvent world access public static void serverTick(Level world, BlockPos pos, BlockState state, SculkCatalystBlockEntity blockEntity) { - org.bukkit.craftbukkit.event.CraftEventFactory.sourceBlockOverride = blockEntity.getBlockPos(); // CraftBukkit - SPIGOT-7068: Add source block override, not the most elegant way but better than passing down a BlockPosition up to five methods deep. @@ -1681,7 +1367,7 @@ index 8cb822fed0cda4268f288feae1079a3dc4dc103e..1bac955a0b734689cc66b1a61e58fcde // CraftBukkit end 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 1338f91a85f5db6ce78705a0c48bec8a449a6220..00af4b8db53a55d252a43a29c4939fea111d3f13 100644 +index 91b538f047428b8836f7ad3b62a0586fb7beb9ec..9f235ee277bb1b47d55288f0058c0bd94b1afc0c 100644 --- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java @@ -419,6 +419,7 @@ public class LevelChunk extends ChunkAccess { @@ -1736,10 +1422,10 @@ index 4cdfc433df67afcd455422e9baf56f167dd712ae..f52b3740bd48f8527a36d48a0454e7d6 // To ensure nothing weird happens with dimension travelling, do not iterate over new entries... // (by dfl iterator() is configured to not iterate over new entries) diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 38d842bc0fb7d9c39a3673983a643248e9563fe2..f6663c2a9984955057e5f070f31b4825d956cf60 100644 +index bfb178c69026e9759e9afaebb9da141b62d1f144..295eca9de3e1e5d7eb01f9ff015b525ab728aa31 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -434,7 +434,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -440,7 +440,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { } private boolean unloadChunk0(int x, int z, boolean save) { @@ -1748,7 +1434,7 @@ index 38d842bc0fb7d9c39a3673983a643248e9563fe2..f6663c2a9984955057e5f070f31b4825 if (!this.isChunkLoaded(x, z)) { return true; } -@@ -449,7 +449,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -455,7 +455,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean regenerateChunk(int x, int z) { @@ -1757,7 +1443,7 @@ index 38d842bc0fb7d9c39a3673983a643248e9563fe2..f6663c2a9984955057e5f070f31b4825 warnUnsafeChunk("regenerating a faraway chunk", x, z); // Paper // Paper start - implement regenerateChunk method final ServerLevel serverLevel = this.world; -@@ -510,6 +510,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -518,6 +518,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean refreshChunk(int x, int z) { @@ -1765,7 +1451,7 @@ index 38d842bc0fb7d9c39a3673983a643248e9563fe2..f6663c2a9984955057e5f070f31b4825 ChunkHolder playerChunk = this.world.getChunkSource().chunkMap.getVisibleChunkIfPresent(ChunkPos.asLong(x, z)); if (playerChunk == null) return false; -@@ -545,7 +546,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -553,7 +554,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean loadChunk(int x, int z, boolean generate) { @@ -1774,7 +1460,7 @@ index 38d842bc0fb7d9c39a3673983a643248e9563fe2..f6663c2a9984955057e5f070f31b4825 warnUnsafeChunk("loading a faraway chunk", x, z); // Paper // Paper start - Optimize this method ChunkPos chunkPos = new ChunkPos(x, z); -@@ -808,6 +809,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -813,6 +814,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) { @@ -1782,7 +1468,7 @@ index 38d842bc0fb7d9c39a3673983a643248e9563fe2..f6663c2a9984955057e5f070f31b4825 this.world.captureTreeGeneration = true; this.world.captureBlockStates = true; boolean grownTree = this.generateTree(loc, type); -@@ -918,11 +920,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -923,11 +925,13 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks, Entity source) { @@ -1796,7 +1482,7 @@ index 38d842bc0fb7d9c39a3673983a643248e9563fe2..f6663c2a9984955057e5f070f31b4825 return !world.explode(source != null ? ((org.bukkit.craftbukkit.entity.CraftEntity) source).getHandle() : null, loc.getX(), loc.getY(), loc.getZ(), power, setFire, breakBlocks ? net.minecraft.world.level.Level.ExplosionInteraction.MOB : net.minecraft.world.level.Level.ExplosionInteraction.NONE).wasCanceled; } // Paper end -@@ -992,6 +996,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1004,6 +1008,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public int getHighestBlockYAt(int x, int z, org.bukkit.HeightMap heightMap) { @@ -1804,7 +1490,7 @@ index 38d842bc0fb7d9c39a3673983a643248e9563fe2..f6663c2a9984955057e5f070f31b4825 warnUnsafeChunk("getting a faraway chunk", x >> 4, z >> 4); // Paper // Transient load for this tick return this.world.getChunk(x >> 4, z >> 4).getHeight(CraftHeightMap.toNMS(heightMap), x, z); -@@ -1022,6 +1027,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -1034,6 +1039,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void setBiome(int x, int y, int z, Holder bb) { BlockPos pos = new BlockPos(x, 0, z); @@ -1812,7 +1498,7 @@ index 38d842bc0fb7d9c39a3673983a643248e9563fe2..f6663c2a9984955057e5f070f31b4825 if (this.world.hasChunkAt(pos)) { net.minecraft.world.level.chunk.LevelChunk chunk = this.world.getChunkAt(pos); -@@ -2366,6 +2372,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2339,6 +2345,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { @Override public void sendGameEvent(Entity sourceEntity, org.bukkit.GameEvent gameEvent, Vector position) { @@ -1820,7 +1506,7 @@ index 38d842bc0fb7d9c39a3673983a643248e9563fe2..f6663c2a9984955057e5f070f31b4825 getHandle().gameEvent(sourceEntity != null ? ((CraftEntity) sourceEntity).getHandle(): null, net.minecraft.core.registries.BuiltInRegistries.GAME_EVENT.get(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(gameEvent.getKey())), org.bukkit.craftbukkit.util.CraftVector.toBlockPos(position)); } // Paper end -@@ -2469,7 +2476,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { +@@ -2459,7 +2466,7 @@ public class CraftWorld extends CraftRegionAccessor implements World { // Paper start public java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { warnUnsafeChunk("getting a faraway chunk async", x, z); // Paper @@ -1830,7 +1516,7 @@ index 38d842bc0fb7d9c39a3673983a643248e9563fe2..f6663c2a9984955057e5f070f31b4825 if (immediate != null) { return java.util.concurrent.CompletableFuture.completedFuture(new CraftChunk(immediate)); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java -index e5506a7d074a9f89d41f4d5d7549a458779bef20..8481a7dfc04b9d663fec909207b744a647067d84 100644 +index 4b42ef2a876ea210d948238e63fd7a2b7035bb5b..0631fcf5749bfd7ca4ba8bad8a959fb024a1d017 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlock.java @@ -75,6 +75,11 @@ public class CraftBlock implements Block { @@ -2000,7 +1686,7 @@ index e5506a7d074a9f89d41f4d5d7549a458779bef20..8481a7dfc04b9d663fec909207b744a6 net.minecraft.server.level.ServerLevel level = this.world.getMinecraftWorld(); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java -index a8290624d8c5b19506f628d049984d2e59c4423c..4b0cb97a9355c77eedf17d36c4313189b23aca73 100644 +index 53d466bfa66573f178fd0e0247bcefc04902c38f..be22fd2344a72b3eb3532af3c4c961296d403a3a 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java @@ -18,7 +18,7 @@ public abstract class CraftBlockEntityState extends Craft @@ -2014,7 +1700,7 @@ index a8290624d8c5b19506f628d049984d2e59c4423c..4b0cb97a9355c77eedf17d36c4313189 super(world, tileEntity.getBlockPos(), tileEntity.getBlockState()); @@ -27,8 +27,8 @@ public abstract class CraftBlockEntityState extends Craft - try { // Paper - show location on failure + try { // Paper - Show blockstate location if we failed to read it // Paper start - this.snapshotDisabled = DISABLE_SNAPSHOT; - if (DISABLE_SNAPSHOT) { @@ -2024,7 +1710,7 @@ index a8290624d8c5b19506f628d049984d2e59c4423c..4b0cb97a9355c77eedf17d36c4313189 } else { this.snapshot = this.createSnapshot(tileEntity); diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java -index 390e1b7fd2721b99cb3ce268c6bc1bf0a38e08a3..9255e51954bd9a43afc366d8c414dd8af7571525 100644 +index d11d854ae90b99aa2ce227994d07fe1fe9b4a60a..3040588155878dcbeb4fb5d71cf99b83f88e0a82 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java @@ -210,6 +210,12 @@ public class CraftBlockState implements BlockState { @@ -2049,10 +1735,10 @@ index 390e1b7fd2721b99cb3ce268c6bc1bf0a38e08a3..9255e51954bd9a43afc366d8c414dd8a // Modelled off EntityHuman#hasBlock diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java -index 9271ff2a9ea05569e3c81886399aa7ab47efb05d..e5891ed14f688413dfe9ebd2b5af6d4b82f43f68 100644 +index 8afc396c162d928902a9d9beb9f039b06630f755..4cde4be86dc03ebbfb5c12a910acbf9978fd42d4 100644 --- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java +++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java -@@ -243,8 +243,8 @@ public final class CraftBlockStates { +@@ -242,8 +242,8 @@ public final class CraftBlockStates { net.minecraft.world.level.block.state.BlockState blockData = craftBlock.getNMS(); BlockEntity tileEntity = craftBlock.getHandle().getBlockEntity(blockPosition); // Paper start - block state snapshots @@ -2063,7 +1749,7 @@ index 9271ff2a9ea05569e3c81886399aa7ab47efb05d..e5891ed14f688413dfe9ebd2b5af6d4b try { // Paper end CraftBlockState blockState = CraftBlockStates.getBlockState(world, blockPosition, blockData, tileEntity); -@@ -252,7 +252,7 @@ public final class CraftBlockStates { +@@ -251,7 +251,7 @@ public final class CraftBlockStates { return blockState; // Paper start } finally { @@ -2073,21 +1759,10 @@ index 9271ff2a9ea05569e3c81886399aa7ab47efb05d..e5891ed14f688413dfe9ebd2b5af6d4b // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 2aab68bac670dcd134d817940020214c7b0797f9..1bc112574337b262e88a8b30ed5b75d62d160db4 100644 +index d677759ac6b6d3cfe5a2af76dc1f0034b216ac2d..f9ef030ab07f2da56e3b1689b9ec9dbc37975694 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -243,8 +243,8 @@ import org.bukkit.potion.PotionEffect; - import org.bukkit.util.Vector; - - public class CraftEventFactory { -- public static org.bukkit.block.Block blockDamage; // For use in EntityDamageByBlockEvent -- public static Entity entityDamage; // For use in EntityDamageByEntityEvent -+ public static final ThreadLocal blockDamageRT = new ThreadLocal<>(); // For use in EntityDamageByBlockEvent // SparklyPaper - parallel world ticking (this is from Folia, fixes concurrency bugs / For use in EntityDamageByEntityEvent) -+ public static final ThreadLocal entityDamageRT = new ThreadLocal<>(); // For use in EntityDamageByEntityEvent // SparklyPaper - parallel world ticking (this is from Folia, fixes concurrency bugs / For use in EntityDamageByEntityEvent) - - // helper methods - private static boolean canBuild(ServerLevel world, Player player, int x, int z) { -@@ -917,7 +917,7 @@ public class CraftEventFactory { +@@ -941,7 +941,7 @@ public class CraftEventFactory { return CraftEventFactory.handleBlockSpreadEvent(world, source, target, block, 2); } @@ -2096,7 +1771,7 @@ index 2aab68bac670dcd134d817940020214c7b0797f9..1bc112574337b262e88a8b30ed5b75d6 public static boolean handleBlockSpreadEvent(LevelAccessor world, BlockPos source, BlockPos target, net.minecraft.world.level.block.state.BlockState block, int flag) { // Suppress during worldgen -@@ -929,7 +929,7 @@ public class CraftEventFactory { +@@ -953,7 +953,7 @@ public class CraftEventFactory { CraftBlockState state = CraftBlockStates.getBlockState(world, target, flag); state.setData(block); @@ -2105,77 +1780,10 @@ index 2aab68bac670dcd134d817940020214c7b0797f9..1bc112574337b262e88a8b30ed5b75d6 Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { -@@ -1056,8 +1056,8 @@ public class CraftEventFactory { - private static EntityDamageEvent handleEntityDamageEvent(Entity entity, DamageSource source, Map modifiers, Map> modifierFunctions, boolean cancelled) { - if (source.is(DamageTypeTags.IS_EXPLOSION)) { - DamageCause damageCause; -- Entity damager = CraftEventFactory.entityDamage; -- CraftEventFactory.entityDamage = null; -+ Entity damager = CraftEventFactory.entityDamageRT.get(); // SparklyPaper - parallel world ticking -+ CraftEventFactory.entityDamageRT.set(null); // SparklyPaper - parallel world ticking - EntityDamageEvent event; - if (damager == null) { - event = new EntityDamageByBlockEvent(null, entity.getBukkitEntity(), DamageCause.BLOCK_EXPLOSION, modifiers, modifierFunctions, source.explodedBlockState); // Paper - handle block state in damage -@@ -1118,13 +1118,13 @@ public class CraftEventFactory { - } - return event; - } else if (source.is(DamageTypes.LAVA)) { -- EntityDamageEvent event = (new EntityDamageByBlockEvent(CraftEventFactory.blockDamage, entity.getBukkitEntity(), DamageCause.LAVA, modifiers, modifierFunctions)); -+ EntityDamageEvent event = (new EntityDamageByBlockEvent(CraftEventFactory.blockDamageRT.get(), entity.getBukkitEntity(), DamageCause.LAVA, modifiers, modifierFunctions)); // SparklyPaper - parallel world ticking - event.setCancelled(cancelled); - -- Block damager = CraftEventFactory.blockDamage; -- CraftEventFactory.blockDamage = null; // SPIGOT-6639: Clear blockDamage to allow other entity damage during event call -+ Block damager = CraftEventFactory.blockDamageRT.get(); // SparklyPaper - parallel world ticking -+ CraftEventFactory.blockDamageRT.set(null); // SPIGOT-6639: Clear blockDamage to allow other entity damage during event call // SparklyPaper - parallel world ticking - CraftEventFactory.callEvent(event); -- CraftEventFactory.blockDamage = damager; // SPIGOT-6639: Re-set blockDamage so that other entities which are also getting damaged have the right cause -+ CraftEventFactory.blockDamageRT.set(damager); // SPIGOT-6639: Re-set blockDamage so that other entities which are also getting damaged have the right cause // SparklyPaper - parallel world ticking - - if (!event.isCancelled()) { - event.getEntity().setLastDamageCause(event); -@@ -1132,9 +1132,9 @@ public class CraftEventFactory { - entity.lastDamageCancelled = true; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled - } - return event; -- } else if (CraftEventFactory.blockDamage != null) { -+ } else if (CraftEventFactory.blockDamageRT.get() != null) { // SparklyPaper - parallel world ticking - DamageCause cause = null; -- Block damager = CraftEventFactory.blockDamage; -+ Block damager = CraftEventFactory.blockDamageRT.get(); // SparklyPaper - parallel world ticking - if (source.is(DamageTypes.CACTUS) || source.is(DamageTypes.SWEET_BERRY_BUSH) || source.is(DamageTypes.STALAGMITE) || source.is(DamageTypes.FALLING_STALACTITE) || source.is(DamageTypes.FALLING_ANVIL)) { - cause = DamageCause.CONTACT; - } else if (source.is(DamageTypes.HOT_FLOOR)) { -@@ -1149,9 +1149,9 @@ public class CraftEventFactory { - EntityDamageEvent event = new EntityDamageByBlockEvent(damager, entity.getBukkitEntity(), cause, modifiers, modifierFunctions); - event.setCancelled(cancelled); - -- CraftEventFactory.blockDamage = null; // SPIGOT-6639: Clear blockDamage to allow other entity damage during event call -+ CraftEventFactory.blockDamageRT.set(null); // SPIGOT-6639: Clear blockDamage to allow other entity damage during event call // SparklyPaper - parallel world ticking - CraftEventFactory.callEvent(event); -- CraftEventFactory.blockDamage = damager; // SPIGOT-6639: Re-set blockDamage so that other entities which are also getting damaged have the right cause -+ CraftEventFactory.blockDamageRT.set(damager); // SPIGOT-6639: Re-set blockDamage so that other entities which are also getting damaged have the right cause // SparklyPaper - parallel world ticking - - if (!event.isCancelled()) { - event.getEntity().setLastDamageCause(event); -@@ -1159,10 +1159,10 @@ public class CraftEventFactory { - entity.lastDamageCancelled = true; // SPIGOT-5339, SPIGOT-6252, SPIGOT-6777: Keep track if the event was canceled - } - return event; -- } else if (CraftEventFactory.entityDamage != null) { -+ } else if (CraftEventFactory.entityDamageRT.get() != null) { // SparklyPaper - parallel world ticking - DamageCause cause = null; -- CraftEntity damager = CraftEventFactory.entityDamage.getBukkitEntity(); -- CraftEventFactory.entityDamage = null; -+ CraftEntity damager = CraftEventFactory.entityDamageRT.get().getBukkitEntity(); // SparklyPaper - parallel world ticking -+ CraftEventFactory.entityDamageRT.set(null); // SparklyPaper - parallel world ticking - if (source.is(DamageTypes.FALLING_STALACTITE) || source.is(DamageTypes.FALLING_BLOCK) || source.is(DamageTypes.FALLING_ANVIL)) { - cause = DamageCause.FALLING_BLOCK; - } else if (damager instanceof LightningStrike) { -@@ -2131,7 +2131,7 @@ public class CraftEventFactory { +@@ -2126,7 +2126,7 @@ public class CraftEventFactory { CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemStack.copyWithCount(1)); - org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), new org.bukkit.util.Vector(to.getX(), to.getY(), to.getZ())); + org.bukkit.event.block.BlockDispenseEvent event = new org.bukkit.event.block.BlockDispenseEvent(bukkitBlock, craftItem.clone(), CraftVector.toBukkit(to)); - if (!net.minecraft.world.level.block.DispenserBlock.eventFired) { + if (!net.minecraft.world.level.block.DispenserBlock.eventFired.get()) { // SparklyPaper - parallel world ticking if (!event.callEvent()) {